- Add employeeNumber and pinHash fields to users table - POST /auth/pin-login: takes combined code (4-digit employee# + 4-digit PIN) - POST /auth/set-pin: employee sets their own PIN (requires full auth) - DELETE /auth/pin: remove PIN - Lock screen with numpad, auto-submits on 8 digits, visual dot separator - POS uses its own auth token separate from admin session - Admin "POS" link clears admin session before navigating - /pos route has no auth guard — lock screen is the auth - API client uses POS token when available, admin token otherwise - Auto-lock timer reads pos_lock_timeout from app_config (default 15 min) - Lock button in POS top bar, shows current cashier name Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
44 lines
1.2 KiB
TypeScript
44 lines
1.2 KiB
TypeScript
import { create } from 'zustand'
|
|
|
|
interface POSUser {
|
|
id: string
|
|
email: string
|
|
firstName: string
|
|
lastName: string
|
|
role: string
|
|
}
|
|
|
|
interface POSState {
|
|
currentTransactionId: string | null
|
|
locationId: string | null
|
|
drawerSessionId: string | null
|
|
locked: boolean
|
|
cashier: POSUser | null
|
|
token: string | null
|
|
lastActivity: number
|
|
setTransaction: (id: string | null) => void
|
|
setLocation: (id: string) => void
|
|
setDrawerSession: (id: string | null) => void
|
|
unlock: (user: POSUser, token: string) => void
|
|
lock: () => void
|
|
touchActivity: () => void
|
|
reset: () => void
|
|
}
|
|
|
|
export const usePOSStore = create<POSState>((set) => ({
|
|
currentTransactionId: null,
|
|
locationId: null,
|
|
drawerSessionId: null,
|
|
locked: true,
|
|
cashier: null,
|
|
token: null,
|
|
lastActivity: Date.now(),
|
|
setTransaction: (id) => set({ currentTransactionId: id }),
|
|
setLocation: (id) => set({ locationId: id }),
|
|
setDrawerSession: (id) => set({ drawerSessionId: id }),
|
|
unlock: (user, token) => set({ locked: false, cashier: user, token, lastActivity: Date.now() }),
|
|
lock: () => set({ locked: true, currentTransactionId: null }),
|
|
touchActivity: () => set({ lastActivity: Date.now() }),
|
|
reset: () => set({ currentTransactionId: null }),
|
|
}))
|