17 Commits

Author SHA1 Message Date
8a7515aaf6 add list in listitem 2025-08-26 20:34:01 +02:00
f9934a0d5d debug ok 2025-08-26 20:29:55 +02:00
09c82da57f add notification test 2025-08-25 23:41:54 +02:00
75b42dd091 Merge pull request 'feature/event-interested' (#48) from feature/event-interested into main
Reviewed-on: #48
2025-08-20 21:40:43 +00:00
dfe21960be add toggle interested in list organizer and tag 2025-08-20 23:39:20 +02:00
4a936cc267 change for heart and and count interested people 2025-08-20 23:22:25 +02:00
bd5bfa94ca remove print debug 2025-08-20 22:49:51 +02:00
f30aa8f630 togleInterested debug 2025-08-19 21:09:44 +02:00
924794e8a0 ad toogle interested method 2025-08-19 00:11:40 +02:00
7528e55dca add button star 2025-08-17 17:42:02 +02:00
02ba067615 Merge pull request 'feature/link' (#47) from feature/link into main
Reviewed-on: #47
2025-08-15 21:19:14 +00:00
9eafb30374 add link and ticket backend side 2025-08-15 23:05:53 +02:00
24cb90959d fix edit event 2025-08-15 17:14:53 +02:00
1620d84137 add link and ticket inàut 2025-08-15 00:29:48 +02:00
6e8ba642a2 add link and ticket 2025-08-12 23:33:15 +02:00
0113fcc382 add Link 2025-08-12 22:30:12 +02:00
e4571cabe7 Merge pull request 'feature/internationale' (#46) from feature/internationale into main
Reviewed-on: #46
2025-08-06 20:38:36 +00:00
14 changed files with 448 additions and 17 deletions

View File

@@ -5,11 +5,15 @@ class Events {
String? startDate; String? startDate;
String? endDate; String? endDate;
String? description; String? description;
String? link;
String? ticket;
double? latitude; double? latitude;
double? longitude; double? longitude;
List<String>? tags; List<String>? tags;
List<String>? organizers; List<String>? organizers;
String? imgUrl; String? imgUrl;
int? interestedCount;
bool? interested;
Events( Events(
{this.place, {this.place,
this.id, this.id,
@@ -21,7 +25,11 @@ class Events {
this.latitude, this.latitude,
this.longitude, this.longitude,
this.organizers, this.organizers,
this.imgUrl}); this.link,
this.ticket,
this.imgUrl,
this.interestedCount,
this.interested});
Events.fromJson(Map<String, dynamic> json) { Events.fromJson(Map<String, dynamic> json) {
id = json['id'] as String?; id = json['id'] as String?;
@@ -38,5 +46,9 @@ class Events {
organizers = (json['organizers'] as List<dynamic>?) organizers = (json['organizers'] as List<dynamic>?)
?.cast<String>(); // Convert List<dynamic> to List<String> ?.cast<String>(); // Convert List<dynamic> to List<String>
imgUrl = json['imgUrl'] as String?; imgUrl = json['imgUrl'] as String?;
link = json['link'] as String?;
ticket = json['ticket'] as String?;
interested = json['interested'] as bool?;
interestedCount = json['interested_count'] as int?;
} }
} }

View File

@@ -0,0 +1,82 @@
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest_all.dart' as tz;
class NotificationService {
static final FlutterLocalNotificationsPlugin _notificationsPlugin =
FlutterLocalNotificationsPlugin();
/// Initialisation (à appeler dans main())
static Future<void> initialize() async {
tz.initializeTimeZones();
const AndroidInitializationSettings androidInitSettings =
AndroidInitializationSettings('@mipmap/ic_launcher');
const InitializationSettings initSettings = InitializationSettings(
android: androidInitSettings,
iOS: DarwinInitializationSettings(),
);
await _notificationsPlugin.initialize(initSettings);
}
/// Planifie une notification 1h avant lévènement
static Future<void> scheduleEventNotification({
required String eventId,
required String title,
required String body,
required DateTime eventDate,
}) async {
final scheduledDate = eventDate.subtract(const Duration(hours: 1));
if (scheduledDate.isBefore(DateTime.now())) {
// Trop tard pour notifier
return;
}
await _notificationsPlugin.zonedSchedule(
eventId.hashCode, // identifiant unique pour lévènement
title,
body,
tz.TZDateTime.from(scheduledDate, tz.local),
const NotificationDetails(
android: AndroidNotificationDetails(
'events_channel', // id du canal
'Évènements', // nom du canal
channelDescription: 'Notifications des évènements favoris',
importance: Importance.high,
priority: Priority.high,
),
iOS: DarwinNotificationDetails(),
),
androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
matchDateTimeComponents: DateTimeComponents.dateAndTime,
);
}
static Future<void> showTestNotification() async {
await _notificationsPlugin.show(
0, // id arbitraire
"Test Notification",
"Ceci est une notification de debug",
const NotificationDetails(
android: AndroidNotificationDetails(
'debug_channel',
'Debug Notifications',
channelDescription: 'Notifications de test pour debug',
importance: Importance.max,
priority: Priority.high,
),
iOS: DarwinNotificationDetails(),
),
);
}
/// Annule une notification planifiée
static Future<void> cancel(String eventId) async {
await _notificationsPlugin.cancel(eventId.hashCode);
}
}

View File

@@ -130,5 +130,14 @@
"unknown_error": "Unbekannter Fehler", "unknown_error": "Unbekannter Fehler",
"app_error": "Anwendungsfehler", "app_error": "Anwendungsfehler",
"at": "um", "at": "um",
"to_date": "bis" "to_date": "bis",
"item_link": "Link : ",
"item_ticket": "Abendkarte : ",
"link": "Link",
"edit_link": "Linkereignis bearbeiten",
"ticket": "Abendkarte",
"edit_ticket": "Ticketlink bearbeiten",
"toogle_interest": "Fehler beim Umschalten des Interesses",
"error_update": "Fehler beim Update",
"count_interested": "Anzahl der Interessenten"
} }

View File

@@ -132,5 +132,14 @@
"unknown_error": "Unknown error", "unknown_error": "Unknown error",
"app_error": "Application error", "app_error": "Application error",
"at": "at", "at": "at",
"to_date": "to" "to_date": "to",
"item_link": "Link : ",
"item_ticket": "Ticket : ",
"link": "Link",
"edit_link": "Edit link name",
"ticket": "Ticket",
"edit_ticket": "Edit ticket link",
"toogle_interest": "Error toggle interest",
"error_update": "Error when updating",
"count_interested": "Interested people number"
} }

