import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../screens/auth/login_screen.dart'; import '../../screens/shell/app_shell.dart'; import '../../screens/stock_in/stock_in_list_screen.dart'; import '../../screens/stock_in/stock_in_form_screen.dart'; import '../../screens/stock_out/stock_out_list_screen.dart'; import '../../screens/stock_out/stock_out_form_screen.dart'; import '../../screens/inventory/inventory_list_screen.dart'; import '../../screens/inventory/inventory_check_screen.dart'; import '../../screens/partners/partners_screen.dart'; import '../../screens/finance/finance_screen.dart'; import '../../screens/products/products_screen.dart'; import '../../screens/products/product_detail_screen.dart'; import '../../screens/public/public_product_screen.dart'; import '../../screens/public/public_shop_products_screen.dart'; import '../../screens/settings/settings_screen.dart'; import '../../screens/about/about_screen.dart'; import '../auth/auth_state.dart'; Page _noTransition(Widget child) => NoTransitionPage(child: child); /// ChangeNotifier that bridges Riverpod auth state → GoRouter refreshListenable. class _RouterNotifier extends ChangeNotifier { final Ref _ref; _RouterNotifier(this._ref) { _ref.listen(authStateProvider, (prev, next) { debugPrint('[Router] authState changed:' ' initialized=${next.initialized}' ' isLoggedIn=${next.isLoggedIn}' ' user=${next.user?.username}'); notifyListeners(); }); } String? redirect(BuildContext context, GoRouterState state) { final authState = _ref.read(authStateProvider); final isLoggedIn = authState.isLoggedIn; final loc = state.matchedLocation; final isPublicRoute = loc == '/login' || loc.startsWith('/product/') || loc.startsWith('/shop/'); final result = !authState.initialized ? null : (!isLoggedIn && !isPublicRoute) ? '/login' : (isLoggedIn && loc == '/login') ? '/stock-in' : null; debugPrint('[Router] redirect: location=$loc' ' initialized=${authState.initialized}' ' isLoggedIn=$isLoggedIn' ' → ${result ?? "null (no redirect)"}'); return result; } } /// Separate provider so that appRouterProvider has NO dependencies and /// is never rebuilt when auth state changes (prevents router reset to /login). final _routerNotifierProvider = Provider<_RouterNotifier>((ref) { final notifier = _RouterNotifier(ref); ref.onDispose(notifier.dispose); return notifier; }); final appRouterProvider = Provider((ref) { // Use ref.read (not ref.watch) so appRouterProvider never rebuilds on auth change. final notifier = ref.read(_routerNotifierProvider); final router = GoRouter( initialLocation: '/login', refreshListenable: notifier, redirect: notifier.redirect, routes: [ // Public product scan — no auth, no shell nav bar GoRoute( path: '/product/:public_id', builder: (context, state) => PublicProductScreen(publicId: state.pathParameters['public_id']!), ), // Public shop product list — no auth, no shell nav bar GoRoute( path: '/shop/:shop_code', builder: (context, state) => PublicShopProductsScreen( shopCode: state.pathParameters['shop_code']!, shopName: state.uri.queryParameters['shopName'] ?? '', ), ), GoRoute( path: '/login', builder: (context, state) => const LoginScreen(), ), ShellRoute( builder: (context, state, child) => AppShell(child: child), routes: [ GoRoute( path: '/stock-in', pageBuilder: (_, __) => _noTransition(const StockInListScreen())), GoRoute( path: '/stock-in/new', pageBuilder: (_, __) => _noTransition(const StockInFormScreen())), GoRoute( path: '/stock-in/edit/:id', pageBuilder: (_, state) => _noTransition( StockInFormScreen( editOrderId: int.parse(state.pathParameters['id']!)))), GoRoute( path: '/stock-out', pageBuilder: (_, __) => _noTransition(const StockOutListScreen())), GoRoute( path: '/stock-out/new', pageBuilder: (_, __) => _noTransition(const StockOutFormScreen())), GoRoute( path: '/stock-out/edit/:id', pageBuilder: (_, state) => _noTransition( StockOutFormScreen( editOrderId: int.parse(state.pathParameters['id']!)))), GoRoute( path: '/inventory', pageBuilder: (_, __) => _noTransition(const InventoryListScreen())), GoRoute( path: '/inventory/check', pageBuilder: (_, __) => _noTransition(const InventoryCheckScreen())), GoRoute( path: '/partners', pageBuilder: (_, __) => _noTransition(const PartnersScreen())), GoRoute( path: '/finance', pageBuilder: (_, __) => _noTransition(const FinanceScreen())), GoRoute( path: '/products', pageBuilder: (_, __) => _noTransition(const ProductsScreen())), GoRoute( path: '/products/:id', pageBuilder: (_, state) => _noTransition(ProductDetailScreen( productId: int.parse(state.pathParameters['id']!)))), GoRoute( path: '/settings', pageBuilder: (_, __) => _noTransition(const SettingsScreen())), GoRoute( path: '/about', pageBuilder: (_, __) => _noTransition(const AboutScreen())), ], ), ], ); ref.onDispose(router.dispose); return router; });