import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:real_estate_mobile/core/constants/app_colors.dart'; import 'package:real_estate_mobile/core/widgets/app_shell.dart'; import 'package:real_estate_mobile/features/auth/presentation/providers/auth_provider.dart'; import 'package:real_estate_mobile/features/auth/presentation/screens/login_screen.dart'; import 'package:real_estate_mobile/features/auth/presentation/screens/signup_screen.dart'; import 'package:real_estate_mobile/features/agents/presentation/screens/agent_detail_screen.dart'; import 'package:real_estate_mobile/features/agents/presentation/screens/agent_search_screen.dart'; import 'package:real_estate_mobile/features/faq/presentation/screens/faq_screen.dart'; import 'package:real_estate_mobile/features/home/presentation/screens/home_screen.dart'; import 'package:real_estate_mobile/features/messaging/presentation/screens/conversations_screen.dart'; import 'package:real_estate_mobile/features/messaging/presentation/screens/chat_screen.dart'; import 'package:real_estate_mobile/features/agents/presentation/screens/agent_home_screen.dart'; import 'package:real_estate_mobile/features/contact/presentation/screens/contact_screen.dart'; import 'package:real_estate_mobile/features/about/presentation/screens/about_screen.dart'; import 'package:real_estate_mobile/features/agents/presentation/screens/agent_network_screen.dart'; import 'package:real_estate_mobile/features/profile/presentation/screens/profile_settings_screen.dart'; import 'package:real_estate_mobile/features/notifications/presentation/screens/notifications_screen.dart'; import 'package:real_estate_mobile/features/agents/presentation/screens/agent_edit_profile_screen.dart'; import 'package:real_estate_mobile/features/profile/presentation/screens/payment_success_screen.dart'; import 'package:real_estate_mobile/features/splash/presentation/screens/splash_screen.dart'; final routerProvider = Provider((ref) { final authRefreshNotifier = _AuthRefreshNotifier(); ref.listen(authProvider, (previous, next) { authRefreshNotifier.notify(); }); ref.onDispose(() { authRefreshNotifier.dispose(); }); // Public routes accessible without authentication (matching web middleware) const publicRoutes = ['/home', '/agents/search', '/agents/detail', '/faq', '/contact', '/about']; const authRoutes = ['/login', '/signup']; return GoRouter( initialLocation: '/splash', refreshListenable: authRefreshNotifier, redirect: (context, state) { final authState = ref.read(authProvider); final isAuthenticated = authState.status == AuthStatus.authenticated; final isLoading = authState.status == AuthStatus.loading; final location = state.matchedLocation; final isAuthRoute = authRoutes.contains(location); final isPublicRoute = publicRoutes.any( (route) => location == route || location.startsWith('$route/'), ); // Never redirect away from splash — it handles its own navigation if (location == '/splash') return null; // While checking auth status, don't redirect if (isLoading) return null; // If authenticated and on auth page (login/signup), go to home if (isAuthenticated && isAuthRoute) return '/home'; // Public routes are always accessible if (isPublicRoute || isAuthRoute) return null; // Protected routes require authentication — redirect to login if (!isAuthenticated) return '/login'; return null; }, routes: [ // Splash screen (full screen, no shell) GoRoute( path: '/splash', builder: (context, state) => const SplashScreen(), ), // Auth routes (no shell — full screen) GoRoute( path: '/login', builder: (context, state) => const LoginScreen(), ), GoRoute( path: '/signup', builder: (context, state) => const SignupScreen(), ), // All main app routes wrapped in AppShell (shared header + bottom nav) ShellRoute( builder: (context, state, child) => AppShell(child: child), routes: [ GoRoute( path: '/home', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const _HomeRouteWrapper(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/agents/search', pageBuilder: (context, state) { final query = state.uri.queryParameters['q']; return CustomTransitionPage( key: state.pageKey, child: AgentSearchScreen(initialQuery: query), transitionsBuilder: _fadeTransition, ); }, ), GoRoute( path: '/agents/detail/:id', pageBuilder: (context, state) { final id = state.pathParameters['id']!; return CustomTransitionPage( key: state.pageKey, child: AgentDetailScreen(agentId: id), transitionsBuilder: _fadeTransition, ); }, ), GoRoute( path: '/messages', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const ConversationsScreen(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/messages/chat/:id', pageBuilder: (context, state) { final id = state.pathParameters['id']!; return CustomTransitionPage( key: state.pageKey, child: ChatScreen(conversationId: id), transitionsBuilder: _fadeTransition, ); }, ), GoRoute( path: '/faq', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const FaqScreen(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/contact', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const ContactScreen(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/about', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const AboutScreen(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/agent/network', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const AgentNetworkScreen(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/profile', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const ProfileSettingsScreen(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/agent/edit-profile', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const AgentEditProfileScreen(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/notifications', pageBuilder: (context, state) => CustomTransitionPage( key: state.pageKey, child: const NotificationsScreen(), transitionsBuilder: _fadeTransition, ), ), GoRoute( path: '/payment-success', pageBuilder: (context, state) { final sessionId = state.uri.queryParameters['session_id']; return CustomTransitionPage( key: state.pageKey, child: PaymentSuccessScreen(sessionId: sessionId), transitionsBuilder: _fadeTransition, ); }, ), ], ), ], ); }); /// Reactively switches between HomeScreen and AgentHomeScreen based on auth. /// Shows a loading indicator while auth status is being determined to prevent /// flashing the wrong screen on refresh. class _HomeRouteWrapper extends ConsumerWidget { const _HomeRouteWrapper(); @override Widget build(BuildContext context, WidgetRef ref) { final authState = ref.watch(authProvider); // Show loader while auth is initializing or loading if (authState.status == AuthStatus.initial || authState.status == AuthStatus.loading) { return const Center( child: CircularProgressIndicator( color: AppColors.accentOrange, ), ); } if (authState.status == AuthStatus.authenticated && authState.user?.role == 'AGENT') { return const AgentHomeScreen(); } return const HomeScreen(); } } /// Smooth fade transition for tab-to-tab navigation. Widget _fadeTransition( BuildContext context, Animation animation, Animation secondaryAnimation, Widget child, ) { return FadeTransition( opacity: CurveTween(curve: Curves.easeInOut).animate(animation), child: child, ); } /// Notifier that triggers GoRouter refresh when auth state changes. class _AuthRefreshNotifier extends ChangeNotifier { void notify() { notifyListeners(); } }