import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import '../providers/dashboard_providers.dart'; import '../../../widgets/status_badge.dart'; import '../../../widgets/error_view.dart'; import '../../../widgets/reservation_card.dart'; import 'customer_form_screen.dart'; class CustomerDetailScreen extends ConsumerWidget { final String id; const CustomerDetailScreen({super.key, required this.id}); @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(customerDetailProvider(id)); final reservationsAsync = ref.watch( reservationsProvider({'customerId': id, 'page': 1, 'pageSize': 10}), ); return async.when( loading: () => const Scaffold(body: Center(child: CircularProgressIndicator())), error: (e, _) => Scaffold( appBar: AppBar(), body: ErrorView( message: 'Could not load customer', onRetry: () => ref.invalidate(customerDetailProvider(id)), ), ), data: (customer) { final fmt = DateFormat('MMM d, yyyy'); return Scaffold( appBar: AppBar( title: Text(customer.fullName), actions: [ IconButton( icon: const Icon(Icons.edit_outlined), onPressed: () async { final result = await Navigator.of(context).push( MaterialPageRoute( builder: (_) => CustomerFormScreen(customer: customer)), ); if (result == true) { ref.invalidate(customerDetailProvider(id)); } }, ), PopupMenuButton( onSelected: (v) async { if (v == 'flag') { await _showFlagDialog(context, ref, customer.isFlagged); } else if (v == 'approve') { await _showApproveLicenseDialog(context, ref); } }, itemBuilder: (_) => [ PopupMenuItem( value: 'flag', child: Row( children: [ Icon( customer.isFlagged ? Icons.flag_outlined : Icons.flag, size: 18, color: const Color(0xFFE02424), ), const SizedBox(width: 8), Text( customer.isFlagged ? 'Remove Flag' : 'Flag Customer', style: const TextStyle(color: Color(0xFFE02424)), ), ], ), ), const PopupMenuItem( value: 'approve', child: Row( children: [ Icon(Icons.badge_outlined, size: 18), SizedBox(width: 8), Text('Review License'), ], ), ), ], ), ], ), body: ListView( padding: const EdgeInsets.all(16), children: [ Center( child: Column( children: [ CircleAvatar( radius: 40, backgroundColor: customer.isFlagged ? const Color(0xFFFDE8E8) : const Color(0xFFE1EFFE), child: Text( customer.firstName.substring(0, 1).toUpperCase(), style: TextStyle( fontSize: 32, color: customer.isFlagged ? const Color(0xFFE02424) : const Color(0xFF1A56DB), fontWeight: FontWeight.bold, ), ), ), const SizedBox(height: 12), Text( customer.fullName, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 6), StatusBadge(status: customer.licenseStatus), if (customer.isFlagged) ...[ const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6), decoration: BoxDecoration( color: const Color(0xFFFDE8E8), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.flag, size: 14, color: Color(0xFFE02424)), const SizedBox(width: 6), Text( customer.flagReason ?? 'Flagged', style: const TextStyle( color: Color(0xFF9B1C1C), fontSize: 13), ), ], ), ), ], ], ), ), const SizedBox(height: 24), Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Contact Information', style: TextStyle( fontWeight: FontWeight.bold, color: Color(0xFF6B7280), fontSize: 12, ), ), const SizedBox(height: 12), if (customer.email != null) _InfoRow( icon: Icons.email_outlined, value: customer.email!), if (customer.phone != null) _InfoRow( icon: Icons.phone_outlined, value: customer.phone!), if (customer.nationality != null) _InfoRow( icon: Icons.flag_outlined, value: customer.nationality!), if (customer.dateOfBirth != null) _InfoRow( icon: Icons.cake_outlined, value: fmt.format(customer.dateOfBirth!), ), _InfoRow( icon: Icons.calendar_today_outlined, value: 'Joined ${fmt.format(customer.createdAt)}', ), ], ), ), ), const SizedBox(height: 16), if (customer.licenseStatus == 'PENDING') _ActionButton( label: 'Approve License', color: const Color(0xFF0E9F6E), icon: Icons.check_circle_outline, onTap: () => _showApproveLicenseDialog(context, ref), ), if (customer.licenseStatus == 'PENDING') _ActionButton( label: 'Reject License', color: const Color(0xFFE02424), icon: Icons.cancel_outlined, onTap: () => _showRejectLicenseDialog(context, ref), ), if (!customer.isFlagged) _ActionButton( label: 'Flag Customer', color: const Color(0xFFE02424), icon: Icons.flag_outlined, onTap: () => _showFlagDialog(context, ref, false), ) else _ActionButton( label: 'Remove Flag', color: const Color(0xFF6B7280), icon: Icons.flag_outlined, onTap: () => _showFlagDialog(context, ref, true), ), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Reservations', style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Color(0xFF111928), ), ), TextButton( onPressed: () => context.push('/dashboard/reservations'), child: const Text('View all'), ), ], ), const SizedBox(height: 8), reservationsAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (_, _) => const SizedBox.shrink(), data: (res) => res.data.isEmpty ? const Padding( padding: EdgeInsets.symmetric(vertical: 16), child: Center( child: Text( 'No reservations yet', style: TextStyle(color: Color(0xFF9CA3AF)), ), ), ) : Column( children: res.data .map( (r) => Padding( padding: const EdgeInsets.only(bottom: 10), child: ReservationCard( reservation: r, onTap: () => context.push( '/dashboard/reservations/${r.id}', ), ), ), ) .toList(), ), ), ], ), ); }, ); } Future _showFlagDialog( BuildContext context, WidgetRef ref, bool isFlagged) async { if (isFlagged) { final confirmed = await showDialog( context: context, builder: (_) => AlertDialog( title: const Text('Remove Flag'), content: const Text('Remove the flag from this customer?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')), ElevatedButton( onPressed: () => Navigator.pop(context, true), child: const Text('Remove Flag')), ], ), ); if (confirmed == true && context.mounted) { await ref.read(customerServiceProvider).unflagCustomer(id); ref.invalidate(customerDetailProvider(id)); } } else { final ctrl = TextEditingController(); final confirmed = await showDialog( context: context, builder: (_) => AlertDialog( title: const Text('Flag Customer'), content: TextField( controller: ctrl, decoration: const InputDecoration(labelText: 'Reason'), ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFE02424)), onPressed: () => Navigator.pop(context, true), child: const Text('Flag'), ), ], ), ); if (confirmed == true && ctrl.text.isNotEmpty && context.mounted) { await ref .read(customerServiceProvider) .flagCustomer(id, ctrl.text.trim()); ref.invalidate(customerDetailProvider(id)); } } } Future _showApproveLicenseDialog( BuildContext context, WidgetRef ref) async { final noteCtrl = TextEditingController(); final confirmed = await showDialog( context: context, builder: (_) => AlertDialog( title: const Text('Approve License'), content: TextField( controller: noteCtrl, decoration: const InputDecoration(labelText: 'Note (optional)'), ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF0E9F6E)), onPressed: () => Navigator.pop(context, true), child: const Text('Approve'), ), ], ), ); if (confirmed == true && context.mounted) { await ref.read(customerServiceProvider).approveLicense( id, 'APPROVED', note: noteCtrl.text.isNotEmpty ? noteCtrl.text : null, ); ref.invalidate(customerDetailProvider(id)); } } Future _showRejectLicenseDialog( BuildContext context, WidgetRef ref) async { final noteCtrl = TextEditingController(); final confirmed = await showDialog( context: context, builder: (_) => AlertDialog( title: const Text('Reject License'), content: TextField( controller: noteCtrl, decoration: const InputDecoration(labelText: 'Reason'), ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFE02424)), onPressed: () => Navigator.pop(context, true), child: const Text('Reject'), ), ], ), ); if (confirmed == true && context.mounted) { await ref.read(customerServiceProvider).approveLicense( id, 'REJECTED', note: noteCtrl.text.isNotEmpty ? noteCtrl.text : null, ); ref.invalidate(customerDetailProvider(id)); } } } class _InfoRow extends StatelessWidget { final IconData icon; final String value; const _InfoRow({required this.icon, required this.value}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Row( children: [ Icon(icon, size: 18, color: const Color(0xFF6B7280)), const SizedBox(width: 10), Expanded( child: Text(value, style: const TextStyle(fontSize: 14)), ), ], ), ); } } class _ActionButton extends StatelessWidget { final String label; final Color color; final IconData icon; final VoidCallback onTap; const _ActionButton({ required this.label, required this.color, required this.icon, required this.onTap, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(bottom: 10), child: ElevatedButton.icon( style: ElevatedButton.styleFrom( backgroundColor: color, minimumSize: const Size.fromHeight(48), ), icon: Icon(icon), label: Text(label), onPressed: onTap, ), ); } }