This commit is contained in:
2026-08-07 14:34:25 +05:30
parent 829e5a8188
commit 0988d39d8b
19 changed files with 850 additions and 932 deletions

View File

@@ -1,5 +1,6 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/config/api_config.dart';
import '../core/config/sync_config.dart';
import '../core/services/connectivity_service.dart';
import '../core/services/receipt_service.dart';
@@ -7,6 +8,7 @@ import '../core/services/sound_service.dart';
import '../data/datasources/local_store.dart';
import '../data/repositories/customer_repository_impl.dart';
import '../data/repositories/product_repository_impl.dart';
import '../data/remote/auth_api.dart';
import '../data/remote/catalogue_source.dart';
import '../data/remote/http_catalogue_source.dart';
import '../data/remote/simulated_catalogue_source.dart';
@@ -17,9 +19,7 @@ import '../data/remote/simulated_order_transport.dart';
import '../data/repositories/store_repository_impl.dart';
import '../data/repositories/sync_repository_impl.dart';
import '../data/repositories/transaction_repository_impl.dart';
import '../data/local/session_store.dart';
import '../data/local/terminal_identity.dart';
import '../data/remote/pos_auth_api.dart';
import '../data/sync/sync_engine.dart';
import '../domain/repositories/customer_repository.dart';
import '../domain/repositories/product_repository.dart';
@@ -91,14 +91,30 @@ final catalogueSourceProvider = Provider<CatalogueSource>((ref) {
/// exists to prevent.
final syncConfigProvider = StateProvider<SyncConfig>((ref) {
final terminal = ref.watch(terminalIdentityProvider);
final session = ref.watch(apiSessionProvider);
return SyncConfig(
transport: TransportKind.http,
httpBaseUrl: 'https://fiesta.nearle.app/live/api/v1/pos',
storeId: terminal.storeId,
httpBaseUrl: ApiConfig.baseUrl,
// The location the sign-in was scoped to, falling back to whatever this
// device was last pointed at. Never a literal: two outlets sharing a
// store id would post sales into each other's books.
storeId: session?.storeId ?? terminal.storeId,
terminalId: terminal.code,
// The bearer token from `POST /login`. Held here rather than in the
// keystore because it expires — see `LoginSession.expiresAt` — so it
// belongs to the session and goes when the session does.
apiKey: session?.token,
);
});
/// Signs the terminal in. Owns its own HTTP client, closed with the provider.
final authApiProvider = Provider<AuthApi>((ref) {
final api = AuthApi();
ref.onDispose(api.dispose);
return api;
});
/// Real network state, folded with the Settings offline switch.
final connectivityServiceProvider = Provider<ConnectivityService>((ref) {
final service = ConnectivityService(
@@ -163,30 +179,16 @@ final storeRepositoryProvider = Provider<StoreRepositoryImpl>(
(ref) => StoreRepositoryImpl(ref.watch(localStoreProvider)),
);
/// Signs a terminal in against the back office.
///
/// Points at the same base URL the uplinks use, so re-pointing a terminal in
/// Settings moves its sign-in with it rather than leaving it authenticating
/// against the endpoint it used to belong to.
final posAuthApiProvider = Provider<PosAuthApi>((ref) {
final api = PosAuthApi(baseUrl: ref.watch(syncConfigProvider).httpBaseUrl);
ref.onDispose(api.dispose);
return api;
});
/// Where the signed session survives a restart.
final sessionStoreProvider = Provider<SessionStore>((ref) => SessionStore());
/// The outlet, refreshed whenever staff or details change.
///
/// The email is the signed-in account's, not a constant. It used to be a
/// `DemoCredentials.email` compiled into the build — the same address on every
/// install, which is what made the store login decorative.
final storeAccountProvider = FutureProvider<StoreAccount>(
(ref) => ref.watch(storeRepositoryProvider).load(
email: ref.watch(authControllerProvider.notifier).session?.email ?? '',
),
);
final storeAccountProvider = FutureProvider<StoreAccount>((ref) {
// The address the back office signed in, so Settings and the invoice header
// show the account that actually owns this till rather than a build
// constant. Falls back only before anyone has signed in.
final email = ref.watch(apiSessionProvider)?.email;
return ref.watch(storeRepositoryProvider).load(
email: (email == null || email.isEmpty) ? DemoCredentials.email : email,
);
});
/// Campaigns stored on this terminal.
final promosProvider = FutureProvider<List<Promo>>(
@@ -246,9 +248,11 @@ final terminalIdentityProvider = Provider<TerminalIdentity>((ref) {
final cashierSessionProvider = StateProvider<CashierSession>((ref) {
final terminal = ref.watch(terminalIdentityProvider);
final session = ref.watch(apiSessionProvider);
return CashierSession(
name: 'Suriya',
role: 'ADMIN',
name: session?.displayUserName ?? 'Operator',
role: (session?.isAdmin ?? false) ? 'ADMIN' : 'CASHIER',
terminalId: terminal.code,
);
});