import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:dio/dio.dart'; import '../../../core/models/vehicle.dart'; import '../providers/dashboard_providers.dart'; import '../../../widgets/vehicle_card.dart'; import '../../../widgets/loading_list.dart'; import '../../../widgets/error_view.dart'; import 'dashboard_shell.dart'; import 'vehicle_form_screen.dart'; class VehiclesScreen extends ConsumerStatefulWidget { const VehiclesScreen({super.key}); @override ConsumerState createState() => _VehiclesScreenState(); } class _VehiclesScreenState extends ConsumerState { String? _statusFilter; final _searchController = TextEditingController(); String _search = ''; @override void dispose() { _searchController.dispose(); super.dispose(); } VehicleQuery get _params => ( page: 1, pageSize: 100, status: null, ); List _filterVehicles(List vehicles) { final query = _search.trim().toLowerCase(); final status = _statusFilter; return vehicles.where((vehicle) { if (status != null && vehicle.status != status) { return false; } if (query.isEmpty) { return true; } final haystack = [ vehicle.displayName, vehicle.licensePlate, vehicle.status, vehicle.category, ].join(' ').toLowerCase(); return haystack.contains(query); }).toList(); } String _errorMessage(Object error) { if (error is DioException) { final data = error.response?.data; if (data is Map) { final message = data['message']; if (message is String && message.isNotEmpty) { return message; } } } return 'Failed to load vehicles'; } @override Widget build(BuildContext context) { final vehiclesAsync = ref.watch(vehiclesProvider(_params)); return DashboardShell( floatingActionButton: FloatingActionButton( onPressed: () async { final result = await Navigator.of(context).push( MaterialPageRoute(builder: (_) => const VehicleFormScreen()), ); if (result == true) ref.invalidate(vehiclesProvider(_params)); }, child: const Icon(Icons.add), ), appBar: AppBar( title: const Text('Fleet'), bottom: PreferredSize( preferredSize: const Size.fromHeight(60), child: Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), child: TextField( controller: _searchController, decoration: const InputDecoration( hintText: 'Search vehicles...', prefixIcon: Icon(Icons.search, size: 20), contentPadding: EdgeInsets.symmetric(vertical: 8), ), onChanged: (v) => setState(() => _search = v), ), ), ), actions: [ PopupMenuButton( icon: Icon( Icons.filter_list, color: _statusFilter != null ? const Color(0xFF1A56DB) : null, ), onSelected: (v) => setState(() => _statusFilter = v), itemBuilder: (_) => [ const PopupMenuItem(value: null, child: Text('All')), const PopupMenuItem(value: 'AVAILABLE', child: Text('Available')), const PopupMenuItem(value: 'RENTED', child: Text('Rented')), const PopupMenuItem( value: 'MAINTENANCE', child: Text('Maintenance'), ), ], ), ], ), body: vehiclesAsync.when( loading: () => const LoadingList(itemHeight: 240), error: (e, _) => ErrorView( message: _errorMessage(e), onRetry: () => ref.invalidate(vehiclesProvider(_params)), ), data: (res) { final filteredVehicles = _filterVehicles(res.data); return filteredVehicles.isEmpty ? const Center( child: Text( 'No vehicles found', style: TextStyle(color: Color(0xFF9CA3AF)), ), ) : RefreshIndicator( onRefresh: () async => ref.invalidate(vehiclesProvider(_params)), child: GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 1, mainAxisExtent: 240, mainAxisSpacing: 12, ), itemCount: filteredVehicles.length, itemBuilder: (_, i) => VehicleCard( vehicle: filteredVehicles[i], onTap: () => context.push( '/dashboard/fleet/${filteredVehicles[i].id}', ), ), ), ); }, ), ); } }