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 '../../../core/models/reservation.dart'; class ContractsScreen extends ConsumerStatefulWidget { const ContractsScreen({super.key}); @override ConsumerState createState() => _ContractsScreenState(); } class _ContractsScreenState extends ConsumerState { final _searchCtrl = TextEditingController(); String _search = ''; List _visibleContracts(List reservations) { final query = _search.trim().toLowerCase(); return reservations.where((reservation) { if (reservation.contractNumber == null) { return false; } if (query.isEmpty) { return true; } final customer = reservation.customer; final vehicle = reservation.vehicle; final haystack = [ customer?.fullName, customer?.email, vehicle?.displayName, vehicle?.licensePlate, reservation.contractNumber, reservation.invoiceNumber, ].whereType().join(' ').toLowerCase(); return haystack.contains(query); }).toList(); } @override void dispose() { _searchCtrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final ReservationQuery params = ( page: 1, pageSize: 100, status: null, source: null, search: null, customerId: null, ); final asyncData = ref.watch(reservationsProvider(params)); return Scaffold( appBar: AppBar( title: const Text('Contracts'), bottom: PreferredSize( preferredSize: const Size.fromHeight(56), child: Padding( padding: const EdgeInsets.fromLTRB(12, 0, 12, 8), child: TextField( controller: _searchCtrl, decoration: InputDecoration( hintText: 'Search by customer, vehicle, contract…', prefixIcon: const Icon(Icons.search, size: 20), suffixIcon: _search.isNotEmpty ? IconButton( icon: const Icon(Icons.clear, size: 20), onPressed: () { _searchCtrl.clear(); setState(() => _search = ''); }, ) : null, isDense: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), filled: true, fillColor: Theme.of(context).colorScheme.surface, ), onChanged: (v) => setState(() => _search = v), ), ), ), ), body: asyncData.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('Error: $e')), data: (response) { final contracts = _visibleContracts(response.data); if (contracts.isEmpty) { return const Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.description_outlined, size: 64, color: Color(0xFF9CA3AF)), SizedBox(height: 12), Text( 'No contracts yet', style: TextStyle( fontSize: 16, color: Color(0xFF6B7280), ), ), ], ), ); } return RefreshIndicator( onRefresh: () async => ref.invalidate(reservationsProvider(params)), child: ListView.separated( padding: const EdgeInsets.all(12), itemCount: contracts.length, separatorBuilder: (context, index) => const SizedBox(height: 8), itemBuilder: (_, i) => _ContractCard(reservation: contracts[i]), ), ); }, ), ); } } class _ContractCard extends StatelessWidget { final Reservation reservation; const _ContractCard({required this.reservation}); @override Widget build(BuildContext context) { final r = reservation; final vehicle = r.vehicle; final customer = r.customer; return Card( margin: EdgeInsets.zero, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: InkWell( borderRadius: BorderRadius.circular(10), onTap: () => context.push('/dashboard/reservations/${r.id}/contract'), child: Padding( padding: const EdgeInsets.all(14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.description_outlined, size: 18, color: Color(0xFF1A56DB)), const SizedBox(width: 6), Text( r.contractNumber!, style: const TextStyle( fontWeight: FontWeight.w700, fontSize: 15, color: Color(0xFF1A56DB), ), ), const Spacer(), _StatusChip(status: r.status), ], ), if (r.invoiceNumber != null) ...[ const SizedBox(height: 4), Text( 'Invoice: ${r.invoiceNumber}', style: const TextStyle( fontSize: 12, color: Color(0xFF6B7280)), ), ], const SizedBox(height: 10), Row( children: [ const Icon(Icons.person_outline, size: 16, color: Color(0xFF6B7280)), const SizedBox(width: 4), Expanded( child: Text( customer?.fullName ?? '—', style: const TextStyle(fontSize: 13), ), ), ], ), const SizedBox(height: 4), Row( children: [ const Icon(Icons.directions_car_outlined, size: 16, color: Color(0xFF6B7280)), const SizedBox(width: 4), Expanded( child: Text( vehicle?.displayName ?? '—', style: const TextStyle(fontSize: 13), ), ), ], ), const SizedBox(height: 10), Row( children: [ const Icon(Icons.calendar_today_outlined, size: 14, color: Color(0xFF9CA3AF)), const SizedBox(width: 4), Text( '${_fmt(r.startDate)} → ${_fmt(r.endDate)}', style: const TextStyle( fontSize: 12, color: Color(0xFF6B7280)), ), const Spacer(), Text( '${(r.totalAmount / 100).toStringAsFixed(2)} DA', style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 13, ), ), ], ), ], ), ), ), ); } String _fmt(DateTime d) => '${d.day.toString().padLeft(2, '0')}/${d.month.toString().padLeft(2, '0')}/${d.year}'; } class _StatusChip extends StatelessWidget { final String status; const _StatusChip({required this.status}); @override Widget build(BuildContext context) { final (label, bg, fg) = switch (status) { 'CONFIRMED' => ('Confirmed', const Color(0xFFEBF5FB), const Color(0xFF1A56DB)), 'ACTIVE' => ('Active', const Color(0xFFECFDF5), const Color(0xFF059669)), 'COMPLETED' => ('Completed', const Color(0xFFF0FDF4), const Color(0xFF16A34A)), 'CLOSED' => ('Closed', const Color(0xFFF9FAFB), const Color(0xFF6B7280)), _ => (status, const Color(0xFFF9FAFB), const Color(0xFF6B7280)), }; return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: bg, borderRadius: BorderRadius.circular(6), ), child: Text( label, style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: fg, ), ), ); } }