import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../providers/auth_provider.dart'; import '../providers/profile_provider.dart'; import '../providers/supabase_provider.dart'; import '../utils/lock_enforcer.dart'; import '../screens/auth/login_screen.dart'; import '../screens/auth/signup_screen.dart'; import '../screens/admin/offices_screen.dart'; import '../screens/admin/user_management_screen.dart'; import '../screens/dashboard/dashboard_screen.dart'; import '../screens/notifications/notifications_screen.dart'; import '../screens/shared/under_development_screen.dart'; import '../screens/tasks/task_detail_screen.dart'; import '../screens/tasks/tasks_list_screen.dart'; import '../screens/tickets/ticket_detail_screen.dart'; import '../screens/tickets/tickets_list_screen.dart'; import '../screens/workforce/workforce_screen.dart'; import '../widgets/app_shell.dart'; import '../screens/teams/teams_screen.dart'; final appRouterProvider = Provider((ref) { final notifier = RouterNotifier(ref); ref.onDispose(notifier.dispose); return GoRouter( initialLocation: '/dashboard', refreshListenable: notifier, redirect: (context, state) { final authState = ref.read(authStateChangesProvider); final session = authState.maybeWhen( data: (state) => state.session, orElse: () => ref.read(sessionProvider), ); final isAuthRoute = state.fullPath == '/login' || state.fullPath == '/signup'; final isSignedIn = session != null; final profileAsync = ref.read(currentProfileProvider); final isAdminRoute = state.matchedLocation.startsWith('/settings'); final isAdmin = profileAsync.maybeWhen( data: (profile) => profile?.role == 'admin', orElse: () => false, ); if (!isSignedIn && !isAuthRoute) { return '/login'; } if (isSignedIn && isAuthRoute) { return '/dashboard'; } if (isAdminRoute && !isAdmin) { return '/tickets'; } return null; }, routes: [ GoRoute(path: '/login', builder: (context, state) => const LoginScreen()), GoRoute( path: '/signup', builder: (context, state) => const SignUpScreen(), ), ShellRoute( builder: (context, state, child) => AppScaffold(child: child), routes: [ GoRoute( path: '/settings/teams', builder: (context, state) => const TeamsScreen(), ), GoRoute( path: '/dashboard', builder: (context, state) => const DashboardScreen(), ), GoRoute( path: '/tickets', builder: (context, state) => const TicketsListScreen(), routes: [ GoRoute( path: ':id', builder: (context, state) => TicketDetailScreen( ticketId: state.pathParameters['id'] ?? '', ), ), ], ), GoRoute( path: '/tasks', builder: (context, state) => const TasksListScreen(), routes: [ GoRoute( path: ':id', builder: (context, state) => TaskDetailScreen(taskId: state.pathParameters['id'] ?? ''), ), ], ), GoRoute( path: '/events', builder: (context, state) => const UnderDevelopmentScreen( title: 'Events', subtitle: 'Event monitoring is under development.', icon: Icons.event, ), ), GoRoute( path: '/announcements', builder: (context, state) => const UnderDevelopmentScreen( title: 'Announcement', subtitle: 'Operational broadcasts are coming soon.', icon: Icons.campaign, ), ), GoRoute( path: '/workforce', builder: (context, state) => const WorkforceScreen(), ), GoRoute( path: '/reports', builder: (context, state) => const UnderDevelopmentScreen( title: 'Reports', subtitle: 'Reporting automation is under development.', icon: Icons.analytics, ), ), GoRoute( path: '/settings/users', builder: (context, state) => const UserManagementScreen(), ), GoRoute( path: '/settings/offices', builder: (context, state) => const OfficesScreen(), ), GoRoute( path: '/notifications', builder: (context, state) => const NotificationsScreen(), ), ], ), ], ); }); class RouterNotifier extends ChangeNotifier { RouterNotifier(this.ref) { _authSub = ref.listen(authStateChangesProvider, (previous, next) { // Enforce auth-level ban when a session becomes available. next.maybeWhen( data: (authState) { final session = authState.session; if (session != null) { // Fire-and-forget enforcement (best-effort client-side sign-out) enforceLockForCurrentUser(ref.read(supabaseClientProvider)); } }, orElse: () {}, ); notifyListeners(); }); _profileSub = ref.listen(currentProfileProvider, (previous, next) { notifyListeners(); }); } final Ref ref; late final ProviderSubscription _authSub; late final ProviderSubscription _profileSub; @override void dispose() { _authSub.close(); _profileSub.close(); super.dispose(); } }