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/providers.dart'; import '../../core/theme.dart'; import '../../widgets/ui.dart'; import 'order_card.dart'; class OrdersScreen extends ConsumerStatefulWidget { const OrdersScreen({super.key}); @override ConsumerState createState() => _OrdersScreenState(); } class _OrdersScreenState extends ConsumerState { String? _code; String _q = ''; @override Widget build(BuildContext context) { final date = ref.watch(selectedDateProvider); final orders = ref.watch(ordersProvider(date)); Future refresh() => refreshData(context, ref, ordersProvider(date)); return Column( children: [ const ScreenHeader(title: 'Orders'), PagePad( top: S.s4, child: Align( alignment: Alignment.centerLeft, child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Column( children: [ const DateStrip(), const SizedBox(height: S.s10), SearchField( hint: 'Search shop, message or ending', onChanged: (v) => setState(() => _q = v.trim().toLowerCase()), ), ], ), ), ), ), Expanded( child: RefreshableView( value: orders, onRefresh: refresh, skeleton: const SkeletonList( top: S.s14, children: [ Padding( padding: EdgeInsets.fromLTRB(S.s2, S.s18, S.s2, S.s10), child: SizedBox( height: 18, child: Row( children: [ Bone(width: 180, height: 14), Spacer(), Bone(width: 110, height: 10), ], ), ), ), TileGridBone(), ], ), builder: (all) { final codes = {for (final o in all) o.shop.code}.toList() ..sort(); final active = codes.contains(_code) ? _code : null; final list = [ for (final o in all) if ((active == null || o.shop.code == active) && o.matches(_q)) o, ]; final tickets = list.fold(0, (a, o) => a + o.tickets); return PageList( top: S.s14, children: [ if (codes.length > 1) SizedBox( height: 38, child: ListView( scrollDirection: Axis.horizontal, children: [ _chip( 'All', active == null, () => setState(() => _code = null), ), for (final c in codes) _chip( c, active == c, () => setState(() => _code = c), ), ], ), ), if (list.isEmpty) _q.isNotEmpty ? const EmptyState( icon: Icons.search_off_rounded, title: 'No matching orders', ) : const EmptyState( icon: Icons.receipt_long_outlined, title: 'No orders for this date', body: 'Orders received via WhatsApp will appear here. Select another date to view earlier orders.', ) else ...[ Padding( padding: const EdgeInsets.fromLTRB( S.s2, S.s18, S.s2, S.s10, ), child: Row( children: [ Expanded( child: Text(dateLong(date), style: ts(15, w: w7)), ), Text( '${plural(list.length, 'order')} ยท ${plural(tickets, 'ticket')}', style: ts(12, c: C.muted), ), ], ), ), CardGrid( children: [ for (final o in list) OrderCard( order: o, onTap: () => context.push('/orders/${o.id}'), ), ], ), ], ], ); }, ), ), ], ); } Widget _chip(String t, bool on, VoidCallback tap) => Padding( padding: const EdgeInsets.only(right: S.s8), child: Pressable( onTap: tap, radius: R.pill, builder: (_, hover) => AnimatedContainer( duration: const Duration(milliseconds: 140), padding: const EdgeInsets.symmetric(horizontal: S.s16), alignment: Alignment.center, decoration: BoxDecoration( color: on ? C.navy : (hover ? C.hover : Colors.white), borderRadius: BorderRadius.circular(R.pill), border: Border.all( color: on ? C.navy : (hover ? C.border2 : C.border), ), ), child: Text( t, style: ts(13, w: w6, c: on ? Colors.white : C.ink), ), ), ), ); }