Vue mobile add event OK
This commit is contained in:
@ -10,7 +10,7 @@ import 'package:em2rp/views/widgets/calendar_widgets/event_details.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/month_view.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/week_view.dart';
|
||||
import 'package:em2rp/views/pages/event_add_page.dart';
|
||||
import 'package:em2rp/views/event_add_page.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/mobile_calendar_view.dart';
|
||||
import 'package:em2rp/utils/colors.dart';
|
||||
|
||||
@ -40,23 +40,43 @@ class _CalendarPageState extends State<CalendarPage> {
|
||||
final events = eventProvider.events;
|
||||
if (events.isNotEmpty) {
|
||||
final now = DateTime.now();
|
||||
events.sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||
int closestIdx = 0;
|
||||
Duration minDiff = (events[0].startDateTime.difference(now)).abs();
|
||||
for (int i = 1; i < events.length; i++) {
|
||||
final diff = (events[i].startDateTime.difference(now)).abs();
|
||||
if (diff < minDiff) {
|
||||
minDiff = diff;
|
||||
closestIdx = i;
|
||||
// Pour mobile : sélectionner le premier événement du jour ou le prochain événement à venir
|
||||
final todayEvents = events
|
||||
.where((e) =>
|
||||
e.startDateTime.year == now.year &&
|
||||
e.startDateTime.month == now.month &&
|
||||
e.startDateTime.day == now.day)
|
||||
.toList()
|
||||
..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||
EventModel? selected;
|
||||
DateTime? selectedDay;
|
||||
int selectedEventIndex = 0;
|
||||
if (todayEvents.isNotEmpty) {
|
||||
selected = todayEvents[0];
|
||||
selectedDay = DateTime(now.year, now.month, now.day);
|
||||
} else {
|
||||
// Chercher le prochain événement à venir
|
||||
final futureEvents = events
|
||||
.where((e) => e.startDateTime.isAfter(now))
|
||||
.toList()
|
||||
..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||
if (futureEvents.isNotEmpty) {
|
||||
selected = futureEvents[0];
|
||||
selectedDay = DateTime(selected.startDateTime.year,
|
||||
selected.startDateTime.month, selected.startDateTime.day);
|
||||
} else {
|
||||
// Aucun événement à venir, prendre le plus proche dans le passé
|
||||
events.sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||
selected = events.last;
|
||||
selectedDay = DateTime(selected.startDateTime.year,
|
||||
selected.startDateTime.month, selected.startDateTime.day);
|
||||
}
|
||||
}
|
||||
final closestEvent = events[closestIdx];
|
||||
setState(() {
|
||||
_selectedDay = DateTime(closestEvent.startDateTime.year,
|
||||
closestEvent.startDateTime.month, closestEvent.startDateTime.day);
|
||||
_focusedDay = _selectedDay!;
|
||||
_selectedDay = selectedDay;
|
||||
_focusedDay = selectedDay!;
|
||||
_selectedEventIndex = 0;
|
||||
_selectedEvent = closestEvent;
|
||||
_selectedEvent = selected;
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -188,111 +208,221 @@ class _CalendarPageState extends State<CalendarPage> {
|
||||
? eventsForSelectedDay[_selectedEventIndex]
|
||||
: null;
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
// Calendrier + détails en dessous
|
||||
AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.easeInOut,
|
||||
top: _calendarCollapsed ? -600 : 0, // cache le calendrier en haut
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: _calendarCollapsed ? 0 : null,
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
children: [
|
||||
_buildMonthHeader(context),
|
||||
if (!_calendarCollapsed)
|
||||
MobileCalendarView(
|
||||
focusedDay: _focusedDay,
|
||||
selectedDay: _selectedDay,
|
||||
events: eventProvider.events,
|
||||
onDaySelected: (day) {
|
||||
final eventsForDay = eventProvider.events
|
||||
.where((e) =>
|
||||
e.startDateTime.year == day.year &&
|
||||
e.startDateTime.month == day.month &&
|
||||
e.startDateTime.day == day.day)
|
||||
.toList()
|
||||
..sort((a, b) =>
|
||||
a.startDateTime.compareTo(b.startDateTime));
|
||||
setState(() {
|
||||
_selectedDay = day;
|
||||
_calendarCollapsed = false;
|
||||
_selectedEventIndex = 0;
|
||||
_selectedEvent =
|
||||
eventsForDay.isNotEmpty ? eventsForDay[0] : null;
|
||||
});
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: hasEvents
|
||||
? EventDetails(
|
||||
event: eventsForSelectedDay[_selectedEventIndex],
|
||||
selectedDate: _selectedDay,
|
||||
events: eventsForSelectedDay.cast<EventModel>(),
|
||||
onSelectEvent: (event, date) {
|
||||
final idx = eventsForSelectedDay
|
||||
.indexWhere((e) => e.id == event.id);
|
||||
setState(() {
|
||||
_selectedEventIndex = idx >= 0 ? idx : 0;
|
||||
_selectedEvent = event;
|
||||
});
|
||||
},
|
||||
)
|
||||
: Center(
|
||||
child:
|
||||
Text('Aucun événement ne démarre à cette date')),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Vue détail (prend tout l'espace quand calendrier caché)
|
||||
if (_calendarCollapsed && _selectedDay != null)
|
||||
// GESTURE DETECTOR pour swipe vertical (plier/déplier) et horizontal (mois)
|
||||
return GestureDetector(
|
||||
onVerticalDragEnd: (details) {
|
||||
if (details.primaryVelocity != null) {
|
||||
if (details.primaryVelocity! < -200) {
|
||||
// Swipe vers le haut : plier
|
||||
setState(() {
|
||||
_calendarCollapsed = true;
|
||||
});
|
||||
} else if (details.primaryVelocity! > 200) {
|
||||
// Swipe vers le bas : déplier
|
||||
setState(() {
|
||||
_calendarCollapsed = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
onHorizontalDragEnd: (details) {
|
||||
if (details.primaryVelocity != null) {
|
||||
if (details.primaryVelocity! < -200) {
|
||||
// Swipe gauche : mois suivant
|
||||
setState(() {
|
||||
_focusedDay =
|
||||
DateTime(_focusedDay.year, _focusedDay.month + 1, 1);
|
||||
});
|
||||
} else if (details.primaryVelocity! > 200) {
|
||||
// Swipe droite : mois précédent
|
||||
setState(() {
|
||||
_focusedDay =
|
||||
DateTime(_focusedDay.year, _focusedDay.month - 1, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
// Calendrier + détails en dessous
|
||||
AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.easeInOut,
|
||||
top: _calendarCollapsed ? 0 : 600,
|
||||
top: _calendarCollapsed ? -600 : 0, // cache le calendrier en haut
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
height: _calendarCollapsed ? 0 : null,
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
children: [
|
||||
_buildMonthHeader(context),
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
if (currentEvent != null)
|
||||
EventDetails(
|
||||
event: currentEvent,
|
||||
selectedDate: _selectedDay,
|
||||
events: eventsForSelectedDay.cast<EventModel>(),
|
||||
onSelectEvent: (event, date) {
|
||||
final idx = eventsForSelectedDay
|
||||
.indexWhere((e) => e.id == event.id);
|
||||
setState(() {
|
||||
_selectedEventIndex = idx >= 0 ? idx : 0;
|
||||
_selectedEvent = event;
|
||||
});
|
||||
},
|
||||
),
|
||||
if (!hasEvents)
|
||||
Center(
|
||||
child:
|
||||
Text('Aucun événement ne démarre à cette date'),
|
||||
),
|
||||
],
|
||||
if (!_calendarCollapsed)
|
||||
// Ajout d'un GestureDetector pour swipe horizontal sur le calendrier
|
||||
GestureDetector(
|
||||
onHorizontalDragEnd: (details) {
|
||||
if (details.primaryVelocity != null) {
|
||||
if (details.primaryVelocity! < -200) {
|
||||
// Swipe gauche : mois suivant
|
||||
setState(() {
|
||||
_focusedDay = DateTime(
|
||||
_focusedDay.year, _focusedDay.month + 1, 1);
|
||||
});
|
||||
} else if (details.primaryVelocity! > 200) {
|
||||
// Swipe droite : mois précédent
|
||||
setState(() {
|
||||
_focusedDay = DateTime(
|
||||
_focusedDay.year, _focusedDay.month - 1, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
child: MobileCalendarView(
|
||||
focusedDay: _focusedDay,
|
||||
selectedDay: _selectedDay,
|
||||
events: eventProvider.events,
|
||||
onDaySelected: (day) {
|
||||
final eventsForDay = eventProvider.events
|
||||
.where((e) =>
|
||||
e.startDateTime.year == day.year &&
|
||||
e.startDateTime.month == day.month &&
|
||||
e.startDateTime.day == day.day)
|
||||
.toList()
|
||||
..sort((a, b) =>
|
||||
a.startDateTime.compareTo(b.startDateTime));
|
||||
setState(() {
|
||||
_selectedDay = day;
|
||||
_calendarCollapsed = false;
|
||||
_selectedEventIndex = 0;
|
||||
_selectedEvent = eventsForDay.isNotEmpty
|
||||
? eventsForDay[0]
|
||||
: null;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: hasEvents
|
||||
// Ajout d'un GestureDetector pour swipe horizontal sur le détail événement
|
||||
? GestureDetector(
|
||||
onHorizontalDragEnd: (details) {
|
||||
if (details.primaryVelocity != null) {
|
||||
if (details.primaryVelocity! < -200) {
|
||||
// Swipe gauche : événement suivant
|
||||
if (_selectedEventIndex <
|
||||
eventsForSelectedDay.length - 1) {
|
||||
setState(() {
|
||||
_selectedEventIndex++;
|
||||
_selectedEvent = eventsForSelectedDay[
|
||||
_selectedEventIndex];
|
||||
});
|
||||
}
|
||||
} else if (details.primaryVelocity! > 200) {
|
||||
// Swipe droite : événement précédent
|
||||
if (_selectedEventIndex > 0) {
|
||||
setState(() {
|
||||
_selectedEventIndex--;
|
||||
_selectedEvent = eventsForSelectedDay[
|
||||
_selectedEventIndex];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: EventDetails(
|
||||
event: eventsForSelectedDay[_selectedEventIndex],
|
||||
selectedDate: _selectedDay,
|
||||
events: eventsForSelectedDay.cast<EventModel>(),
|
||||
onSelectEvent: (event, date) {
|
||||
final idx = eventsForSelectedDay
|
||||
.indexWhere((e) => e.id == event.id);
|
||||
setState(() {
|
||||
_selectedEventIndex = idx >= 0 ? idx : 0;
|
||||
_selectedEvent = event;
|
||||
});
|
||||
},
|
||||
),
|
||||
)
|
||||
: Center(
|
||||
child: Text(
|
||||
'Aucun événement ne démarre à cette date')),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
// Vue détail (prend tout l'espace quand calendrier caché)
|
||||
if (_calendarCollapsed && _selectedDay != null)
|
||||
AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.easeInOut,
|
||||
top: _calendarCollapsed ? 0 : 600,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
children: [
|
||||
_buildMonthHeader(context),
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
if (currentEvent != null)
|
||||
// Ajout d'un GestureDetector pour swipe horizontal sur le détail événement
|
||||
GestureDetector(
|
||||
onHorizontalDragEnd: (details) {
|
||||
if (details.primaryVelocity != null) {
|
||||
if (details.primaryVelocity! < -200) {
|
||||
// Swipe gauche : événement suivant
|
||||
if (_selectedEventIndex <
|
||||
eventsForSelectedDay.length - 1) {
|
||||
setState(() {
|
||||
_selectedEventIndex++;
|
||||
_selectedEvent = eventsForSelectedDay[
|
||||
_selectedEventIndex];
|
||||
});
|
||||
}
|
||||
} else if (details.primaryVelocity! > 200) {
|
||||
// Swipe droite : événement précédent
|
||||
if (_selectedEventIndex > 0) {
|
||||
setState(() {
|
||||
_selectedEventIndex--;
|
||||
_selectedEvent = eventsForSelectedDay[
|
||||
_selectedEventIndex];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: EventDetails(
|
||||
event: currentEvent,
|
||||
selectedDate: _selectedDay,
|
||||
events: eventsForSelectedDay.cast<EventModel>(),
|
||||
onSelectEvent: (event, date) {
|
||||
final idx = eventsForSelectedDay
|
||||
.indexWhere((e) => e.id == event.id);
|
||||
setState(() {
|
||||
_selectedEventIndex = idx >= 0 ? idx : 0;
|
||||
_selectedEvent = event;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
if (!hasEvents)
|
||||
Center(
|
||||
child: Text(
|
||||
'Aucun événement ne démarre à cette date'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user