import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../../../core/network/supabase_status.dart'; import '../../features/auth/presentation/controllers/auth_controller.dart'; import '../../features/auth/presentation/screens/login_screen.dart'; import '../../features/medication/presentation/screens/medication_screen.dart'; import '../../features/nutrition/presentation/screens/nutrition_screen.dart'; import '../../features/meal_planner/presentation/screens/meal_planner_screen.dart'; import '../../features/pantry/presentation/screens/pantry_screen.dart'; import '../scaffold/adaptive_home_scaffold.dart'; /// Locations that may be visited without an authenticated session. const Set _publicPaths = {'/login'}; final _rootNavigatorKey = GlobalKey(); final _shellNavigatorKey = GlobalKey(); /// Application router with a reactive authentication guard. /// /// The guard re-evaluates on every GoTrue auth transition (bridged into /// [refreshListenable] below), so a successful magic-link or OAuth round trip /// immediately navigates into the protected shell, and signing out bounces the /// user back to `/login`. final routerProvider = Provider((ref) { final authRefreshNotifier = ValueNotifier(0); ref.onDispose(authRefreshNotifier.dispose); ref.listen(authStateProvider, (_, __) => authRefreshNotifier.value++); return GoRouter( navigatorKey: _rootNavigatorKey, initialLocation: '/medication', refreshListenable: authRefreshNotifier, redirect: _authGuard, routes: [ GoRoute( path: '/login', builder: (context, state) => const LoginScreen(), ), ShellRoute( navigatorKey: _shellNavigatorKey, builder: (context, state, child) { return AdaptiveHomeScaffold(child: child); }, routes: [ GoRoute( path: '/medication', builder: (context, state) => const MedicationScreen(), ), GoRoute( path: '/nutrition', builder: (context, state) => const NutritionScreen(), ), GoRoute( path: '/meal-planner', builder: (context, state) => const MealPlannerScreen(), ), GoRoute( path: '/pantry', builder: (context, state) => const PantryScreen(), ), ], ), ], ); }); /// Redirect guard enforcing the passwordless session lifecycle: /// * Unauthenticated sessions on a protected route -> `/login`. /// * Authenticated sessions on `/login` -> `/medication`. String? _authGuard(BuildContext context, GoRouterState state) { final location = state.matchedLocation; final isAuthenticated = isSupabaseAvailable && Supabase.instance.client.auth.currentSession != null; if (!isAuthenticated && !_publicPaths.contains(location)) { return '/login'; } if (isAuthenticated && location == '/login') { return '/medication'; } return null; }