import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../data/bible.dart'; import '../models/tracker.dart'; import '../services/progress.dart'; import '../services/tracker_service.dart'; import '../widgets/book_tile.dart'; import '../widgets/progress_bar.dart'; import '../widgets/theme.dart'; import 'book_screen.dart'; import 'stats_screen.dart'; class TrackerScreen extends ConsumerWidget { const TrackerScreen({super.key, required this.trackerId}); final String trackerId; @override Widget build(BuildContext context, WidgetRef ref) { final Tracker? tracker = ref.watch(trackerByIdProvider(trackerId)); if (tracker == null) { return Scaffold( appBar: AppBar(), body: const Center(child: Text('Tracker not found')), ); } final Color accent = Color(tracker.colorValue); final TrackerProgress progress = TrackerProgress(tracker); return Scaffold( appBar: AppBar( title: Text(tracker.name), actions: [ IconButton( tooltip: 'Stats', icon: const Icon(Icons.insert_chart_outlined), onPressed: () => Navigator.of(context).push( MaterialPageRoute( builder: (_) => StatsScreen(trackerId: tracker.id), ), ), ), ], ), body: CustomScrollView( slivers: [ SliverToBoxAdapter( child: _HeaderCard( tracker: tracker, accent: accent, progress: progress, ), ), SliverToBoxAdapter( child: _SectionHeader( title: 'Old Testament', chaptersRead: progress.chaptersReadInTestament(Testament.old), total: Bible.totalChaptersIn(Testament.old), ), ), _BooksSliver( tracker: tracker, accent: accent, testament: Testament.old, ), SliverToBoxAdapter( child: _SectionHeader( title: 'New Testament', chaptersRead: progress.chaptersReadInTestament(Testament.newT), total: Bible.totalChaptersIn(Testament.newT), ), ), _BooksSliver( tracker: tracker, accent: accent, testament: Testament.newT, ), const SliverToBoxAdapter(child: SizedBox(height: AppTokens.spaceXL)), ], ), ); } } class _HeaderCard extends StatelessWidget { const _HeaderCard({ required this.tracker, required this.accent, required this.progress, }); final Tracker tracker; final Color accent; final TrackerProgress progress; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(AppTokens.spaceL), child: Card( child: Padding( padding: const EdgeInsets.all(AppTokens.spaceL), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${(progress.overall * 100).toStringAsFixed(1)}%', style: Theme.of(context).textTheme.headlineMedium ?.copyWith( color: accent, fontWeight: FontWeight.w700, ), ), const SizedBox(height: AppTokens.spaceXS), Text( '${progress.totalRead} / ${Bible.totalChapters} chapters', style: Theme.of(context).textTheme.bodyMedium ?.copyWith( color: Theme.of( context, ).colorScheme.onSurfaceVariant, ), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( 'Started', style: Theme.of(context).textTheme.labelSmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), const SizedBox(height: AppTokens.spaceXS), Text( _formatDate(tracker.startDate), style: Theme.of(context).textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w500, ), ), ], ), ], ), const SizedBox(height: AppTokens.spaceL), ProgressBar(value: progress.overall, color: accent, height: 8), ], ), ), ), ); } static String _formatDate(DateTime date) { const List months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; return '${months[date.month - 1]} ${date.day}, ${date.year}'; } } class _SectionHeader extends StatelessWidget { const _SectionHeader({ required this.title, required this.chaptersRead, required this.total, }); final String title; final int chaptersRead; final int total; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.fromLTRB( AppTokens.spaceL, AppTokens.spaceL, AppTokens.spaceL, AppTokens.spaceS, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( title, style: Theme.of( context, ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600), ), Text( '$chaptersRead / $total', style: Theme.of(context).textTheme.labelMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], ), ); } } class _BooksSliver extends ConsumerWidget { const _BooksSliver({ required this.tracker, required this.accent, required this.testament, }); final Tracker tracker; final Color accent; final Testament testament; @override Widget build(BuildContext context, WidgetRef ref) { final List books = Bible.books .where((Book book) => book.testament == testament) .toList(growable: false); final TrackerProgress progress = TrackerProgress(tracker); return SliverList.separated( itemCount: books.length, separatorBuilder: (_, __) => const Divider(indent: AppTokens.spaceXL), itemBuilder: (BuildContext context, int index) { final Book book = books[index]; return BookTile( book: book, chaptersRead: progress.chaptersReadIn(book), accent: accent, onTap: () => Navigator.of(context).push( MaterialPageRoute( builder: (_) => BookScreen(trackerId: tracker.id, bookIndex: book.index), ), ), ); }, ); } }