From 8c4c436241ba83a967b03bd56b5eb8ba443328ad Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sat, 7 Dec 2024 17:10:02 +0100 Subject: [PATCH 1/8] add floating button --- covas_mobile/lib/pages/ItemMenu.dart | 40 +++++++++++++++++----------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index e991885..be0c762 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -194,21 +194,21 @@ class _ItemMenuState extends State with ShowErrorDialog { // fast, so that you can just rebuild anything that needs updating rather // 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}", overflow: TextOverflow.ellipsis), - backgroundColor: Colors.blue, - foregroundColor: Colors.white, - leading: IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () { - Navigator.push( - context, MaterialPageRoute(builder: (_) => ListItemMenu())); - }, - )), - body: SingleChildScrollView( - child: Column( + 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}", overflow: TextOverflow.ellipsis), + 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: [ Padding( padding: const EdgeInsets.only(top: 60.0), @@ -394,6 +394,14 @@ class _ItemMenuState extends State with ShowErrorDialog { ], ) ], - ))); + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () {}, + backgroundColor: Colors.blue, + tooltip: 'Recherche', + child: const Icon(Icons.edit, color: Colors.white), + ), + ); } } From 4b71867ee0c60826f0a0c8434b15585b84259aef Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sat, 7 Dec 2024 18:44:53 +0100 Subject: [PATCH 2/8] add editevent wip --- covas_mobile/lib/pages/EditEvent.dart | 871 ++++++++++++++++++++++++++ 1 file changed, 871 insertions(+) create mode 100644 covas_mobile/lib/pages/EditEvent.dart diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart new file mode 100644 index 0000000..44246f5 --- /dev/null +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -0,0 +1,871 @@ +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 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:textfield_tags/textfield_tags.dart'; + +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'ItemMenu.dart'; +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 id = ""; + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + home: EditEvent(id: id), + ); + } +} + +class EditEvent extends StatefulWidget { + const EditEvent({Key? key, required this.id}) : super(key: key); + final String id; + + @override + _EditEventState createState() => _EditEventState(); +} + +class _EditEventState extends State + with ShowErrorDialog, ShowEventDialog { + TextEditingController inputName = TextEditingController(); + + TextEditingController inputDate = TextEditingController(); + TextEditingController inputDesc = TextEditingController(); + + TextEditingController inputGeo = TextEditingController(); + + TextEditingController startDatepicker = TextEditingController(); + TextEditingController startTimepicker = TextEditingController(); + TextEditingController endDatepicker = TextEditingController(); + TextEditingController endTimepicker = TextEditingController(); + final _stringTagController = StringTagController(); + + List> suggestions = []; + String geographicalZone = ""; + String imgUrl = ""; + Map events = {}; + + List initialTags = []; + + final _stringOrgaController = StringTagController(); + List initialOrga = []; + + onTapFunctionDatePicker( + {required BuildContext context, required String position}) async { + String date = "start_date"; + if (position == "end") { + date = "end_date"; + } + DateTime dateEvent; + if (events[date].toString().isEmpty) { + dateEvent = DateTime.now(); + } else { + dateEvent = DateTime.parse(events[date]); + } + DateTime? pickedDate = await showDatePicker( + context: context, + firstDate: dateEvent, + initialDate: dateEvent, + 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 { + String date = "start_date"; + if (position == "end") { + date = "end_date"; + } + TimeOfDay timeEvent; + if (widget.events[date].toString().isEmpty) { + timeEvent = TimeOfDay.now(); + } else { + timeEvent = TimeOfDay.fromDateTime(DateTime.parse(widget.events[date])); + } + TimeOfDay? pickedDate = + await showTimePicker(context: context, initialTime: timeEvent); + if (pickedDate == null) return; + if (position == "start") { + startTimepicker.text = pickedDate.format(context); + } + if (position == "end") { + endTimepicker.text = pickedDate.format(context); + } + } + + convertNulltoEmptyString(var check) { + if (check == null) { + return ""; + } + return check; + } + + convertNulltoArray(List check) { + if (check == null) { + return []; + } + return check; + } + + 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 _getEventInfos() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var accessToken = prefs.getString("access_token") ?? ""; + String formerName = ""; + String formerMap = ""; + String formerImage = ""; + String formerDesc = ""; + var date = null; + var time = null; + var dateE = null; + var timeE = null; + List formerTags = []; + List formerOrga = []; + + if (accessToken.isNotEmpty) { + var urlGet = Uri.parse("${globals.api}/events/${widget.id}"); + + var responseGet = await http.get(urlGet, + headers: {HttpHeaders.cookieHeader: 'access_token=${accessToken}'}); + stderr.writeln('Response Get status: ${responseGet.statusCode}'); + if (responseGet.statusCode == 200) { + stderr.writeln('Username : ${responseGet.body}'); + events = jsonDecode(utf8.decode(responseGet.bodyBytes)); + formerName = convertNulltoEmptyString(events["name"]); + formerMap = convertNulltoEmptyString(events["place"]); + formerDesc = convertNulltoEmptyString(events["description"]); + formerTags = List.from(events['tags'] as List); + formerOrga = List.from(events['organizers'] as List); + final startDate = DateTime.parse(events["start_date"]); + date = DateFormat.yMd().format(startDate); + time = DateFormat.Hm().format(startDate); + + final endDate = DateTime.parse(events["end_date"]); + + dateE = DateFormat.yMd().format(endDate); + timeE = DateFormat.Hm().format(endDate); + if (events["imgUrl"] != null) { + formerImage = events["imgUrl"]; + } + } else { + var text = ""; + switch (responseGet.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 = "Vous n'avez pas l'autorisation de faire cette action"; + } + 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); + } + } else { + showErrorDialog(context, "Cache invalide"); + } + + setState(() { + // This call to setState tells the Flutter framework that something has + // changed in this State, which causes it to rerun the build method below + // so that the display can reflect the updated values. If we changed + // _counter without calling setState(), then the build method would not be + // called again, and so nothing would appear to happen. + inputName.text = formerName; + startDatepicker.text = date.toString(); + startTimepicker.text = time.toString(); + endDatepicker.text = dateE.toString(); + endTimepicker.text = timeE.toString(); + initialOrga = formerOrga; + inputGeo.text = formerMap; + imgUrl = formerImage; + inputDesc.text = formerDesc; + initialTags = formerTags; + }); + } + + Future _updateEvent(BuildContext context) async { + var name = inputName.text; + var place = inputGeo.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); + DateTime startDateCompare = DateTime.parse(startDateFormat); + DateTime dateNow = DateTime.now(); + var endDateFormat = formatDate(endDatepicker.text); + var startDate = + "${startDateFormat}T${startTimepicker.text.replaceAll('-', ':')}"; + var endDate = "${endDateFormat}T${endTimepicker.text.replaceAll('-', ':')}"; + if (startDateCompare.isAfter(dateNow)) { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var accessToken = prefs.getString("access_token") ?? ""; + + if (accessToken.isNotEmpty) { + try { + await dotenv.load(); + final mapboxAccessToken = dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? ''; + print("place non encoded : ${place}"); + final url = + 'https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${mapboxAccessToken}&types=poi,address,place'; + var encoded = Uri.encodeFull(url); + print("encoded : ${encoded}"); + final response = await http.get(Uri.parse(encoded)); + + if (response.statusCode == 200) { + final data = json.decode(response.body); + print("data : ${data}"); + + if (data['features'].isNotEmpty) { + place = data['features'][0]['place_name']; + final coordinates = + data['features'][0]['geometry']['coordinates']; + final longitude = coordinates[0]; // Longitude + final latitude = coordinates[1]; // Latitude + var urlGet = Uri.parse( + "${globals.api}/events/search?item=${name}&date_event=${startDate}"); + + var responseGet = await http.get(urlGet, headers: { + HttpHeaders.cookieHeader: 'access_token=${accessToken}' + }); + if (responseGet.statusCode == 200) { + var events = jsonDecode(utf8.decode(responseGet.bodyBytes)); + print("reponse http : ${events.length}"); + if (events.length == 0) { + urlGet = Uri.parse( + "${globals.api}/events/search?min_lat=$latitude&max_lat=$latitude" + "&min_lon=$longitude&max_lon=$longitude&date_event=${startDate}"); + responseGet = await http.get(urlGet, headers: { + HttpHeaders.cookieHeader: 'access_token=${accessToken}' + }); + if (responseGet.statusCode == 200) { + events = jsonDecode(utf8.decode(responseGet.bodyBytes)); + print("reponse http : ${events.length}"); + if (events.length != 0) { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => + ItemMenu(title: events[0]["id"]))); + return; + } + } + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ItemMenu(title: events[0]["id"]))); + return; + } + } + + final params = { + 'expiration': '15552000', + 'key': dotenv.env["IMGBB_API_KEY"], + }; + print("Post Img"); + final urlPost = Uri.parse('https://api.imgbb.com/1/upload') + .replace(queryParameters: params); + + final req = http.MultipartRequest('POST', urlPost); + + final stream = await req.send(); + final res = await http.Response.fromStream(stream); + + final status = res.statusCode; + print("code status imgbb ${status}"); + if (status == 200) { + var body = json.decode(utf8.decode(res.bodyBytes)); + String imgUrl = body["data"]["url"]; + + //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, + 'organizers': organizers, + 'latitude': latitude, + 'longitude': longitude, + 'description': description, + "imgUrl": imgUrl, + "tags": tags + })); + 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); + } + } else { + print("imgbb error : ${status}"); + } + } else { + showErrorDialog(context, "Aucune donnée geographique"); + } + } else { + showErrorDialog(context, "Mapbox non accessible"); + } + } catch (e) { + showErrorDialog(context, "${e}"); + } + } else { + showErrorDialog(context, "Champ vide"); + } + } else { + showErrorDialog(context, "Evenement non futur"); + } + } + + @override + void initState() { + _getEventInfos(); + super.initState(); + } + + final _formKey = GlobalKey(); + String? _validateField(String? value) { + return value!.isEmpty ? 'Champ requis' : null; + } + + Future searchSuggestions(String input) async { + await dotenv.load(fileName: ".env"); // Load .env file + + final mapboxAccessToken = dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? ''; + final url = + 'https://api.mapbox.com/geocoding/v5/mapbox.places/${input}.json?access_token=${mapboxAccessToken}&types=poi,address,place'; + var encoded = Uri.encodeFull(url); + final response = await http.get(Uri.parse(encoded)); + print("response code suggesttion : ${response.statusCode}"); + + if (response.statusCode == 200) { + final data = json.decode(response.body); + print("data suggestion : ${data}"); + setState(() { + suggestions = (data['features'] as List) + .map((feature) => { + 'place_name': feature['place_name'], + 'text': feature['text'], + 'geometry': feature[ + 'geometry'], // Include geometry for latitude/longitude + }) + .toList(); + }); + } else { + throw Exception('Failed to load suggestions'); + } + } + + Padding _buildGeographicalZoneSearchField() { + return Padding( + padding: + const EdgeInsets.only(left: 15.0, right: 15.0, top: 15, bottom: 0), + child: Column( + children: [ + TextField( + controller: inputGeo, + decoration: InputDecoration( + labelText: 'Lieu', + border: OutlineInputBorder(), + suffixIcon: IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + setState(() { + inputGeo.clear(); // Clear the text field + geographicalZone = ''; // Reset the geographical zone state + suggestions.clear(); // Optionally clear suggestions + }); + }, + ), + ), + onChanged: (value) { + setState(() { + geographicalZone = value; + searchSuggestions(value); + }); + }, + ), + if (suggestions.isNotEmpty) + Container( + height: 200, + decoration: BoxDecoration( + border: Border.all(color: Colors.blue), + borderRadius: BorderRadius.circular(8), + ), + child: ListView.builder( + shrinkWrap: true, + itemCount: suggestions.length, + itemBuilder: (context, index) { + return ListTile( + title: Text(suggestions[index]['text']), + subtitle: Text(suggestions[index]['place_name']), + onTap: () async { + print("suggestion tapped : ${suggestions[index]}"); + final latitude = + suggestions[index]['geometry']['coordinates'][1]; + final longitude = + suggestions[index]['geometry']['coordinates'][0]; + + setState(() { + geographicalZone = suggestions[index]['text']; + inputGeo.text = geographicalZone; + suggestions.clear(); + }); + }, + ); + }, + ), + ), + ], + ), + ); + } + + @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: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 60.0), + child: Image.network( + imgUrl, + width: MediaQuery.of(context).size.width * + 0.5, // 50% of screen width + height: MediaQuery.of(context).size.height * 0.5, + loadingBuilder: (BuildContext context, Widget child, + ImageChunkEvent? loadingProgress) { + if (loadingProgress == null) { + return child; // The image has finished loading + } + return Center( + child: CircularProgressIndicator(), + ); + }, + errorBuilder: (BuildContext context, Object error, + StackTrace? stackTrace) { + return Center( + child: Icon(Icons.error, + size: MediaQuery.of(context).size.width * 0.1), + ); + }, + )), + 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'), + ), + ), + _buildGeographicalZoneSearchField(), + 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), + ), + ), + ) + ], + ), + ), + )); + } +} From c12a95709982e8840cac5de649a395b75f185f00 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sun, 8 Dec 2024 21:23:51 +0100 Subject: [PATCH 3/8] fix datetpicker wip --- covas_mobile/lib/pages/EditEvent.dart | 56 +++++++++++++-------------- covas_mobile/lib/pages/ItemMenu.dart | 11 +++++- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart index 44246f5..61a700d 100644 --- a/covas_mobile/lib/pages/EditEvent.dart +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -54,6 +54,10 @@ class _EditEventState extends State TextEditingController endTimepicker = TextEditingController(); final _stringTagController = StringTagController(); + var dateS = null; + var timeS = null; + var dateE = null; + var timeE = null; List> suggestions = []; String geographicalZone = ""; String imgUrl = ""; @@ -66,20 +70,19 @@ class _EditEventState extends State onTapFunctionDatePicker( {required BuildContext context, required String position}) async { - String date = "start_date"; - if (position == "end") { - date = "end_date"; - } - DateTime dateEvent; - if (events[date].toString().isEmpty) { - dateEvent = DateTime.now(); + DateTime date; + if ((startDatepicker.text.isEmpty) || (endDatepicker.text.isEmpty)) { + date = DateTime.now(); } else { - dateEvent = DateTime.parse(events[date]); + date = DateTime.parse(formatDate(startDatepicker.text)); + if (position == "end") { + date = DateTime.parse(formatDate(endDatepicker.text)); + } } DateTime? pickedDate = await showDatePicker( context: context, - firstDate: dateEvent, - initialDate: dateEvent, + firstDate: date, + initialDate: date, lastDate: DateTime(2104)); if (pickedDate == null) return; if (position == "start") { @@ -92,18 +95,19 @@ class _EditEventState extends State onTapFunctionTimePicker( {required BuildContext context, required String position}) async { - String date = "start_date"; - if (position == "end") { - date = "end_date"; - } - TimeOfDay timeEvent; - if (widget.events[date].toString().isEmpty) { - timeEvent = TimeOfDay.now(); + TimeOfDay time; + + if ((startTimepicker.text.isEmpty) || (endTimepicker.text.isEmpty)) { + time = TimeOfDay.now(); } else { - timeEvent = TimeOfDay.fromDateTime(DateTime.parse(widget.events[date])); + time = TimeOfDay.fromDateTime(DateTime.parse(startTimepicker.text)); + if (position == "end") { + time = TimeOfDay.fromDateTime(DateTime.parse(endTimepicker.text)); + } } + TimeOfDay? pickedDate = - await showTimePicker(context: context, initialTime: timeEvent); + await showTimePicker(context: context, initialTime: time); if (pickedDate == null) return; if (position == "start") { startTimepicker.text = pickedDate.format(context); @@ -143,10 +147,6 @@ class _EditEventState extends State String formerMap = ""; String formerImage = ""; String formerDesc = ""; - var date = null; - var time = null; - var dateE = null; - var timeE = null; List formerTags = []; List formerOrga = []; @@ -165,8 +165,8 @@ class _EditEventState extends State formerTags = List.from(events['tags'] as List); formerOrga = List.from(events['organizers'] as List); final startDate = DateTime.parse(events["start_date"]); - date = DateFormat.yMd().format(startDate); - time = DateFormat.Hm().format(startDate); + dateS = DateFormat.yMd().format(startDate); + timeS = DateFormat.Hm().format(startDate); final endDate = DateTime.parse(events["end_date"]); @@ -227,9 +227,9 @@ class _EditEventState extends State // _counter without calling setState(), then the build method would not be // called again, and so nothing would appear to happen. inputName.text = formerName; - startDatepicker.text = date.toString(); - startTimepicker.text = time.toString(); - endDatepicker.text = dateE.toString(); + startDatepicker.text = DateFormat("dd-MM-yyyy").format(dateS); + startTimepicker.text = timeS.toString(); + endDatepicker.text = DateFormat("dd-MM-yyyy").format(dateE); endTimepicker.text = timeE.toString(); initialOrga = formerOrga; inputGeo.text = formerMap; diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index be0c762..d5c7ed8 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -18,6 +18,7 @@ import '../classes/events.dart'; import 'ListItemMenu.dart'; import 'MapboxPages.dart'; import 'ListItemByOrganizers.dart'; +import 'EditEvent.dart'; void main() { initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); @@ -76,6 +77,8 @@ class _ItemMenuState extends State with ShowErrorDialog { List tags = []; List organizers = []; + String id = ""; + Events? events; @override void initState() { @@ -104,6 +107,7 @@ class _ItemMenuState extends State with ShowErrorDialog { if (responseGet.statusCode == 200) { stderr.writeln('Username : ${responseGet.body}'); var events = jsonDecode(utf8.decode(responseGet.bodyBytes)); + id = events["id"]; formerName = events["name"]; formerMap = "${events["place"]}"; formerDesc = events["description"]; @@ -397,7 +401,12 @@ class _ItemMenuState extends State with ShowErrorDialog { ), ), floatingActionButton: FloatingActionButton( - onPressed: () {}, + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (_) => EditEvent(id: id)), + ); + }, backgroundColor: Colors.blue, tooltip: 'Recherche', child: const Icon(Icons.edit, color: Colors.white), From ac566053b139ac0eb7f5645882545134906422b3 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 9 Dec 2024 23:00:54 +0100 Subject: [PATCH 4/8] fix datepicker --- covas_mobile/lib/pages/EditEvent.dart | 48 ++++++++++++++++----------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart index 61a700d..4f5846b 100644 --- a/covas_mobile/lib/pages/EditEvent.dart +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -1,3 +1,5 @@ +import 'dart:ffi'; + import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; @@ -54,10 +56,8 @@ class _EditEventState extends State TextEditingController endTimepicker = TextEditingController(); final _stringTagController = StringTagController(); - var dateS = null; - var timeS = null; - var dateE = null; - var timeE = null; + DateTime startDate = DateTime.now(); + DateTime endDate = DateTime.now(); List> suggestions = []; String geographicalZone = ""; String imgUrl = ""; @@ -86,10 +86,10 @@ class _EditEventState extends State lastDate: DateTime(2104)); if (pickedDate == null) return; if (position == "start") { - startDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedDate); + startDatepicker.text = DateFormat("dd/MM/yyyy").format(pickedDate); } if (position == "end") { - endDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedDate); + endDatepicker.text = DateFormat("dd/MM/yyyy").format(pickedDate); } } @@ -100,9 +100,16 @@ class _EditEventState extends State if ((startTimepicker.text.isEmpty) || (endTimepicker.text.isEmpty)) { time = TimeOfDay.now(); } else { - time = TimeOfDay.fromDateTime(DateTime.parse(startTimepicker.text)); + DateTime date = new DateTime.now(); + date = date.copyWith( + hour: int.parse(startTimepicker.text.split(":")[0]), + minute: int.parse(startTimepicker.text.split(":")[1])); + time = TimeOfDay.fromDateTime(date); if (position == "end") { - time = TimeOfDay.fromDateTime(DateTime.parse(endTimepicker.text)); + date = date.copyWith( + hour: int.parse(endTimepicker.text.split(":")[0]), + minute: int.parse(endTimepicker.text.split(":")[1])); + time = TimeOfDay.fromDateTime(date); } } @@ -132,7 +139,8 @@ class _EditEventState extends State } String formatDate(String date) { - var splitedDate = date.split("-"); + var splitedDate = date.split("/"); + var day = splitedDate[0]; var month = splitedDate[1]; var year = splitedDate[2]; @@ -164,14 +172,15 @@ class _EditEventState extends State formerDesc = convertNulltoEmptyString(events["description"]); formerTags = List.from(events['tags'] as List); formerOrga = List.from(events['organizers'] as List); - final startDate = DateTime.parse(events["start_date"]); - dateS = DateFormat.yMd().format(startDate); - timeS = DateFormat.Hm().format(startDate); + startDate = DateTime.parse(events["start_date"]); + //dateS = DateFormat.yMd().format(startDate); + //print("startdate : ${dateS}"); + //timeS = DateFormat.Hm().format(startDate); - final endDate = DateTime.parse(events["end_date"]); + endDate = DateTime.parse(events["end_date"]); - dateE = DateFormat.yMd().format(endDate); - timeE = DateFormat.Hm().format(endDate); + //dateE = DateFormat.yMd().format(endDate); + //timeE = DateFormat.Hm().format(endDate); if (events["imgUrl"] != null) { formerImage = events["imgUrl"]; } @@ -227,10 +236,11 @@ class _EditEventState extends State // _counter without calling setState(), then the build method would not be // called again, and so nothing would appear to happen. inputName.text = formerName; - startDatepicker.text = DateFormat("dd-MM-yyyy").format(dateS); - startTimepicker.text = timeS.toString(); - endDatepicker.text = DateFormat("dd-MM-yyyy").format(dateE); - endTimepicker.text = timeE.toString(); + startDatepicker.text = + DateFormat("dd/MM/yyyy").format(startDate).toString(); + startTimepicker.text = DateFormat("HH:mm").format(startDate).toString(); + endDatepicker.text = DateFormat("dd/MM/yyyy").format(endDate).toString(); + endTimepicker.text = DateFormat("HH:mm").format(endDate).toString(); initialOrga = formerOrga; inputGeo.text = formerMap; imgUrl = formerImage; From b8e6adf2e821885e7eed246a35b26c6b141ae9bf Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 9 Dec 2024 23:34:44 +0100 Subject: [PATCH 5/8] try tags organizers --- covas_mobile/lib/pages/EditEvent.dart | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart index 4f5846b..af5a8f0 100644 --- a/covas_mobile/lib/pages/EditEvent.dart +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -1,5 +1,3 @@ -import 'dart:ffi'; - import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; @@ -9,7 +7,6 @@ import 'package:textfield_tags/textfield_tags.dart'; import 'dart:convert'; import 'dart:io'; -import 'dart:typed_data'; import 'ItemMenu.dart'; import '../classes/alert.dart'; @@ -170,17 +167,11 @@ class _EditEventState extends State formerName = convertNulltoEmptyString(events["name"]); formerMap = convertNulltoEmptyString(events["place"]); formerDesc = convertNulltoEmptyString(events["description"]); - formerTags = List.from(events['tags'] as List); - formerOrga = List.from(events['organizers'] as List); + startDate = DateTime.parse(events["start_date"]); - //dateS = DateFormat.yMd().format(startDate); - //print("startdate : ${dateS}"); - //timeS = DateFormat.Hm().format(startDate); endDate = DateTime.parse(events["end_date"]); - //dateE = DateFormat.yMd().format(endDate); - //timeE = DateFormat.Hm().format(endDate); if (events["imgUrl"] != null) { formerImage = events["imgUrl"]; } @@ -241,11 +232,15 @@ class _EditEventState extends State startTimepicker.text = DateFormat("HH:mm").format(startDate).toString(); endDatepicker.text = DateFormat("dd/MM/yyyy").format(endDate).toString(); endTimepicker.text = DateFormat("HH:mm").format(endDate).toString(); - initialOrga = formerOrga; inputGeo.text = formerMap; imgUrl = formerImage; inputDesc.text = formerDesc; - initialTags = formerTags; + for (int i = 0; i < events["tags"].length; i++) { + _stringTagController.addTag(events["tags"][i]); + } + for (int i = 0; i < events["organizers"].length; i++) { + _stringOrgaController.addTag(events["organizers"][i]); + } }); } From 0dc098554c76f178f0944be007b141240deb1bad Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 11 Dec 2024 22:20:32 +0100 Subject: [PATCH 6/8] tags and organizers work --- covas_mobile/lib/pages/EditEvent.dart | 25 ++++++++++++++----------- covas_mobile/lib/pages/ItemMenu.dart | 4 +++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart index af5a8f0..001b4b4 100644 --- a/covas_mobile/lib/pages/EditEvent.dart +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -21,18 +21,27 @@ void main() { class MyApp extends StatelessWidget { Map events = {}; String id = ""; + List organizers = []; + List tags = []; @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, - home: EditEvent(id: id), + home: EditEvent(id: id, organizers: organizers, tags: tags), ); } } class EditEvent extends StatefulWidget { - const EditEvent({Key? key, required this.id}) : super(key: key); + const EditEvent( + {Key? key, + required this.id, + required this.tags, + required this.organizers}) + : super(key: key); final String id; + final List tags; + final List organizers; @override _EditEventState createState() => _EditEventState(); @@ -152,8 +161,6 @@ class _EditEventState extends State String formerMap = ""; String formerImage = ""; String formerDesc = ""; - List formerTags = []; - List formerOrga = []; if (accessToken.isNotEmpty) { var urlGet = Uri.parse("${globals.api}/events/${widget.id}"); @@ -235,12 +242,6 @@ class _EditEventState extends State inputGeo.text = formerMap; imgUrl = formerImage; inputDesc.text = formerDesc; - for (int i = 0; i < events["tags"].length; i++) { - _stringTagController.addTag(events["tags"][i]); - } - for (int i = 0; i < events["organizers"].length; i++) { - _stringOrgaController.addTag(events["organizers"][i]); - } }); } @@ -430,8 +431,10 @@ class _EditEventState extends State @override void initState() { - _getEventInfos(); + initialTags = List.from(widget.tags as List); + initialOrga = List.from(widget.organizers as List); super.initState(); + _getEventInfos(); } final _formKey = GlobalKey(); diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index d5c7ed8..22e5978 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -404,7 +404,9 @@ class _ItemMenuState extends State with ShowErrorDialog { onPressed: () { Navigator.push( context, - MaterialPageRoute(builder: (_) => EditEvent(id: id)), + MaterialPageRoute( + builder: (_) => + EditEvent(id: id, tags: tags, organizers: organizers)), ); }, backgroundColor: Colors.blue, From c58127342b735d2615b76294f5a74dd135dff584 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 13 Dec 2024 23:49:56 +0100 Subject: [PATCH 7/8] display edit event --- covas_mobile/lib/classes/events.dart | 39 ++++++-- covas_mobile/lib/pages/EditEvent.dart | 138 ++++++-------------------- covas_mobile/lib/pages/ItemMenu.dart | 30 +++--- 3 files changed, 74 insertions(+), 133 deletions(-) diff --git a/covas_mobile/lib/classes/events.dart b/covas_mobile/lib/classes/events.dart index 5879a30..c0c4fba 100644 --- a/covas_mobile/lib/classes/events.dart +++ b/covas_mobile/lib/classes/events.dart @@ -7,17 +7,36 @@ class Events { String? description; double? latitude; double? longitude; - - Events({this.place, this.id, this.name, this.startDate}); + List? tags; + List? organizers; + String? imgUrl; + Events( + {this.place, + this.id, + this.name, + this.startDate, + this.description, + this.endDate, + this.tags, + this.latitude, + this.longitude, + this.organizers, + this.imgUrl}); Events.fromJson(Map json) { - id = json['id']; - name = json['name']; - place = json['place']; - startDate = json["start_date"]; - endDate = json['end_date']; - description = json['description']; - latitude = json['latitude']; - longitude = json['longitude']; + id = json['id'] as String?; + name = json['name'] as String?; + place = json['place'] as String?; + startDate = json['start_date'] as String?; + endDate = json['end_date'] as String?; + description = json['description'] as String?; + latitude = (json['latitude'] as num?)?.toDouble(); // Safely cast to double + longitude = + (json['longitude'] as num?)?.toDouble(); // Safely cast to double + tags = (json['tags'] as List?) + ?.cast(); // Convert List to List + organizers = (json['organizers'] as List?) + ?.cast(); // Convert List to List + imgUrl = json['imgUrl'] as String?; } } diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart index 001b4b4..85adc11 100644 --- a/covas_mobile/lib/pages/EditEvent.dart +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -7,6 +7,7 @@ import 'package:textfield_tags/textfield_tags.dart'; import 'dart:convert'; import 'dart:io'; +import '../classes/events.dart'; import 'ItemMenu.dart'; import '../classes/alert.dart'; @@ -19,29 +20,20 @@ void main() { } class MyApp extends StatelessWidget { - Map events = {}; - String id = ""; - List organizers = []; - List tags = []; + Events? events; + @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, - home: EditEvent(id: id, organizers: organizers, tags: tags), + home: EditEvent(events: events), ); } } class EditEvent extends StatefulWidget { - const EditEvent( - {Key? key, - required this.id, - required this.tags, - required this.organizers}) - : super(key: key); - final String id; - final List tags; - final List organizers; + const EditEvent({Key? key, required this.events}) : super(key: key); + final Events? events; @override _EditEventState createState() => _EditEventState(); @@ -67,7 +59,6 @@ class _EditEventState extends State List> suggestions = []; String geographicalZone = ""; String imgUrl = ""; - Map events = {}; List initialTags = []; @@ -154,97 +145,6 @@ class _EditEventState extends State return "${year}-${month}-${day}"; } - Future _getEventInfos() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - var accessToken = prefs.getString("access_token") ?? ""; - String formerName = ""; - String formerMap = ""; - String formerImage = ""; - String formerDesc = ""; - - if (accessToken.isNotEmpty) { - var urlGet = Uri.parse("${globals.api}/events/${widget.id}"); - - var responseGet = await http.get(urlGet, - headers: {HttpHeaders.cookieHeader: 'access_token=${accessToken}'}); - stderr.writeln('Response Get status: ${responseGet.statusCode}'); - if (responseGet.statusCode == 200) { - stderr.writeln('Username : ${responseGet.body}'); - events = jsonDecode(utf8.decode(responseGet.bodyBytes)); - formerName = convertNulltoEmptyString(events["name"]); - formerMap = convertNulltoEmptyString(events["place"]); - formerDesc = convertNulltoEmptyString(events["description"]); - - startDate = DateTime.parse(events["start_date"]); - - endDate = DateTime.parse(events["end_date"]); - - if (events["imgUrl"] != null) { - formerImage = events["imgUrl"]; - } - } else { - var text = ""; - switch (responseGet.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 = "Vous n'avez pas l'autorisation de faire cette action"; - } - 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); - } - } else { - showErrorDialog(context, "Cache invalide"); - } - - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - inputName.text = formerName; - startDatepicker.text = - DateFormat("dd/MM/yyyy").format(startDate).toString(); - startTimepicker.text = DateFormat("HH:mm").format(startDate).toString(); - endDatepicker.text = DateFormat("dd/MM/yyyy").format(endDate).toString(); - endTimepicker.text = DateFormat("HH:mm").format(endDate).toString(); - inputGeo.text = formerMap; - imgUrl = formerImage; - inputDesc.text = formerDesc; - }); - } - Future _updateEvent(BuildContext context) async { var name = inputName.text; var place = inputGeo.text; @@ -431,10 +331,30 @@ class _EditEventState extends State @override void initState() { - initialTags = List.from(widget.tags as List); - initialOrga = List.from(widget.organizers as List); + inputName.text = widget.events!.name ?? ""; + startDatepicker.text = DateFormat("dd/MM/yyyy") + .format(DateTime.parse( + widget.events!.startDate ?? DateTime.now().toString())) + .toString(); + startTimepicker.text = DateFormat("HH:mm") + .format(DateTime.parse( + widget.events!.startDate ?? DateTime.now().toString())) + .toString(); + endDatepicker.text = DateFormat("dd/MM/yyyy") + .format( + DateTime.parse(widget.events!.endDate ?? DateTime.now().toString())) + .toString(); + endTimepicker.text = DateFormat("HH:mm") + .format( + DateTime.parse(widget.events!.endDate ?? DateTime.now().toString())) + .toString(); + inputGeo.text = widget.events!.place ?? ""; + + imgUrl = widget.events!.imgUrl ?? ""; + inputDesc.text = widget.events!.description ?? ""; + initialTags = List.from(widget.events!.tags as List); + initialOrga = List.from(widget.events!.organizers as List); super.initState(); - _getEventInfos(); } final _formKey = GlobalKey(); diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 22e5978..ce4498d 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -106,23 +106,27 @@ class _ItemMenuState extends State with ShowErrorDialog { stderr.writeln('Response Get status: ${responseGet.statusCode}'); if (responseGet.statusCode == 200) { stderr.writeln('Username : ${responseGet.body}'); - var events = jsonDecode(utf8.decode(responseGet.bodyBytes)); - id = events["id"]; - formerName = events["name"]; - formerMap = "${events["place"]}"; - formerDesc = events["description"]; - formerTags = List.from(events['tags'] as List); - formerOrga = List.from(events['organizers'] as List); - final startDate = DateTime.parse(events["start_date"]); + events = + Events.fromJson(jsonDecode(utf8.decode(responseGet.bodyBytes))); + id = events!.id ?? ""; + formerName = events!.name ?? ""; + formerMap = "${events!.place}" ?? ""; + formerDesc = events!.description ?? ""; + + formerTags = List.from(events!.tags as List); + formerOrga = List.from(events!.organizers as List); + final startDate = + DateTime.parse(events!.startDate ?? DateTime.now().toString()); final date = DateFormat.yMd().format(startDate); final time = DateFormat.Hm().format(startDate); - final endDate = DateTime.parse(events["end_date"]); + final endDate = + DateTime.parse(events!.endDate ?? DateTime.now().toString()); final dateE = DateFormat.yMd().format(endDate); final timeE = DateFormat.Hm().format(endDate); - if (events["imgUrl"] != null) { - formerImage = events["imgUrl"]; + if (events!.imgUrl != null) { + formerImage = events!.imgUrl ?? ""; } formerDate = "${date} ${time} à ${dateE} ${timeE}"; @@ -404,9 +408,7 @@ class _ItemMenuState extends State with ShowErrorDialog { onPressed: () { Navigator.push( context, - MaterialPageRoute( - builder: (_) => - EditEvent(id: id, tags: tags, organizers: organizers)), + MaterialPageRoute(builder: (_) => EditEvent(events: events)), ); }, backgroundColor: Colors.blue, From 63f6bd2af21bd2ee281fcd0ceb144b31fc09add1 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sat, 14 Dec 2024 00:34:08 +0100 Subject: [PATCH 8/8] edit event without edit image --- covas_mobile/lib/pages/EditEvent.dart | 186 ++++++++++---------------- 1 file changed, 71 insertions(+), 115 deletions(-) diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart index 85adc11..1f38d90 100644 --- a/covas_mobile/lib/pages/EditEvent.dart +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -154,12 +154,13 @@ class _EditEventState extends State List.from(_stringOrgaController.getTags as List); var startDateFormat = formatDate(startDatepicker.text); - DateTime startDateCompare = DateTime.parse(startDateFormat); + //DateTime startDateCompare = DateTime.parse(startDateFormat); DateTime dateNow = DateTime.now(); var endDateFormat = formatDate(endDatepicker.text); var startDate = "${startDateFormat}T${startTimepicker.text.replaceAll('-', ':')}"; var endDate = "${endDateFormat}T${endTimepicker.text.replaceAll('-', ':')}"; + DateTime startDateCompare = DateTime.parse(startDate); if (startDateCompare.isAfter(dateNow)) { SharedPreferences prefs = await SharedPreferences.getInstance(); var accessToken = prefs.getString("access_token") ?? ""; @@ -186,131 +187,86 @@ class _EditEventState extends State final longitude = coordinates[0]; // Longitude final latitude = coordinates[1]; // Latitude var urlGet = Uri.parse( - "${globals.api}/events/search?item=${name}&date_event=${startDate}"); + "${globals.api}/events/search?item=${name}&date_event=${startDate}&min_lat=$latitude&max_lat=$latitude" + "&min_lon=$longitude&max_lon=$longitude"); var responseGet = await http.get(urlGet, headers: { HttpHeaders.cookieHeader: 'access_token=${accessToken}' }); if (responseGet.statusCode == 200) { var events = jsonDecode(utf8.decode(responseGet.bodyBytes)); - print("reponse http : ${events.length}"); - if (events.length == 0) { - urlGet = Uri.parse( - "${globals.api}/events/search?min_lat=$latitude&max_lat=$latitude" - "&min_lon=$longitude&max_lon=$longitude&date_event=${startDate}"); - responseGet = await http.get(urlGet, headers: { - HttpHeaders.cookieHeader: 'access_token=${accessToken}' - }); - if (responseGet.statusCode == 200) { - events = jsonDecode(utf8.decode(responseGet.bodyBytes)); - print("reponse http : ${events.length}"); - if (events.length != 0) { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => - ItemMenu(title: events[0]["id"]))); - return; - } - } - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => ItemMenu(title: events[0]["id"]))); + if (events.length > 0) { + showErrorDialog(context, "Evenement deja existant"); + return; } } - final params = { - 'expiration': '15552000', - 'key': dotenv.env["IMGBB_API_KEY"], - }; - print("Post Img"); - final urlPost = Uri.parse('https://api.imgbb.com/1/upload') - .replace(queryParameters: params); - - final req = http.MultipartRequest('POST', urlPost); - - final stream = await req.send(); - final res = await http.Response.fromStream(stream); - - final status = res.statusCode; - print("code status imgbb ${status}"); - if (status == 200) { - var body = json.decode(utf8.decode(res.bodyBytes)); - String imgUrl = body["data"]["url"]; - - //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, - 'organizers': organizers, - 'latitude': latitude, - 'longitude': longitude, - 'description': description, - "imgUrl": imgUrl, - "tags": tags - })); - 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); - } + var urlPut = + Uri.parse("${globals.api}/events/${widget.events!.id}"); + 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, + 'organizers': organizers, + 'latitude': latitude, + 'longitude': longitude, + 'description': description, + "imgUrl": imgUrl, + "tags": tags + })); + print(responsePut.statusCode); + if ((responsePut.statusCode == 200) || + (responsePut.statusCode == 201)) { + showEventDialog(context, "Evenement ${name} modifie"); } else { - print("imgbb error : ${status}"); + 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); } } else { showErrorDialog(context, "Aucune donnée geographique");