diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart index 8beb2e5..69d7691 100644 --- a/covas_mobile/lib/pages/EditEvent.dart +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -22,7 +22,12 @@ import '../classes/eventAdded.dart'; import '../variable/globals.dart' as globals; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -54,6 +59,7 @@ class EditEvent extends StatefulWidget { class _EditEventState extends State with ShowAlertDialog, ShowEventDialog { + BannerAd? _bannerAd; TextEditingController inputName = TextEditingController(); TextEditingController inputDate = TextEditingController(); @@ -159,177 +165,161 @@ class _EditEventState extends State } 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('-', ':')}"; - DateTime startDateCompare = DateTime.parse(startDate); - if (startDateCompare.isAfter(dateNow)) { - SharedPreferences prefs = await SharedPreferences.getInstance(); - var accessToken = prefs.getString("access_token") ?? ""; - - if (accessToken.isNotEmpty) { - try { - await dotenv.load(); - final ApiTokenGoogle = dotenv.env['PLACE_API_KEY'] ?? ''; - // Searchbox API for geocoding the place (No session token) - final searchboxUrl = Uri.parse( - 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=${place}&key=${ApiTokenGoogle}'); - - // Perform the request - final searchboxResponse = await http.get(searchboxUrl); - - if (searchboxResponse.statusCode == 200) { - final data = json.decode(searchboxResponse.body); - print("data : ${data}"); - - if (data['results'].isNotEmpty) { - place = data['results'][0]['formatted_address']; - final coordinates = data['results'][0]['geometry']['location']; - final longitude = coordinates["lng"]; // Longitude - final latitude = coordinates["lat"]; // Latitude - var urlGet = Uri.parse( - "${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)); - if (events.length > 0) { - if (events[0]["id"] != widget.events!.id) { - showAlertDialog( - context, "Info evenement", "Evenement deja existant"); - } - - return; - } - } - - if (widget.imgPath.isNotEmpty) { - 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); - File image = File(widget.imgPath); - Uint8List _bytes = await image.readAsBytes(); - String _base64String = base64.encode(_bytes); - - final req = http.MultipartRequest('POST', urlPost) - ..fields['image'] = _base64String; - - final stream = await req.send(); - final res = await http.Response.fromStream(stream); - - final status = res.statusCode; - print("code status imgbb ${status}"); - if (status != 200) { - showAlertDialog(context, "Erreur image", "Image non posté"); - return; - } - var body = json.decode(utf8.decode(res.bodyBytes)); - imgUrl = body["data"]["url"]; - } - 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 { - 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; - } - showAlertDialog(context, "Erreur serveur", text); - } - } else { - showAlertDialog( - context, "Erreur serveur", "Aucune donnée geographique"); - } - } else { - showAlertDialog(context, "Erreur serveur", "Mapbox non accessible"); - } - } catch (e) { - showAlertDialog(context, "Erreur serveur", "${e}"); - } - } else { - showAlertDialog(context, "Erreur utilisateur", "Champ vide"); - } - } else { - showAlertDialog(context, "Erreur evenement", "Evenement non futur"); + if (!_isEventInFuture()) { + _showErrorDialog(context, "Erreur evenement", "Evenement non futur"); + return; } + + final accessToken = await _getAccessToken(); + if (accessToken.isEmpty) { + _showErrorDialog(context, "Erreur utilisateur", "Champ vide"); + return; + } + + try { + await dotenv.load(); + final geolocation = await _fetchGeolocation(); + if (geolocation == null) { + _showErrorDialog( + context, "Erreur serveur", "Aucune donnée geographique"); + return; + } + + if (await _isDuplicateEvent(accessToken, geolocation)) { + _showErrorDialog(context, "Info evenement", "Evenement deja existant"); + return; + } + + if (widget.imgPath.isNotEmpty) { + imgUrl = await _uploadImage(widget.imgPath); + if (imgUrl.isEmpty) { + _showErrorDialog(context, "Erreur image", "Image non postée"); + return; + } + } + + await _updateEventData(accessToken, geolocation); + showEventDialog(context, "Evenement ${inputName.text} modifie"); + } catch (e) { + _showErrorDialog(context, "Erreur serveur", "$e"); + } + } + + bool _isEventInFuture() { + DateTime startDateCompare = DateTime.parse( + "${formatDate(startDatepicker.text)}T${startTimepicker.text.replaceAll('-', ':')}"); + return startDateCompare.isAfter(DateTime.now()); + } + + Future _getAccessToken() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString("access_token") ?? ""; + } + + Future?> _fetchGeolocation() async { + final apiKey = dotenv.env['PLACE_API_KEY'] ?? ''; + final response = await http.get(Uri.parse( + 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=${inputGeo.text}&key=$apiKey')); + + if (response.statusCode == 200) { + final data = json.decode(response.body); + if (data['results'].isNotEmpty) { + return data['results'][0]['geometry']['location']; + } + } + return null; + } + + Future _isDuplicateEvent( + String accessToken, Map location) async { + final url = Uri.parse( + "${globals.api}/events/search?item=${inputName.text}&date_event=${formatDate(startDatepicker.text)}" + "&min_lat=${location['lat']}&max_lat=${location['lat']}" + "&min_lon=${location['lng']}&max_lon=${location['lng']}"); + + final response = await http.get(url, + headers: {HttpHeaders.cookieHeader: 'access_token=$accessToken'}); + + if (response.statusCode == 200) { + final events = jsonDecode(utf8.decode(response.bodyBytes)); + return events.isNotEmpty && events[0]["id"] != widget.events!.id; + } + return false; + } + + Future _uploadImage(String imagePath) async { + final params = { + 'expiration': '15552000', + 'key': dotenv.env["IMGBB_API_KEY"] + }; + final url = Uri.parse('https://api.imgbb.com/1/upload') + .replace(queryParameters: params); + + final image = File(imagePath); + final req = http.MultipartRequest('POST', url) + ..fields['image'] = base64.encode(await image.readAsBytes()); + + final response = await http.Response.fromStream(await req.send()); + return response.statusCode == 200 + ? json.decode(response.body)["data"]["url"] + : ""; + } + + Future _updateEventData( + String accessToken, Map location) async { + final url = Uri.parse("${globals.api}/events/${widget.events!.id}"); + final response = await http.put(url, + headers: { + HttpHeaders.cookieHeader: 'access_token=$accessToken', + HttpHeaders.acceptHeader: 'application/json, text/plain, */*', + HttpHeaders.contentTypeHeader: 'application/json' + }, + body: jsonEncode({ + 'name': inputName.text, + 'place': inputGeo.text, + 'start_date': + "${formatDate(startDatepicker.text)}T${startTimepicker.text.replaceAll('-', ':')}", + 'end_date': + "${formatDate(endDatepicker.text)}T${endTimepicker.text.replaceAll('-', ':')}", + 'organizers': + List.from(_stringOrgaController.getTags as List), + 'latitude': location['lat'], + 'longitude': location['lng'], + 'description': inputDesc.text, + "imgUrl": imgUrl, + "tags": List.from(_stringTagController.getTags as List) + })); + + if (response.statusCode != 200 && response.statusCode != 201) { + _handleErrorResponse(context, response.statusCode); + } + } + + void _handleErrorResponse(BuildContext context, int statusCode) { + final messages = { + 400: "Requête mal construite", + 406: "Mot de passe incorrect", + 404: "Utilisateur inconnu", + 403: "Utilisateur désactivé", + 410: "Token invalide", + 500: "Problème interne du serveur" + }; + _showErrorDialog(context, "Erreur serveur", + messages[statusCode] ?? "Problème d'authentification inconnu"); + } + + void _showErrorDialog(BuildContext context, String title, String message) { + showAlertDialog(context, title, message); } @override void initState() { + super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); inputName.text = widget.events!.name ?? ""; startDatepicker.text = DateFormat("dd/MM/yyyy") .format(DateTime.parse( @@ -353,7 +343,6 @@ class _EditEventState extends State inputDesc.text = widget.events!.description ?? ""; initialTags = List.from(widget.events!.tags as List); initialOrga = List.from(widget.events!.organizers as List); - super.initState(); } final _formKey = GlobalKey(); @@ -467,7 +456,6 @@ class _EditEventState extends State return Scaffold( backgroundColor: Colors.white, drawer: MyDrawer(), - appBar: AppBar( title: Text("Add or Update a event"), backgroundColor: Colors.blue, @@ -478,6 +466,12 @@ class _EditEventState extends State child: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), if (widget.imgPath.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 60.0), diff --git a/covas_mobile/lib/pages/EditProfile.dart b/covas_mobile/lib/pages/EditProfile.dart index 805c5b7..50a9aee 100644 --- a/covas_mobile/lib/pages/EditProfile.dart +++ b/covas_mobile/lib/pages/EditProfile.dart @@ -15,7 +15,12 @@ import '../classes/eventAdded.dart'; import '../variable/globals.dart' as globals; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -38,6 +43,7 @@ class EditProfile extends StatefulWidget { class _EditProfileState extends State with ShowAlertDialog, ShowEventDialog { + BannerAd? _bannerAd; TextEditingController inputUserName = TextEditingController(); TextEditingController inputName = TextEditingController(); @@ -192,6 +198,11 @@ class _EditProfileState extends State @override void initState() { super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); _getInfoProfile(); } @@ -215,6 +226,12 @@ class _EditProfileState extends State child: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), Padding( padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15, bottom: 0), diff --git a/covas_mobile/lib/pages/EditSettings.dart b/covas_mobile/lib/pages/EditSettings.dart index e9c25ce..c79e6c2 100644 --- a/covas_mobile/lib/pages/EditSettings.dart +++ b/covas_mobile/lib/pages/EditSettings.dart @@ -10,7 +10,12 @@ import '../classes/MyDrawer.dart'; import '../classes/alert.dart'; import '../classes/eventAdded.dart'; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -33,6 +38,7 @@ class EditSettings extends StatefulWidget { class _EditProfileState extends State with ShowAlertDialog, ShowEventDialog { + BannerAd? _bannerAd; TextEditingController inputUserName = TextEditingController(); int? kilometer; @@ -54,6 +60,11 @@ class _EditProfileState extends State @override void initState() { super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); getParameter(); } @@ -71,6 +82,12 @@ class _EditProfileState extends State child: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), Padding( padding: const EdgeInsets.only( left: 15.0,