import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../auth/providers/auth_controller.dart'; /// The modules a cashier needs. Deliberately excludes analytics — this /// terminal is for billing, not back-office reporting. enum PosModule { pos('Point of Sale', 'POS', Icons.point_of_sale_rounded, NavSection.billing), customers('Customers', 'Customers', Icons.people_alt_rounded, NavSection.billing,), productImport('Product Import', 'Product Import', Icons.cloud_download_rounded, NavSection.catalogue,), promos('Promotions', 'Promo', Icons.sell_rounded, NavSection.catalogue), events('Events', 'Events', Icons.sync_rounded, NavSection.session), settings('Settings', 'Settings', Icons.settings_rounded, NavSection.session); const PosModule(this.title, this.label, this.icon, this.section); /// Long form, shown in the page header. final String title; /// Short form, shown in the sidebar. final String label; final IconData icon; final NavSection section; } /// Groups the navigation into labelled blocks. enum NavSection { billing('Billing'), catalogue('Catalogue'), session('Session'); const NavSection(this.label); final String label; List get modules => PosModule.values.where((m) => m.section == this).toList(); } /// What a cashier session may open. /// /// Billing, and nothing else — not the catalogue, the promos, the sync log or /// the terminal's configuration. The sidebar is hidden in cashier mode anyway, /// so this is the belt to that braces: a module reached some other way (a scan /// handler, a deep link, a stale value left in [activeModuleProvider] from the /// admin's session) still cannot render. const cashierModules = [PosModule.pos]; final activeModuleProvider = StateProvider((ref) => PosModule.pos); /// The modules the current session is allowed to reach. final visibleModulesProvider = Provider>((ref) { return ref.watch(isCashierModeProvider) ? cashierModules : PosModule.values; }); /// [activeModuleProvider], clamped to what this session may open. /// /// Read this rather than the raw value anywhere a module decides what gets /// built. An admin who leaves the shell on Settings and hands the till to a /// cashier would otherwise reopen it on Settings. final resolvedModuleProvider = Provider((ref) { final active = ref.watch(activeModuleProvider); final visible = ref.watch(visibleModulesProvider); return visible.contains(active) ? active : PosModule.pos; }); /// Sections that still have at least one module this session may open. final visibleSectionsProvider = Provider>((ref) { final visible = ref.watch(visibleModulesProvider); return NavSection.values .where((s) => s.modules.any(visible.contains)) .toList(); });