import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../models/vehicle.dart'; import '../services/app_state.dart'; import '../services/onboarding_keys.dart'; import 'add_edit_vehicle_screen.dart'; import 'vehicle_detail_screen.dart'; /// The "Vehicles" tab body — Settings and Reports are reached via the /// bottom nav now (see [MainShell]), not from icons here. class HomeScreen extends StatelessWidget { const HomeScreen({super.key}); @override Widget build(BuildContext context) { final appState = context.watch(); final vehicles = appState.vehicles; return Scaffold( appBar: AppBar( title: const Text('Vehicles'), actionsPadding: const EdgeInsets.only(right: 20), actions: [ IconButton( key: OnboardingKeys.vehiclesAddButton, icon: const Icon(Icons.add), tooltip: 'Add Vehicle', onPressed: () => Navigator.of(context).push( MaterialPageRoute(builder: (_) => const AddEditVehicleScreen()), ), ), ], ), body: vehicles.isEmpty ? const _EmptyState() : ListView.separated( padding: const EdgeInsets.all(12), itemCount: vehicles.length, separatorBuilder: (_, _) => const SizedBox(height: 8), itemBuilder: (context, index) { final vehicle = vehicles[index]; final gallons = appState.totalGallonsForVehicle(vehicle.id); return _VehicleCard(vehicle: vehicle, totalGallons: gallons); }, ), ); } } class _VehicleCard extends StatelessWidget { final Vehicle vehicle; final double totalGallons; const _VehicleCard({required this.vehicle, required this.totalGallons}); @override Widget build(BuildContext context) { final hasNickname = vehicle.nickname?.trim().isNotEmpty ?? false; final gallonsLine = '${totalGallons.toStringAsFixed(3)} gallons logged'; return Card( clipBehavior: Clip.antiAlias, child: InkWell( onTap: () => Navigator.of(context).push( MaterialPageRoute(builder: (_) => VehicleDetailScreen(vehicleId: vehicle.id)), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), // Row cross-axis defaults to center, so the chevron sits // vertically centered against the title+subtitle block even when // the nickname line makes that block taller — ListTile's // isThreeLine forces leading/trailing to the top instead, per // Material spec, which is what pinned it to the top before. child: Row( children: [ const CircleAvatar(child: Icon(Icons.directions_car_outlined)), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text(vehicle.displayLabel, style: Theme.of(context).textTheme.titleMedium), // Only repeat the VIN here when the title is already // showing the nickname instead — otherwise the title // (falling back to the VIN when there's no nickname) // would show it twice. Text( hasNickname ? 'VIN: ${vehicle.vin}\n$gallonsLine' : gallonsLine, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], ), ), const Icon(Icons.chevron_right), ], ), ), ), ); } } class _EmptyState extends StatelessWidget { const _EmptyState(); @override Widget build(BuildContext context) { return Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.local_shipping_outlined, size: 64, color: Theme.of(context).colorScheme.outline), const SizedBox(height: 16), Text( 'No vehicles yet. Add a vehicle to start logging fuel receipts.', textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyLarge, ), ], ), ), ); } }