import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../data/routing_repository.dart'; class RoutingState { final double? originLat; final double? originLon; final String originName; final double? destLat; final double? destLon; final String destName; final String profile; // driving, walking, cycling final List routes; final int selectedRouteIndex; final bool isLoading; final String? error; const RoutingState({ this.originLat, this.originLon, this.originName = 'My Location', this.destLat, this.destLon, this.destName = '', this.profile = 'driving', this.routes = const [], this.selectedRouteIndex = 0, this.isLoading = false, this.error, }); RoutingState copyWith({ double? originLat, double? originLon, String? originName, double? destLat, double? destLon, String? destName, String? profile, List? routes, int? selectedRouteIndex, bool? isLoading, String? error, bool clearError = false, }) { return RoutingState( originLat: originLat ?? this.originLat, originLon: originLon ?? this.originLon, originName: originName ?? this.originName, destLat: destLat ?? this.destLat, destLon: destLon ?? this.destLon, destName: destName ?? this.destName, profile: profile ?? this.profile, routes: routes ?? this.routes, selectedRouteIndex: selectedRouteIndex ?? this.selectedRouteIndex, isLoading: isLoading ?? this.isLoading, error: clearError ? null : (error ?? this.error), ); } RouteData? get selectedRoute => routes.isNotEmpty && selectedRouteIndex < routes.length ? routes[selectedRouteIndex] : null; } class RoutingNotifier extends StateNotifier { final RoutingRepository _repository; RoutingNotifier(this._repository) : super(const RoutingState()); void setOrigin(double lat, double lon, String name) { state = state.copyWith( originLat: lat, originLon: lon, originName: name, routes: [], ); } void setDestination(double lat, double lon, String name) { state = state.copyWith( destLat: lat, destLon: lon, destName: name, routes: [], ); } void setProfile(String profile) { state = state.copyWith(profile: profile, routes: []); } void selectRoute(int index) { state = state.copyWith(selectedRouteIndex: index); } Future calculateRoute() async { if (state.originLat == null || state.originLon == null || state.destLat == null || state.destLon == null) { state = state.copyWith(error: 'Please set both origin and destination.'); return; } state = state.copyWith(isLoading: true, clearError: true, routes: []); try { final routes = await _repository.getRoute( profile: state.profile, originLat: state.originLat!, originLon: state.originLon!, destLat: state.destLat!, destLon: state.destLon!, ); if (mounted) { state = state.copyWith( routes: routes, selectedRouteIndex: 0, isLoading: false, ); } } catch (e) { if (mounted) { state = state.copyWith( isLoading: false, error: 'Could not calculate route. Please try again.', ); } } } } final routingProvider = StateNotifierProvider.autoDispose((ref) { return RoutingNotifier(ref.watch(routingRepositoryProvider)); });