diff --git a/covas_mobile/images/search.png b/covas_mobile/images/search.png new file mode 100644 index 0000000..9454673 Binary files /dev/null and b/covas_mobile/images/search.png differ diff --git a/covas_mobile/lib/classes/descriptionImage.dart b/covas_mobile/lib/classes/addEventImage.dart similarity index 100% rename from covas_mobile/lib/classes/descriptionImage.dart rename to covas_mobile/lib/classes/addEventImage.dart diff --git a/covas_mobile/lib/classes/eventAdded.dart b/covas_mobile/lib/classes/eventAdded.dart new file mode 100644 index 0000000..d2c75b7 --- /dev/null +++ b/covas_mobile/lib/classes/eventAdded.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +import '../pages/ListItemMenu.dart'; + +mixin ShowEventDialog on State { + void showEventDialog(BuildContext context, String text) { + // Create AlertDialog + AlertDialog dialog = AlertDialog( + title: Text("Evenement ajoute"), + content: Text(text), + actions: [ + ElevatedButton( + child: Text("OK"), + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20), + textStyle: + TextStyle(fontSize: 15, fontWeight: FontWeight.normal)), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ListItemMenu())); // Return value + }), + ], + ); + + // Call showDialog function to show dialog. + Future futureValue = showDialog( + context: context, + builder: (BuildContext context) { + return dialog; + }); + } +} diff --git a/covas_mobile/lib/classes/getEventImage.dart b/covas_mobile/lib/classes/getEventImage.dart new file mode 100644 index 0000000..a0db5dc --- /dev/null +++ b/covas_mobile/lib/classes/getEventImage.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'events.dart'; +import '../variable/globals.dart' as globals; +import 'package:http/http.dart' as http; +import 'dart:io'; +import 'dart:convert'; + +import 'package:shared_preferences/shared_preferences.dart'; + +mixin ShowDescImageGet on State { + Future getEvents(var events) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var accessToken = prefs.getString("access_token") ?? ""; + List send = ["toto"]; + + if (accessToken.isNotEmpty) { + var urlPut = Uri.parse("${globals.api}/events"); + print("start date : ${events["start_date"]}"); + var responsePut = await http.put(urlPut, + headers: { + HttpHeaders.cookieHeader: 'access_token=${accessToken}', + HttpHeaders.acceptHeader: 'application/json, text/plain, */*', + HttpHeaders.contentTypeHeader: 'application/json' + }, + body: jsonEncode({ + 'name': events["name"], + 'place': events["place"], + 'start_date': events['date'], + 'end_date': events['date'], + 'organizers': send, + 'latitude': '0.0', + 'longitude': '0.0', + })); + + print("http put code status : ${responsePut.statusCode}"); + print("http put body : ${responsePut.body}"); + } + } + + void showDescImageGetDialog(BuildContext context, var events) { + // Create AlertDialog + String name = events['name']; + AlertDialog dialog = AlertDialog( + title: Text("Voir la description de l'evenement"), + content: Text("${name} a été trouvé. Voulez-vous voir sa description ? "), + actions: [ + TextButton( + child: Text("Annuler"), + onPressed: () { + Navigator.of(context).pop("Yes, Of course!"); // Return value + }), + TextButton( + child: Text("Oui"), + onPressed: () { + getEvents(events); // Return value + }), + ], + ); + + // Call showDialog function to show dialog. + Future futureValue = showDialog( + context: context, + builder: (BuildContext context) { + return dialog; + }); + } +} diff --git a/covas_mobile/lib/pages/DisplayPictureScreen.dart b/covas_mobile/lib/pages/DisplayPictureScreen.dart index 64a7e58..9815034 100644 --- a/covas_mobile/lib/pages/DisplayPictureScreen.dart +++ b/covas_mobile/lib/pages/DisplayPictureScreen.dart @@ -1,11 +1,13 @@ import 'package:flutter/material.dart'; import 'dart:io'; -import '../classes/descriptionImage.dart'; +import '../classes/addEventImage.dart'; import '../classes/alert.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_gemini/flutter_gemini.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; +import "ItemMenu.dart"; +import 'UpdateEventImage.dart'; import 'dart:convert'; @@ -52,21 +54,37 @@ class DisplayPictureScreen extends StatefulWidget { // A widget that displays the picture taken by the user. class DisplayPictureScreenState extends State - with ShowDescImageAdd, ShowErrorDialog { + with ShowDescImageAdd, ShowErrorDialog, TickerProviderStateMixin { + late AnimationController controller; @override void initState() { + controller = AnimationController( + /// [AnimationController]s can be created with `vsync: this` because of + /// [TickerProviderStateMixin]. + vsync: this, + duration: const Duration(seconds: 5), + )..addListener(() { + setState(() {}); + }); + controller.repeat(reverse: false); super.initState(); _getEventInfosFromImage(); } + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + Future displayError(String e) async { print("problem gemini : ${e}"); showErrorDialog(context, "L'IA de Google n'a pas su analyser l'image. Recommecer avec une autre"); } - Future searchEvents(String json) async { + Future searchEvents(String json, String imagePath) async { print(json); SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -84,7 +102,16 @@ class DisplayPictureScreenState extends State var events = jsonDecode(utf8.decode(responseGet.bodyBytes)); print("reponse http : ${events.length}"); if (events.length == 0) { - showDescImageAddDialog(context, jsonData); + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => UpdateeventImage( + events: jsonData, imagePath: imagePath))); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ItemMenu(title: events[0]["id"]))); } } } else { @@ -105,10 +132,11 @@ class DisplayPictureScreenState extends State gemini .textAndImage( text: - "Peux-tu donner le nom, la date et le lieu de l'évènement sous format JSON avec les valeurs suivantes : name, place et date avec le format suivant YYYY-MM-ddTTHH:mm, et sans la présence de json dans la chaîne de caractère", + "Peux-tu donner le nom, la date avec l'année actuelle ou d'une année future proche et le lieu de l'évènement sous format JSON avec les valeurs suivantes : name, address, city, zip_code, country, description, start_date et end_date sous le format en YYYY-MM-DD HH:mm:ssZ, et sans la présence du mot json dans la chaîne de caractère", images: [file.readAsBytesSync()], - modelName: "models/gemini-1.5-flash-latest") - .then((value) => searchEvents(value?.content?.parts?.last.text ?? '')) + modelName: "models/gemini-1.5-pro-latest") + .then((value) => searchEvents( + value?.content?.parts?.last.text ?? '', widget.imagePath)) .catchError((e) => displayError); } @@ -118,10 +146,19 @@ class DisplayPictureScreenState extends State appBar: AppBar(title: const Text('Display the Picture')), // The image is stored as a file on the device. Use the `Image.file` // constructor with the given path to display the image. - body: SingleChildScrollView( - child: Column(children: [ - Image.file(File(widget.imagePath)), - Text("Analyse en cours...") - ]))); + body: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Text( + 'Analyse de l\'image en cours', + style: Theme.of(context).textTheme.titleLarge, + ), + CircularProgressIndicator( + value: controller.value, + semanticsLabel: 'Loading progress', + ), + ]))); } } diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 63f83b7..e42162e 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -14,6 +14,8 @@ import '../variable/globals.dart' as globals; import '../classes/events.dart'; +import 'ListItemMenu.dart'; + void main() { initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); } @@ -181,12 +183,18 @@ class _ItemMenuState extends State with ShowErrorDialog { // than having to individually change instances of widgets. return Scaffold( appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text("${eventName}"), - backgroundColor: Colors.blue, - foregroundColor: Colors.white, - ), + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text("${eventName}"), + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + leading: IconButton( + icon: Icon(Icons.arrow_back), + onPressed: () { + Navigator.push( + context, MaterialPageRoute(builder: (_) => ListItemMenu())); + }, + )), body: SingleChildScrollView( child: Column( children: [ diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart new file mode 100644 index 0000000..d770ab3 --- /dev/null +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -0,0 +1,393 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:http/http.dart' as http; +import 'package:intl/intl.dart'; + +import 'dart:convert'; +import 'dart:io'; + +import '../classes/alert.dart'; +import '../classes/eventAdded.dart'; + +import '../variable/globals.dart' as globals; + +void main() { + runApp(MyApp()); +} + +class MyApp extends StatelessWidget { + Map events = {}; + String imagePath = ""; + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + home: UpdateeventImage(events: events, imagePath: imagePath), + ); + } +} + +class UpdateeventImage extends StatefulWidget { + const UpdateeventImage( + {Key? key, required this.events, required this.imagePath}) + : super(key: key); + final Map events; + final String imagePath; + + @override + _UpdateeventImageState createState() => _UpdateeventImageState(); +} + +class _UpdateeventImageState extends State + with ShowErrorDialog, ShowEventDialog { + TextEditingController inputName = TextEditingController(); + TextEditingController inputAddress = TextEditingController(); + TextEditingController inputZipCode = TextEditingController(); + + TextEditingController inputCity = TextEditingController(); + TextEditingController inputCountry = TextEditingController(); + + TextEditingController inputDate = TextEditingController(); + TextEditingController inputDesc = TextEditingController(); + + TextEditingController startDatepicker = TextEditingController(); + TextEditingController startTimepicker = TextEditingController(); + TextEditingController endDatepicker = TextEditingController(); + TextEditingController endTimepicker = TextEditingController(); + + onTapFunctionDatePicker( + {required BuildContext context, required String position}) async { + DateTime? pickedDate = await showDatePicker( + context: context, + firstDate: DateTime.parse(widget.events["date"]), + initialDate: DateTime.parse(widget.events["date"]), + lastDate: DateTime(2104)); + if (pickedDate == null) return; + if (position == "start") { + startDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedDate); + } + if (position == "end") { + endDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedDate); + } + } + + onTapFunctionTimePicker( + {required BuildContext context, required String position}) async { + TimeOfDay? pickedDate = await showTimePicker( + context: context, + initialTime: + TimeOfDay.fromDateTime(DateTime.parse(widget.events["date"]))); + if (pickedDate == null) return; + if (position == "start") { + startTimepicker.text = pickedDate.format(context); + } + if (position == "end") { + endTimepicker.text = pickedDate.format(context); + } + } + + String formatDate(String date) { + var splitedDate = date.split("-"); + var day = splitedDate[0]; + var month = splitedDate[1]; + var year = splitedDate[2]; + + return "${year}-${month}-${day}"; + } + + Future _updateEvent(BuildContext context) async { + var url = Uri.parse("${globals.api}/token"); + var name = inputName.text; + var place = inputAddress.text; + var city = inputCity.text; + var country = inputCountry.text; + var zipCode = inputZipCode.text; + var description = inputDesc.text; + + var startDateFormat = formatDate(startDatepicker.text); + var endDateFormat = formatDate(endDatepicker.text); + var startDate = + "${startDateFormat}T${startTimepicker.text.replaceAll('-', ':')}"; + var endDate = "${endDateFormat}T${endTimepicker.text.replaceAll('-', ':')}"; + print("start date : ${startDate}"); + print("end date : ${endDate}"); + SharedPreferences prefs = await SharedPreferences.getInstance(); + var accessToken = prefs.getString("access_token") ?? ""; + List send = ["toto"]; + if (accessToken.isNotEmpty) { + try { + //String credentials = "${pseudo}:${password}"; + //Codec stringToBase64 = utf8.fuse(base64); + //String encoded = stringToBase64.encode(credentials); + var urlPut = Uri.parse("${globals.api}/events"); + var responsePut = await http.put(urlPut, + headers: { + HttpHeaders.cookieHeader: 'access_token=${accessToken}', + HttpHeaders.acceptHeader: 'application/json, text/plain, */*', + HttpHeaders.contentTypeHeader: 'application/json' + }, + body: jsonEncode({ + 'name': name, + 'place': place, + 'start_date': startDate, + 'end_date': endDate, + 'zip_code': zipCode, + 'country': country, + 'city': city, + 'organizers': send, + 'latitude': '0.0', + 'longitude': '0.0', + 'description': description + })); + print(responsePut.statusCode); + if ((responsePut.statusCode == 200) || + (responsePut.statusCode == 201)) { + showEventDialog(context, "Evenement ${name} ajoute"); + } else { + var text = ""; + switch (responsePut.statusCode) { + case 400: + { + text = "Requête mal construite"; + } + break; + case 406: + { + text = "Mot de passe incorrect"; + } + break; + case 404: + { + text = "Utilisateur inconnu"; + } + break; + case 403: + { + text = "Utilisateur desactive"; + } + break; + case 410: + { + text = "Token invalide"; + } + break; + case 500: + { + text = "Probleme interne du serveur"; + } + break; + default: + { + text = "Probleme d'authentification inconnu"; + } + break; + } + showErrorDialog(context, text); + } + } catch (e) { + showErrorDialog(context, "${e}"); + } + } else { + showErrorDialog(context, "Champ vide"); + } + } + + void start() async { + inputName.text = widget.events["name"]; + inputCity.text = widget.events["city"]; + inputAddress.text = widget.events["address"]; + inputZipCode.text = widget.events["zip_code"]; + inputCountry.text = widget.events["country"]; + inputDesc.text = widget.events["description"]; + + DateTime pickedStartDate = DateTime.parse(widget.events["start_date"]); + DateTime pickedEndDate = DateTime.parse(widget.events["end_date"]); + + startDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedStartDate); + endDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedEndDate); + startTimepicker.text = DateFormat("HH-mm").format(pickedStartDate); + endTimepicker.text = DateFormat("HH-mm").format(pickedEndDate); + } + + @override + void initState() { + start(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + title: Text("Add or Update a event"), + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + body: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 60.0), + child: Center( + child: Container( + width: 200, + height: 150, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100.0)), + child: Image.file(File(widget.imagePath))), + ), + ), + Padding( + //padding: const EdgeInsets.only(left:15.0,right: 15.0,top:0,bottom: 0), + padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: inputName, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Nom', + hintText: 'Modifier le nom de l\'évènement'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: inputAddress, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Adresse', + hintText: 'Entrer une adresse'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: inputZipCode, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Code postal', + hintText: 'Entrer un code postal'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: inputCity, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Ville', + hintText: 'Entrer une ville'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: inputCountry, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Pays', + hintText: 'Entrer un pays'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: startDatepicker, + readOnly: true, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Date de debut de l\'évènement', + hintText: 'Cliquez ici pour selectionner une date'), + onTap: () => onTapFunctionDatePicker( + context: context, position: "start")), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: startTimepicker, + readOnly: true, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Heure de debut de l\'évènement', + hintText: 'Cliquez ici pour selectionner une heure'), + onTap: () => onTapFunctionTimePicker( + context: context, position: "start")), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: endDatepicker, + readOnly: true, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Date de fin de l\'évènement', + hintText: 'Cliquez ici pour selectionner une date'), + onTap: () => onTapFunctionDatePicker( + context: context, position: "end")), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: endTimepicker, + readOnly: true, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Heure de fin de l\'évènement', + hintText: 'Cliquez ici pour selectionner une heure'), + onTap: () => onTapFunctionTimePicker( + context: context, position: "end")), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextField( + controller: inputDesc, + keyboardType: TextInputType.multiline, + maxLines: 10, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Description', + hintText: 'Décrire l\'evènement'), + ), + ), + SizedBox( + height: 30, + ), + Container( + height: 50, + width: 250, + decoration: BoxDecoration( + color: Colors.blue, borderRadius: BorderRadius.circular(20)), + child: TextButton( + onPressed: () { + _updateEvent(context); + }, + child: Text( + 'Ajouter', + style: TextStyle(color: Colors.white, fontSize: 25), + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/covas_mobile/pubspec.lock b/covas_mobile/pubspec.lock index db6c022..e3c01b0 100644 --- a/covas_mobile/pubspec.lock +++ b/covas_mobile/pubspec.lock @@ -21,26 +21,26 @@ packages: dependency: "direct main" description: name: camera - sha256: "2170a943dcb67be2af2c6bcda8775e74b41d4c02d6a4eb10bdc832ee185c4eea" + sha256: "26ff41045772153f222ffffecba711a206f670f5834d40ebf5eed3811692f167" url: "https://pub.dev" source: hosted - version: "0.11.0+1" + version: "0.11.0+2" camera_android_camerax: dependency: transitive description: name: camera_android_camerax - sha256: "7c03940cb8c92eb5b184952674a07cc4a73c6ba2b3568aad70255ad4cb913660" + sha256: "8bd9cab67551642eb33ceb33ece7acc0890014fc90ddfae637c7e2b683657e65" url: "https://pub.dev" source: hosted - version: "0.6.7+1" + version: "0.6.7+2" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - sha256: b5093a82537b64bb88d4244f8e00b5ba69e822a5994f47b31d11400e1db975e5 + sha256: "7c28969a975a7eb2349bc2cb2dfe3ad218a33dba9968ecfb181ce08c87486655" url: "https://pub.dev" source: hosted - version: "0.9.17+1" + version: "0.9.17+3" camera_platform_interface: dependency: transitive description: @@ -53,10 +53,10 @@ packages: dependency: "direct main" description: name: camera_web - sha256: b9235ec0a2ce949daec546f1f3d86f05c3921ed31c7d9ab6b7c03214d152fc2d + sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f" url: "https://pub.dev" source: hosted - version: "0.3.4" + version: "0.3.5" characters: dependency: transitive description: @@ -85,10 +85,10 @@ packages: dependency: transitive description: name: cross_file - sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" url: "https://pub.dev" source: hosted - version: "0.3.4+1" + version: "0.3.4+2" cupertino_icons: dependency: "direct main" description: @@ -97,6 +97,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + date_format_field: + dependency: "direct main" + description: + name: date_format_field + sha256: d07a428bd253454ff3123f2e57511cf6ec101d1135af3b79cebb40e1bee8bab8 + url: "https://pub.dev" + source: hosted + version: "0.1.0" dio: dependency: transitive description: @@ -165,10 +173,10 @@ packages: dependency: transitive description: name: file_selector_windows - sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" url: "https://pub.dev" source: hosted - version: "0.9.3+1" + version: "0.9.3+2" flutter: dependency: "direct main" description: flutter @@ -186,10 +194,10 @@ packages: dependency: "direct main" description: name: flutter_gemini - sha256: c6079dc6f95c6191e609e9cc627c268ef0bf2526cbba6a2f61aa41ea0053e9a0 + sha256: "993765fafb595e5d32153f393b9c5e71f853caa5bef123d292c21f672d2b9675" url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.0.5" flutter_lints: dependency: "direct dev" description: @@ -202,10 +210,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: c6b0b4c05c458e1c01ad9bcc14041dd7b1f6783d487be4386f793f47a8a4d03e + sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de" url: "https://pub.dev" source: hosted - version: "2.0.20" + version: "2.0.21" flutter_test: dependency: "direct dev" description: flutter @@ -228,10 +236,10 @@ packages: dependency: "direct main" description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_parser: dependency: transitive description: @@ -252,18 +260,18 @@ packages: dependency: transitive description: name: image_picker_android - sha256: cea2bd5b9fcff039a4901d3b13c67fe747f940be9ba76bde1bcd218d168eeb7f + sha256: c0e72ecd170b00a5590bb71238d57dc8ad22ee14c60c6b0d1a4e05cafbc5db4b url: "https://pub.dev" source: hosted - version: "0.8.12+6" + version: "0.8.12+11" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - sha256: "5d6eb13048cd47b60dbf1a5495424dea226c5faf3950e20bf8120a58efb5b5f3" + sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50" url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" image_picker_ios: dependency: transitive description: @@ -324,18 +332,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -364,18 +372,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" mime: dependency: transitive description: @@ -396,18 +404,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "30c5aa827a6ae95ce2853cdc5fe3971daaac00f6f081c419c013f7f57bff2f5e" + sha256: "490539678396d4c3c0b06efdaab75ae60675c3e0c66f72bc04c2e2c1e0e2abeb" url: "https://pub.dev" source: hosted - version: "2.2.7" + version: "2.2.9" path_provider_foundation: dependency: transitive description: @@ -436,10 +444,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" platform: dependency: transitive description: @@ -460,58 +468,58 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 + sha256: c272f9cabca5a81adc9b0894381e9c1def363e980f960fa903c604c471b22f68 url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.1" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" + sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974 url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.1" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" + sha256: "776786cff96324851b656777648f36ac772d88bc4c669acff97b7fce5de3c849" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.5.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.2" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" sky_engine: dependency: transitive description: flutter @@ -569,10 +577,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.2" typed_data: dependency: transitive description: @@ -593,26 +601,18 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.2.5" web: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 url: "https://pub.dev" source: hosted - version: "0.5.1" - win32: - dependency: transitive - description: - name: win32 - sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 - url: "https://pub.dev" - source: hosted - version: "5.5.1" + version: "1.0.0" xdg_directories: dependency: transitive description: diff --git a/covas_mobile/pubspec.yaml b/covas_mobile/pubspec.yaml index d0d79eb..59db286 100644 --- a/covas_mobile/pubspec.yaml +++ b/covas_mobile/pubspec.yaml @@ -44,6 +44,7 @@ dependencies: flutter_gemini: ^2.0.4 flutter_dotenv: ^5.1.0 image_picker: ^1.1.2 + date_format_field: ^0.1.0 dev_dependencies: flutter_test: @@ -71,6 +72,7 @@ flutter: assets: - images/flutter.png - .env + - images/search.png # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see