import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hl_lieferservice/feature/authentication/bloc/auth_bloc.dart'; import 'package:hl_lieferservice/feature/authentication/bloc/auth_state.dart'; import 'package:hl_lieferservice/feature/car_selection/bloc/bloc.dart'; import 'package:hl_lieferservice/feature/car_selection/bloc/events.dart'; import 'package:hl_lieferservice/feature/car_selection/bloc/state.dart'; import 'package:hl_lieferservice/feature/car_selection/presentation/car_selection_card.dart'; import 'package:hl_lieferservice/feature/cars/bloc/cars_bloc.dart'; import 'package:hl_lieferservice/feature/cars/bloc/cars_event.dart'; import 'package:hl_lieferservice/feature/cars/bloc/cars_state.dart'; import 'package:hl_lieferservice/feature/cars/presentation/car_dialog.dart'; import 'package:hl_lieferservice/model/car.dart'; class CarSelectionPage extends StatefulWidget { /// When set, the page is in "change" mode: the car is pre-highlighted /// and a cancel button is shown to revert without choosing a new car. final Car? previousCar; const CarSelectionPage({super.key, this.previousCar}); @override State createState() => _CarSelectionPageState(); } class _CarSelectionPageState extends State { Car? _selectedCar; bool get _isChanging => widget.previousCar != null; @override void initState() { super.initState(); _selectedCar = widget.previousCar; final authState = context.read().state as Authenticated; context.read().add(CarLoad(teamId: authState.user.number)); } void _onAddCar() { final authState = context.read().state as Authenticated; showDialog( context: context, builder: (_) => CarDialog( onAction: (plate) { context.read().add( CarAdd(teamId: authState.user.number, plate: plate), ); }, ), ); } void _onConfirm() { if (_selectedCar == null) return; final authState = context.read().state as Authenticated; context.read().add( CarSelectConfirm( userId: authState.user.number, car: _selectedCar!, ), ); } Widget _buildCarList(List cars) { if (cars.isEmpty) { return Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.local_shipping_outlined, size: 72, color: Colors.grey), const SizedBox(height: 24), Text( "Noch kein Fahrzeug vorhanden.", style: Theme.of(context).textTheme.bodyLarge, textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( "Füge zuerst ein Fahrzeug hinzu, bevor du fortfahren kannst.", style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.grey, ), textAlign: TextAlign.center, ), const SizedBox(height: 24), FilledButton.icon( onPressed: _onAddCar, icon: const Icon(Icons.add), label: const Text("Fahrzeug hinzufügen"), ), ], ), ), ); } final authState = context.read().state as Authenticated; return RefreshIndicator( onRefresh: () async { context.read().add( CarLoad(teamId: authState.user.number, force: true), ); }, child: ListView.builder( physics: const AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), itemCount: cars.length, itemBuilder: (context, index) { final car = cars[index]; return CarSelectionCard( car: car, isSelected: _selectedCar?.id == car.id, onTap: () => setState(() => _selectedCar = car), ); }, ), ); } @override Widget build(BuildContext context) { return BlocListener( listener: (context, state) { if (state is CarSelectFailed) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("Fehler beim Speichern der Fahrzeugauswahl."), ), ); } }, child: Scaffold( appBar: _isChanging ? AppBar( leading: IconButton( icon: const Icon(Icons.close), onPressed: () => context.read().add( CarSelectCancel(car: widget.previousCar!), ), ), title: const Text("Fahrzeug wechseln"), backgroundColor: Theme.of(context).primaryColor, foregroundColor: Theme.of(context).colorScheme.onSecondary, ) : null, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (!_isChanging) ...[ Padding( padding: const EdgeInsets.fromLTRB(20, 24, 20, 4), child: Text( "Fahrzeug auswählen", style: Theme.of(context).textTheme.headlineSmall, ), ), Padding( padding: const EdgeInsets.fromLTRB(20, 4, 20, 16), child: Text( "Wähle das Fahrzeug aus, das du heute verwendest.", style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.grey, ), ), ), ], Expanded( child: BlocBuilder( builder: (context, state) { if (state is CarsLoading) { return const Center(child: CircularProgressIndicator()); } if (state is CarsLoaded) { return _buildCarList(state.cars); } if (state is CarsLoadingFailed) { return Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.error_outline, size: 72, color: Theme.of(context).colorScheme.error, ), const SizedBox(height: 24), const Text( "Fehler beim Laden der Fahrzeuge.", textAlign: TextAlign.center, ), const SizedBox(height: 16), FilledButton( onPressed: () { final authState = context.read().state as Authenticated; context.read().add( CarLoad( teamId: authState.user.number, ), ); }, child: const Text("Erneut versuchen"), ), ], ), ), ); } return const SizedBox.shrink(); }, ), ), Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), child: SizedBox( width: double.infinity, child: FilledButton( onPressed: _selectedCar != null ? _onConfirm : null, child: const Text("Auswählen"), ), ), ), ], ), ), ), ); } }