View File

@@ -132,6 +132,15 @@
"unknown_error": "Erreur inconnue", "unknown_error": "Erreur inconnue",
"app_error": "Erreur d'application", "app_error": "Erreur d'application",
"at": "à", "at": "à",
"to_date": "jusqu'à" "to_date": "jusqu'à",
"item_link": "Lien : ",
"item_ticket": "Billet : ",
"link": "Lien",
"edit_link": "Editer le lien",
"ticket": "Billet",
"edit_ticket": "Editer le lien du billet",
"toogle_interest": "Erreur de bouton de changement",
"error_update": "Erreur lors de la mise à jour",
"count_interested": "Nombre de personne interessé"
} }

View File

@@ -5,10 +5,12 @@ import 'package:provider/provider.dart';
import 'pages/LoginDemo.dart'; import 'pages/LoginDemo.dart';
import 'locale_provider.dart'; // <-- à adapter selon ton arborescence import 'locale_provider.dart'; // <-- à adapter selon ton arborescence
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'classes/notification_service.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await MobileAds.instance.initialize(); await MobileAds.instance.initialize();
await NotificationService.initialize();
runApp( runApp(
ChangeNotifierProvider( ChangeNotifierProvider(

View File

@@ -66,6 +66,8 @@ class _EditEventState extends State<EditEvent>
TextEditingController inputName = TextEditingController(); TextEditingController inputName = TextEditingController();
TextEditingController inputTicket = TextEditingController();
TextEditingController inputLink = TextEditingController();
TextEditingController inputDate = TextEditingController(); TextEditingController inputDate = TextEditingController();
TextEditingController inputDesc = TextEditingController(); TextEditingController inputDesc = TextEditingController();
@@ -311,6 +313,8 @@ class _EditEventState extends State<EditEvent>
'longitude': location['lng'], 'longitude': location['lng'],
'description': inputDesc.text, 'description': inputDesc.text,
"imgUrl": imgUrl, "imgUrl": imgUrl,
'link': inputLink.text,
'ticket': inputTicket.text,
"tags": List<String>.from(_stringTagController.getTags as List) "tags": List<String>.from(_stringTagController.getTags as List)
})); }));
@@ -354,6 +358,8 @@ class _EditEventState extends State<EditEvent>
}); });
}); });
inputName.text = widget.events!.name ?? ""; inputName.text = widget.events!.name ?? "";
inputTicket.text = widget.events!.ticket ?? "";
inputLink.text = widget.events!.link ?? "";
startDatepicker.text = DateFormat("dd/MM/yyyy") startDatepicker.text = DateFormat("dd/MM/yyyy")
.format(DateTime.parse( .format(DateTime.parse(
widget.events!.startDate ?? DateTime.now().toString())) widget.events!.startDate ?? DateTime.now().toString()))
@@ -641,6 +647,35 @@ class _EditEventState extends State<EditEvent>
onTap: () => onTapFunctionTimePicker( onTap: () => onTapFunctionTimePicker(
context: context, position: "end")), context: context, position: "end")),
), ),
Padding(
//padding: const EdgeInsets.only(left:15.0,right: 15.0,top:0,bottom: 0),
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
child: TextFormField(
controller: inputLink,
validator: (value) => _validateField(value),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: AppLocalizations.of(context)?.link ?? "Link",
hintText: AppLocalizations.of(context)?.edit_link ??
"Edit link event"),
),
),
Padding(
//padding: const EdgeInsets.only(left:15.0,right: 15.0,top:0,bottom: 0),
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
child: TextFormField(
controller: inputTicket,
validator: (value) => _validateField(value),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText:
AppLocalizations.of(context)?.ticket ?? "Ticket",
hintText: AppLocalizations.of(context)?.edit_ticket ??
"Edit ticket link"),
),
),
TextFieldTags<String>( TextFieldTags<String>(
textfieldTagsController: _stringTagController, textfieldTagsController: _stringTagController,
initialTags: initialTags, initialTags: initialTags,

View File

@@ -87,6 +87,8 @@ class _ItemMenuState extends State<ItemMenu> with ShowAlertDialog {
String eventName = ""; String eventName = "";
String eventStartDate = ""; String eventStartDate = "";
String eventDescription = ""; String eventDescription = "";
String eventTicket = "";
String eventLink = "";
String place = ""; String place = "";
String imgUrl = ""; String imgUrl = "";
List<String> tags = []; List<String> tags = [];
@@ -128,17 +130,17 @@ class _ItemMenuState extends State<ItemMenu> with ShowAlertDialog {
if (responseGet.statusCode == 200) { if (responseGet.statusCode == 200) {
final responseBody = utf8.decode(responseGet.bodyBytes); final responseBody = utf8.decode(responseGet.bodyBytes);
final event = Events.fromJson(jsonDecode(responseBody)); events = Events.fromJson(jsonDecode(responseBody));
final locale = Provider.of<LocaleProvider>(context, listen: false) final locale = Provider.of<LocaleProvider>(context, listen: false)
.locale .locale
?.toString() ?? ?.toString() ??
'en_US'; 'en_US';
final startDate = final startDate =
DateTime.parse(event.startDate ?? DateTime.now().toString()); DateTime.parse(events?.startDate ?? DateTime.now().toString());
//final date = DateFormat.yMd().format(startDate); //final date = DateFormat.yMd().format(startDate);
//final time = DateFormat.Hm().format(startDate); //final time = DateFormat.Hm().format(startDate);
final endDate = final endDate =
DateTime.parse(event.endDate ?? DateTime.now().toString()); DateTime.parse(events?.endDate ?? DateTime.now().toString());
String separator = AppLocalizations.of(context)?.at ?? "at"; String separator = AppLocalizations.of(context)?.at ?? "at";
final formattedStartDate = final formattedStartDate =
DateFormat("EEEE d MMMM y '${separator}' HH:mm", locale) DateFormat("EEEE d MMMM y '${separator}' HH:mm", locale)
@@ -151,14 +153,16 @@ class _ItemMenuState extends State<ItemMenu> with ShowAlertDialog {
String link = AppLocalizations.of(context)?.to_date ?? "to"; String link = AppLocalizations.of(context)?.to_date ?? "to";
setState(() { setState(() {
eventName = event.name ?? ""; eventName = events?.name ?? "";
eventStartDate = "$formattedStartDate ${link} $formattedEndDate"; eventStartDate = "$formattedStartDate ${link} $formattedEndDate";
organizers = List<String>.from(event.organizers ?? []); organizers = List<String>.from(events?.organizers ?? []);
place = event.place ?? ""; place = events?.place ?? "";
imgUrl = event.imgUrl ?? ""; imgUrl = events?.imgUrl ?? "";
eventDescription = event.description ?? ""; eventLink = events?.link ?? "";
tags = List<String>.from(event.tags ?? []); eventTicket = events?.ticket ?? "";
eventDescription = events?.description ?? "";
tags = List<String>.from(events?.tags ?? []);
}); });
} else { } else {
final messages = { final messages = {
@@ -276,6 +280,34 @@ class _ItemMenuState extends State<ItemMenu> with ShowAlertDialog {
maxLines: 3, maxLines: 3,
overflow: TextOverflow.ellipsis))) overflow: TextOverflow.ellipsis)))
]), ]),
Row(children: [
Icon(Icons.link),
Text(
AppLocalizations.of(context)?.item_link ?? "Link : ",
style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold),
)
]),
Row(
children: [
Flexible(
child:
Text("${eventLink}", style: TextStyle(fontSize: 15.0)))
],
),
Row(children: [
Icon(Icons.add_shopping_cart),
Text(
AppLocalizations.of(context)?.item_ticket ?? "Ticket : ",
style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold),
)
]),
Row(
children: [
Flexible(
child: Text("${eventTicket}",
style: TextStyle(fontSize: 15.0)))
],
),
Row(children: [ Row(children: [
Icon(Icons.group), Icon(Icons.group),
Text( Text(

View File

@@ -18,6 +18,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../locale_provider.dart'; // import '../locale_provider.dart'; //
import '../classes/notification_service.dart';
// app starting point // app starting point
void main() async { void main() async {
@@ -94,6 +95,30 @@ class _MyHomePageState extends State<ListItemOrganizers> {
}); });
} }
Future<Map<String, dynamic>> toggleInterested(String eventId) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var accessToken = prefs.getString("access_token") ?? "";
final url = Uri.parse("${globals.api}/events/${eventId}/interest");
if (accessToken.isNotEmpty) {
final response = await http.post(
url,
headers: {
"Content-Type": "application/json",
HttpHeaders.cookieHeader: "access_token=$accessToken"
},
);
if (response.statusCode != 200) {
throw (AppLocalizations.of(context)?.toogle_interest ??
"Error toogle interest: ${response.statusCode}");
}
var event = json.decode(response.body);
return event;
}
return {"interested": false, "interested_count": 0};
}
// variable to call and store future list of posts // variable to call and store future list of posts
// function to fetch data from api and return future list of posts // function to fetch data from api and return future list of posts
@@ -190,10 +215,50 @@ class _MyHomePageState extends State<ListItemOrganizers> {
final dateLongue = final dateLongue =
DateFormat('EEEE d MMMM y', locale).format(startDate); DateFormat('EEEE d MMMM y', locale).format(startDate);
final countInterestedString =
AppLocalizations.of(context)?.count_interested ??
"Interested people number";
final countInterested =
"${countInterestedString} : ${post.interestedCount}";
return ListTile( return ListTile(
title: Text('${post.name!}'), title: Text('${post.name!}'),
subtitle: Text('${post.place!}\n${dateLongue}'), subtitle:
Text('${post.place!}\n${dateLongue}\n${countInterested}'),
trailing: IconButton(
onPressed: () async {
try {
final result = await toggleInterested(post.id!);
setState(() {
post.interested = result["interested"];
post.interestedCount = result["interested_count"];
});
if (result["interested"] == true) {
NotificationService.scheduleEventNotification(
eventId: post.id!,
title: "Rappel évènement",
body:
"Ton évènement '${post.name}' commence dans 1 heure !",
eventDate: DateTime.parse(post.startDate!),
);
} else {
NotificationService.cancel(post.id!);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context)?.error_update ??
"Error when updating")),
);
}
},
icon: Icon(
post.interested ?? false
? Icons.favorite
: Icons.favorite_border,
color:
post.interested ?? false ? Colors.red : Colors.grey)),
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,

View File

@@ -19,6 +19,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../locale_provider.dart'; // import '../locale_provider.dart'; //
import '../classes/notification_service.dart';
// app starting point // app starting point
void main() async { void main() async {
@@ -121,6 +122,30 @@ class _MyHomePageState extends State<ListItemTags> {
return body; return body;
} }
Future<Map<String, dynamic>> toggleInterested(String eventId) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var accessToken = prefs.getString("access_token") ?? "";
final url = Uri.parse("${globals.api}/events/${eventId}/interest");
if (accessToken.isNotEmpty) {
final response = await http.post(
url,
headers: {
"Content-Type": "application/json",
HttpHeaders.cookieHeader: "access_token=$accessToken"
},
);
if (response.statusCode != 200) {
throw (AppLocalizations.of(context)?.toogle_interest ??
"Error toogle interest: ${response.statusCode}");
}
var event = json.decode(response.body);
return event;
}
return {"interested": false, "interested_count": 0};
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -168,6 +193,7 @@ class _MyHomePageState extends State<ListItemTags> {
Widget buildPosts(List<Events> posts) { Widget buildPosts(List<Events> posts) {
// ListView Builder to show data in a list // ListView Builder to show data in a list
String tag = AppLocalizations.of(context)?.item_tags ?? "Tags : "; String tag = AppLocalizations.of(context)?.item_tags ?? "Tags : ";
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by // Here we take the value from the MyHomePage object that was created by
@@ -191,9 +217,50 @@ class _MyHomePageState extends State<ListItemTags> {
final dateLongue = final dateLongue =
DateFormat('EEEE d MMMM y', locale).format(startDate); DateFormat('EEEE d MMMM y', locale).format(startDate);
final countInterestedString =
AppLocalizations.of(context)?.count_interested ??
"Interested people number";
final countInterested =
"${countInterestedString} : ${post.interestedCount}";
return ListTile( return ListTile(
title: Text('${post.name!}'), title: Text('${post.name!}'),
subtitle: Text('${post.place!}\n${dateLongue}'), subtitle:
Text('${post.place!}\n${dateLongue}\n${countInterested}'),
trailing: IconButton(
onPressed: () async {
try {
final result = await toggleInterested(post.id!);
setState(() {
post.interested = result["interested"];
post.interestedCount = result["interested_count"];
});
if (result["interested"] == true) {
NotificationService.scheduleEventNotification(
eventId: post.id!,
title: "Rappel évènement",
body:
"Ton évènement '${post.name}' commence dans 1 heure !",
eventDate: DateTime.parse(post.startDate!),
);
} else {
NotificationService.cancel(post.id!);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context)?.error_update ??
"Error when updating")),
);
}
},
icon: Icon(
post.interested ?? false
? Icons.favorite
: Icons.favorite_border,
color:
post.interested ?? false ? Colors.red : Colors.grey)),
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,

View File

@@ -23,6 +23,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../locale_provider.dart'; // Créé plus loin import '../locale_provider.dart'; // Créé plus loin
import '../classes/notification_service.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@@ -423,7 +424,7 @@ class _MyHomePageState extends State<ListItemMenu> {
var url = await getUrlForEvents(); var url = await getUrlForEvents();
final response = await http.get(url, headers: { final response = await http.get(url, headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
HttpHeaders.cookieHeader: "acce0ss_token=$accessToken" HttpHeaders.cookieHeader: "access_token=$accessToken"
}); });
if (response.statusCode == 200) { if (response.statusCode == 200) {
@@ -469,6 +470,30 @@ class _MyHomePageState extends State<ListItemMenu> {
} }
} }
Future<Map<String, dynamic>> toggleInterested(String eventId) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var accessToken = prefs.getString("access_token") ?? "";
final url = Uri.parse("${globals.api}/events/${eventId}/interest");
if (accessToken.isNotEmpty) {
final response = await http.post(
url,
headers: {
"Content-Type": "application/json",
HttpHeaders.cookieHeader: "access_token=$accessToken"
},
);
if (response.statusCode != 200) {
throw (AppLocalizations.of(context)?.toogle_interest ??
"Error toogle interest: ${response.statusCode}");
}
var event = json.decode(response.body);
return event;
}
return {"interested": false, "interested_count": 0};
}
Future<void> fetchPostsByLocation() async { Future<void> fetchPostsByLocation() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
var accessToken = prefs.getString("access_token") ?? ""; var accessToken = prefs.getString("access_token") ?? "";
@@ -871,9 +896,49 @@ class _MyHomePageState extends State<ListItemMenu> {
'en_US'; 'en_US';
final dateLongue = final dateLongue =
DateFormat('EEEE d MMMM y', locale).format(startDate); DateFormat('EEEE d MMMM y', locale).format(startDate);
final countInterestedString =
AppLocalizations.of(context)?.count_interested ??
"Interested people number";
final countInterested =
"${countInterestedString} : ${post.interestedCount}";
return ListTile( return ListTile(
title: Text('${post.name!}'), title: Text('${post.name!}'),
subtitle: Text('${post.place!}\n${dateLongue}'), subtitle: Text('${post.place!}\n${dateLongue}\n${countInterested}'),
trailing: IconButton(
onPressed: () async {
try {
final result = await toggleInterested(post.id!);
setState(() {
post.interested = result["interested"];
post.interestedCount = result["interested_count"];
});
if (result["interested"] == true) {
NotificationService.scheduleEventNotification(
eventId: post.id!,
title: "Rappel évènement",
body:
"Ton évènement '${post.name}' commence dans 1 heure !",
eventDate: DateTime.parse(post.startDate!),
);
} else {
NotificationService.cancel(post.id!);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context)?.error_update ??
"Error when updating")),
);
}
},
icon: Icon(
post.interested ?? false
? Icons.favorite
: Icons.favorite_border,
color:
post.interested ?? false ? Colors.red : Colors.grey)),
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,

View File

@@ -6,6 +6,7 @@ import FlutterMacOS
import Foundation import Foundation
import file_selector_macos import file_selector_macos
import flutter_local_notifications
import geolocator_apple import geolocator_apple
import path_provider_foundation import path_provider_foundation
import shared_preferences_foundation import shared_preferences_foundation
@@ -14,6 +15,7 @@ import webview_flutter_wkwebview
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))

View File

@@ -145,6 +145,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.0" version: "0.1.0"
dbus:
dependency: transitive
description:
name: dbus
sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c"
url: "https://pub.dev"
source: hosted
version: "0.7.11"
dio: dio:
dependency: transitive dependency: transitive
description: description:
@@ -270,6 +278,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "4.0.0"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
sha256: "674173fd3c9eda9d4c8528da2ce0ea69f161577495a9cc835a2a4ecd7eadeb35"
url: "https://pub.dev"
source: hosted
version: "17.2.4"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af
url: "https://pub.dev"
source: hosted
version: "4.0.1"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
name: flutter_local_notifications_platform_interface
sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66"
url: "https://pub.dev"
source: hosted
version: "7.2.0"
flutter_localizations: flutter_localizations:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@@ -850,6 +882,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
timezone:
dependency: "direct main"
description:
name: timezone
sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
url: "https://pub.dev"
source: hosted
version: "0.9.4"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:

View File

@@ -36,6 +36,8 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
flutter_local_notifications: ^17.2.0
timezone: ^0.9.4
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
http: ^1.2.1 http: ^1.2.1
shared_preferences: ^2.2.3 shared_preferences: ^2.2.3