second commit
This commit is contained in:
140
lib/core/router/app_router.dart
Normal file
140
lib/core/router/app_router.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../domain/entities/transaction.dart';
|
||||
import '../../presentation/auth/providers/auth_controller.dart';
|
||||
import '../../presentation/auth/screens/login_screen.dart';
|
||||
import '../../presentation/customer/screens/customer_registration_screen.dart';
|
||||
import '../../presentation/customer/screens/existing_customer_screen.dart';
|
||||
import '../../presentation/payment/screens/payment_screen.dart';
|
||||
import '../../presentation/pos/screens/pos_dashboard_screen.dart';
|
||||
import '../../presentation/receipt/screens/receipt_screen.dart';
|
||||
import '../../presentation/welcome/screens/welcome_screen.dart';
|
||||
|
||||
class AppRoutes {
|
||||
const AppRoutes._();
|
||||
|
||||
static const String login = '/login';
|
||||
static const String welcome = '/';
|
||||
static const String registerCustomer = '/customer/new';
|
||||
static const String existingCustomer = '/customer/find';
|
||||
static const String pos = '/pos';
|
||||
static const String payment = '/pos/payment';
|
||||
static const String receipt = '/pos/receipt';
|
||||
}
|
||||
|
||||
/// Router with an authentication guard.
|
||||
///
|
||||
/// Every route except [AppRoutes.login] requires a signed-in store, and an
|
||||
/// already-signed-in terminal is bounced away from the login screen.
|
||||
final routerProvider = Provider<GoRouter>((ref) {
|
||||
// GoRouter re-evaluates `redirect` whenever this notifier fires.
|
||||
final authChanged = ValueNotifier<bool>(
|
||||
ref.read(authControllerProvider).isAuthenticated,
|
||||
);
|
||||
ref.listen<AuthState>(
|
||||
authControllerProvider,
|
||||
(_, next) => authChanged.value = next.isAuthenticated,
|
||||
);
|
||||
ref.onDispose(authChanged.dispose);
|
||||
|
||||
return GoRouter(
|
||||
initialLocation: AppRoutes.login,
|
||||
refreshListenable: authChanged,
|
||||
debugLogDiagnostics: false,
|
||||
redirect: (context, state) {
|
||||
final signedIn = ref.read(authControllerProvider).isAuthenticated;
|
||||
final atLogin = state.matchedLocation == AppRoutes.login;
|
||||
|
||||
if (!signedIn) return atLogin ? null : AppRoutes.login;
|
||||
if (atLogin) return AppRoutes.welcome;
|
||||
return null;
|
||||
},
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.login,
|
||||
name: 'login',
|
||||
pageBuilder: (context, state) => _fade(state, const LoginScreen()),
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.welcome,
|
||||
name: 'welcome',
|
||||
pageBuilder: (context, state) => _fade(state, const WelcomeScreen()),
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.registerCustomer,
|
||||
name: 'registerCustomer',
|
||||
pageBuilder: (context, state) => _slide(
|
||||
state,
|
||||
CustomerRegistrationScreen(
|
||||
prefillMobile: state.uri.queryParameters['mobile'],
|
||||
),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.existingCustomer,
|
||||
name: 'existingCustomer',
|
||||
pageBuilder: (context, state) =>
|
||||
_slide(state, const ExistingCustomerScreen()),
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.pos,
|
||||
name: 'pos',
|
||||
pageBuilder: (context, state) =>
|
||||
_fade(state, const PosDashboardScreen()),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'payment',
|
||||
name: 'payment',
|
||||
pageBuilder: (context, state) =>
|
||||
_slide(state, const PaymentScreen()),
|
||||
),
|
||||
GoRoute(
|
||||
path: 'receipt',
|
||||
name: 'receipt',
|
||||
pageBuilder: (context, state) => _fade(
|
||||
state,
|
||||
ReceiptScreen(transaction: state.extra! as SaleTransaction),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
errorBuilder: (context, state) => Scaffold(
|
||||
body: Center(child: Text('Route not found: ${state.uri}')),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
CustomTransitionPage<void> _fade(GoRouterState state, Widget child) {
|
||||
return CustomTransitionPage(
|
||||
key: state.pageKey,
|
||||
child: child,
|
||||
transitionDuration: const Duration(milliseconds: 220),
|
||||
transitionsBuilder: (_, animation, __, child) =>
|
||||
FadeTransition(opacity: animation, child: child),
|
||||
);
|
||||
}
|
||||
|
||||
CustomTransitionPage<void> _slide(GoRouterState state, Widget child) {
|
||||
return CustomTransitionPage(
|
||||
key: state.pageKey,
|
||||
child: child,
|
||||
transitionDuration: const Duration(milliseconds: 260),
|
||||
transitionsBuilder: (_, animation, __, child) {
|
||||
final curved =
|
||||
CurvedAnimation(parent: animation, curve: Curves.easeOutCubic);
|
||||
return FadeTransition(
|
||||
opacity: curved,
|
||||
child: SlideTransition(
|
||||
position: Tween<Offset>(
|
||||
begin: const Offset(0, 0.03),
|
||||
end: Offset.zero,
|
||||
).animate(curved),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user