import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tm_app/views/board/pages/board_screen.dart'; import 'package:tm_app/views/completion_of_documents/pages/complectopn_of_documents_screen.dart'; import 'package:tm_app/views/detail/pages/detail_screen.dart'; import 'package:tm_app/views/forget_password_create/pages/forgot_password_create_screen.dart'; import 'package:tm_app/views/forget_password_otp/pages/forgot_password_otp_screen.dart'; import 'package:tm_app/views/home/pages/home_screen.dart'; import 'package:tm_app/views/liked_tenders/pages/liked_tenders_screen.dart'; import 'package:tm_app/views/login/pages/login_screen.dart'; import '../../views/final_completion_of_documents/pages/final_completion_of_documents_screen.dart'; import '../../views/forgot_password/pages/forgot_password_screen.dart'; import '../../views/notification/pages/notification_screen.dart'; import '../../views/profile/pages/profile_screen.dart'; import '../../views/splash/pages/splash_screen.dart'; import '../../views/tenders/pages/tenders_screen.dart'; import '../../views/your_tenders/pages/your_tenders_screen.dart'; import '../providers/board_provider.dart'; import '../providers/final_completion_provider.dart'; import '../providers/forgot_password_provider.dart'; import '../providers/home_provider.dart'; import '../providers/liked_tenders_provider.dart'; import '../providers/notification_provider.dart'; import '../providers/profile_provider.dart'; import '../providers/reset_password_provider.dart'; import '../providers/tender_detail_provider.dart'; import '../providers/tenders_provider.dart'; import '../providers/verify_otp_provider.dart'; import '../providers/your_tenders_provider.dart'; import 'app_shell/app_shell_screen.dart'; part 'app_routes.g.dart'; // Global navigator keys final GlobalKey rootNavigatorKey = GlobalKey(); final GlobalKey homeNavigatorKey = GlobalKey(); final GlobalKey tendersNavigatorKey = GlobalKey(); final GlobalKey profileNavigatorKey = GlobalKey(); final GlobalKey notificationNavigatorKey = GlobalKey(); // Main app router final GoRouter appRouter = GoRouter( routes: $appRoutes, initialLocation: '/splash', navigatorKey: rootNavigatorKey, redirect: (context, state) { final prefs = context.read(); final hasToken = prefs.getString('bearer') != null; final path = state.uri.path; final location = state.matchedLocation; final isSplash = path == '/splash' || location == '/splash'; final isLogin = path == '/login' || location == '/login'; final isForgotFlow = path.startsWith('/forgot-password') || location.startsWith('/forgot-password'); final isPublic = isSplash || isLogin || isForgotFlow; // If user has token and tries to access login page, redirect to home if (hasToken && isLogin) { return '/home'; } // If user doesn't have token and tries to access protected routes, redirect to splash if (!hasToken && !isPublic) { return '/splash'; } return null; }, ); // Login route - outside the shell @TypedGoRoute(path: '/login') class LoginScreenRoute extends GoRouteData with _$LoginScreenRoute { const LoginScreenRoute(); @override Widget build(BuildContext context, GoRouterState state) { return const LoginScreen(); } } // splash route - outside the shell @TypedGoRoute(path: '/splash') class SplashScreenRoute extends GoRouteData with _$SplashScreenRoute { final bool? navigateToNotification; const SplashScreenRoute({this.navigateToNotification}); @override Widget build(BuildContext context, GoRouterState state) { return SplashScreen( navigateToNotification: navigateToNotification ?? false, ); } } // Shell route with bottom navigation using StatefulShellRoute.indexedStack @TypedStatefulShellRoute( branches: >[ TypedStatefulShellBranch( routes: >[ TypedGoRoute(path: '/home'), ], ), TypedStatefulShellBranch( routes: >[ TypedGoRoute(path: '/tenders'), ], ), TypedStatefulShellBranch( routes: >[ TypedGoRoute(path: '/notification'), ], ), TypedStatefulShellBranch( routes: >[ TypedGoRoute(path: '/profile'), ], ), ], ) class AppShellRouteData extends StatefulShellRouteData { const AppShellRouteData(); static final GlobalKey $parentNavigatorKey = rootNavigatorKey; @override Widget builder( BuildContext context, GoRouterState state, StatefulNavigationShell navigationShell, ) { return AppShellScreen(navigationShell: navigationShell); } } // Branch data classes class HomeBranch extends StatefulShellBranchData { const HomeBranch(); static final GlobalKey $navigatorKey = homeNavigatorKey; } class TendersBranch extends StatefulShellBranchData { const TendersBranch(); static final GlobalKey $navigatorKey = tendersNavigatorKey; } class ProfileBranch extends StatefulShellBranchData { const ProfileBranch(); static final GlobalKey $navigatorKey = profileNavigatorKey; } class NotificationBranch extends StatefulShellBranchData { const NotificationBranch(); static final GlobalKey $navigatorKey = notificationNavigatorKey; } // Route data classes class HomeRouteData extends GoRouteData with _$HomeRouteData { const HomeRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return homeProvider(child: const HomeScreen()); } // @override // Page buildPage(BuildContext context, GoRouterState state) { // return CustomTransitionPage( // key: state.pageKey, // child: const HomeScreen(), // transitionDuration: const Duration(milliseconds: 500), // transitionsBuilder: (context, animation, secondaryAnimation, child) { // const begin = Offset(1.0, 0.0); // From right to left // const end = Offset.zero; // const curve = Curves.linearToEaseOut; // var tween = Tween( // begin: begin, // end: end, // ).chain(CurveTween(curve: curve)); // var offsetAnimation = animation.drive(tween); // return SlideTransition(position: offsetAnimation, child: child); // }, // ); // } } class TendersRouteData extends GoRouteData with _$TendersRouteData { const TendersRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return tendersProvider(child: const TendersScreen()); } } class ProfileRouteData extends GoRouteData with _$ProfileRouteData { const ProfileRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return profileProvider(child: const ProfileScreen()); } } class NotificationRouteData extends GoRouteData with _$NotificationRouteData { const NotificationRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return notificationProvider(child: const NotificationScreen()); } } @TypedGoRoute(path: '/your-tenders') class YourTendersRouteData extends GoRouteData with _$YourTendersRouteData { final String status; const YourTendersRouteData({required this.status}); @override Widget build(BuildContext context, GoRouterState state) { return yourTendersProvider(child: YourTendersScreen(status: status)); } } @TypedGoRoute( path: '/final_completion_of_documents', ) class FinalCompletionOfDocumentsRouteData extends GoRouteData with _$FinalCompletionOfDocumentsRouteData { const FinalCompletionOfDocumentsRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return finalCompletionProvider( child: const FinalCompletionOfDocumentsScreen(), ); } } @TypedGoRoute(path: '/completion_of_documents') class CompletionOfDocumentsRouteData extends GoRouteData with _$CompletionOfDocumentsRouteData { const CompletionOfDocumentsRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return const CompletionOfDocumentsScreen(); } } @TypedGoRoute(path: '/like-tenders') class LikedTendersRouteData extends GoRouteData with _$LikedTendersRouteData { const LikedTendersRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return likedTendersProvider(child: const LikedTendersScreen()); } } @TypedGoRoute(path: '/board') class BoardRouteData extends GoRouteData with _$BoardRouteData { const BoardRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return boardProvider(child: const BoardScreen()); } } // @TypedGoRoute( // path: '/completion-of-documents', // ) // class CompletionOfDocumentsMobileRouteData extends GoRouteData // with _$CompletionOfDocumentsMobileRouteData { // const CompletionOfDocumentsMobileRouteData(); // @override // Widget build(BuildContext context, GoRouterState state) { // return finalCompletionProvider( // child: const CompletionOfDocumentsMobilePage(), // ); // } // } @TypedGoRoute(path: '/tender-detail') class TenderDetailRouteData extends GoRouteData with _$TenderDetailRouteData { final String tenderId; const TenderDetailRouteData({required this.tenderId}); @override Widget build(BuildContext context, GoRouterState state) { return tenderDetailProvider(child: TenderDetailScreen(tenderId: tenderId)); } } @TypedGoRoute(path: '/forgot-password') class ForgotPasswordRouteData extends GoRouteData with _$ForgotPasswordRouteData { const ForgotPasswordRouteData(); @override Widget build(BuildContext context, GoRouterState state) { return forgotPasswordProvider(child: const ForgotPasswordScreen()); } } @TypedGoRoute(path: '/forgot-password-otp') class ForgotPasswordOtpRouteData extends GoRouteData with _$ForgotPasswordOtpRouteData { final String email; const ForgotPasswordOtpRouteData({required this.email}); @override Widget build(BuildContext context, GoRouterState state) { return verifyOtpProvider(child: ForgotPasswordOtpScreen(email: email)); } } @TypedGoRoute(path: '/forgot-password-create') class ForgotPasswordCreateRouteData extends GoRouteData with _$ForgotPasswordCreateRouteData { final String resetToken; const ForgotPasswordCreateRouteData({required this.resetToken}); @override Widget build(BuildContext context, GoRouterState state) { return resetPasswordProvider( child: ForgotPasswordCreateScreen(resetToken: resetToken), ); } }