import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../providers/dashboard_providers.dart'; import '../../../widgets/reservation_card.dart'; import '../../../widgets/loading_list.dart'; import '../../../widgets/error_view.dart'; import 'dashboard_shell.dart'; import 'new_reservation_screen.dart'; class ReservationsScreen extends ConsumerStatefulWidget { const ReservationsScreen({super.key}); @override ConsumerState createState() => _ReservationsScreenState(); } class _ReservationsScreenState extends ConsumerState with SingleTickerProviderStateMixin { late final TabController _tabs; final _statuses = [ null, 'DRAFT', 'CONFIRMED', 'ACTIVE', 'COMPLETED', 'CLOSED', 'CANCELLED', ]; final _labels = [ 'All', 'Pending', 'Confirmed', 'Active', 'Completed', 'Closed', 'Cancelled', ]; final _searchController = TextEditingController(); String _search = ''; @override void initState() { super.initState(); _tabs = TabController(length: _statuses.length, vsync: this); } @override void dispose() { _tabs.dispose(); _searchController.dispose(); super.dispose(); } Map _params(int tabIndex) => { 'page': 1, 'pageSize': 50, if (_statuses[tabIndex] != null) 'status': _statuses[tabIndex], if (_search.isNotEmpty) 'search': _search, }; @override Widget build(BuildContext context) { return DashboardShell( floatingActionButton: FloatingActionButton( onPressed: () async { final result = await Navigator.of(context).push( MaterialPageRoute(builder: (_) => const NewReservationScreen()), ); if (result == true) { ref.invalidate(reservationsProvider); setState(() {}); } }, child: const Icon(Icons.add), ), appBar: AppBar( title: const Text('Reservations'), bottom: TabBar( controller: _tabs, isScrollable: true, tabs: _labels.map((l) => Tab(text: l)).toList(), onTap: (_) => setState(() {}), ), ), body: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 0), child: TextField( controller: _searchController, decoration: const InputDecoration( hintText: 'Search reservations...', prefixIcon: Icon(Icons.search, size: 20), contentPadding: EdgeInsets.symmetric(vertical: 8), ), onChanged: (v) => setState(() => _search = v), ), ), Expanded( child: TabBarView( controller: _tabs, children: List.generate( _statuses.length, (i) => _ReservationTab( params: _params(i), onTap: (id) => context.push('/dashboard/reservations/$id'), ), ), ), ), ], ), ); } } class _ReservationTab extends ConsumerWidget { final Map params; final void Function(String id) onTap; const _ReservationTab({required this.params, required this.onTap}); @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(reservationsProvider(params)); return async.when( loading: () => const LoadingList(itemHeight: 110), error: (e, _) => ErrorView( message: 'Failed to load reservations', onRetry: () => ref.invalidate(reservationsProvider(params)), ), data: (res) => res.data.isEmpty ? const Center( child: Text( 'No reservations found', style: TextStyle(color: Color(0xFF9CA3AF)), ), ) : RefreshIndicator( onRefresh: () async => ref.invalidate(reservationsProvider(params)), child: ListView.separated( padding: const EdgeInsets.all(16), itemCount: res.data.length, separatorBuilder: (_, _) => const SizedBox(height: 10), itemBuilder: (_, i) => ReservationCard( reservation: res.data[i], onTap: () => onTap(res.data[i].id), ), ), ), ); } }