Saltar al contenido principal

User UI Preferences (PWA)

FlowPOS PWA stores user-scoped UI preferences with a local-first adapter to keep behavior stable across Sale, Quote, and Restaurant forms.

Scope

Preferences are scoped by:

  • userId
  • businessId
  • locationId

When any scope value is missing, anon-* fallbacks are used to avoid key collisions.

Stored Fields

  • panelLayout: "catalog-left" | "summary-left" — Order Taking split, Sale/Quote menu tabs, and the restaurant Add Item modal (TwoPanelSplitLayout)
  • showLayoutControls: boolean
  • autoCollapseSidebarOnWorkspaceRoutes: boolean — desktop sidebar auto-collapse on Restaurant workspace routes (default false)
  • saleDefaultTab: "search" | "menu" | "customer" | "checkout"
  • restaurantDefaultTab: "orders" | "orderTaking" | "searchProducts" | "detail" | "guests" | "billing"
  • gatewayOrderByModuleId: Record<string, string[]> (ordered gateway item keys per module)
  • schemaVersion: currently 1

When autoCollapseSidebarOnWorkspaceRoutes is true, these routes start with the collapsed icon rail (~96px) and use session-only expand/collapse (re-collapses on navigation within workspace routes):

  • /forms/restaurantOrders
  • /forms/restaurantKds (staff mode)
  • /forms/restaurantExpo
  • /forms/restaurantPackingScanner

When the preference is false, those routes use the persisted sidebar collapse state (flowpos-sidebar-collapsed in localStorage).

KDS kiosk (/forms/restaurantKds?kiosk=true) always uses transient collapsed sidebar regardless of this preference.

Manual sidebar width (flowpos-sidebar-width) remains device-scoped and is not part of user UI preferences.

Policy resolution lives in resolveSidebarCollapseMode() (apps/frontend-pwa/src/routes/routeLayout.ts); layout state is applied via useSidebarCollapsePolicy().

Storage Keys

  • New key: flowpos:ui:user-preferences:{userId}:{businessId}:{locationId}
  • Legacy compatibility key: flowpos:ui:two-panel-layout:{segment}:{userId}:{businessId}:{locationId}

The repository reads legacy layout when the new key is absent and writes both keys to preserve backward compatibility.

After each write, the repository dispatches flowpos:ui-preferences-changed on the same window so all useUserUiPreferences hook instances (for example layout shell + settings page) stay in sync without a full reload. Cross-tab updates still use the browser storage event.

Precedence Rules

Default tab behavior follows this precedence:

  1. Explicit URL/query/deep-link intent
  2. Existing explicit page state
  3. Saved user preference
  4. Hardcoded fallback

This prevents user preferences from overriding intentional navigation flows.

Gateway ordering behavior follows this precedence:

  1. Saved restaurantGatewayOrder keys that still exist
  2. Current gateway items not present in saved keys (appended in remote default order)

This keeps ordering resilient when menu entries are added, removed, or renamed.

Sidebar auto-collapse follows this precedence:

  1. KDS kiosk mode → always transient collapsed
  2. User preference autoCollapseSidebarOnWorkspaceRoutes (default off)
  3. Persisted device sidebar state (flowpos-sidebar-collapsed)