From 47d80791e50687cb3e494b413be530d969ff740f Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Thu, 3 Oct 2024 23:54:54 +0200 Subject: [PATCH 01/16] add input categories --- covas_mobile/lib/pages/ItemMenu.dart | 2 ++ covas_mobile/lib/pages/UpdateEventImage.dart | 22 ++++++++++++++++++++ covas_mobile/pubspec.lock | 8 +++++++ covas_mobile/pubspec.yaml | 1 + 4 files changed, 33 insertions(+) diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index b45ee48..901e488 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -16,6 +16,8 @@ import '../classes/events.dart'; import 'ListItemMenu.dart'; +import 'package:textfield_tags/textfield_tags.dart'; + void main() { initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); } diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index 3ee5d9c..3c5bace 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -3,6 +3,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:textfield_tags/textfield_tags.dart'; import 'dart:convert'; import 'dart:io'; @@ -56,6 +57,7 @@ class _UpdateeventImageState extends State TextEditingController startTimepicker = TextEditingController(); TextEditingController endDatepicker = TextEditingController(); TextEditingController endTimepicker = TextEditingController(); + final _stringTagController = StringTagController(); onTapFunctionDatePicker( {required BuildContext context, required String position}) async { @@ -392,6 +394,26 @@ class _UpdateeventImageState extends State 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: TextFieldTags( + textfieldTagsController: _stringTagController, + initialTags: ['python', 'java'], + textSeparators: const [' ', ','], + validator: (String tag) { + if (tag == 'php') { + return 'Php not allowed'; + } + return null; + }, + inputFieldBuilder: (context, inputFieldValues) { + return TextField( + controller: inputFieldValues.textEditingController, + focusNode: inputFieldValues.focusNode, + ); + })), Padding( padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15, bottom: 0), diff --git a/covas_mobile/pubspec.lock b/covas_mobile/pubspec.lock index e3c01b0..84f9170 100644 --- a/covas_mobile/pubspec.lock +++ b/covas_mobile/pubspec.lock @@ -581,6 +581,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.2" + textfield_tags: + dependency: "direct main" + description: + name: textfield_tags + sha256: d1f2204114157a1296bb97c20d7f8c8c7fd036212812afb2e19de7bb34acc55b + url: "https://pub.dev" + source: hosted + version: "3.0.1" typed_data: dependency: transitive description: diff --git a/covas_mobile/pubspec.yaml b/covas_mobile/pubspec.yaml index 59db286..418204f 100644 --- a/covas_mobile/pubspec.yaml +++ b/covas_mobile/pubspec.yaml @@ -45,6 +45,7 @@ dependencies: flutter_dotenv: ^5.1.0 image_picker: ^1.1.2 date_format_field: ^0.1.0 + textfield_tags: ^3.0.1 dev_dependencies: flutter_test: -- 2.47.2 From 7e6de0aa382cf758dfa739540b5971dd47e93778 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 7 Oct 2024 23:59:15 +0200 Subject: [PATCH 02/16] input tags 50% --- covas_mobile/lib/pages/UpdateEventImage.dart | 40 +++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index 3c5bace..ded3e96 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -394,26 +394,30 @@ class _UpdateeventImageState extends State 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: TextFieldTags( - textfieldTagsController: _stringTagController, - initialTags: ['python', 'java'], - textSeparators: const [' ', ','], - validator: (String tag) { - if (tag == 'php') { - return 'Php not allowed'; - } - return null; - }, - inputFieldBuilder: (context, inputFieldValues) { - return TextField( + TextFieldTags( + textfieldTagsController: _stringTagController, + initialTags: ['python', 'java'], + textSeparators: const [' ', ','], + validator: (String tag) { + if (tag == 'php') { + return 'Php not allowed'; + } + return null; + }, + inputFieldBuilder: (context, inputFieldValues) { + return Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + child: TextField( controller: inputFieldValues.textEditingController, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Tags evenement', + hintText: + 'Cliquez ici pour ajouter ou supprimer des tags'), focusNode: inputFieldValues.focusNode, - ); - })), + )); + }), Padding( padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15, bottom: 0), -- 2.47.2 From b1a8b932b912a1631daf346f977dfb05b0454028 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 9 Oct 2024 23:28:24 +0200 Subject: [PATCH 03/16] tags work --- covas_mobile/lib/pages/UpdateEventImage.dart | 96 +++++++++++++++++--- 1 file changed, 82 insertions(+), 14 deletions(-) diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index ded3e96..8abc7b0 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -396,27 +396,95 @@ class _UpdateeventImageState extends State ), TextFieldTags( textfieldTagsController: _stringTagController, - initialTags: ['python', 'java'], + initialTags: [], textSeparators: const [' ', ','], validator: (String tag) { - if (tag == 'php') { - return 'Php not allowed'; + if (_stringTagController.getTags!.contains(tag)) { + return 'Tu as deja rentre ce tag'; } return null; }, inputFieldBuilder: (context, inputFieldValues) { return Padding( - padding: const EdgeInsets.only( - left: 15.0, right: 15.0, top: 15, bottom: 0), - child: TextField( - controller: inputFieldValues.textEditingController, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Tags evenement', - hintText: - 'Cliquez ici pour ajouter ou supprimer des tags'), - focusNode: inputFieldValues.focusNode, - )); + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + child: TextField( + controller: inputFieldValues.textEditingController, + focusNode: inputFieldValues.focusNode, + onChanged: inputFieldValues.onTagChanged, + onSubmitted: inputFieldValues.onTagSubmitted, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Tags evenement', + hintText: inputFieldValues.tags.isNotEmpty + ? '' + : "Enter tag...", + errorText: inputFieldValues.error, + prefixIcon: inputFieldValues.tags.isNotEmpty + ? SingleChildScrollView( + controller: + inputFieldValues.tagScrollController, + scrollDirection: Axis.vertical, + child: Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 8, + left: 8, + ), + child: Wrap( + runSpacing: 4.0, + spacing: 4.0, + children: inputFieldValues.tags + .map((String tag) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.0), + ), + color: Colors.blue, + ), + margin: const EdgeInsets.symmetric( + horizontal: 5.0), + padding: const EdgeInsets.symmetric( + horizontal: 10.0, vertical: 5.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: Text( + '#$tag', + style: const TextStyle( + color: Colors.white), + ), + onTap: () { + //print("$tag selected"); + }, + ), + const SizedBox(width: 4.0), + InkWell( + child: const Icon( + Icons.cancel, + size: 14.0, + color: Color.fromARGB( + 255, 233, 233, 233), + ), + onTap: () { + inputFieldValues + .onTagRemoved(tag); + }, + ) + ], + ), + ); + }).toList()), + ), + ) + : null, + ), + ), + ); }), Padding( padding: const EdgeInsets.only( -- 2.47.2 From b1ca67ed723efd722862f2837590a7482bb4ae73 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 14 Oct 2024 17:49:39 +0200 Subject: [PATCH 04/16] add tags automatically --- covas_mobile/lib/pages/DisplayPictureScreen.dart | 2 +- covas_mobile/lib/pages/UpdateEventImage.dart | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/covas_mobile/lib/pages/DisplayPictureScreen.dart b/covas_mobile/lib/pages/DisplayPictureScreen.dart index 9815034..584d55e 100644 --- a/covas_mobile/lib/pages/DisplayPictureScreen.dart +++ b/covas_mobile/lib/pages/DisplayPictureScreen.dart @@ -132,7 +132,7 @@ class DisplayPictureScreenState extends State gemini .textAndImage( text: - "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", + "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, tags (tableau sans espace), 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-pro-latest") .then((value) => searchEvents( diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index 8abc7b0..86809d1 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -58,6 +58,7 @@ class _UpdateeventImageState extends State TextEditingController endDatepicker = TextEditingController(); TextEditingController endTimepicker = TextEditingController(); final _stringTagController = StringTagController(); + List initialTags = []; onTapFunctionDatePicker( {required BuildContext context, required String position}) async { @@ -97,6 +98,13 @@ class _UpdateeventImageState extends State return check; } + convertNulltoArray(List check) { + if (check == null) { + return []; + } + return check; + } + String formatDate(String date) { var splitedDate = date.split("-"); var day = splitedDate[0]; @@ -248,6 +256,7 @@ class _UpdateeventImageState extends State endDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedEndDate); startTimepicker.text = DateFormat("HH-mm").format(pickedStartDate); endTimepicker.text = DateFormat("HH-mm").format(pickedEndDate); + initialTags = List.from(widget.events['tags'] as List); } @override @@ -396,7 +405,7 @@ class _UpdateeventImageState extends State ), TextFieldTags( textfieldTagsController: _stringTagController, - initialTags: [], + initialTags: initialTags, textSeparators: const [' ', ','], validator: (String tag) { if (_stringTagController.getTags!.contains(tag)) { -- 2.47.2 From 4d73360f7426984625690500f30f2ad125733514 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 15 Oct 2024 23:44:41 +0200 Subject: [PATCH 05/16] add tags to api --- covas_mobile/lib/pages/UpdateEventImage.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index 86809d1..86390e0 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -122,6 +122,7 @@ class _UpdateeventImageState extends State var country = inputCountry.text; var zipCode = inputZipCode.text; var description = inputDesc.text; + List tags = List.from(_stringTagController.getTags as List); var startDateFormat = formatDate(startDatepicker.text); var endDateFormat = formatDate(endDatepicker.text); @@ -181,7 +182,8 @@ class _UpdateeventImageState extends State 'latitude': '0.0', 'longitude': '0.0', 'description': description, - "imgUrl": imgUrl + "imgUrl": imgUrl, + "tags": tags })); print(responsePut.statusCode); if ((responsePut.statusCode == 200) || -- 2.47.2 From b3c4980b52902a8ce8623ea99920bcbaaaf9f99d Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 15 Oct 2024 23:57:22 +0200 Subject: [PATCH 06/16] input organizaters wip --- .../lib/pages/DisplayPictureScreen.dart | 2 +- covas_mobile/lib/pages/UpdateEventImage.dart | 96 +++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/covas_mobile/lib/pages/DisplayPictureScreen.dart b/covas_mobile/lib/pages/DisplayPictureScreen.dart index 584d55e..0c6d18a 100644 --- a/covas_mobile/lib/pages/DisplayPictureScreen.dart +++ b/covas_mobile/lib/pages/DisplayPictureScreen.dart @@ -132,7 +132,7 @@ class DisplayPictureScreenState extends State gemini .textAndImage( text: - "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, tags (tableau sans espace), 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", + "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, tags (tableau sans espace), organizers (tableau), 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-pro-latest") .then((value) => searchEvents( diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index 86390e0..14f01ed 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -60,6 +60,9 @@ class _UpdateeventImageState extends State final _stringTagController = StringTagController(); List initialTags = []; + final _stringOrgaController = StringTagController(); + List initialOrga = []; + onTapFunctionDatePicker( {required BuildContext context, required String position}) async { DateTime? pickedDate = await showDatePicker( @@ -259,6 +262,7 @@ class _UpdateeventImageState extends State startTimepicker.text = DateFormat("HH-mm").format(pickedStartDate); endTimepicker.text = DateFormat("HH-mm").format(pickedEndDate); initialTags = List.from(widget.events['tags'] as List); + initialOrga = List.from(widget.events['organizers'] as List); } @override @@ -497,6 +501,98 @@ class _UpdateeventImageState extends State ), ); }), + TextFieldTags( + textfieldTagsController: _stringOrgaController, + initialTags: initialOrga, + textSeparators: const [','], + validator: (String tag) { + if (_stringOrgaController.getTags!.contains(tag)) { + return 'Cet organisateur est déjà rentré'; + } + return null; + }, + inputFieldBuilder: (context, inputFieldValues) { + return Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + child: TextField( + controller: inputFieldValues.textEditingController, + focusNode: inputFieldValues.focusNode, + onChanged: inputFieldValues.onTagChanged, + onSubmitted: inputFieldValues.onTagSubmitted, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Organisateurs', + hintText: inputFieldValues.tags.isNotEmpty + ? '' + : "Enter un organisateur...", + errorText: inputFieldValues.error, + prefixIcon: inputFieldValues.tags.isNotEmpty + ? SingleChildScrollView( + controller: + inputFieldValues.tagScrollController, + scrollDirection: Axis.vertical, + child: Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 8, + left: 8, + ), + child: Wrap( + runSpacing: 4.0, + spacing: 4.0, + children: inputFieldValues.tags + .map((String tag) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.0), + ), + color: Colors.blue, + ), + margin: const EdgeInsets.symmetric( + horizontal: 5.0), + padding: const EdgeInsets.symmetric( + horizontal: 10.0, vertical: 5.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: Text( + '$tag', + style: const TextStyle( + color: Colors.white), + ), + onTap: () { + //print("$tag selected"); + }, + ), + const SizedBox(width: 4.0), + InkWell( + child: const Icon( + Icons.cancel, + size: 14.0, + color: Color.fromARGB( + 255, 233, 233, 233), + ), + onTap: () { + inputFieldValues + .onTagRemoved(tag); + }, + ) + ], + ), + ); + }).toList()), + ), + ) + : null, + ), + ), + ); + }), Padding( padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15, bottom: 0), -- 2.47.2 From f0780c2a3ec47ee3bc08b55b541b0857259af858 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 18 Oct 2024 21:28:46 +0200 Subject: [PATCH 07/16] add organizers --- covas_mobile/lib/pages/UpdateEventImage.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index 14f01ed..961ee21 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -362,7 +362,7 @@ class _UpdateeventImageState extends State readOnly: true, decoration: InputDecoration( border: OutlineInputBorder(), - labelText: 'Date de debut de l\'évènement', + labelText: 'Date de debut', hintText: 'Cliquez ici pour selectionner une date'), onTap: () => onTapFunctionDatePicker( context: context, position: "start")), @@ -376,7 +376,7 @@ class _UpdateeventImageState extends State readOnly: true, decoration: InputDecoration( border: OutlineInputBorder(), - labelText: 'Heure de debut de l\'évènement', + labelText: 'Heure de debut', hintText: 'Cliquez ici pour selectionner une heure'), onTap: () => onTapFunctionTimePicker( context: context, position: "start")), @@ -390,7 +390,7 @@ class _UpdateeventImageState extends State readOnly: true, decoration: InputDecoration( border: OutlineInputBorder(), - labelText: 'Date de fin de l\'évènement', + labelText: 'Date de fin', hintText: 'Cliquez ici pour selectionner une date'), onTap: () => onTapFunctionDatePicker( context: context, position: "end")), @@ -404,7 +404,7 @@ class _UpdateeventImageState extends State readOnly: true, decoration: InputDecoration( border: OutlineInputBorder(), - labelText: 'Heure de fin de l\'évènement', + labelText: 'Heure de fin', hintText: 'Cliquez ici pour selectionner une heure'), onTap: () => onTapFunctionTimePicker( context: context, position: "end")), @@ -430,7 +430,7 @@ class _UpdateeventImageState extends State onSubmitted: inputFieldValues.onTagSubmitted, decoration: InputDecoration( border: OutlineInputBorder(), - labelText: 'Tags evenement', + labelText: 'Tags', hintText: inputFieldValues.tags.isNotEmpty ? '' : "Enter tag...", -- 2.47.2 From 792ce0227e6683ba02149bffe8b11bf664c4f76f Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 18 Oct 2024 21:40:20 +0200 Subject: [PATCH 08/16] add string orga --- covas_mobile/lib/pages/UpdateEventImage.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index 961ee21..fb058e4 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -126,6 +126,8 @@ class _UpdateeventImageState extends State var zipCode = inputZipCode.text; var description = inputDesc.text; List tags = List.from(_stringTagController.getTags as List); + List organizers = + List.from(_stringOrgaController.getTags as List); var startDateFormat = formatDate(startDatepicker.text); var endDateFormat = formatDate(endDatepicker.text); @@ -136,7 +138,7 @@ class _UpdateeventImageState extends State print("end date : ${endDate}"); SharedPreferences prefs = await SharedPreferences.getInstance(); var accessToken = prefs.getString("access_token") ?? ""; - List send = ["toto"]; + if (accessToken.isNotEmpty) { try { await dotenv.load(); @@ -181,7 +183,7 @@ class _UpdateeventImageState extends State 'zip_code': zipCode, 'country': country, 'city': city, - 'organizers': send, + 'organizers': organizers, 'latitude': '0.0', 'longitude': '0.0', 'description': description, -- 2.47.2 From 045209575e42edc5ac679b189af18f38b7af8983 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 18 Oct 2024 22:53:50 +0200 Subject: [PATCH 09/16] fix datepicker --- covas_mobile/lib/pages/UpdateEventImage.dart | 747 ++++++++++--------- 1 file changed, 390 insertions(+), 357 deletions(-) diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index fb058e4..650aa4c 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -65,10 +65,14 @@ class _UpdateeventImageState extends State onTapFunctionDatePicker( {required BuildContext context, required String position}) async { + String date = "start_date"; + if (position == "end") { + date = "end_date"; + } DateTime? pickedDate = await showDatePicker( context: context, - firstDate: DateTime.parse(widget.events["date"]), - initialDate: DateTime.parse(widget.events["date"]), + firstDate: DateTime.parse(widget.events[date]), + initialDate: DateTime.parse(widget.events[date]), lastDate: DateTime(2104)); if (pickedDate == null) return; if (position == "start") { @@ -81,10 +85,14 @@ class _UpdateeventImageState extends State onTapFunctionTimePicker( {required BuildContext context, required String position}) async { + String date = "start_date"; + if (position == "end") { + date = "end_date"; + } TimeOfDay? pickedDate = await showTimePicker( context: context, initialTime: - TimeOfDay.fromDateTime(DateTime.parse(widget.events["date"]))); + TimeOfDay.fromDateTime(DateTime.parse(widget.events[date]))); if (pickedDate == null) return; if (position == "start") { startTimepicker.text = pickedDate.format(context); @@ -273,363 +281,388 @@ class _UpdateeventImageState extends State super.initState(); } + final _formKey = GlobalKey(); + String? _validateField(String? value) { + return value!.isEmpty ? 'Champ requis' : null; + } + @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', - 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', - 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', - 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', - hintText: 'Cliquez ici pour selectionner une heure'), - onTap: () => onTapFunctionTimePicker( - context: context, position: "end")), - ), - TextFieldTags( - textfieldTagsController: _stringTagController, - initialTags: initialTags, - textSeparators: const [' ', ','], - validator: (String tag) { - if (_stringTagController.getTags!.contains(tag)) { - return 'Tu as deja rentre ce tag'; - } - return null; - }, - inputFieldBuilder: (context, inputFieldValues) { - return Padding( - padding: const EdgeInsets.only( - left: 15.0, right: 15.0, top: 15, bottom: 0), - child: TextField( - controller: inputFieldValues.textEditingController, - focusNode: inputFieldValues.focusNode, - onChanged: inputFieldValues.onTagChanged, - onSubmitted: inputFieldValues.onTagSubmitted, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Tags', - hintText: inputFieldValues.tags.isNotEmpty - ? '' - : "Enter tag...", - errorText: inputFieldValues.error, - prefixIcon: inputFieldValues.tags.isNotEmpty - ? SingleChildScrollView( - controller: - inputFieldValues.tagScrollController, - scrollDirection: Axis.vertical, - child: Padding( - padding: const EdgeInsets.only( - top: 8, - bottom: 8, - left: 8, - ), - child: Wrap( - runSpacing: 4.0, - spacing: 4.0, - children: inputFieldValues.tags - .map((String tag) { - return Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(20.0), - ), - color: Colors.blue, - ), - margin: const EdgeInsets.symmetric( - horizontal: 5.0), - padding: const EdgeInsets.symmetric( - horizontal: 10.0, vertical: 5.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - InkWell( - child: Text( - '#$tag', - style: const TextStyle( - color: Colors.white), - ), - onTap: () { - //print("$tag selected"); - }, - ), - const SizedBox(width: 4.0), - InkWell( - child: const Icon( - Icons.cancel, - size: 14.0, - color: Color.fromARGB( - 255, 233, 233, 233), - ), - onTap: () { - inputFieldValues - .onTagRemoved(tag); - }, - ) - ], - ), - ); - }).toList()), - ), - ) - : null, - ), - ), - ); - }), - TextFieldTags( - textfieldTagsController: _stringOrgaController, - initialTags: initialOrga, - textSeparators: const [','], - validator: (String tag) { - if (_stringOrgaController.getTags!.contains(tag)) { - return 'Cet organisateur est déjà rentré'; - } - return null; - }, - inputFieldBuilder: (context, inputFieldValues) { - return Padding( - padding: const EdgeInsets.only( - left: 15.0, right: 15.0, top: 15, bottom: 0), - child: TextField( - controller: inputFieldValues.textEditingController, - focusNode: inputFieldValues.focusNode, - onChanged: inputFieldValues.onTagChanged, - onSubmitted: inputFieldValues.onTagSubmitted, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Organisateurs', - hintText: inputFieldValues.tags.isNotEmpty - ? '' - : "Enter un organisateur...", - errorText: inputFieldValues.error, - prefixIcon: inputFieldValues.tags.isNotEmpty - ? SingleChildScrollView( - controller: - inputFieldValues.tagScrollController, - scrollDirection: Axis.vertical, - child: Padding( - padding: const EdgeInsets.only( - top: 8, - bottom: 8, - left: 8, - ), - child: Wrap( - runSpacing: 4.0, - spacing: 4.0, - children: inputFieldValues.tags - .map((String tag) { - return Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(20.0), - ), - color: Colors.blue, - ), - margin: const EdgeInsets.symmetric( - horizontal: 5.0), - padding: const EdgeInsets.symmetric( - horizontal: 10.0, vertical: 5.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - InkWell( - child: Text( - '$tag', - style: const TextStyle( - color: Colors.white), - ), - onTap: () { - //print("$tag selected"); - }, - ), - const SizedBox(width: 4.0), - InkWell( - child: const Icon( - Icons.cancel, - size: 14.0, - color: Color.fromARGB( - 255, 233, 233, 233), - ), - onTap: () { - inputFieldValues - .onTagRemoved(tag); - }, - ) - ], - ), - ); - }).toList()), - ), - ) - : null, - ), - ), - ); - }), - 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), - ), - ), - ) - ], + backgroundColor: Colors.white, + appBar: AppBar( + title: Text("Add or Update a event"), + backgroundColor: Colors.blue, + foregroundColor: Colors.white, ), - ), - ); + body: Form( + key: _formKey, + child: 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: TextFormField( + controller: inputName, + validator: (value) => _validateField(value), + 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: TextFormField( + controller: inputAddress, + validator: (value) => _validateField(value), + 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: TextFormField( + controller: inputZipCode, + validator: (value) => _validateField(value), + 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: TextFormField( + controller: inputCity, + validator: (value) => _validateField(value), + 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: TextFormField( + controller: inputCountry, + validator: (value) => _validateField(value), + 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: TextFormField( + controller: startDatepicker, + readOnly: true, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Date de debut', + 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: TextFormField( + controller: startTimepicker, + readOnly: true, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Heure de debut', + 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: TextFormField( + controller: endDatepicker, + readOnly: true, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Date de fin', + 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: TextFormField( + controller: endTimepicker, + readOnly: true, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Heure de fin', + hintText: 'Cliquez ici pour selectionner une heure'), + onTap: () => onTapFunctionTimePicker( + context: context, position: "end")), + ), + TextFieldTags( + textfieldTagsController: _stringTagController, + initialTags: initialTags, + textSeparators: const [' ', ','], + validator: (String tag) { + if (_stringTagController.getTags!.contains(tag)) { + return 'Tu as deja rentre ce tag'; + } + return null; + }, + inputFieldBuilder: (context, inputFieldValues) { + return Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + child: TextField( + controller: inputFieldValues.textEditingController, + focusNode: inputFieldValues.focusNode, + onChanged: inputFieldValues.onTagChanged, + onSubmitted: inputFieldValues.onTagSubmitted, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Tags', + hintText: inputFieldValues.tags.isNotEmpty + ? '' + : "Enter tag...", + errorText: inputFieldValues.error, + prefixIcon: inputFieldValues.tags.isNotEmpty + ? SingleChildScrollView( + controller: + inputFieldValues.tagScrollController, + scrollDirection: Axis.vertical, + child: Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 8, + left: 8, + ), + child: Wrap( + runSpacing: 4.0, + spacing: 4.0, + children: inputFieldValues.tags + .map((String tag) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.0), + ), + color: Colors.blue, + ), + margin: + const EdgeInsets.symmetric( + horizontal: 5.0), + padding: + const EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 5.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: Text( + '$tag', + style: const TextStyle( + color: Colors.white), + ), + onTap: () { + //print("$tag selected"); + }, + ), + const SizedBox(width: 4.0), + InkWell( + child: const Icon( + Icons.cancel, + size: 14.0, + color: Color.fromARGB( + 255, 233, 233, 233), + ), + onTap: () { + inputFieldValues + .onTagRemoved(tag); + }, + ) + ], + ), + ); + }).toList()), + ), + ) + : null, + ), + ), + ); + }), + TextFieldTags( + textfieldTagsController: _stringOrgaController, + initialTags: initialOrga, + textSeparators: const [','], + validator: (String tag) { + if (_stringOrgaController.getTags!.contains(tag)) { + return 'Cet organisateur est déjà rentré'; + } + return null; + }, + inputFieldBuilder: (context, inputFieldValues) { + return Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + child: TextField( + controller: inputFieldValues.textEditingController, + focusNode: inputFieldValues.focusNode, + onChanged: inputFieldValues.onTagChanged, + onSubmitted: inputFieldValues.onTagSubmitted, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Organisateurs', + hintText: inputFieldValues.tags.isNotEmpty + ? '' + : "Enter un organisateur...", + errorText: inputFieldValues.error, + prefixIcon: inputFieldValues.tags.isNotEmpty + ? SingleChildScrollView( + controller: + inputFieldValues.tagScrollController, + scrollDirection: Axis.vertical, + child: Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 8, + left: 8, + ), + child: Wrap( + runSpacing: 4.0, + spacing: 4.0, + children: inputFieldValues.tags + .map((String tag) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.0), + ), + color: Colors.blue, + ), + margin: + const EdgeInsets.symmetric( + horizontal: 5.0), + padding: + const EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 5.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: Text( + '$tag', + style: const TextStyle( + color: Colors.white), + ), + onTap: () { + //print("$tag selected"); + }, + ), + const SizedBox(width: 4.0), + InkWell( + child: const Icon( + Icons.cancel, + size: 14.0, + color: Color.fromARGB( + 255, 233, 233, 233), + ), + onTap: () { + inputFieldValues + .onTagRemoved(tag); + }, + ) + ], + ), + ); + }).toList()), + ), + ) + : null, + ), + ), + ); + }), + 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: () { + if (_formKey.currentState!.validate()) { + _updateEvent(context); + } + }, + child: Text( + 'Ajouter', + style: TextStyle(color: Colors.white, fontSize: 25), + ), + ), + ) + ], + ), + ), + )); } } -- 2.47.2 From f2cd07089895d2e2ec2e78e62ce9c5bd7e2f0d2e Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sun, 20 Oct 2024 11:32:33 +0200 Subject: [PATCH 10/16] add tags in item --- covas_mobile/lib/pages/ItemMenu.dart | 59 +++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 901e488..c7ba670 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -16,8 +16,6 @@ import '../classes/events.dart'; import 'ListItemMenu.dart'; -import 'package:textfield_tags/textfield_tags.dart'; - void main() { initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); } @@ -73,6 +71,7 @@ class _ItemMenuState extends State with ShowErrorDialog { String organizers = ""; String place = ""; String imgUrl = ""; + List tags = []; Events? events; @override @@ -91,6 +90,7 @@ class _ItemMenuState extends State with ShowErrorDialog { String formerMap = ""; String formerImage = ""; String formerDesc = ""; + List formerTags = []; if (accessToken.isNotEmpty) { var urlGet = Uri.parse("${globals.api}/events/${widget.title}"); @@ -105,6 +105,7 @@ class _ItemMenuState extends State with ShowErrorDialog { formerMap = "${events["place"]} - ${events["zip_code"]} ${events["city"]} - ${events["country"]}"; formerDesc = events["description"]; + formerTags = List.from(events['tags'] as List); final startDate = DateTime.parse(events["start_date"]); final date = DateFormat.yMd().format(startDate); final time = DateFormat.Hm().format(startDate); @@ -118,13 +119,13 @@ class _ItemMenuState extends State with ShowErrorDialog { } formerDate = "${date} ${time} à ${dateE} ${timeE}"; - if (events["organizers"].length > 1) { + if (events["organizers"].length > 0) { formerOrga = "${events['organizers'][0]}"; for (var i = 1; i < events["organizers"].length; i++) { formerOrga = "${formerOrga}, ${events['organizers'][i]}"; } } else { - formerOrga = "${events['organizers'][0]}"; + formerOrga = ""; } } else { var text = ""; @@ -183,6 +184,7 @@ class _ItemMenuState extends State with ShowErrorDialog { place = formerMap; imgUrl = formerImage; eventDescription = formerDesc; + tags = formerTags; }); } @@ -274,7 +276,54 @@ class _ItemMenuState extends State with ShowErrorDialog { style: TextStyle(fontSize: 15.0), maxLines: 3, overflow: TextOverflow.ellipsis)) - ]) + ]), + Row(children: [ + Icon(Icons.category), + Text("Tags : ", + style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold)) + ]), + Row( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 8, + left: 8, + ), + child: Wrap( + runSpacing: 4.0, + spacing: 4.0, + children: tags.map((String tag) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.0), + ), + color: Colors.blue, + ), + margin: const EdgeInsets.symmetric(horizontal: 5.0), + padding: const EdgeInsets.symmetric( + horizontal: 10.0, vertical: 5.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: Text( + '$tag', + style: const TextStyle(color: Colors.white), + ), + onTap: () { + //print("$tag selected"); + }, + ), + ], + ), + ); + }).toList()), + ), + ], + ) ], ))); } -- 2.47.2 From fb34b413857b0f77a4c160e8f5b9a1d7a8eceb70 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sun, 20 Oct 2024 11:46:51 +0200 Subject: [PATCH 11/16] direction vertical --- covas_mobile/lib/pages/ItemMenu.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index c7ba670..3406264 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -293,6 +293,7 @@ class _ItemMenuState extends State with ShowErrorDialog { child: Wrap( runSpacing: 4.0, spacing: 4.0, + direction: Axis.vertical, children: tags.map((String tag) { return Container( decoration: const BoxDecoration( -- 2.47.2 From 519d20fd63369c39671a3ef1718cf6b06ecb89fb Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sun, 20 Oct 2024 18:23:34 +0200 Subject: [PATCH 12/16] add organizateurs --- covas_mobile/lib/pages/ItemMenu.dart | 59 ++++++++++++++++++---------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 3406264..788d204 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -68,10 +68,10 @@ class _ItemMenuState extends State with ShowErrorDialog { String eventName = ""; String eventStartDate = ""; String eventDescription = ""; - String organizers = ""; String place = ""; String imgUrl = ""; List tags = []; + List organizers = []; Events? events; @override @@ -86,11 +86,11 @@ class _ItemMenuState extends State with ShowErrorDialog { var accessToken = prefs.getString("access_token") ?? ""; String formerName = ""; String formerDate = ""; - String formerOrga = ""; String formerMap = ""; String formerImage = ""; String formerDesc = ""; List formerTags = []; + List formerOrga = []; if (accessToken.isNotEmpty) { var urlGet = Uri.parse("${globals.api}/events/${widget.title}"); @@ -106,6 +106,7 @@ class _ItemMenuState extends State with ShowErrorDialog { "${events["place"]} - ${events["zip_code"]} ${events["city"]} - ${events["country"]}"; formerDesc = events["description"]; formerTags = List.from(events['tags'] as List); + formerOrga = List.from(events['organizers'] as List); final startDate = DateTime.parse(events["start_date"]); final date = DateFormat.yMd().format(startDate); final time = DateFormat.Hm().format(startDate); @@ -119,14 +120,6 @@ class _ItemMenuState extends State with ShowErrorDialog { } formerDate = "${date} ${time} à ${dateE} ${timeE}"; - if (events["organizers"].length > 0) { - formerOrga = "${events['organizers'][0]}"; - for (var i = 1; i < events["organizers"].length; i++) { - formerOrga = "${formerOrga}, ${events['organizers'][i]}"; - } - } else { - formerOrga = ""; - } } else { var text = ""; switch (responseGet.statusCode) { @@ -257,13 +250,42 @@ class _ItemMenuState extends State with ShowErrorDialog { ) ]), Row(children: [ - Flexible( - child: Text( - "${organizers}", - style: TextStyle(fontSize: 15.0), - maxLines: 3, - overflow: TextOverflow.ellipsis, - )) + Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 8, + left: 8, + ), + child: Wrap( + runSpacing: 4.0, + spacing: 4.0, + direction: Axis.vertical, + children: organizers.map((String tag) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.0), + ), + color: Colors.blue, + ), + margin: const EdgeInsets.symmetric(horizontal: 5.0), + padding: const EdgeInsets.symmetric( + horizontal: 10.0, vertical: 5.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: Text( + '$tag', + style: const TextStyle(color: Colors.white), + ), + ), + ], + ), + ); + }).toList()), + ), ]), Row(children: [ Icon(Icons.description), @@ -314,9 +336,6 @@ class _ItemMenuState extends State with ShowErrorDialog { '$tag', style: const TextStyle(color: Colors.white), ), - onTap: () { - //print("$tag selected"); - }, ), ], ), -- 2.47.2 From 8b87f55bf910427ee5a1a313e2db2bbc099cd7e7 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sun, 20 Oct 2024 20:27:17 +0200 Subject: [PATCH 13/16] flexible horizontal tags --- covas_mobile/lib/pages/ItemMenu.dart | 142 ++++++++++++++------------- 1 file changed, 74 insertions(+), 68 deletions(-) diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 788d204..3d923e9 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -250,42 +250,44 @@ class _ItemMenuState extends State with ShowErrorDialog { ) ]), Row(children: [ - Padding( - padding: const EdgeInsets.only( - top: 8, - bottom: 8, - left: 8, - ), - child: Wrap( - runSpacing: 4.0, - spacing: 4.0, - direction: Axis.vertical, - children: organizers.map((String tag) { - return Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(20.0), - ), - color: Colors.blue, - ), - margin: const EdgeInsets.symmetric(horizontal: 5.0), - padding: const EdgeInsets.symmetric( - horizontal: 10.0, vertical: 5.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - InkWell( - child: Text( - '$tag', - style: const TextStyle(color: Colors.white), + Flexible( + flex: 3, + fit: FlexFit.tight, + child: Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 8, + left: 8, + ), + child: Wrap( + runSpacing: 2.0, + spacing: 2.0, + children: organizers.map((String tag) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.0), ), + color: Colors.blue, ), - ], - ), - ); - }).toList()), - ), + margin: const EdgeInsets.symmetric(horizontal: 5.0), + padding: const EdgeInsets.symmetric( + horizontal: 10.0, vertical: 5.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: Text( + '$tag', + style: const TextStyle(color: Colors.white), + ), + ), + ], + ), + ); + }).toList()), + )), ]), Row(children: [ Icon(Icons.description), @@ -306,42 +308,46 @@ class _ItemMenuState extends State with ShowErrorDialog { ]), Row( children: [ - Padding( - padding: const EdgeInsets.only( - top: 8, - bottom: 8, - left: 8, - ), - child: Wrap( - runSpacing: 4.0, - spacing: 4.0, - direction: Axis.vertical, - children: tags.map((String tag) { - return Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(20.0), - ), - color: Colors.blue, - ), - margin: const EdgeInsets.symmetric(horizontal: 5.0), - padding: const EdgeInsets.symmetric( - horizontal: 10.0, vertical: 5.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - InkWell( - child: Text( - '$tag', - style: const TextStyle(color: Colors.white), + Flexible( + flex: 3, + fit: FlexFit.tight, + child: Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 8, + left: 8, + ), + child: Wrap( + runSpacing: 2.0, + spacing: 2.0, + children: tags.map((String tag) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.0), ), + color: Colors.blue, ), - ], - ), - ); - }).toList()), - ), + margin: + const EdgeInsets.symmetric(horizontal: 5.0), + padding: const EdgeInsets.symmetric( + horizontal: 10.0, vertical: 5.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: Text( + '$tag', + style: + const TextStyle(color: Colors.white), + ), + ), + ], + ), + ); + }).toList()), + )), ], ) ], -- 2.47.2 From 3861a3c5e1c574faf1a29fc6795a0ac68c1cd724 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 21 Oct 2024 22:02:21 +0200 Subject: [PATCH 14/16] list item menu by tags --- covas_mobile/lib/pages/ItemMenu.dart | 9 ++ covas_mobile/lib/pages/ListItemByTags.dart | 122 +++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 covas_mobile/lib/pages/ListItemByTags.dart diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 3d923e9..5d93215 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'dart:convert'; import 'package:covas_mobile/classes/alert.dart'; +import 'package:covas_mobile/pages/ListItemByTags.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; @@ -15,6 +16,7 @@ import '../variable/globals.dart' as globals; import '../classes/events.dart'; import 'ListItemMenu.dart'; +import 'ListItemByTags.dart'; void main() { initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); @@ -337,6 +339,13 @@ class _ItemMenuState extends State with ShowErrorDialog { mainAxisSize: MainAxisSize.min, children: [ InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => + ListItemTags(tags: '$tag'))); + }, child: Text( '$tag', style: diff --git a/covas_mobile/lib/pages/ListItemByTags.dart b/covas_mobile/lib/pages/ListItemByTags.dart new file mode 100644 index 0000000..35a0d88 --- /dev/null +++ b/covas_mobile/lib/pages/ListItemByTags.dart @@ -0,0 +1,122 @@ +import 'dart:convert'; +import 'dart:io'; +import "ItemMenu.dart"; + +import 'package:http/http.dart' as http; +import 'package:flutter/material.dart'; +import '../classes/events.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:intl/intl.dart'; +import 'package:intl/date_symbol_data_local.dart'; + +import '../variable/globals.dart' as globals; + +// app starting point +void main() { + initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: const ListItemTags(tags: "default"), + debugShowCheckedModeBanner: false, + ); + } +} + +// homepage class +class ListItemTags extends StatefulWidget { + const ListItemTags({Key? key, required this.tags}) : super(key: key); + + final String tags; + @override + State createState() => _MyHomePageState(); +} + +// homepage state +class _MyHomePageState extends State { + // variable to call and store future list of posts + + // function to fetch data from api and return future list of posts + static Future> getPosts(tags) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var accessToken = prefs.getString("access_token") ?? ""; + final List body = []; + if (accessToken.isNotEmpty) { + var url = Uri.parse("${globals.api}/events?tags=${tags}"); + final response = await http.get(url, headers: { + "Content-Type": "application/json", + HttpHeaders.cookieHeader: "access_token=${accessToken}" + }); + final List body = json.decode(utf8.decode(response.bodyBytes)); + return body.map((e) => Events.fromJson(e)).toList(); + } + return body; + } + + // build function + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + // FutureBuilder + child: FutureBuilder>( + future: getPosts(widget.tags), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + // until data is fetched, show loader + return const CircularProgressIndicator(); + } else if (snapshot.hasData) { + // once data is fetched, display it on screen (call buildPosts()) + final posts = snapshot.data!; + return buildPosts(posts); + } else { + // if no data, show simple Text + return const Text("No data available"); + } + }, + ), + ), + ); + } + + // function to display fetched data on screen + Widget buildPosts(List posts) { + // ListView Builder to show data in a list + 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("Tags : ${widget.tags}"), + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + body: ListView.separated( + itemCount: posts.length, + itemBuilder: (context, index) { + final post = posts[index]; + final startDate = DateTime.parse(post.startDate!); + final date = DateFormat.yMd().format(startDate); + final time = DateFormat.Hm().format(startDate); + + return ListTile( + title: Text('${post.name!}'), + subtitle: Text('${post.place!}\n${date} ${time}'), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ItemMenu(title: post.id!))); + }); + }, + separatorBuilder: (context, index) { + return Divider(); + }, + ), + ); + } +} -- 2.47.2 From df80137f46b67475707387e49beea79f11aa05fc Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 21 Oct 2024 22:29:02 +0200 Subject: [PATCH 15/16] add organizers item list --- covas_mobile/lib/pages/ItemMenu.dart | 8 ++ .../lib/pages/ListItemByOrganizers.dart | 123 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 covas_mobile/lib/pages/ListItemByOrganizers.dart diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 5d93215..6e9f417 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -17,6 +17,7 @@ import '../classes/events.dart'; import 'ListItemMenu.dart'; import 'ListItemByTags.dart'; +import 'ListItemByOrganizers.dart'; void main() { initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); @@ -280,6 +281,13 @@ class _ItemMenuState extends State with ShowErrorDialog { mainAxisSize: MainAxisSize.min, children: [ InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ListItemOrganizers( + organizer: '$tag'))); + }, child: Text( '$tag', style: const TextStyle(color: Colors.white), diff --git a/covas_mobile/lib/pages/ListItemByOrganizers.dart b/covas_mobile/lib/pages/ListItemByOrganizers.dart new file mode 100644 index 0000000..8a78c62 --- /dev/null +++ b/covas_mobile/lib/pages/ListItemByOrganizers.dart @@ -0,0 +1,123 @@ +import 'dart:convert'; +import 'dart:io'; +import "ItemMenu.dart"; + +import 'package:http/http.dart' as http; +import 'package:flutter/material.dart'; +import '../classes/events.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:intl/intl.dart'; +import 'package:intl/date_symbol_data_local.dart'; + +import '../variable/globals.dart' as globals; + +// app starting point +void main() { + initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: const ListItemOrganizers(organizer: "default"), + debugShowCheckedModeBanner: false, + ); + } +} + +// homepage class +class ListItemOrganizers extends StatefulWidget { + const ListItemOrganizers({Key? key, required this.organizer}) + : super(key: key); + + final String organizer; + @override + State createState() => _MyHomePageState(); +} + +// homepage state +class _MyHomePageState extends State { + // variable to call and store future list of posts + + // function to fetch data from api and return future list of posts + static Future> getPosts(organizer) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var accessToken = prefs.getString("access_token") ?? ""; + final List body = []; + if (accessToken.isNotEmpty) { + var url = Uri.parse("${globals.api}/events?organizers=${organizer}"); + final response = await http.get(url, headers: { + "Content-Type": "application/json", + HttpHeaders.cookieHeader: "access_token=${accessToken}" + }); + final List body = json.decode(utf8.decode(response.bodyBytes)); + return body.map((e) => Events.fromJson(e)).toList(); + } + return body; + } + + // build function + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + // FutureBuilder + child: FutureBuilder>( + future: getPosts(widget.organizer), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + // until data is fetched, show loader + return const CircularProgressIndicator(); + } else if (snapshot.hasData) { + // once data is fetched, display it on screen (call buildPosts()) + final posts = snapshot.data!; + return buildPosts(posts); + } else { + // if no data, show simple Text + return const Text("No data available"); + } + }, + ), + ), + ); + } + + // function to display fetched data on screen + Widget buildPosts(List posts) { + // ListView Builder to show data in a list + 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("Organisateur : ${widget.organizer}"), + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + body: ListView.separated( + itemCount: posts.length, + itemBuilder: (context, index) { + final post = posts[index]; + final startDate = DateTime.parse(post.startDate!); + final date = DateFormat.yMd().format(startDate); + final time = DateFormat.Hm().format(startDate); + + return ListTile( + title: Text('${post.name!}'), + subtitle: Text('${post.place!}\n${date} ${time}'), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ItemMenu(title: post.id!))); + }); + }, + separatorBuilder: (context, index) { + return Divider(); + }, + ), + ); + } +} -- 2.47.2 From f2de4a2faa8f3bb6d03e3d8a10e668bd13bd8d54 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 21 Oct 2024 22:47:04 +0200 Subject: [PATCH 16/16] overflow text --- covas_mobile/lib/pages/ItemMenu.dart | 2 +- covas_mobile/lib/pages/ListItemByOrganizers.dart | 3 ++- covas_mobile/lib/pages/ListItemByTags.dart | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 6e9f417..d14cea6 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -198,7 +198,7 @@ class _ItemMenuState extends State with ShowErrorDialog { 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}"), + title: Text("${eventName}", overflow: TextOverflow.ellipsis), backgroundColor: Colors.blue, foregroundColor: Colors.white, leading: IconButton( diff --git a/covas_mobile/lib/pages/ListItemByOrganizers.dart b/covas_mobile/lib/pages/ListItemByOrganizers.dart index 8a78c62..1500a1b 100644 --- a/covas_mobile/lib/pages/ListItemByOrganizers.dart +++ b/covas_mobile/lib/pages/ListItemByOrganizers.dart @@ -92,7 +92,8 @@ class _MyHomePageState extends State { 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("Organisateur : ${widget.organizer}"), + title: Text("Organisateur : ${widget.organizer}", + overflow: TextOverflow.ellipsis), backgroundColor: Colors.blue, foregroundColor: Colors.white, ), diff --git a/covas_mobile/lib/pages/ListItemByTags.dart b/covas_mobile/lib/pages/ListItemByTags.dart index 35a0d88..59ddcbc 100644 --- a/covas_mobile/lib/pages/ListItemByTags.dart +++ b/covas_mobile/lib/pages/ListItemByTags.dart @@ -91,7 +91,7 @@ class _MyHomePageState extends State { 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("Tags : ${widget.tags}"), + title: Text("Tags : ${widget.tags}", overflow: TextOverflow.ellipsis), backgroundColor: Colors.blue, foregroundColor: Colors.white, ), -- 2.47.2