import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/format.dart'; import '../../core/models.dart'; import '../../core/providers.dart'; import '../../core/theme.dart'; import '../../widgets/account_sheet.dart'; import 'calendar_picker.dart'; import '../../widgets/ui.dart'; class ResultsScreen extends ConsumerWidget { const ResultsScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final date = ref.watch(selectedDateProvider); final res = ref.watch(resultsProvider(date)); return Column( children: [ ScreenHeader( title: 'Results', trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Builder( builder: (anchor) => RoundIcon( Icons.calendar_month_rounded, label: 'Calendar', onTap: () => showCalendarPicker(anchor), ), ), // Wider windows show the account in the sidebar. if (!isWide(context)) ...[ const SizedBox(width: S.s10), RoundIcon( Icons.person_outline_rounded, label: 'Account', onTap: () => showAccountSheet(context, ref), ), ], ], ), ), Expanded( child: asyncView( res, (r) => _Body(results: r, date: date), retry: () => ref.invalidate(resultsProvider(date)), ), ), ], ); } } class _Body extends ConsumerWidget { const _Body({required this.results, required this.date}); final DrawResults results; final DateTime date; @override Widget build(BuildContext context, WidgetRef ref) { final r = results; final d = r.draw; final n = ref.read(selectedDateProvider.notifier); return PageList( children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(d.label, style: ts(16, w: w7)), const SizedBox(height: S.s2), Text( '${dateLong(d.date)} · 3:00 PM', style: ts(13, c: C.muted), ), ], ), ), RoundIcon( Icons.chevron_left_rounded, label: 'Previous draw', size: 40, onTap: () => n.set(addDays(date, -1)), ), const SizedBox(width: S.s8), RoundIcon( Icons.chevron_right_rounded, label: 'Next draw', size: 40, onTap: () => n.set(addDays(date, 1)), ), ], ), const SizedBox(height: S.s16), if (d.published) ..._published(context, r) else ..._notOut(context, r), ], ); } List _published(BuildContext context, DrawResults r) { final top = r.topShop; return [ _HeroRow( hero: NavyCard( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'TOTAL PRIZE', style: ts(11, w: w6, c: C.softOnNavy, ls: 1.2), ), const SizedBox(height: S.s10), Text( rupees(r.totalPrize), style: ts( 40, w: w7, c: r.totalPrize > 0 ? C.gold : C.softOnNavy, ls: -1, ), ), const SizedBox(height: S.s10), Text( r.totalPrize > 0 ? '${plural(r.winningTickets, 'winning ticket')} · ${plural(r.winningShops, 'shop')}' : 'No winning tickets in this draw', style: ts(13, w: w5, c: C.softOnNavy), ), ], ), ), stats: [ StatCard(label: 'TOTAL TICKETS', value: inr(r.totalTickets)), StatCard( label: 'TOP SHOP', value: top?.shop.code ?? '—', valueColor: top == null ? C.muted : C.ink, ), ], ), SectionTitle( 'Shops', trailing: r.shops.isEmpty ? null : plural(r.shops.length, 'shop'), ), if (r.shops.isEmpty) const SrsCard( child: EmptyState( icon: Icons.receipt_long_outlined, title: 'No orders for this draw', body: 'Orders placed for your shops on this date will appear here.', ), ) else CardGrid(children: [for (final s in r.shops) _ShopRow(s: s)]), ]; } List _notOut(BuildContext context, DrawResults r) { return [ _HeroRow( hero: NavyCard( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.symmetric( horizontal: S.s10, vertical: S.s6, ), decoration: BoxDecoration( color: C.goldSoft, borderRadius: BorderRadius.circular(R.pill), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.schedule_rounded, size: 14, color: C.gold), const SizedBox(width: S.s6), Text( 'AWAITING RESULTS', style: ts(10, w: w7, c: C.gold, ls: 1), ), ], ), ), const SizedBox(height: S.s14), Text( 'Results not yet published', style: ts(26, w: w7, c: Colors.white, ls: -0.4), ), const SizedBox(height: S.s8), Text( 'Official results are usually published after 4 PM. Prize details will appear here once available.', style: ts(13, c: C.softOnNavy, h: 1.5), ), ], ), ), stats: [ StatCard(label: 'ORDERS', value: inr(r.orders)), StatCard(label: 'TICKETS', value: inr(r.totalTickets)), ], ), SectionTitle( 'Shops', trailing: r.shops.isEmpty ? null : plural(r.shops.length, 'shop'), ), if (r.shops.isEmpty) const SrsCard( child: EmptyState( icon: Icons.inbox_outlined, title: 'No orders', body: 'No orders have been placed for this draw.', ), ) else CardGrid( children: [for (final s in r.shops) _ShopRow(s: s, pending: true)], ), ]; } } /// The navy hero with its two stat cards: stacked under it on phones, /// beside it on wide windows. class _HeroRow extends StatelessWidget { const _HeroRow({required this.hero, required this.stats}); final Widget hero; final List stats; @override Widget build(BuildContext context) => LayoutBuilder( builder: (context, c) { if (c.maxWidth < 760) { return Column( children: [ hero, const SizedBox(height: S.s12), Row( children: [ Expanded(child: stats[0]), const SizedBox(width: S.s12), Expanded(child: stats[1]), ], ), ], ); } return IntrinsicHeight( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded(flex: 2, child: hero), const SizedBox(width: S.s12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded(child: stats[0]), const SizedBox(height: S.s12), Expanded(child: stats[1]), ], ), ), ], ), ); }, ); } class _ShopRow extends StatelessWidget { const _ShopRow({required this.s, this.pending = false}); final ShopResult s; final bool pending; @override Widget build(BuildContext context) { final win = s.prize > 0; return SrsCard( onTap: () => context.push('/shops/${s.shop.id}'), padding: const EdgeInsets.all(S.s14), child: Row( children: [ CodeTile(s.shop.code, dark: win), const SizedBox(width: S.s14), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.shop.name, maxLines: 1, overflow: TextOverflow.ellipsis, style: ts(15, w: w6), ), const SizedBox(height: S.s4), Text( pending ? plural(s.tickets, 'ticket') : win ? plural(s.winTickets, 'winning ticket') : 'No winning tickets', style: ts(12, c: C.muted), ), ], ), ), if (!pending) Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( rupees(s.prize), style: ts(16, w: w7, c: win ? C.green : C.muted), ), if (win) ...[ const SizedBox(height: S.s2), Text( plural(s.winTickets, 'ticket'), style: ts(11, c: C.muted), ), ], ], ) else const Icon(Icons.chevron_right_rounded, color: C.placeholder), ], ), ); } }