import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:intaleq_maps/intaleq_maps.dart'; import '../features/auth/cubit/auth_cubit.dart'; import '../features/auth/cubit/auth_state.dart'; import '../features/splash/view/splash_screen.dart'; import '../features/onboarding/view/onboarding_screen.dart'; import '../features/auth/view/phone_screen.dart'; import '../features/auth/view/otp_screen.dart'; import '../features/auth/view/name_screen.dart'; import '../features/home/view/home_screen.dart'; import '../features/home/view/destination_screen.dart'; import '../features/home/view/route_preview_screen.dart'; import '../features/trip/view/trip_tracking_screen.dart'; import '../features/trip/view/trip_invoice_screen.dart'; import '../features/trip/view/rating_screen.dart'; import '../features/home/cubit/home_cubit.dart'; import '../features/home/cubit/destination_cubit.dart'; import '../features/home/cubit/quote_cubit.dart'; import '../features/home/cubit/saved_places_cubit.dart'; import '../features/home/data/models/place_model.dart'; import '../features/home/data/maps_repository.dart'; import '../features/home/data/tariff_repository.dart'; import '../core/storage/saved_places_store.dart'; import '../core/l10n/app_localizations.dart'; import 'di.dart'; GoRouter buildRouter(AuthCubit auth) { return GoRouter( initialLocation: '/splash', refreshListenable: _StreamRefresh(auth.stream), redirect: (context, state) { final status = auth.state.status; final loc = state.matchedLocation; final onSplash = loc == '/splash'; final onOnboarding = loc == '/onboarding'; final onAuthPages = loc == '/phone' || loc == '/otp' || loc == '/name'; final onNamePage = loc == '/name'; if (status == AuthStatus.authenticated) { final hasName = auth.state.user?.name != null && auth.state.user!.name!.trim().isNotEmpty; if (!hasName && !onNamePage) return '/name'; if (hasName && onNamePage) return '/home'; if (onAuthPages || onSplash || onOnboarding) return hasName ? '/home' : '/name'; return null; } if (onSplash || onOnboarding) return null; if (status == AuthStatus.codeSent && loc == '/phone') return '/otp'; if (status != AuthStatus.authenticated && !onAuthPages) return '/phone'; return null; }, routes: [ GoRoute(path: '/splash', builder: (_, __) => const SplashScreen()), GoRoute(path: '/onboarding', builder: (_, __) => const OnboardingScreen()), GoRoute(path: '/phone', builder: (_, __) => const PhoneScreen()), GoRoute(path: '/otp', builder: (_, __) => const OtpScreen()), GoRoute(path: '/name', builder: (_, __) => const NameScreen()), GoRoute( path: '/home', builder: (_, __) => MultiBlocProvider( providers: [ BlocProvider(create: (_) => HomeCubit(getIt())), BlocProvider(create: (_) => SavedPlacesCubit(getIt())), ], child: const HomeScreen(), ), ), GoRoute( path: '/destination', builder: (_, state) { final extra = state.extra as Map?; final currentLocation = extra?['currentLocation'] as LatLng?; return BlocProvider( create: (_) => DestinationCubit(getIt()), child: DestinationScreen(currentLocation: currentLocation), ); }, ), GoRoute( path: '/route-preview', builder: (_, state) { final extra = state.extra as Map?; final pickup = extra?['pickup'] as PlaceModel?; final destination = extra?['destination'] as PlaceModel?; if (pickup == null || destination == null) { return Builder( builder: (ctx) => Scaffold( body: Center( child: Text(AppLocalizations.of(ctx)?.missingDataError ?? ''), ), ), ); } return BlocProvider( create: (_) => QuoteCubit(getIt()), child: RoutePreviewScreen(pickup: pickup, destination: destination), ); }, ), GoRoute(path: '/trip-tracking', builder: (_, __) => const TripTrackingScreen()), GoRoute(path: '/trip-invoice', builder: (_, __) => const TripInvoiceScreen()), GoRoute(path: '/trip-rating', builder: (_, __) => const RatingScreen()), ], ); } class _StreamRefresh extends ChangeNotifier { late final StreamSubscription _sub; _StreamRefresh(Stream stream) { notifyListeners(); _sub = stream.asBroadcastStream().listen((_) => notifyListeners()); } @override void dispose() { _sub.cancel(); super.dispose(); } }