import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:timetrack/features/entries/domain/entries_provider.dart'; import 'package:timetrack/features/entries/domain/time_entry.dart'; import 'package:timetrack/features/entries/presentation/widgets/date_range_filter.dart'; import 'package:timetrack/features/entries/presentation/widgets/day_header.dart'; import 'package:timetrack/features/entries/presentation/widgets/entry_form_sheet.dart'; import 'package:timetrack/features/entries/presentation/widgets/entry_list_tile.dart'; import 'package:timetrack/features/projects/domain/project.dart'; import 'package:timetrack/features/projects/domain/projects_provider.dart'; class EntriesScreen extends ConsumerStatefulWidget { const EntriesScreen({super.key}); @override ConsumerState createState() => _EntriesScreenState(); } class _EntriesScreenState extends ConsumerState { DateRangeFilter _filter = DateRangeFilter.thisWeek; @override Widget build(BuildContext context) { final (from, to) = dateRangeBounds(_filter); final entriesAsync = ref.watch( entriesByDateRangeProvider(rangeFrom: from, rangeTo: to), ); final projectsAsync = ref.watch(allProjectsProvider); return Scaffold( appBar: AppBar( title: const Text('Entries'), actions: [ IconButton( icon: const Icon(Icons.add), tooltip: 'Add entry', onPressed: () => EntryFormSheet.show(context), ), ], ), body: Column( children: [ DateRangeFilterChips( selected: _filter, onChanged: (f) => setState(() => _filter = f), ), Expanded( child: entriesAsync.when( data: (entries) => projectsAsync.when( data: (projects) => _buildList(entries, projects), loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('Error: $e')), ), loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('Error: $e')), ), ), ], ), ); } Widget _buildList(List entries, List projects) { if (entries.isEmpty) { return const Center( key: Key('entries_empty'), child: Text('No entries yet.'), ); } final projectMap = {for (final p in projects) p.id: p}; // Group by date final grouped = >{}; for (final entry in entries) { final day = DateTime( entry.startTime.year, entry.startTime.month, entry.startTime.day, ); grouped.putIfAbsent(day, () => []).add(entry); } final sortedDays = grouped.keys.toList() ..sort((a, b) => b.compareTo(a)); return ListView.builder( itemCount: sortedDays.length, itemBuilder: (context, index) { final day = sortedDays[index]; final dayEntries = grouped[day]!; final totalSeconds = dayEntries.fold( 0, (sum, e) => sum + (e.durationSeconds ?? 0), ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ DayHeader( date: day, totalDuration: Duration(seconds: totalSeconds), ), ...dayEntries.map((entry) { final project = projectMap[entry.projectId]; return EntryListTile( key: Key('entry_tile_${entry.id}'), entry: entry, projectName: project?.name ?? '—', projectColor: project?.colorValue ?? 0xFF888888, onTap: () => EntryFormSheet.show(context, existing: entry), onDelete: () => _deleteWithUndo(entry), ); }), ], ); }, ); } void _deleteWithUndo(TimeEntry entry) { ref.read(entriesNotifierProvider.notifier).delete(entry.id); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('Entry deleted'), action: SnackBarAction( label: 'Undo', onPressed: () => ref.read(entriesNotifierProvider.notifier).create(entry), ), ), ); } }