import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/constants/app_constants.dart'; import '../../../domain/entities/store_account.dart'; /// Sign-in state for the terminal. sealed class AuthState { const AuthState(); bool get isAuthenticated => this is Authenticated; } class Unauthenticated extends AuthState { const Unauthenticated(); } class Authenticating extends AuthState { const Authenticating(); } class Authenticated extends AuthState { const Authenticated({required this.store, required this.user}); final StoreAccount store; final StaffUser user; } class AuthFailure extends AuthState { const AuthFailure(this.message); final String message; } /// Credentials that ship with the demo build. class DemoCredentials { const DemoCredentials._(); static const String email = 'admin@nearle.in'; static const String password = 'nearle123'; } const _demoStore = StoreAccount( id: 'store-001', name: AppConstants.storeName, email: DemoCredentials.email, address: AppConstants.storeAddress, gstin: AppConstants.storeGstin, phone: AppConstants.storePhone, staff: [ StaffUser(id: 'u1', name: 'Suriya', role: StaffRole.admin, pin: '1234'), StaffUser(id: 'u2', name: 'Divya', role: StaffRole.manager, pin: '2345'), StaffUser(id: 'u3', name: 'Rahul', role: StaffRole.cashier, pin: '3456'), ], ); /// Validates store credentials and holds the signed-in session. /// /// Backed by a hardcoded account for now; swapping in a real identity provider /// means changing only [signIn]. class AuthController extends StateNotifier { AuthController() : super(const Unauthenticated()); Future signIn({ required String email, required String password, }) async { state = const Authenticating(); // Stand-in for the network round trip. await Future.delayed(const Duration(milliseconds: 600)); final normalised = email.trim().toLowerCase(); if (normalised != DemoCredentials.email) { state = const AuthFailure('No store is registered against that email.'); return false; } if (password != DemoCredentials.password) { state = const AuthFailure('Incorrect password. Please try again.'); return false; } state = Authenticated(store: _demoStore, user: _demoStore.staff.first); return true; } /// Switches the active operator without signing the store out. void switchUser(StaffUser user) { final current = state; if (current is! Authenticated) return; state = Authenticated(store: current.store, user: user); } void signOut() => state = const Unauthenticated(); void clearError() { if (state is AuthFailure) state = const Unauthenticated(); } } final authControllerProvider = StateNotifierProvider((ref) => AuthController()); /// The signed-in store, or null before sign-in. final currentStoreProvider = Provider((ref) { final s = ref.watch(authControllerProvider); return s is Authenticated ? s.store : null; }); /// The active operator, or null before sign-in. final currentUserProvider = Provider((ref) { final s = ref.watch(authControllerProvider); return s is Authenticated ? s.user : null; });