import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import '../viewmodels/admin_pin_view_model.dart'; import '../viewmodels/pin_lock_view_model.dart'; import '../views/admin_screen_view.dart'; import '../views/bar_screen_view.dart'; import '../views/dev_menu_view.dart'; import '../views/error_screen_view.dart'; import '../views/history_screen_view.dart'; import '../views/import_names_view.dart'; import '../views/pin_lock_view.dart'; import '../views/product_form_view.dart'; import '../views/product_list_view.dart'; import '../views/settings_view.dart'; import '../views/update_progress_view.dart'; import '../utils/app_update_util.dart'; final RouteObserver routeObserver = RouteObserver(); GoRouter createAppRouter( PinLockViewModel pinLockViewModel, { required AdminPinViewModel adminPinViewModel, }) { return GoRouter( initialLocation: '/bar', observers: [routeObserver, SentryNavigatorObserver()], refreshListenable: Listenable.merge([pinLockViewModel, adminPinViewModel]), redirect: (context, state) { if (!pinLockViewModel.hasLoaded || !adminPinViewModel.hasLoaded) { return null; } final needsPinSetup = !pinLockViewModel.isPinSet && pinLockViewModel.pinRequired; final isLocked = pinLockViewModel.isPinSet && !pinLockViewModel.isUnlocked && pinLockViewModel.pinRequired; final mustBeOnLock = needsPinSetup || isLocked; final location = state.uri.path; final goingToLock = location == '/lock'; final goingToAdminLock = location == '/admin/lock'; final isAdminArea = location == '/admin' || location.startsWith('/admin/') || location == '/products' || location.startsWith('/products/'); if (mustBeOnLock && !goingToLock) return '/lock'; if (!mustBeOnLock && goingToLock) return '/bar'; if (isAdminArea && !goingToAdminLock && !adminPinViewModel.isUnlocked) { return '/admin/lock'; } if (goingToAdminLock && adminPinViewModel.isUnlocked) return '/admin'; return null; }, routes: [ GoRoute(path: '/', redirect: (context, state) => '/bar'), GoRoute( path: '/lock', builder: (context, state) => PinEntryView( mode: pinLockViewModel.isPinSet ? PinEntryMode.unlock : PinEntryMode.create, onSuccess: () { context.go("/bar"); }, ), ), GoRoute(path: '/bar', builder: (context, state) => const BarScreenView()), GoRoute( path: '/admin/lock', builder: (context, state) => PinEntryView( mode: adminPinViewModel.isPinSet ? PinEntryMode.unlock : PinEntryMode.create, isAdmin: true, onVerify: adminPinViewModel.verify, onSet: adminPinViewModel.setPin, errorMessage: () => adminPinViewModel.errorMessage, onSuccess: () => context.go('/admin'), ), ), GoRoute( path: '/admin', builder: (context, state) => const AdminScreenView(), routes: [ GoRoute( path: 'import', builder: (context, state) => const ImportNamesView(), ), ], ), GoRoute( path: '/products', builder: (context, state) => const ProductListView(), routes: [ GoRoute( path: 'new', builder: (context, state) => const ProductFormView(), ), GoRoute( path: ':id/edit', builder: (context, state) { final productId = state.pathParameters['id']!; return ProductFormView(productId: productId); }, ), ], ), GoRoute( path: '/history', builder: (context, state) => const HistoryScreenView(), ), GoRoute( path: '/settings', builder: (context, state) => const SettingsScreenView(), ), GoRoute( path: '/update-progress', builder: (context, state) { final update = state.extra as UpdateInfo; final simulate = state.uri.queryParameters['simulate'] == 'true'; final simulateError = state.uri.queryParameters['simulateError'] == 'true'; return UpdateProgressView( update: update, simulate: simulate, simulateError: simulateError, ); }, ), GoRoute(path: '/dev', builder: (context, state) => const DevMenuView()), GoRoute( path: '/error', builder: (context, state) => const ErrorScreenView(), ), ], ); }