import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:table_calendar/table_calendar.dart'; import 'package:intl/intl.dart'; import '../../../models/trip.dart'; import '../../../models/activity.dart'; import '../../../blocs/activity/activity_bloc.dart'; import '../../../blocs/activity/activity_state.dart'; import '../../../blocs/activity/activity_event.dart'; class CalendarPage extends StatefulWidget { final Trip trip; const CalendarPage({super.key, required this.trip}); @override State createState() => _CalendarPageState(); } class _CalendarPageState extends State { late DateTime _focusedDay; DateTime? _selectedDay; CalendarFormat _calendarFormat = CalendarFormat.month; @override void initState() { super.initState(); _focusedDay = widget.trip.startDate; _selectedDay = _focusedDay; } List _getActivitiesForDay(DateTime day, List activities) { return activities.where((activity) { if (activity.date == null) return false; return isSameDay(activity.date, day); }).toList(); } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: const Text('Calendrier du voyage'), backgroundColor: theme.colorScheme.surface, foregroundColor: theme.colorScheme.onSurface, elevation: 0, ), body: BlocBuilder( builder: (context, state) { if (state is ActivityLoading) { return const Center(child: CircularProgressIndicator()); } List allActivities = []; if (state is ActivityLoaded) { allActivities = state.activities; } else if (state is ActivitySearchResults) { // Fallback if we are in search state, though ideally we should be in loaded state // This might happen if we navigate back and forth } // Filter approved activities final approvedActivities = allActivities.where((a) { return a.isApprovedByAllParticipants([ ...widget.trip.participants, widget.trip.createdBy, ]); }).toList(); final scheduledActivities = approvedActivities .where((a) => a.date != null) .toList(); final unscheduledActivities = approvedActivities .where((a) => a.date == null) .toList(); final selectedActivities = _getActivitiesForDay( _selectedDay ?? _focusedDay, scheduledActivities, ); return Column( children: [ TableCalendar( firstDay: DateTime.now().subtract(const Duration(days: 365)), lastDay: DateTime.now().add(const Duration(days: 365)), focusedDay: _focusedDay, calendarFormat: _calendarFormat, selectedDayPredicate: (day) { return isSameDay(_selectedDay, day); }, onDaySelected: (selectedDay, focusedDay) { setState(() { _selectedDay = selectedDay; _focusedDay = focusedDay; }); }, onFormatChanged: (format) { setState(() { _calendarFormat = format; }); }, onPageChanged: (focusedDay) { _focusedDay = focusedDay; }, eventLoader: (day) { return _getActivitiesForDay(day, scheduledActivities); }, calendarBuilders: CalendarBuilders( markerBuilder: (context, day, events) { if (events.isEmpty) return null; return Positioned( bottom: 1, child: Container( width: 7, height: 7, decoration: BoxDecoration( shape: BoxShape.circle, color: theme.colorScheme.primary, ), ), ); }, ), calendarStyle: CalendarStyle( todayDecoration: BoxDecoration( color: theme.colorScheme.primary.withValues(alpha: 0.5), shape: BoxShape.circle, ), selectedDecoration: BoxDecoration( color: theme.colorScheme.primary, shape: BoxShape.circle, ), ), ), const Divider(), Expanded( child: Row( children: [ // Scheduled Activities for Selected Day Expanded( flex: 3, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Text( 'Activités du ${DateFormat('dd/MM/yyyy').format(_selectedDay!)}', style: theme.textTheme.titleMedium, ), ), Expanded( child: selectedActivities.isEmpty ? Center( child: Text( 'Aucune activité prévue', style: theme.textTheme.bodyMedium ?.copyWith( color: theme.colorScheme.onSurface .withValues(alpha: 0.6), ), ), ) : ListView.builder( itemCount: selectedActivities.length, itemBuilder: (context, index) { final activity = selectedActivities[index]; return ListTile( title: Text(activity.name), subtitle: Text(activity.category), trailing: IconButton( icon: const Icon(Icons.close), onPressed: () { context.read().add( UpdateActivityDate( tripId: widget.trip.id!, activityId: activity.id, date: null, ), ); }, ), ); }, ), ), ], ), ), const VerticalDivider(), // Unscheduled Activities Expanded( flex: 2, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Text( 'À planifier', style: theme.textTheme.titleMedium, ), ), Expanded( child: unscheduledActivities.isEmpty ? Center( child: Text( 'Tout est planifié !', style: theme.textTheme.bodyMedium ?.copyWith( color: theme.colorScheme.onSurface .withValues(alpha: 0.6), ), textAlign: TextAlign.center, ), ) : ListView.builder( itemCount: unscheduledActivities.length, itemBuilder: (context, index) { final activity = unscheduledActivities[index]; return Draggable( data: activity, feedback: Material( elevation: 4, child: Container( padding: const EdgeInsets.all(8), color: theme.cardColor, child: Text(activity.name), ), ), child: ListTile( title: Text( activity.name, style: theme.textTheme.bodySmall, ), trailing: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { if (_selectedDay != null) { context .read() .add( UpdateActivityDate( tripId: widget.trip.id!, activityId: activity.id, date: _selectedDay, ), ); } }, ), ), ); }, ), ), ], ), ), ], ), ), ], ); }, ), ); } }