import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:timetrack/features/projects/domain/projects_provider.dart'; import 'package:timetrack/features/reports/domain/report_data.dart'; import 'package:timetrack/features/reports/domain/reports_provider.dart'; import 'package:timetrack/features/reports/presentation/widgets/duration_bar_chart.dart'; import 'package:timetrack/features/reports/presentation/widgets/period_navigator.dart'; import 'package:timetrack/features/reports/presentation/widgets/project_breakdown_list.dart'; import 'package:timetrack/features/reports/presentation/widgets/summary_header.dart'; class ReportsScreen extends ConsumerWidget { const ReportsScreen({super.key}); static const _weekLabels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; static const _dayLabels = [ '0', '2', '4', '6', '8', '10', '12', '14', '16', '18', '20', '22', ]; @override Widget build(BuildContext context, WidgetRef ref) { final notifier = ref.read(reportsNotifierProvider.notifier); final reportAsync = ref.watch(reportsNotifierProvider); final projectsAsync = ref.watch(allProjectsProvider); return Scaffold( appBar: AppBar( title: const Text('Reports'), bottom: PreferredSize( preferredSize: const Size.fromHeight(48), child: _PeriodTabs( current: notifier.period, onChanged: notifier.selectPeriod, ), ), ), body: reportAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('Error: $e')), data: (report) => _buildBody(context, ref, report, projectsAsync, notifier), ), ); } Widget _buildBody( BuildContext context, WidgetRef ref, ReportData report, AsyncValue projectsAsync, ReportsNotifier notifier, ) { final chartLabels = _labelsFor(notifier.period, report.chartValues.length); return ListView( children: [ PeriodNavigator( period: notifier.period, periodStart: report.periodStart, periodEnd: report.periodEnd, onPrevious: notifier.goToPrevious, onNext: notifier.goToNext, ), SummaryHeader( totalDuration: report.totalDuration, entryCount: report.durationByProject.length, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: SizedBox( height: 200, child: report.chartValues.isEmpty || report.chartValues.every((v) => v == 0) ? Center( child: Text( 'No data for this period', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ) : DurationBarChart( values: report.chartValues, labels: chartLabels, ), ), ), Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 4), child: Text( 'By project', style: Theme.of(context).textTheme.labelLarge, ), ), projectsAsync.when( data: (projects) => ProjectBreakdownList( durationByProject: report.durationByProject, projects: projects, totalDuration: report.totalDuration, ), loading: () => const SizedBox.shrink(), error: (e, _) => const SizedBox.shrink(), ), ], ); } List _labelsFor(ReportPeriod period, int count) { switch (period) { case ReportPeriod.week: return _weekLabels; case ReportPeriod.day: return _dayLabels; case ReportPeriod.month: return List.generate(count, (i) => '${i + 1}'); } } } class _PeriodTabs extends StatelessWidget { const _PeriodTabs({required this.current, required this.onChanged}); final ReportPeriod current; final ValueChanged onChanged; @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: ReportPeriod.values.map((p) { final label = p.name[0].toUpperCase() + p.name.substring(1); return Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: ChoiceChip( label: Text(label), selected: current == p, onSelected: (_) => onChanged(p), ), ); }).toList(), ); } }