import { useEffect, useRef, useCallback } from 'react' import { useQuery } from '@tanstack/react-query' import { queryOptions } from '@tanstack/react-query' import { api } from '@/lib/api-client' import { usePOSStore } from '@/stores/pos.store' import { currentDrawerOptions, transactionOptions } from '@/api/pos' import { POSTopBar } from './pos-top-bar' import { POSItemPanel } from './pos-item-panel' import { POSCartPanel } from './pos-cart-panel' import { POSLockScreen } from './pos-lock-screen' interface Location { id: string name: string } interface AppConfigEntry { key: string value: string | null } function locationsOptions() { return queryOptions({ queryKey: ['locations'], queryFn: () => api.get<{ data: Location[] }>('/v1/locations'), }) } function configOptions(key: string) { return queryOptions({ queryKey: ['config', key], queryFn: async (): Promise => { try { const entry = await api.get(`/v1/config/${key}`) return entry.value } catch { return null } }, }) } interface POSRegisterProps { embedded?: boolean } export function POSRegister({ embedded }: POSRegisterProps = {}) { const { locationId, setLocation, currentTransactionId, setDrawerSession, locked, lock, touchActivity, token } = usePOSStore() // Fetch lock timeout from config (standalone only) const { data: lockTimeoutStr } = useQuery({ ...configOptions('pos_lock_timeout'), enabled: !!token && !embedded, }) const lockTimeoutMinutes = parseInt(lockTimeoutStr ?? '15') || 15 // Auto-lock timer (standalone only — station shell handles this when embedded) const timerRef = useRef | null>(null) useEffect(() => { if (embedded) return if (locked || lockTimeoutMinutes === 0) { if (timerRef.current) clearInterval(timerRef.current) return } timerRef.current = setInterval(() => { const { lastActivity, locked: isLocked } = usePOSStore.getState() if (!isLocked && Date.now() - lastActivity > lockTimeoutMinutes * 60_000) { lock() } }, 30_000) return () => { if (timerRef.current) clearInterval(timerRef.current) } }, [embedded, locked, lockTimeoutMinutes, lock]) // Track activity (standalone only) const handleActivity = useCallback(() => { if (!embedded && !locked) touchActivity() }, [embedded, locked, touchActivity]) // Fetch locations (standalone only — station shell handles this when embedded) const { data: locationsData } = useQuery({ ...locationsOptions(), enabled: !!token && !embedded, }) const locations = locationsData?.data ?? [] // Auto-select first location (standalone only) useEffect(() => { if (embedded) return if (!locationId && locations.length > 0) { setLocation(locations[0].id) } }, [embedded, locationId, locations, setLocation]) // Fetch current drawer for selected location const { data: drawer } = useQuery({ ...currentDrawerOptions(locationId), retry: false, enabled: !!locationId && !!token, }) // Sync drawer session ID useEffect(() => { if (drawer?.id && drawer.status === 'open') { setDrawerSession(drawer.id) } else { setDrawerSession(null) } }, [drawer, setDrawerSession]) // Fetch current transaction const { data: transaction } = useQuery({ ...transactionOptions(currentTransactionId), enabled: !!currentTransactionId && !!token, }) // Embedded mode: just the content panels, no wrapper/lock/topbar if (embedded) { return (
) } return (
{locked && }
) }