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/ui.dart'; import '../orders/order_card.dart'; class TicketsScreen extends ConsumerStatefulWidget { const TicketsScreen({super.key, required this.shopId}); final int shopId; @override ConsumerState createState() => _TicketsScreenState(); } class _TicketsScreenState extends ConsumerState { bool _byEnding = true; String _q = ''; @override Widget build(BuildContext context) { final date = ref.watch(selectedDateProvider); final detail = ref.watch(shopDetailProvider((widget.shopId, date))); return Scaffold( body: SafeArea( child: asyncView( detail, (d) => Column( children: [ ScreenHeader( title: '${d.shop.name} tickets', subtitle: '${plural(d.tickets, 'ticket')} · ${dateShort(date)}', back: true, ), PagePad( top: S.s4, bottom: S.s10, child: Container( constraints: const BoxConstraints(maxWidth: 420), padding: const EdgeInsets.all(S.s4), decoration: BoxDecoration( color: C.chip, borderRadius: BorderRadius.circular(R.input), ), child: Row( children: [ _seg( 'By ending', _byEnding, () => setState(() => _byEnding = true), ), _seg( 'By order', !_byEnding, () => setState(() => _byEnding = false), ), ], ), ), ), if (_byEnding) PagePad( bottom: S.s8, child: SearchField( hint: 'Search endings (e.g. 0987)', onChanged: (v) => setState(() => _q = v.trim()), ), ), Expanded(child: _byEnding ? _endings(d) : _orders(d)), ], ), retry: () => ref.invalidate(shopDetailProvider((widget.shopId, date))), ), ), ); } Widget _seg(String t, bool on, VoidCallback tap) => Expanded( child: Pressable( onTap: tap, radius: R.md, builder: (_, hover) => AnimatedContainer( duration: const Duration(milliseconds: 160), height: 38, alignment: Alignment.center, decoration: BoxDecoration( color: on ? Colors.white : (hover ? C.hover : Colors.transparent), borderRadius: BorderRadius.circular(R.md), ), child: Text( t, style: ts(13, w: on ? w7 : w5, c: on ? C.navy : C.muted), ), ), ), ); Widget _endings(ShopDetail d) { final list = d.endings .where((e) => _q.isEmpty || e.ending.contains(_q)) .toList(); if (list.isEmpty) { return ListView( children: const [ EmptyState( icon: Icons.search_off_rounded, title: 'No matching endings', ), ], ); } return PageList( children: [ Wrap( spacing: 8, runSpacing: 8, children: [for (final e in list) _chip(e)], ), ], ); } Widget _chip(EndingQty e) { final win = e.wins; return Container( padding: const EdgeInsets.symmetric(horizontal: S.s12, vertical: S.s8), decoration: BoxDecoration( color: win ? C.greenTint : Colors.white, borderRadius: BorderRadius.circular(R.md), border: Border.all(color: win ? C.green : C.border), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( e.ending, style: ts(14, w: w7, c: win ? C.green : C.ink, ls: 0.4), ), const SizedBox(width: S.s6), Text( '×${inr(e.qty)}', style: ts(12, w: w6, c: win ? C.green : C.muted), ), ], ), ); } Widget _orders(ShopDetail d) { if (d.orders.isEmpty) { return ListView( children: const [ EmptyState(icon: Icons.receipt_long_outlined, title: 'No orders'), ], ); } return PageList( children: [ CardGrid( children: [ for (final o in d.orders) OrderCard(order: o, onTap: () => context.push('/orders/${o.id}')), ], ), ], ); } }