14 — Frontend
CEO Summary
Two React apps: frontend (dashboard, POS, admin) and public-site (marketing, signup). Business value: User experience; signup conversion. Key metrics: Page load, offline capability. If this breaks: Users cannot access dashboard; signup fails.
Overview
| App | Port | Purpose |
|---|---|---|
| frontend | 5173 | Dashboard, POS, admin, reports |
| public-site | 5174 | Marketing, signup, login |
Frontend Routes (key)
/dashboard, /pos, /pos/bar, /pos/kitchen (KDS; optional ?station= slug to filter tickets), /pos/mobile, /pos/kiosk, /admin/* (includes /admin/signage, /admin/kitchen-displays — KDS routing settings), /inventory/*, /reports/*, /customers, /master-admin/*, /:tenantSlug/signage/:displaySlug (public fullscreen player; optional ?reloadSec=)
Public Site Routes
/, /signup, /signup/success, /login, /forgot-password, /reset-password/:token, /pricing, /features, /about, /employee-portal
Offline Support & POS mutation envelope
Path: frontend/src/lib/offline/
- db.js — IndexedDB
pawspos_offline, object storequeue; runs one-time migration from legacyppos_offline_v1viamigrateLegacyQueue.js - queue.js — Enqueue/replay jobs with
Idempotency-Key+ PPO headers; coordinates with service worker (queueSignal.js) - mutationEnvelope.js — Device/register ids, monotonic sequence, header builder;
getRegisterId()aligns withpos_device_keyfromDeviceSelector - tryOnlineThenQueue.js — Shared “attempt API → on network/5xx enqueue” helper (same headers online and queued)
- migrateLegacyQueue.js — Copies queued jobs from old DB name into
pawspos_offline - registerSW.js / queue registration — Service worker at
frontend/public/sw.js(built todist/sw.js): same DB name for background sync; migrates legacy DB on activate - useOfflineStatus.js, useOfflineSimple.js — React hooks
- OfflineBanner.jsx — UI indicator
POS API wrapper: frontend/src/pos/api.js exports posApi — all mutating cart operations use tryOnlineThenQueue with full /api/pos/... URLs. Used by ModernPOS, StandardPOS, Kiosk, Storefront (and pos/offlineActions.js as thin re-exports). frontend/src/api/client.js does not overwrite an existing Idempotency-Key header.
Register scope: components/POS/DeviceSelector.jsx calls setRegisterId() so offline sequences scope to the selected terminal.
Shared Components
BarcodeScanInput, FeatureGate, Protected, StaffProtected, CustomerProtected, RegisterLoginScreen, RegisterOpeningDialog
API Client & Modules
Primary: frontend/src/api/client.js — Axios, withCredentials, X-Tenant-Slug, X-Org-Id from localStorage
Domain APIs: userProfiles.js, hr.js, reports.js, audit.js, catalog.js, adminCatalog.js, users.js, tx.js, staff.js, profiles.js, inventory.js, features.js, devices.js, customers.js, adminPayments.js, admin.js
Other: tenantClient.js, http.js, v1/client.js, catalogLocal.js, api.ts (TypeScript)
Navigation
Path: frontend/src/lib/navigation/
themes.js, registry.js — Theme registry, navigation config. Used by NavigationRenderer.
Lib Modules
| Path | Purpose |
|---|---|
| lib/offline/ | db.js, queue.js, queueSignal.js, mutationEnvelope.js, tryOnlineThenQueue.js, migrateLegacyQueue.js, registerSW.js, sw-client.js, useOfflineStatus, useOfflineSimple, OfflineBanner |
| lib/ui/ | NotificationSystem, toast, badge |
| lib/error/ | GlobalErrorBoundary |
| lib/navigation/ | themes, registry |
| lib/api.ts | TypeScript API client |
Layouts
Layout.jsx, MasterAdminLayout.jsx, WordPressAdminLayout.jsx, KioskLayout.jsx
Admin vs Business Hub (where settings live)
The dashboard SPA serves both tenant admin (/admin/*) and Business Hub (/business-hub). They are different products in the same shell: Business Hub aggregates analytics, payments, and operations status from /api/business-hub/*; it does not own per-register JSON such as Devices.metadata.posModules.
Device registry — /admin/devices/manager (DeviceManager.jsx): CRUD for Devices; POS Forecourt / fuel module (metadata.posModules) and Forecourt site config form (FuelSiteFormSection.jsx → metadata.fuelSite). Admin home (Admin.jsx): nav search uses keywords (e.g. fuel, forecourt) to surface Device registry. See 13 — Bridge & Devices and 06 — POS & Invoicing.
POS vertical modules (frontend/src/pos/modules/)
PosModuleHost.jsx — maps device.posModules from GET /api/pos/settings to panel components. Passes fuelSite into fuel UI.
FuelModulePanel.jsx — Forecourt panel when fuel is enabled: pump selection (chips + select), optional grade, preview line amount, Add fuel line to cart with structured line metadata (lineKind: fuel, pump/grade keys).