import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:table_calendar/table_calendar.dart'; import '../../data/models/calendar_event.dart'; import '../../providers/calendar_provider.dart'; import 'event_form_sheet.dart'; class CalendarScreen extends ConsumerWidget { const CalendarScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final calAsync = ref.watch(calendarProvider); final notifier = ref.read(calendarProvider.notifier); return Scaffold( appBar: AppBar(title: const Text('Calendar')), body: calAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Could not load calendar.'), const SizedBox(height: 12), FilledButton.tonal( onPressed: () => ref.invalidate(calendarProvider), child: const Text('Retry'), ), ], ), ), data: (cal) => Column( children: [ TableCalendar( firstDay: DateTime(2020), lastDay: DateTime(2030), focusedDay: cal.focusedMonth, selectedDayPredicate: (day) => isSameDay(day, cal.selectedDay), eventLoader: (day) => cal.eventsByDay[dateOnly(day)] ?? [], calendarFormat: CalendarFormat.month, headerStyle: const HeaderStyle( formatButtonVisible: false, titleCentered: true, ), calendarStyle: CalendarStyle( selectedDecoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, shape: BoxShape.circle, ), todayDecoration: BoxDecoration( color: Theme.of(context) .colorScheme .primary .withValues(alpha: 0.3), shape: BoxShape.circle, ), markerDecoration: BoxDecoration( color: Theme.of(context).colorScheme.secondary, shape: BoxShape.circle, ), ), onDaySelected: (selected, _) => notifier.selectDay(selected), onPageChanged: (focused) => notifier.loadMonth(focused), ), const Divider(height: 1), Expanded( child: RefreshIndicator( onRefresh: () => ref.read(calendarProvider.notifier).refresh(), child: _AgendaList( events: cal.eventsByDay[dateOnly(cal.selectedDay)] ?? [], notifier: notifier, ), ), ), ], ), ), floatingActionButton: calAsync.hasValue ? FloatingActionButton( onPressed: () => showModalBottomSheet( context: context, isScrollControlled: true, useSafeArea: true, builder: (_) => EventFormSheet( event: null, initialDate: calAsync.value!.selectedDay, notifier: notifier, ), ), child: const Icon(Icons.add), ) : null, ); } } // ── Agenda list ─────────────────────────────────────────────────────────────── class _AgendaList extends StatelessWidget { final List events; final CalendarNotifier notifier; const _AgendaList({required this.events, required this.notifier}); @override Widget build(BuildContext context) { if (events.isEmpty) { return ListView( children: const [ SizedBox(height: 80), Center(child: Text('No events')), ], ); } return ListView.builder( padding: const EdgeInsets.symmetric(vertical: 8), itemCount: events.length, itemBuilder: (_, i) => _EventTile(event: events[i], notifier: notifier), ); } } // ── Event tile ──────────────────────────────────────────────────────────────── class _EventTile extends StatelessWidget { final CalendarEvent event; final CalendarNotifier notifier; const _EventTile({required this.event, required this.notifier}); Color _dotColor(BuildContext context) { if (event.color.isEmpty) return Theme.of(context).colorScheme.primary; try { return Color(int.parse(event.color.replaceFirst('#', '0xFF'))); } catch (_) { return Theme.of(context).colorScheme.primary; } } String _timeLabel() { if (event.allDay) return 'All day'; final h = event.startDt.hour.toString().padLeft(2, '0'); final m = event.startDt.minute.toString().padLeft(2, '0'); return '$h:$m'; } @override Widget build(BuildContext context) { return ListTile( leading: CircleAvatar( radius: 6, backgroundColor: _dotColor(context), ), title: Text(event.title), subtitle: Text(_timeLabel()), onTap: () => showModalBottomSheet( context: context, isScrollControlled: true, useSafeArea: true, builder: (_) => EventFormSheet( event: event, initialDate: null, notifier: notifier, ), ), ); } }