@burdenoff/microfe-eventfullymanaged 2026.722.1 → 2026.728.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/eventfullymanaged/api/eventApi.d.ts +22 -0
- package/dist/eventfullymanaged/api/eventApi.d.ts.map +1 -1
- package/dist/eventfullymanaged/api/eventApi.js +74 -54
- package/dist/eventfullymanaged/api/eventApi.js.map +1 -1
- package/dist/eventfullymanaged/lib/offlineCheckInQueue.d.ts +54 -0
- package/dist/eventfullymanaged/lib/offlineCheckInQueue.d.ts.map +1 -0
- package/dist/eventfullymanaged/lib/offlineCheckInQueue.js +68 -0
- package/dist/eventfullymanaged/lib/offlineCheckInQueue.js.map +1 -0
- package/dist/eventfullymanaged/lib/useOfflineCheckInSync.d.ts +29 -0
- package/dist/eventfullymanaged/lib/useOfflineCheckInSync.d.ts.map +1 -0
- package/dist/eventfullymanaged/lib/useOfflineCheckInSync.js +73 -0
- package/dist/eventfullymanaged/lib/useOfflineCheckInSync.js.map +1 -0
- package/dist/eventfullymanaged/pages/modules/KioskPage.d.ts.map +1 -1
- package/dist/eventfullymanaged/pages/modules/KioskPage.js +381 -311
- package/dist/eventfullymanaged/pages/modules/KioskPage.js.map +1 -1
- package/dist/eventfullymanaged/pages/modules/RegistrationPage.d.ts.map +1 -1
- package/dist/eventfullymanaged/pages/modules/RegistrationPage.js +236 -182
- package/dist/eventfullymanaged/pages/modules/RegistrationPage.js.map +1 -1
- package/dist/eventfullymanaged/types/index.d.ts.map +1 -1
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KioskPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/KioskPage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n EmphasisPanel,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n Label,\n PagePurpose,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ScrollArea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n} from '@burdenoff/fe-libs/ui';\nimport {\n ArrowLeftFromLine,\n ArrowRightToLine,\n Camera,\n CameraOff,\n Keyboard,\n LogIn,\n Plus,\n QrCode,\n ScanLine,\n} from 'lucide-react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport {\n useAttendeesQuery,\n useCheckInRecordsQuery,\n useCheckInStationsQuery,\n useCreateCheckInRecordMutation,\n useCreateCheckInStationMutation,\n useDeleteCheckInRecordMutation,\n useDeleteCheckInStationMutation,\n useEventSessionsQuery,\n useEventsQuery,\n useUpdateCheckInRecordMutation,\n useUpdateCheckInStationMutation,\n} from '../../api/eventApi';\nimport { ActionMenu, Pagination, usePagination } from '../../components';\nimport { describeError, mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\n\n// ---------------------------------------------------------------------------\n// BarcodeDetector — a built-in browser API (Chromium/Edge). No new dependency;\n// feature-detected so the scanner degrades gracefully to manual entry when the\n// API (or a camera) is unavailable.\n// ---------------------------------------------------------------------------\n\ninterface DetectedBarcode {\n rawValue: string;\n}\ninterface BarcodeDetectorLike {\n detect(source: CanvasImageSource): Promise<DetectedBarcode[]>;\n}\ninterface BarcodeDetectorCtor {\n new (options?: { formats: string[] }): BarcodeDetectorLike;\n}\ndeclare global {\n interface Window {\n BarcodeDetector?: BarcodeDetectorCtor;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Shared types\n// ---------------------------------------------------------------------------\n\ntype StationRow = {\n id: string;\n eventId?: string | null;\n name?: string | null;\n metadata?: Record<string, unknown> | null;\n};\n\ntype RecordRow = {\n id: string;\n eventId: string;\n stationId?: string | null;\n attendeeId?: string | null;\n registrationId?: string | null;\n method: string;\n status: string;\n direction: string;\n recordedAt: string;\n metadata?: Record<string, unknown> | null;\n};\n\nconst STATION_TYPES = ['DESK', 'GATE', 'SELF_SERVICE', 'MOBILE'] as const;\nconst CHECKIN_METHODS = ['QR', 'MANUAL'] as const;\nconst CHECKIN_DIRECTIONS = ['IN', 'OUT'] as const;\n\n/**\n * The stations list resolver projects a CheckInStation onto the generic\n * SimpleEntity shape (id/name/metadata) — it does NOT expose the `code`,\n * `location` or `isActive` columns. To keep create → list → edit lossless we\n * mirror those attributes into `metadata` on every write, so an edit opened from\n * a list row can rebuild the full required input without a by-id resolver.\n */\ntype StationMeta = {\n code?: string;\n location?: string;\n type?: string;\n isActive?: boolean;\n};\n\nfunction readStationMeta(metadata: Record<string, unknown> | null | undefined): StationMeta {\n if (!metadata || typeof metadata !== 'object') {\n return {};\n }\n const m = metadata as Record<string, unknown>;\n return {\n code: typeof m.code === 'string' ? m.code : undefined,\n location: typeof m.location === 'string' ? m.location : undefined,\n type: typeof m.type === 'string' ? m.type : undefined,\n isActive: typeof m.isActive === 'boolean' ? m.isActive : undefined,\n };\n}\n\nfunction slugCode(name: string): string {\n return (\n name\n .trim()\n .toUpperCase()\n .replace(/[^A-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 24) || 'STATION'\n );\n}\n\nfunction initials(label: string): string {\n const parts = label.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) {\n return '?';\n }\n if (parts.length === 1) {\n return parts[0].slice(0, 2).toUpperCase();\n }\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n}\n\nfunction formatTime(iso: string): string {\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });\n}\n\n// ===========================================================================\n// Camera QR scanner viewfinder\n// ===========================================================================\n\ninterface QrViewfinderProps {\n onDetected: (value: string) => void;\n}\n\nfunction QrViewfinder({ onDetected }: QrViewfinderProps) {\n const supported = typeof window !== 'undefined' && Boolean(window.BarcodeDetector);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const streamRef = useRef<MediaStream | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const [active, setActive] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const stop = useCallback(() => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (streamRef.current) {\n for (const track of streamRef.current.getTracks()) {\n track.stop();\n }\n streamRef.current = null;\n }\n if (videoRef.current) {\n videoRef.current.srcObject = null;\n }\n setActive(false);\n }, []);\n\n // Always release the camera when the component unmounts.\n useEffect(() => stop, [stop]);\n\n const start = useCallback(async () => {\n if (!supported || !window.BarcodeDetector) {\n return;\n }\n setError(null);\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n video: { facingMode: 'environment' },\n audio: false,\n });\n streamRef.current = stream;\n setActive(true);\n const video = videoRef.current;\n if (video) {\n video.srcObject = stream;\n await video.play().catch(() => undefined);\n }\n const detector = new window.BarcodeDetector({ formats: ['qr_code'] });\n intervalRef.current = setInterval(async () => {\n const el = videoRef.current;\n if (!el || el.readyState < 2) {\n return;\n }\n try {\n const results = await detector.detect(el);\n const hit = results.find((r) => r.rawValue.trim());\n if (hit) {\n onDetected(hit.rawValue.trim());\n stop();\n }\n } catch {\n // Transient decode frames can throw; ignore and keep polling.\n }\n }, 350);\n } catch {\n setError('Camera unavailable. Grant camera access or use manual lookup.');\n stop();\n }\n }, [onDetected, stop, supported]);\n\n return (\n <div className=\"relative aspect-square w-full overflow-hidden rounded-card border-2 border-accent-primary/70 bg-bg-sunken\">\n {/* Live camera feed (hidden until active). */}\n <video\n ref={videoRef}\n className={`h-full w-full object-cover transition-opacity duration-300 ${active ? 'opacity-100' : 'opacity-0'}`}\n muted\n playsInline\n aria-label=\"Attendee QR camera preview\"\n />\n\n {/* Corner brackets + scan affordance overlay. */}\n <div className=\"pointer-events-none absolute inset-0 p-5\">\n <div className=\"relative h-full w-full\">\n <span className=\"absolute left-0 top-0 h-10 w-10 rounded-tl-lg border-l-4 border-t-4 border-accent-primary\" />\n <span className=\"absolute right-0 top-0 h-10 w-10 rounded-tr-lg border-r-4 border-t-4 border-accent-primary\" />\n <span className=\"absolute bottom-0 left-0 h-10 w-10 rounded-bl-lg border-b-4 border-l-4 border-accent-primary\" />\n <span className=\"absolute bottom-0 right-0 h-10 w-10 rounded-br-lg border-b-4 border-r-4 border-accent-primary\" />\n {active ? <span className=\"absolute inset-x-6 top-1/2 h-0.5 animate-pulse bg-accent-primary/80\" /> : null}\n </div>\n </div>\n\n {/* Idle state. */}\n {!active ? (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-3 text-center\">\n <QrCode className=\"h-16 w-16 text-text-muted\" aria-hidden=\"true\" />\n <p className=\"text-lg font-semibold text-text-primary\">Scan attendee QR</p>\n {supported ? (\n <Button type=\"button\" size=\"sm\" variant=\"secondary\" onClick={() => void start()}>\n <Camera className=\"h-4 w-4\" />\n Start camera\n </Button>\n ) : (\n <p className=\"max-w-56 text-xs text-text-secondary\">\n Camera scanning isn't available in this browser — use manual lookup below.\n </p>\n )}\n {error ? <p className=\"max-w-56 text-xs text-status-danger-text\">{error}</p> : null}\n </div>\n ) : (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center justify-between gap-2 bg-bg-canvas/70 p-3 backdrop-blur\">\n <span className=\"flex items-center gap-1.5 text-xs font-medium text-text-primary\">\n <span className=\"h-2 w-2 animate-pulse rounded-full bg-status-success-text\" />\n Scanning…\n </span>\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={stop}>\n <CameraOff className=\"h-4 w-4\" />\n Stop\n </Button>\n </div>\n )}\n </div>\n );\n}\n\n// ===========================================================================\n// Segmented toggle (Method / Direction)\n// ===========================================================================\n\ninterface SegmentedProps<T extends string> {\n label: string;\n value: T;\n options: readonly { value: T; label: string; icon?: React.ComponentType<{ className?: string }> }[];\n onChange: (value: T) => void;\n}\n\nfunction Segmented<T extends string>({ label, value, options, onChange }: SegmentedProps<T>) {\n return (\n <div className=\"space-y-1.5\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">{label}</span>\n <div\n role=\"group\"\n aria-label={label}\n className=\"inline-flex rounded-input border border-border-default bg-bg-sunken p-0.5\"\n >\n {options.map((opt) => {\n const Icon = opt.icon;\n const selected = opt.value === value;\n return (\n <button\n key={opt.value}\n type=\"button\"\n aria-pressed={selected}\n onClick={() => onChange(opt.value)}\n className={`inline-flex items-center gap-1.5 rounded-[calc(var(--radius-input)-2px)] px-3 py-1.5 text-sm font-medium transition-colors ${\n selected\n ? 'bg-action-primary-bg text-action-primary-text shadow-elevation-1'\n : 'text-text-secondary hover:text-text-primary'\n }`}\n >\n {Icon ? <Icon className=\"h-4 w-4\" /> : null}\n {opt.label}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n\n// ===========================================================================\n// Station create / edit dialog\n// ===========================================================================\n\ntype StationFormState = {\n name: string;\n code: string;\n location: string;\n type: string;\n isActive: boolean;\n};\n\ninterface StationDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n eventId: string;\n eventName: string;\n /** Present when editing an existing station. */\n station?: StationRow;\n}\n\nfunction StationDialog({ open, onOpenChange, eventId, eventName, station }: StationDialogProps) {\n const isEdit = Boolean(station);\n const [createStation, { loading: creating }] = useCreateCheckInStationMutation();\n const [updateStation, { loading: updating }] = useUpdateCheckInStationMutation();\n\n const initial = useMemo<StationFormState>(() => {\n if (!station) {\n return { name: '', code: '', location: '', type: 'DESK', isActive: true };\n }\n const meta = readStationMeta(station.metadata);\n return {\n name: station.name ?? '',\n code: meta.code ?? slugCode(station.name ?? ''),\n location: meta.location ?? '',\n type: meta.type ?? 'DESK',\n isActive: meta.isActive ?? true,\n };\n }, [station]);\n\n const [form, setForm] = useState<StationFormState>(initial);\n // Reset the form to the active station whenever the dialog is (re)opened.\n const [seededFor, setSeededFor] = useState<string | null>(null);\n const seedKey = `${open ? 'open' : 'closed'}:${station?.id ?? 'new'}`;\n if (open && seededFor !== seedKey) {\n setSeededFor(seedKey);\n setForm(initial);\n }\n if (!open && seededFor !== null) {\n setSeededFor(null);\n }\n\n const onChange = <K extends keyof StationFormState>(field: K, value: StationFormState[K]) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n };\n\n const saving = creating || updating;\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const code = form.code.trim() || slugCode(form.name);\n const input = {\n eventId,\n name: form.name.trim(),\n code,\n location: form.location.trim() || null,\n isActive: form.isActive,\n kioskConfig: { type: form.type },\n // Mirror the write-only columns so the SimpleEntity list can rebuild them.\n metadata: { code, location: form.location.trim(), type: form.type, isActive: form.isActive },\n };\n\n try {\n if (isEdit && station) {\n const res = await updateStation({ variables: { id: station.id, input } });\n if (!mutationSucceeded(res, res.data?.updateCheckInStation?.id, 'Could not update station')) {\n return;\n }\n notify.success('Station updated', `“${input.name}” is now ${form.isActive ? 'active' : 'disabled'}.`);\n } else {\n const res = await createStation({ variables: { input } });\n if (!mutationSucceeded(res, res.data?.createCheckInStation?.id, 'Could not create station')) {\n return;\n }\n notify.success('Station created', `“${input.name}” is ready at ${eventName}.`);\n }\n onOpenChange(false);\n } catch (error) {\n notify.error('Could not save station', describeError(error));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{isEdit ? 'Edit check-in station' : 'New check-in station'}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n A station is a desk, gate or device where attendees scan in at {eventName}.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form id=\"station-form\" onSubmit={onSubmit} className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Name</span>\n <Input\n value={form.name}\n onChange={(e) => onChange('name', e.target.value)}\n placeholder=\"Main entrance\"\n required\n />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Code</span>\n <Input\n value={form.code}\n onChange={(e) => onChange('code', e.target.value)}\n placeholder=\"Auto from name\"\n />\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Location</span>\n <Input\n value={form.location}\n onChange={(e) => onChange('location', e.target.value)}\n placeholder=\"North lobby\"\n />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Type</span>\n <Select value={form.type} onValueChange={(value) => onChange('type', value)}>\n <SelectTrigger aria-label=\"Station type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATION_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {type.replace('_', ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <div className=\"flex items-center justify-between rounded-card border border-border-seam bg-bg-surface p-3\">\n <div>\n <Label htmlFor=\"station-active\" className=\"text-text-primary\">\n Active\n </Label>\n <p className=\"text-xs text-text-secondary\">Disabled stations stay configured but cannot accept scans.</p>\n </div>\n <Switch\n id=\"station-active\"\n checked={form.isActive}\n onCheckedChange={(checked) => onChange('isActive', checked)}\n aria-label=\"Station active\"\n />\n </div>\n </form>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)} disabled={saving}>\n Cancel\n </Button>\n <Button type=\"submit\" form=\"station-form\" disabled={saving}>\n {saving ? 'Saving…' : isEdit ? 'Save station' : 'Create station'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ===========================================================================\n// Check-in record edit dialog\n// ===========================================================================\n\ntype RecordFormState = {\n method: string;\n direction: string;\n status: string;\n stationId: string;\n attendeeId: string;\n};\n\ninterface RecordDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n record: RecordRow | null;\n stations: StationRow[];\n}\n\nfunction RecordDialog({ open, onOpenChange, record, stations }: RecordDialogProps) {\n const [updateRecord, { loading }] = useUpdateCheckInRecordMutation();\n\n const initial = useMemo<RecordFormState>(\n () => ({\n method: record?.method ?? 'MANUAL',\n direction: record?.direction ?? 'IN',\n status: record?.status ?? 'checked_in',\n stationId: record?.stationId ?? '',\n attendeeId: record?.attendeeId ?? '',\n }),\n [record]\n );\n const [form, setForm] = useState<RecordFormState>(initial);\n const [seededFor, setSeededFor] = useState<string | null>(null);\n const seedKey = `${open ? 'open' : 'closed'}:${record?.id ?? 'none'}`;\n if (open && seededFor !== seedKey) {\n setSeededFor(seedKey);\n setForm(initial);\n }\n if (!open && seededFor !== null) {\n setSeededFor(null);\n }\n\n const onChange = <K extends keyof RecordFormState>(field: K, value: RecordFormState[K]) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n };\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!record) {\n return;\n }\n const input = {\n eventId: record.eventId,\n attendeeId: form.attendeeId.trim() || null,\n registrationId: record.registrationId ?? null,\n stationId: form.stationId || null,\n method: form.method,\n direction: form.direction,\n status: form.status.trim() || 'checked_in',\n metadata: record.metadata ?? {},\n };\n try {\n const res = await updateRecord({ variables: { id: record.id, input } });\n if (!mutationSucceeded(res, res.data?.updateCheckInRecord?.id, 'Could not update record')) {\n return;\n }\n notify.success('Check-in updated');\n onOpenChange(false);\n } catch (error) {\n notify.error('Could not update record', describeError(error));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Edit check-in record</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Correct the direction, method or station for this scan.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form id=\"record-form\" onSubmit={onSubmit} className=\"space-y-4\">\n <label className=\"block space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Attendee ID</span>\n <Input value={form.attendeeId} onChange={(e) => onChange('attendeeId', e.target.value)} />\n </label>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Method</span>\n <Select value={form.method} onValueChange={(value) => onChange('method', value)}>\n <SelectTrigger aria-label=\"Method\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CHECKIN_METHODS.map((method) => (\n <SelectItem key={method} value={method}>\n {method}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Direction</span>\n <Select value={form.direction} onValueChange={(value) => onChange('direction', value)}>\n <SelectTrigger aria-label=\"Direction\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CHECKIN_DIRECTIONS.map((direction) => (\n <SelectItem key={direction} value={direction}>\n {direction}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Status</span>\n <Input value={form.status} onChange={(e) => onChange('status', e.target.value)} />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Station</span>\n <Select\n value={form.stationId || 'none'}\n onValueChange={(value) => onChange('stationId', value === 'none' ? '' : value)}\n >\n <SelectTrigger aria-label=\"Station\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">No station</SelectItem>\n {stations.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.name ?? s.id}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n </form>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button type=\"submit\" form=\"record-form\" disabled={loading}>\n {loading ? 'Saving…' : 'Save record'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ===========================================================================\n// Kiosk check-in panel (the hero workflow)\n// ===========================================================================\n\ninterface AttendeeLite {\n id: string;\n fullName: string;\n email?: string | null;\n}\n\ninterface CheckInPanelProps {\n eventId: string;\n eventName: string;\n stations: StationRow[];\n attendees: AttendeeLite[];\n activeStationId: string;\n onStationChange: (stationId: string) => void;\n onCheckedIn: () => void;\n}\n\nfunction CheckInPanel({\n eventId,\n eventName,\n stations,\n attendees,\n activeStationId,\n onStationChange,\n onCheckedIn,\n}: CheckInPanelProps) {\n const [scanValue, setScanValue] = useState('');\n const [method, setMethod] = useState<(typeof CHECKIN_METHODS)[number]>('QR');\n const [direction, setDirection] = useState<(typeof CHECKIN_DIRECTIONS)[number]>('IN');\n const [sessionId, setSessionId] = useState('');\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n const [createRecord, { loading }] = useCreateCheckInRecordMutation();\n const sessionsQuery = useEventSessionsQuery({ eventId, limit: 100, offset: 0 });\n const sessions = sessionsQuery.data?.eventSessions.items ?? [];\n\n const resolveAttendee = (raw: string): { attendeeId: string | null; label: string; matched: boolean } => {\n const value = raw.trim();\n if (!value) {\n return { attendeeId: null, label: 'attendee', matched: false };\n }\n if (value.includes('@')) {\n const match = attendees.find((a) => a.email?.toLowerCase() === value.toLowerCase());\n return { attendeeId: match?.id ?? null, label: match?.fullName ?? value, matched: Boolean(match) };\n }\n const byId = attendees.find((a) => a.id === value);\n return { attendeeId: value, label: byId?.fullName ?? `attendee ${value}`, matched: Boolean(byId) };\n };\n\n const onScanDetected = (value: string) => {\n setScanValue(value);\n setMethod('QR');\n notify.info('QR captured', 'Confirm the details and tap Check in.');\n inputRef.current?.focus();\n };\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const { attendeeId, label } = resolveAttendee(scanValue);\n if (scanValue.trim().includes('@') && !attendeeId) {\n notify.error('Attendee not found', `No attendee at this event matches “${scanValue.trim()}”.`);\n return;\n }\n const input = {\n eventId,\n attendeeId,\n stationId: activeStationId || null,\n method,\n direction,\n status: direction === 'OUT' ? 'checked_out' : 'checked_in',\n recordedAt: new Date().toISOString(),\n metadata: sessionId ? { sessionId } : {},\n };\n try {\n const res = await createRecord({ variables: { input } });\n if (!mutationSucceeded(res, res.data?.createCheckInRecord?.id, 'Could not record check-in')) {\n return;\n }\n const activeStation = stations.find((s) => s.id === activeStationId);\n notify.success(\n `${label} checked ${direction === 'OUT' ? 'out' : 'in'}`,\n `Recorded via ${method}${activeStation?.name ? ` • ${activeStation.name}` : ''}.`\n );\n setScanValue('');\n inputRef.current?.focus();\n onCheckedIn();\n } catch (error) {\n notify.error('Could not record check-in', describeError(error));\n }\n };\n\n return (\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-5 sm:p-6\">\n <div className=\"flex items-center gap-2\">\n <ScanLine className=\"h-5 w-5 text-accent-primary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Kiosk mode</h2>\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Scan an attendee badge or look them up, set the direction, and check them into {eventName}.\n </p>\n\n <div className=\"mt-5\">\n <QrViewfinder onDetected={onScanDetected} />\n </div>\n\n <form onSubmit={onSubmit} className=\"mt-5 space-y-5\">\n <label className=\"block space-y-1.5\">\n <span className=\"flex items-center gap-1.5 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n <Keyboard className=\"h-3.5 w-3.5\" />\n Manual lookup\n </span>\n <Input\n ref={inputRef}\n value={scanValue}\n onChange={(e) => setScanValue(e.target.value)}\n placeholder=\"Enter name, email or attendee ID\"\n autoComplete=\"off\"\n className=\"h-12 text-base\"\n />\n </label>\n\n <div className=\"flex flex-wrap gap-5\">\n <Segmented\n label=\"Method\"\n value={method}\n onChange={setMethod}\n options={[\n { value: 'QR', label: 'QR', icon: QrCode },\n { value: 'MANUAL', label: 'Manual', icon: Keyboard },\n ]}\n />\n <Segmented\n label=\"Direction\"\n value={direction}\n onChange={setDirection}\n options={[\n { value: 'IN', label: 'In', icon: ArrowRightToLine },\n { value: 'OUT', label: 'Out', icon: ArrowLeftFromLine },\n ]}\n />\n <label className=\"space-y-1.5\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">Station</span>\n <Select value={activeStationId || 'none'} onValueChange={(v) => onStationChange(v === 'none' ? '' : v)}>\n <SelectTrigger aria-label=\"Station\" className=\"min-w-40\">\n <SelectValue placeholder=\"No station\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">No station</SelectItem>\n {stations.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.name ?? s.id}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <label className=\"space-y-1.5\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">Session</span>\n <Select value={sessionId || 'none'} onValueChange={(v) => setSessionId(v === 'none' ? '' : v)}>\n <SelectTrigger aria-label=\"Session\" className=\"min-w-40\">\n <SelectValue placeholder=\"Whole event\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">Whole event</SelectItem>\n {sessions.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.title}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <Button type=\"submit\" size=\"lg\" disabled={loading || !scanValue.trim()} className=\"h-12 w-full text-base\">\n <LogIn className=\"h-5 w-5\" />\n {loading ? 'Recording…' : `Check ${direction === 'OUT' ? 'out' : 'in'}`}\n </Button>\n </form>\n </GlassCard>\n );\n}\n\n// ===========================================================================\n// Page\n// ===========================================================================\n\nconst PAGE_SIZE = 10;\nconst COUNTER_FETCH = 500;\n\nexport default function KioskPage() {\n const eventsQuery = useEventsQuery({ limit: 100, offset: 0 });\n const events = eventsQuery.data?.events.items ?? [];\n const [selectedEventId, setSelectedEventId] = useState('');\n const scopeEventId = selectedEventId || undefined;\n const selectedEvent = events.find((e) => e.id === selectedEventId);\n\n const [activeStationId, setActiveStationId] = useState('');\n const recordsPagination = usePagination({ pageSize: PAGE_SIZE, resetKey: selectedEventId });\n\n const stationsQuery = useCheckInStationsQuery({ eventId: scopeEventId, limit: 100, offset: 0 });\n const recordsQuery = useCheckInRecordsQuery({\n eventId: scopeEventId,\n limit: recordsPagination.limit,\n offset: recordsPagination.offset,\n });\n // Broad fetch powering the live \"checked in X / Y\" meter and per-station counts.\n const counterQuery = useCheckInRecordsQuery({ eventId: scopeEventId, limit: COUNTER_FETCH, offset: 0 });\n const attendeesQuery = useAttendeesQuery({ eventId: scopeEventId, limit: 200, offset: 0 });\n\n const stations = useMemo(\n () => (stationsQuery.data?.checkInStations.items ?? []) as StationRow[],\n [stationsQuery.data]\n );\n const records = (recordsQuery.data?.checkInRecords.items ?? []) as RecordRow[];\n const recordsTotal = recordsQuery.data?.checkInRecords.total ?? 0;\n const allRecords = useMemo(() => (counterQuery.data?.checkInRecords.items ?? []) as RecordRow[], [counterQuery.data]);\n const attendees = useMemo<AttendeeLite[]>(() => attendeesQuery.data?.attendees.items ?? [], [attendeesQuery.data]);\n const attendeesTotal = attendeesQuery.data?.attendees.total ?? 0;\n\n const attendeeNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const a of attendees) {\n map.set(a.id, a.fullName);\n }\n return map;\n }, [attendees]);\n\n const stationNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const s of stations) {\n map.set(s.id, s.name ?? s.id);\n }\n return map;\n }, [stations]);\n\n // Live counters derived from the broad records fetch — no fabricated numbers.\n const { checkedInCount, stationCounts } = useMemo(() => {\n const insideAttendees = new Set<string>();\n const anonInside = { count: 0 };\n const perStation = new Map<string, Set<string>>();\n // Replay records oldest→newest so the latest IN/OUT wins per attendee.\n const ordered = [...allRecords].sort((a, b) => new Date(a.recordedAt).getTime() - new Date(b.recordedAt).getTime());\n for (const r of ordered) {\n const key = r.attendeeId ?? '';\n if (r.direction === 'OUT') {\n if (key) {\n insideAttendees.delete(key);\n } else if (anonInside.count > 0) {\n anonInside.count -= 1;\n }\n } else {\n if (key) {\n insideAttendees.add(key);\n } else {\n anonInside.count += 1;\n }\n }\n if (r.stationId && r.direction !== 'OUT') {\n const set = perStation.get(r.stationId) ?? new Set<string>();\n set.add(r.id);\n perStation.set(r.stationId, set);\n }\n }\n const counts = new Map<string, number>();\n for (const [id, set] of perStation) {\n counts.set(id, set.size);\n }\n return { checkedInCount: insideAttendees.size + anonInside.count, stationCounts: counts };\n }, [allRecords]);\n\n const capacityTarget = attendeesTotal;\n const meterPct = capacityTarget > 0 ? Math.min(100, Math.round((checkedInCount / capacityTarget) * 100)) : 0;\n\n const [deleteStation] = useDeleteCheckInStationMutation();\n const [deleteRecord] = useDeleteCheckInRecordMutation();\n\n const [stationDialogOpen, setStationDialogOpen] = useState(false);\n const [editingStation, setEditingStation] = useState<StationRow | undefined>(undefined);\n const [recordDialogOpen, setRecordDialogOpen] = useState(false);\n const [editingRecord, setEditingRecord] = useState<RecordRow | null>(null);\n\n const openNewStation = () => {\n setEditingStation(undefined);\n setStationDialogOpen(true);\n };\n const openEditStation = (station: StationRow) => {\n setEditingStation(station);\n setStationDialogOpen(true);\n };\n const openEditRecord = (record: RecordRow) => {\n setEditingRecord(record);\n setRecordDialogOpen(true);\n };\n\n const onDeleteStation = async (station: StationRow) => {\n const res = await deleteStation({ variables: { id: station.id } });\n if (!mutationSucceeded(res, res.data?.deleteCheckInStation ? station.id : null, 'Could not delete station')) {\n return;\n }\n if (activeStationId === station.id) {\n setActiveStationId('');\n }\n notify.success('Station deleted', `“${station.name ?? station.id}” was removed.`);\n };\n\n const onDeleteRecord = async (record: RecordRow) => {\n const res = await deleteRecord({ variables: { id: record.id } });\n if (!mutationSucceeded(res, res.data?.deleteCheckInRecord ? record.id : null, 'Could not delete record')) {\n return;\n }\n notify.success('Check-in record deleted');\n };\n\n const refreshAfterCheckIn = () => {\n void recordsQuery.refetch();\n void counterQuery.refetch();\n };\n\n const recordLabel = (record: RecordRow): string => {\n if (record.attendeeId) {\n return attendeeNames.get(record.attendeeId) ?? `Attendee ${record.attendeeId.slice(0, 8)}`;\n }\n return 'Walk-in guest';\n };\n\n const hasEvent = Boolean(selectedEventId);\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Kiosks are the front desk of your event. Each check-in station is a device or counter where attendees scan in,\n and check-in records are the live log of who arrived and when. Configure your stations before doors open, then\n check attendees in from this page and watch arrivals flow in on the day.\n </PagePurpose>\n\n <EmphasisPanel>\n <div className=\"flex flex-wrap items-start justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Kiosk</GradientText> & Check-In\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Manage check-in stations and record attendee arrivals against a live backend.\n </p>\n </div>\n <div className=\"flex flex-wrap items-end gap-3\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Event</span>\n <Select value={selectedEventId || 'all'} onValueChange={(v) => setSelectedEventId(v === 'all' ? '' : v)}>\n <SelectTrigger aria-label=\"Event\" className=\"min-w-52\">\n <SelectValue placeholder=\"All events\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All events</SelectItem>\n {events.map((event) => (\n <SelectItem key={event.id} value={event.id}>\n {event.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <Button type=\"button\" onClick={openNewStation} disabled={!hasEvent}>\n <Plus className=\"h-4 w-4\" />\n New station\n </Button>\n </div>\n </div>\n </EmphasisPanel>\n\n {!hasEvent ? (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"Select an event to open the kiosk\"\n description=\"Check-in stations and records belong to a specific event. Pick one above to start scanning attendees in.\"\n className=\"py-8\"\n />\n </GlassCard>\n ) : (\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-12\">\n {/* Left — kiosk scan panel */}\n <div className=\"lg:col-span-5\">\n <CheckInPanel\n eventId={selectedEventId}\n eventName={selectedEvent?.name ?? 'this event'}\n stations={stations}\n attendees={attendees}\n activeStationId={activeStationId}\n onStationChange={setActiveStationId}\n onCheckedIn={refreshAfterCheckIn}\n />\n </div>\n\n {/* Right — stations + live records */}\n <div className=\"space-y-6 lg:col-span-7\">\n {/* Stations chip strip */}\n <section>\n <h2 className=\"text-sm font-semibold uppercase tracking-wide text-text-secondary\">Stations</h2>\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {stations.map((station) => {\n const active = activeStationId === station.id;\n const count = stationCounts.get(station.id) ?? 0;\n return (\n <div\n key={station.id}\n className={`group inline-flex items-center gap-1.5 rounded-full border px-3 py-1.5 text-sm transition-colors ${\n active\n ? 'border-accent-primary bg-accent-primary/10 text-accent-primary'\n : 'border-border-default bg-bg-surface text-text-secondary hover:border-border-strong'\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={active}\n onClick={() => setActiveStationId(active ? '' : station.id)}\n className=\"inline-flex items-center gap-1.5 font-medium outline-none\"\n >\n {station.name ?? station.id}\n {count > 0 ? (\n <span className=\"rounded-full bg-bg-sunken px-1.5 py-0.5 text-xs tabular-nums text-text-secondary\">\n {count}\n </span>\n ) : null}\n </button>\n <ActionMenu\n ariaLabel={`Station ${station.name ?? station.id} actions`}\n entityName={station.name ?? undefined}\n onEdit={() => openEditStation(station)}\n onDelete={() => onDeleteStation(station)}\n />\n </div>\n );\n })}\n <button\n type=\"button\"\n onClick={openNewStation}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-dashed border-border-strong px-3 py-1.5 text-sm font-medium text-text-secondary transition-colors hover:border-accent-primary hover:text-accent-primary\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n New station\n </button>\n </div>\n {stationsQuery.loading && stations.length === 0 ? (\n <p className=\"mt-2 text-sm text-text-secondary\">Loading stations…</p>\n ) : null}\n </section>\n\n {/* Live records */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Check-In Records</h2>\n <p className=\"text-sm text-text-secondary\">\n Checked in{' '}\n <span className=\"text-lg font-bold tabular-nums text-text-primary\">\n {checkedInCount.toLocaleString()}\n </span>\n {capacityTarget > 0 ? (\n <>\n {' '}\n / <span className=\"tabular-nums\">{capacityTarget.toLocaleString()}</span>\n </>\n ) : null}\n </p>\n </div>\n\n {capacityTarget > 0 ? (\n <div\n className=\"mt-3 h-2 w-full overflow-hidden rounded-full bg-bg-sunken\"\n role=\"progressbar\"\n aria-valuenow={checkedInCount}\n aria-valuemin={0}\n aria-valuemax={capacityTarget}\n aria-label=\"Attendees checked in\"\n >\n <div\n className=\"h-full rounded-full bg-action-primary-bg transition-[width] duration-500\"\n style={{ width: `${meterPct}%` }}\n />\n </div>\n ) : null}\n\n <div className=\"mt-4\">\n {records.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={recordsQuery.loading ? 'Loading check-in records…' : 'No check-in records yet'}\n description=\"Arrivals recorded from this kiosk show up here, newest first.\"\n className=\"py-8\"\n />\n ) : (\n <ScrollArea className=\"max-h-[28rem] pr-3\">\n <ul className=\"space-y-2.5\">\n {records.map((record) => {\n const label = recordLabel(record);\n const isOut = record.direction === 'OUT';\n const station = record.stationId ? stationNames.get(record.stationId) : null;\n return (\n <li\n key={record.id}\n className=\"flex items-center gap-3 rounded-card border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] duration-200 hover:border-border-strong hover:shadow-elevation-1\"\n >\n <span\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent-primary/10 text-sm font-semibold text-accent-primary\"\n aria-hidden=\"true\"\n >\n {initials(label)}\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate font-medium text-text-primary\">{label}</p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {formatTime(record.recordedAt)} • {record.method}\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant={isOut ? 'secondary' : 'success'} className=\"uppercase\">\n {isOut ? 'Checked out' : 'Checked in'}\n </Badge>\n {station ? (\n <span className=\"hidden text-sm text-text-secondary sm:inline\">{station}</span>\n ) : null}\n <ActionMenu\n ariaLabel={`Check-in record ${record.id} actions`}\n onEdit={() => openEditRecord(record)}\n onDelete={() => onDeleteRecord(record)}\n />\n </div>\n </li>\n );\n })}\n </ul>\n </ScrollArea>\n )}\n </div>\n <Pagination\n offset={recordsPagination.offset}\n limit={recordsPagination.limit}\n loadedCount={records.length}\n total={recordsTotal}\n onPrev={recordsPagination.prevPage}\n onNext={recordsPagination.nextPage}\n itemLabel=\"records\"\n loading={recordsQuery.loading}\n />\n </GlassCard>\n </div>\n </div>\n )}\n\n {selectedEventId ? (\n <StationDialog\n open={stationDialogOpen}\n onOpenChange={setStationDialogOpen}\n eventId={selectedEventId}\n eventName={selectedEvent?.name ?? 'this event'}\n station={editingStation}\n />\n ) : null}\n\n <RecordDialog\n open={recordDialogOpen}\n onOpenChange={setRecordDialogOpen}\n record={editingRecord}\n stations={stations}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;AAmGA,IAAM,KAAgB;CAAC;CAAQ;CAAQ;CAAgB;CAAS,EAC1D,IAAkB,CAAC,MAAM,SAAS,EAClC,KAAqB,CAAC,MAAM,MAAM;AAgBxC,SAAS,EAAgB,GAAmE;AAC1F,KAAI,CAAC,KAAY,OAAO,KAAa,SACnC,QAAO,EAAE;CAEX,IAAM,IAAI;AACV,QAAO;EACL,MAAM,OAAO,EAAE,QAAS,WAAW,EAAE,OAAO,KAAA;EAC5C,UAAU,OAAO,EAAE,YAAa,WAAW,EAAE,WAAW,KAAA;EACxD,MAAM,OAAO,EAAE,QAAS,WAAW,EAAE,OAAO,KAAA;EAC5C,UAAU,OAAO,EAAE,YAAa,YAAY,EAAE,WAAW,KAAA;EAC1D;;AAGH,SAAS,EAAS,GAAsB;AACtC,QACE,EACG,MAAM,CACN,aAAa,CACb,QAAQ,eAAe,IAAI,CAC3B,QAAQ,YAAY,GAAG,CACvB,MAAM,GAAG,GAAG,IAAI;;AAIvB,SAAS,GAAS,GAAuB;CACvC,IAAM,IAAQ,EAAM,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,QAAQ;AAOvD,QANI,EAAM,WAAW,IACZ,MAEL,EAAM,WAAW,IACZ,EAAM,GAAG,MAAM,GAAG,EAAE,CAAC,aAAa,IAEnC,EAAM,GAAG,KAAK,EAAM,EAAM,SAAS,GAAG,IAAI,aAAa;;AAGjE,SAAS,GAAW,GAAqB;CACvC,IAAM,IAAO,IAAI,KAAK,EAAI;AAI1B,QAHI,OAAO,MAAM,EAAK,SAAS,CAAC,GACvB,KAEF,EAAK,mBAAmB,EAAE,EAAE;EAAE,MAAM;EAAW,QAAQ;EAAW,CAAC;;AAW5E,SAAS,EAAa,EAAE,iBAAiC;CACvD,IAAM,IAAY,OAAO,SAAW,OAAe,EAAQ,OAAO,iBAC5D,IAAW,EAAgC,KAAK,EAChD,IAAY,EAA2B,KAAK,EAC5C,IAAc,EAA8C,KAAK,EACjE,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,CAAC,GAAO,KAAY,EAAwB,KAAK,EAEjD,IAAO,QAAkB;AAK7B,MAJA,AAEE,EAAY,aADZ,cAAc,EAAY,QAAQ,EACZ,OAEpB,EAAU,SAAS;AACrB,QAAK,IAAM,KAAS,EAAU,QAAQ,WAAW,CAC/C,GAAM,MAAM;AAEd,KAAU,UAAU;;AAKtB,EAHI,EAAS,YACX,EAAS,QAAQ,YAAY,OAE/B,EAAU,GAAM;IACf,EAAE,CAAC;AAGN,SAAgB,GAAM,CAAC,EAAK,CAAC;CAE7B,IAAM,IAAQ,EAAY,YAAY;AAChC,SAAC,KAAa,CAAC,OAAO,kBAG1B;KAAS,KAAK;AACd,OAAI;IACF,IAAM,IAAS,MAAM,UAAU,aAAa,aAAa;KACvD,OAAO,EAAE,YAAY,eAAe;KACpC,OAAO;KACR,CAAC;AAEF,IADA,EAAU,UAAU,GACpB,EAAU,GAAK;IACf,IAAM,IAAQ,EAAS;AACvB,IAAI,MACF,EAAM,YAAY,GAClB,MAAM,EAAM,MAAM,CAAC,YAAY,KAAA,EAAU;IAE3C,IAAM,IAAW,IAAI,OAAO,gBAAgB,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC;AACrE,MAAY,UAAU,YAAY,YAAY;KAC5C,IAAM,IAAK,EAAS;AAChB,YAAC,KAAM,EAAG,aAAa,GAG3B,KAAI;MAEF,IAAM,KADU,MAAM,EAAS,OAAO,EAAG,EACrB,MAAM,MAAM,EAAE,SAAS,MAAM,CAAC;AAClD,MAAI,MACF,EAAW,EAAI,SAAS,MAAM,CAAC,EAC/B,GAAM;aAEF;OAGP,IAAI;WACD;AAEN,IADA,EAAS,gEAAgE,EACzE,GAAM;;;IAEP;EAAC;EAAY;EAAM;EAAU,CAAC;AAEjC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,SAAD;IACE,KAAK;IACL,WAAW,8DAA8D,IAAS,gBAAgB;IAClG,OAAA;IACA,aAAA;IACA,cAAW;IACX,CAAA;GAGF,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,QAAD,EAAM,WAAU,6FAA8F,CAAA;MAC9G,kBAAC,QAAD,EAAM,WAAU,8FAA+F,CAAA;MAC/G,kBAAC,QAAD,EAAM,WAAU,gGAAiG,CAAA;MACjH,kBAAC,QAAD,EAAM,WAAU,iGAAkG,CAAA;MACjH,IAAS,kBAAC,QAAD,EAAM,WAAU,uEAAwE,CAAA,GAAG;MACjG;;IACF,CAAA;GAGJ,IAiBA,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,QAAD,EAAM,WAAU,6DAA8D,CAAA,EAAA,YAEzE;QACP,kBAAC,GAAD;KAAQ,MAAK;KAAS,MAAK;KAAK,SAAQ;KAAU,SAAS;eAA3D,CACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAAA,OAE1B;OACL;QAzBN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MAAQ,WAAU;MAA4B,eAAY;MAAS,CAAA;KACnE,kBAAC,KAAD;MAAG,WAAU;gBAA0C;MAAoB,CAAA;KAC1E,IACC,kBAAC,GAAD;MAAQ,MAAK;MAAS,MAAK;MAAK,SAAQ;MAAY,eAAe,KAAK,GAAO;gBAA/E,CACE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA,EAAA,eAEvB;UAET,kBAAC,KAAD;MAAG,WAAU;gBAAuC;MAEhD,CAAA;KAEL,IAAQ,kBAAC,KAAD;MAAG,WAAU;gBAA4C;MAAU,CAAA,GAAG;KAC3E;;GAaJ;;;AAeV,SAAS,EAA4B,EAAE,UAAO,UAAO,YAAS,eAA+B;AAC3F,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,QAAD;GAAM,WAAU;aAAmE;GAAa,CAAA,EAChG,kBAAC,OAAD;GACE,MAAK;GACL,cAAY;GACZ,WAAU;aAET,EAAQ,KAAK,MAAQ;IACpB,IAAM,IAAO,EAAI,MACX,IAAW,EAAI,UAAU;AAC/B,WACE,kBAAC,UAAD;KAEE,MAAK;KACL,gBAAc;KACd,eAAe,EAAS,EAAI,MAAM;KAClC,WAAW,8HACT,IACI,qEACA;eARR,CAWG,IAAO,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,GAAG,MACtC,EAAI,MACE;OAZF,EAAI,MAYF;KAEX;GACE,CAAA,CACF;;;AAyBV,SAAS,GAAc,EAAE,SAAM,iBAAc,YAAS,cAAW,cAA+B;CAC9F,IAAM,IAAS,EAAQ,GACjB,CAAC,GAAe,EAAE,SAAS,OAAc,GAAiC,EAC1E,CAAC,GAAe,EAAE,SAAS,OAAc,GAAiC,EAE1E,IAAU,QAAgC;AAC9C,MAAI,CAAC,EACH,QAAO;GAAE,MAAM;GAAI,MAAM;GAAI,UAAU;GAAI,MAAM;GAAQ,UAAU;GAAM;EAE3E,IAAM,IAAO,EAAgB,EAAQ,SAAS;AAC9C,SAAO;GACL,MAAM,EAAQ,QAAQ;GACtB,MAAM,EAAK,QAAQ,EAAS,EAAQ,QAAQ,GAAG;GAC/C,UAAU,EAAK,YAAY;GAC3B,MAAM,EAAK,QAAQ;GACnB,UAAU,EAAK,YAAY;GAC5B;IACA,CAAC,EAAQ,CAAC,EAEP,CAAC,GAAM,KAAW,EAA2B,EAAQ,EAErD,CAAC,GAAW,KAAgB,EAAwB,KAAK,EACzD,IAAU,GAAG,IAAO,SAAS,SAAS,GAAG,GAAS,MAAM;AAK9D,CAJI,KAAQ,MAAc,MACxB,EAAa,EAAQ,EACrB,EAAQ,EAAQ,GAEd,CAAC,KAAQ,MAAc,QACzB,EAAa,KAAK;CAGpB,IAAM,KAA8C,GAAU,MAA+B;AAC3F,KAAS,OAAU;GAAE,GAAG;IAAO,IAAQ;GAAO,EAAE;IAG5C,IAAS,KAAY;AAoC3B,QACE,kBAAC,GAAD;EAAwB;EAAoB;YAC1C,kBAAC,GAAD;GAAyB,WAAU;aAAnC;IACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAwB,IAAS,0BAA0B,wBAA+C,CAAA,EAC1G,kBAAC,GAAD,EAAA,UAAA;KAA6B;KACqC;KAAU;KAC9C,EAAA,CAAA,CACP,EAAA,CAAA;IAEzB,kBAAC,QAAD;KAAM,IAAG;KAAyB,UA5CvB,OAAO,MAA4C;AAClE,QAAM,gBAAgB;MACtB,IAAM,IAAO,EAAK,KAAK,MAAM,IAAI,EAAS,EAAK,KAAK,EAC9C,IAAQ;OACZ;OACA,MAAM,EAAK,KAAK,MAAM;OACtB;OACA,UAAU,EAAK,SAAS,MAAM,IAAI;OAClC,UAAU,EAAK;OACf,aAAa,EAAE,MAAM,EAAK,MAAM;OAEhC,UAAU;QAAE;QAAM,UAAU,EAAK,SAAS,MAAM;QAAE,MAAM,EAAK;QAAM,UAAU,EAAK;QAAU;OAC7F;AAED,UAAI;AACF,WAAI,KAAU,GAAS;QACrB,IAAM,IAAM,MAAM,EAAc,EAAE,WAAW;SAAE,IAAI,EAAQ;SAAI;SAAO,EAAE,CAAC;AACzE,YAAI,CAAC,EAAkB,GAAK,EAAI,MAAM,sBAAsB,IAAI,2BAA2B,CACzF;AAEF,UAAO,QAAQ,mBAAmB,IAAI,EAAM,KAAK,WAAW,EAAK,WAAW,WAAW,WAAW,GAAG;cAChG;QACL,IAAM,IAAM,MAAM,EAAc,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC;AACzD,YAAI,CAAC,EAAkB,GAAK,EAAI,MAAM,sBAAsB,IAAI,2BAA2B,CACzF;AAEF,UAAO,QAAQ,mBAAmB,IAAI,EAAM,KAAK,gBAAgB,EAAU,GAAG;;AAEhF,SAAa,GAAM;eACZ,GAAO;AACd,SAAO,MAAM,0BAA0B,EAAc,EAAM,CAAC;;;KAcd,WAAU;eAAtD;MACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAW,CAAA,EAC3D,kBAAC,GAAD;SACE,OAAO,EAAK;SACZ,WAAW,MAAM,EAAS,QAAQ,EAAE,OAAO,MAAM;SACjD,aAAY;SACZ,UAAA;SACA,CAAA,CACI;WACR,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAW,CAAA,EAC3D,kBAAC,GAAD;SACE,OAAO,EAAK;SACZ,WAAW,MAAM,EAAS,QAAQ,EAAE,OAAO,MAAM;SACjD,aAAY;SACZ,CAAA,CACI;UACJ;;MAEN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAe,CAAA,EAC/D,kBAAC,GAAD;SACE,OAAO,EAAK;SACZ,WAAW,MAAM,EAAS,YAAY,EAAE,OAAO,MAAM;SACrD,aAAY;SACZ,CAAA,CACI;WACR,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAW,CAAA,EAC3D,kBAAC,GAAD;SAAQ,OAAO,EAAK;SAAM,gBAAgB,MAAU,EAAS,QAAQ,EAAM;mBAA3E,CACE,kBAAC,GAAD;UAAe,cAAW;oBACxB,kBAAC,GAAD,EAAe,CAAA;UACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,GAAc,KAAK,MAClB,kBAAC,GAAD;UAAuB,OAAO;oBAC3B,EAAK,QAAQ,KAAK,IAAI;UACZ,EAFI,EAEJ,CACb,EACY,CAAA,CACT;WACH;UACJ;;MAEN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,IAAD;QAAO,SAAQ;QAAiB,WAAU;kBAAoB;QAEtD,CAAA,EACR,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAA8D,CAAA,CACrG,EAAA,CAAA,EACN,kBAAC,IAAD;QACE,IAAG;QACH,SAAS,EAAK;QACd,kBAAkB,MAAY,EAAS,YAAY,EAAQ;QAC3D,cAAW;QACX,CAAA,CACE;;MACD;;IAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KAAQ,MAAK;KAAS,SAAQ;KAAU,eAAe,EAAa,GAAM;KAAE,UAAU;eAAQ;KAErF,CAAA,EACT,kBAAC,GAAD;KAAQ,MAAK;KAAS,MAAK;KAAe,UAAU;eACjD,IAAS,YAAY,IAAS,iBAAiB;KACzC,CAAA,CACc,EAAA,CAAA;IACD;;EACT,CAAA;;AAuBvB,SAAS,GAAa,EAAE,SAAM,iBAAc,WAAQ,eAA+B;CACjF,IAAM,CAAC,GAAc,EAAE,gBAAa,GAAgC,EAE9D,IAAU,SACP;EACL,QAAQ,GAAQ,UAAU;EAC1B,WAAW,GAAQ,aAAa;EAChC,QAAQ,GAAQ,UAAU;EAC1B,WAAW,GAAQ,aAAa;EAChC,YAAY,GAAQ,cAAc;EACnC,GACD,CAAC,EAAO,CACT,EACK,CAAC,GAAM,KAAW,EAA0B,EAAQ,EACpD,CAAC,GAAW,KAAgB,EAAwB,KAAK,EACzD,IAAU,GAAG,IAAO,SAAS,SAAS,GAAG,GAAQ,MAAM;AAK7D,CAJI,KAAQ,MAAc,MACxB,EAAa,EAAQ,EACrB,EAAQ,EAAQ,GAEd,CAAC,KAAQ,MAAc,QACzB,EAAa,KAAK;CAGpB,IAAM,KAA6C,GAAU,MAA8B;AACzF,KAAS,OAAU;GAAE,GAAG;IAAO,IAAQ;GAAO,EAAE;;AA8BlD,QACE,kBAAC,GAAD;EAAwB;EAAoB;YAC1C,kBAAC,GAAD;GAAyB,WAAU;aAAnC;IACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAuB,wBAA4C,CAAA,EACnE,kBAAC,GAAD,EAAA,UAA6B,2DAEC,CAAA,CACP,EAAA,CAAA;IAEzB,kBAAC,QAAD;KAAM,IAAG;KAAwB,UArCtB,OAAO,MAA4C;AAElE,UADA,EAAM,gBAAgB,EAClB,CAAC,EACH;MAEF,IAAM,IAAQ;OACZ,SAAS,EAAO;OAChB,YAAY,EAAK,WAAW,MAAM,IAAI;OACtC,gBAAgB,EAAO,kBAAkB;OACzC,WAAW,EAAK,aAAa;OAC7B,QAAQ,EAAK;OACb,WAAW,EAAK;OAChB,QAAQ,EAAK,OAAO,MAAM,IAAI;OAC9B,UAAU,EAAO,YAAY,EAAE;OAChC;AACD,UAAI;OACF,IAAM,IAAM,MAAM,EAAa,EAAE,WAAW;QAAE,IAAI,EAAO;QAAI;QAAO,EAAE,CAAC;AACvE,WAAI,CAAC,EAAkB,GAAK,EAAI,MAAM,qBAAqB,IAAI,0BAA0B,CACvF;AAGF,OADA,EAAO,QAAQ,mBAAmB,EAClC,EAAa,GAAM;eACZ,GAAO;AACd,SAAO,MAAM,2BAA2B,EAAc,EAAM,CAAC;;;KAchB,WAAU;eAArD;MACE,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAgC;QAAkB,CAAA,EAClE,kBAAC,GAAD;QAAO,OAAO,EAAK;QAAY,WAAW,MAAM,EAAS,cAAc,EAAE,OAAO,MAAM;QAAI,CAAA,CACpF;;MAER,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAa,CAAA,EAC7D,kBAAC,GAAD;SAAQ,OAAO,EAAK;SAAQ,gBAAgB,MAAU,EAAS,UAAU,EAAM;mBAA/E,CACE,kBAAC,GAAD;UAAe,cAAW;oBACxB,kBAAC,GAAD,EAAe,CAAA;UACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAgB,KAAK,MACpB,kBAAC,GAAD;UAAyB,OAAO;oBAC7B;UACU,EAFI,EAEJ,CACb,EACY,CAAA,CACT;WACH;WACR,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAgB,CAAA,EAChE,kBAAC,GAAD;SAAQ,OAAO,EAAK;SAAW,gBAAgB,MAAU,EAAS,aAAa,EAAM;mBAArF,CACE,kBAAC,GAAD;UAAe,cAAW;oBACxB,kBAAC,GAAD,EAAe,CAAA;UACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,GAAmB,KAAK,MACvB,kBAAC,GAAD;UAA4B,OAAO;oBAChC;UACU,EAFI,EAEJ,CACb,EACY,CAAA,CACT;WACH;UACJ;;MAEN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAa,CAAA,EAC7D,kBAAC,GAAD;SAAO,OAAO,EAAK;SAAQ,WAAW,MAAM,EAAS,UAAU,EAAE,OAAO,MAAM;SAAI,CAAA,CAC5E;WACR,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAc,CAAA,EAC9D,kBAAC,GAAD;SACE,OAAO,EAAK,aAAa;SACzB,gBAAgB,MAAU,EAAS,aAAa,MAAU,SAAS,KAAK,EAAM;mBAFhF,CAIE,kBAAC,GAAD;UAAe,cAAW;oBACxB,kBAAC,GAAD,EAAe,CAAA;UACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;UAAY,OAAM;oBAAO;UAAuB,CAAA,EAC/C,EAAS,KAAK,MACb,kBAAC,GAAD;UAAuB,OAAO,EAAE;oBAC7B,EAAE,QAAQ,EAAE;UACF,EAFI,EAAE,GAEN,CACb,CACY,EAAA,CAAA,CACT;WACH;UACJ;;MACD;;IAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KAAQ,MAAK;KAAS,SAAQ;KAAU,eAAe,EAAa,GAAM;KAAE,UAAU;eAAS;KAEtF,CAAA,EACT,kBAAC,GAAD;KAAQ,MAAK;KAAS,MAAK;KAAc,UAAU;eAChD,IAAU,YAAY;KAChB,CAAA,CACc,EAAA,CAAA;IACD;;EACT,CAAA;;AAwBvB,SAAS,GAAa,EACpB,YACA,cACA,aACA,cACA,oBACA,oBACA,kBACoB;CACpB,IAAM,CAAC,GAAW,KAAgB,EAAS,GAAG,EACxC,CAAC,GAAQ,KAAa,EAA2C,KAAK,EACtE,CAAC,GAAW,KAAgB,EAA8C,KAAK,EAC/E,CAAC,GAAW,KAAgB,EAAS,GAAG,EACxC,IAAW,EAAgC,KAAK,EAEhD,CAAC,GAAc,EAAE,gBAAa,GAAgC,EAE9D,IADgB,EAAsB;EAAE;EAAS,OAAO;EAAK,QAAQ;EAAG,CAAC,CAChD,MAAM,cAAc,SAAS,EAAE,EAExD,MAAmB,MAAgF;EACvG,IAAM,IAAQ,EAAI,MAAM;AACxB,MAAI,CAAC,EACH,QAAO;GAAE,YAAY;GAAM,OAAO;GAAY,SAAS;GAAO;AAEhE,MAAI,EAAM,SAAS,IAAI,EAAE;GACvB,IAAM,IAAQ,EAAU,MAAM,MAAM,EAAE,OAAO,aAAa,KAAK,EAAM,aAAa,CAAC;AACnF,UAAO;IAAE,YAAY,GAAO,MAAM;IAAM,OAAO,GAAO,YAAY;IAAO,SAAS,EAAQ;IAAQ;;EAEpG,IAAM,IAAO,EAAU,MAAM,MAAM,EAAE,OAAO,EAAM;AAClD,SAAO;GAAE,YAAY;GAAO,OAAO,GAAM,YAAY,YAAY;GAAS,SAAS,EAAQ;GAAO;;AA6CpG,QACE,kBAAC,GAAD;EAAW,WAAU;EAAQ,MAAA;EAAK,WAAU;YAA5C;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAU,WAAU;KAA8B,eAAY;KAAS,CAAA,EACvE,kBAAC,MAAD;KAAI,WAAU;eAA0C;KAAe,CAAA,CACnE;;GACN,kBAAC,KAAD;IAAG,WAAU;cAAb;KAAgD;KACkC;KAAU;KACxF;;GAEJ,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,EAAc,aArDI,MAAkB;AAIxC,KAHA,EAAa,EAAM,EACnB,EAAU,KAAK,EACf,EAAO,KAAK,eAAe,wCAAwC,EACnE,EAAS,SAAS,OAAO;OAiDuB,CAAA;IACxC,CAAA;GAEN,kBAAC,QAAD;IAAgB,UAjDH,OAAO,MAA4C;AAClE,OAAM,gBAAgB;KACtB,IAAM,EAAE,eAAY,aAAU,GAAgB,EAAU;AACxD,SAAI,EAAU,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,GAAY;AACjD,QAAO,MAAM,sBAAsB,sCAAsC,EAAU,MAAM,CAAC,IAAI;AAC9F;;KAEF,IAAM,IAAQ;MACZ;MACA;MACA,WAAW,KAAmB;MAC9B;MACA;MACA,QAAQ,MAAc,QAAQ,gBAAgB;MAC9C,6BAAY,IAAI,MAAM,EAAC,aAAa;MACpC,UAAU,IAAY,EAAE,cAAW,GAAG,EAAE;MACzC;AACD,SAAI;MACF,IAAM,IAAM,MAAM,EAAa,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC;AACxD,UAAI,CAAC,EAAkB,GAAK,EAAI,MAAM,qBAAqB,IAAI,4BAA4B,CACzF;MAEF,IAAM,IAAgB,EAAS,MAAM,MAAM,EAAE,OAAO,EAAgB;AAOpE,MANA,EAAO,QACL,GAAG,EAAM,WAAW,MAAc,QAAQ,QAAQ,QAClD,gBAAgB,IAAS,GAAe,OAAO,MAAM,EAAc,SAAS,GAAG,GAChF,EACD,EAAa,GAAG,EAChB,EAAS,SAAS,OAAO,EACzB,GAAa;cACN,GAAO;AACd,QAAO,MAAM,6BAA6B,EAAc,EAAM,CAAC;;;IAkBrC,WAAU;cAApC;KACE,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAhB,CACE,kBAAC,GAAD,EAAU,WAAU,eAAgB,CAAA,EAAA,gBAE/B;UACP,kBAAC,GAAD;OACE,KAAK;OACL,OAAO;OACP,WAAW,MAAM,EAAa,EAAE,OAAO,MAAM;OAC7C,aAAY;OACZ,cAAa;OACb,WAAU;OACV,CAAA,CACI;;KAER,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,GAAD;QACE,OAAM;QACN,OAAO;QACP,UAAU;QACV,SAAS,CACP;SAAE,OAAO;SAAM,OAAO;SAAM,MAAM;SAAQ,EAC1C;SAAE,OAAO;SAAU,OAAO;SAAU,MAAM;SAAU,CACrD;QACD,CAAA;OACF,kBAAC,GAAD;QACE,OAAM;QACN,OAAO;QACP,UAAU;QACV,SAAS,CACP;SAAE,OAAO;SAAM,OAAO;SAAM,MAAM;SAAkB,EACpD;SAAE,OAAO;SAAO,OAAO;SAAO,MAAM;SAAmB,CACxD;QACD,CAAA;OACF,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAkE;SAAc,CAAA,EAChG,kBAAC,GAAD;SAAQ,OAAO,KAAmB;SAAQ,gBAAgB,MAAM,EAAgB,MAAM,SAAS,KAAK,EAAE;mBAAtG,CACE,kBAAC,GAAD;UAAe,cAAW;UAAU,WAAU;oBAC5C,kBAAC,GAAD,EAAa,aAAY,cAAe,CAAA;UAC1B,CAAA,EAChB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;UAAY,OAAM;oBAAO;UAAuB,CAAA,EAC/C,EAAS,KAAK,MACb,kBAAC,GAAD;UAAuB,OAAO,EAAE;oBAC7B,EAAE,QAAQ,EAAE;UACF,EAFI,EAAE,GAEN,CACb,CACY,EAAA,CAAA,CACT;WACH;;OACR,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAkE;SAAc,CAAA,EAChG,kBAAC,GAAD;SAAQ,OAAO,KAAa;SAAQ,gBAAgB,MAAM,EAAa,MAAM,SAAS,KAAK,EAAE;mBAA7F,CACE,kBAAC,GAAD;UAAe,cAAW;UAAU,WAAU;oBAC5C,kBAAC,GAAD,EAAa,aAAY,eAAgB,CAAA;UAC3B,CAAA,EAChB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;UAAY,OAAM;oBAAO;UAAwB,CAAA,EAChD,EAAS,KAAK,MACb,kBAAC,GAAD;UAAuB,OAAO,EAAE;oBAC7B,EAAE;UACQ,EAFI,EAAE,GAEN,CACb,CACY,EAAA,CAAA,CACT;WACH;;OACJ;;KAEN,kBAAC,GAAD;MAAQ,MAAK;MAAS,MAAK;MAAK,UAAU,KAAW,CAAC,EAAU,MAAM;MAAE,WAAU;gBAAlF,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC5B,IAAU,eAAe,SAAS,MAAc,QAAQ,QAAQ,OAC1D;;KACJ;;GACG;;;AAQhB,IAAM,KAAY,IACZ,KAAgB;AAEtB,SAAwB,KAAY;CAElC,IAAM,IADc,EAAe;EAAE,OAAO;EAAK,QAAQ;EAAG,CAAC,CAClC,MAAM,OAAO,SAAS,EAAE,EAC7C,CAAC,GAAiB,KAAsB,EAAS,GAAG,EACpD,IAAe,KAAmB,KAAA,GAClC,IAAgB,EAAO,MAAM,MAAM,EAAE,OAAO,EAAgB,EAE5D,CAAC,GAAiB,KAAsB,EAAS,GAAG,EACpD,IAAoB,EAAc;EAAE,UAAU;EAAW,UAAU;EAAiB,CAAC,EAErF,IAAgB,EAAwB;EAAE,SAAS;EAAc,OAAO;EAAK,QAAQ;EAAG,CAAC,EACzF,IAAe,EAAuB;EAC1C,SAAS;EACT,OAAO,EAAkB;EACzB,QAAQ,EAAkB;EAC3B,CAAC,EAEI,IAAe,EAAuB;EAAE,SAAS;EAAc,OAAO;EAAe,QAAQ;EAAG,CAAC,EACjG,IAAiB,EAAkB;EAAE,SAAS;EAAc,OAAO;EAAK,QAAQ;EAAG,CAAC,EAEpF,IAAW,QACR,EAAc,MAAM,gBAAgB,SAAS,EAAE,EACtD,CAAC,EAAc,KAAK,CACrB,EACK,IAAW,EAAa,MAAM,eAAe,SAAS,EAAE,EACxD,IAAe,EAAa,MAAM,eAAe,SAAS,GAC1D,IAAa,QAAe,EAAa,MAAM,eAAe,SAAS,EAAE,EAAkB,CAAC,EAAa,KAAK,CAAC,EAC/G,IAAY,QAA8B,EAAe,MAAM,UAAU,SAAS,EAAE,EAAE,CAAC,EAAe,KAAK,CAAC,EAC5G,IAAiB,EAAe,MAAM,UAAU,SAAS,GAEzD,KAAgB,QAAc;EAClC,IAAM,oBAAM,IAAI,KAAqB;AACrC,OAAK,IAAM,KAAK,EACd,GAAI,IAAI,EAAE,IAAI,EAAE,SAAS;AAE3B,SAAO;IACN,CAAC,EAAU,CAAC,EAET,IAAe,QAAc;EACjC,IAAM,oBAAM,IAAI,KAAqB;AACrC,OAAK,IAAM,KAAK,EACd,GAAI,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG;AAE/B,SAAO;IACN,CAAC,EAAS,CAAC,EAGR,EAAE,mBAAgB,qBAAkB,QAAc;EACtD,IAAM,oBAAkB,IAAI,KAAa,EACnC,IAAa,EAAE,OAAO,GAAG,EACzB,oBAAa,IAAI,KAA0B,EAE3C,IAAU,CAAC,GAAG,EAAW,CAAC,MAAM,GAAG,MAAM,IAAI,KAAK,EAAE,WAAW,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;AACnH,OAAK,IAAM,KAAK,GAAS;GACvB,IAAM,IAAM,EAAE,cAAc;AAc5B,OAbI,EAAE,cAAc,QACd,IACF,EAAgB,OAAO,EAAI,GAClB,EAAW,QAAQ,KAC5B,IAAW,QAGT,IACF,EAAgB,IAAI,EAAI,GAExB,EAAW,SAAS,GAGpB,EAAE,aAAa,EAAE,cAAc,OAAO;IACxC,IAAM,IAAM,EAAW,IAAI,EAAE,UAAU,oBAAI,IAAI,KAAa;AAE5D,IADA,EAAI,IAAI,EAAE,GAAG,EACb,EAAW,IAAI,EAAE,WAAW,EAAI;;;EAGpC,IAAM,oBAAS,IAAI,KAAqB;AACxC,OAAK,IAAM,CAAC,GAAI,MAAQ,EACtB,GAAO,IAAI,GAAI,EAAI,KAAK;AAE1B,SAAO;GAAE,gBAAgB,EAAgB,OAAO,EAAW;GAAO,eAAe;GAAQ;IACxF,CAAC,EAAW,CAAC,EAEV,IAAiB,GACjB,IAAW,IAAiB,IAAI,KAAK,IAAI,KAAK,KAAK,MAAO,IAAiB,IAAkB,IAAI,CAAC,GAAG,GAErG,CAAC,KAAiB,GAAiC,EACnD,CAAC,MAAgB,GAAgC,EAEjD,CAAC,IAAmB,KAAwB,EAAS,GAAM,EAC3D,CAAC,IAAgB,KAAqB,EAAiC,KAAA,EAAU,EACjF,CAAC,GAAkB,KAAuB,EAAS,GAAM,EACzD,CAAC,GAAe,MAAoB,EAA2B,KAAK,EAEpE,UAAuB;AAE3B,EADA,EAAkB,KAAA,EAAU,EAC5B,EAAqB,GAAK;IAEtB,MAAmB,MAAwB;AAE/C,EADA,EAAkB,EAAQ,EAC1B,EAAqB,GAAK;IAEtB,MAAkB,MAAsB;AAE5C,EADA,GAAiB,EAAO,EACxB,EAAoB,GAAK;IAGrB,KAAkB,OAAO,MAAwB;EACrD,IAAM,IAAM,MAAM,EAAc,EAAE,WAAW,EAAE,IAAI,EAAQ,IAAI,EAAE,CAAC;AAC7D,IAAkB,GAAK,EAAI,MAAM,uBAAuB,EAAQ,KAAK,MAAM,2BAA2B,KAGvG,MAAoB,EAAQ,MAC9B,EAAmB,GAAG,EAExB,EAAO,QAAQ,mBAAmB,IAAI,EAAQ,QAAQ,EAAQ,GAAG,gBAAgB;IAG7E,KAAiB,OAAO,MAAsB;EAClD,IAAM,IAAM,MAAM,GAAa,EAAE,WAAW,EAAE,IAAI,EAAO,IAAI,EAAE,CAAC;AAC3D,IAAkB,GAAK,EAAI,MAAM,sBAAsB,EAAO,KAAK,MAAM,0BAA0B,IAGxG,EAAO,QAAQ,0BAA0B;IAGrC,WAA4B;AAE3B,EADA,EAAa,SAAS,EACtB,EAAa,SAAS;IAGvB,MAAe,MACf,EAAO,aACF,GAAc,IAAI,EAAO,WAAW,IAAI,YAAY,EAAO,WAAW,MAAM,GAAG,EAAE,KAEnF,iBAGH,KAAW,EAAQ;AAEzB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,IAAD,EAAA,UAAa,0SAIC,CAAA;GAEd,kBAAC,IAAD,EAAA,UACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAd,CACE,kBAAC,IAAD,EAAA,UAAc,SAAoB,CAAA,EAAA,cAC/B;QACL,kBAAC,KAAD;KAAG,WAAU;eAAmC;KAE5C,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAgC;OAAY,CAAA,EAC5D,kBAAC,GAAD;OAAQ,OAAO,KAAmB;OAAO,gBAAgB,MAAM,EAAmB,MAAM,QAAQ,KAAK,EAAE;iBAAvG,CACE,kBAAC,GAAD;QAAe,cAAW;QAAQ,WAAU;kBAC1C,kBAAC,GAAD,EAAa,aAAY,cAAe,CAAA;QAC1B,CAAA,EAChB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;QAAY,OAAM;kBAAM;QAAuB,CAAA,EAC9C,EAAO,KAAK,MACX,kBAAC,GAAD;QAA2B,OAAO,EAAM;kBACrC,EAAM;QACI,EAFI,EAAM,GAEV,CACb,CACY,EAAA,CAAA,CACT;SACH;SACR,kBAAC,GAAD;MAAQ,MAAK;MAAS,SAAS;MAAgB,UAAU,CAAC;gBAA1D,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,cAErB;QACL;OACF;OACQ,CAAA;GAEd,KAUA,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,IAAD;MACE,SAAS;MACT,WAAW,GAAe,QAAQ;MACxB;MACC;MACM;MACjB,iBAAiB;MACjB,aAAa;MACb,CAAA;KACE,CAAA,EAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CAEE,kBAAC,WAAD,EAAA,UAAA;MACE,kBAAC,MAAD;OAAI,WAAU;iBAAoE;OAAa,CAAA;MAC/F,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACG,EAAS,KAAK,MAAY;QACzB,IAAM,IAAS,MAAoB,EAAQ,IACrC,IAAQ,EAAc,IAAI,EAAQ,GAAG,IAAI;AAC/C,eACE,kBAAC,OAAD;SAEE,WAAW,oGACT,IACI,mEACA;mBALR,CAQE,kBAAC,UAAD;UACE,MAAK;UACL,gBAAc;UACd,eAAe,EAAmB,IAAS,KAAK,EAAQ,GAAG;UAC3D,WAAU;oBAJZ,CAMG,EAAQ,QAAQ,EAAQ,IACxB,IAAQ,IACP,kBAAC,QAAD;WAAM,WAAU;qBACb;WACI,CAAA,GACL,KACG;aACT,kBAAC,GAAD;UACE,WAAW,WAAW,EAAQ,QAAQ,EAAQ,GAAG;UACjD,YAAY,EAAQ,QAAQ,KAAA;UAC5B,cAAc,GAAgB,EAAQ;UACtC,gBAAgB,GAAgB,EAAQ;UACxC,CAAA,CACE;WA1BC,EAAQ,GA0BT;SAER,EACF,kBAAC,UAAD;QACE,MAAK;QACL,SAAS;QACT,WAAU;kBAHZ,CAKE,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA,EAAA,cAEzB;UACL;;MACL,EAAc,WAAW,EAAS,WAAW,IAC5C,kBAAC,KAAD;OAAG,WAAU;iBAAmC;OAAqB,CAAA,GACnE;MACI,EAAA,CAAA,EAGV,kBAAC,GAAD;MAAW,WAAU;MAAQ,WAAU;gBAAvC;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA0C;SAAqB,CAAA,EAC7E,kBAAC,KAAD;SAAG,WAAU;mBAAb;UAA2C;UAC9B;UACX,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAe,gBAAgB;WAC3B,CAAA;UACN,IAAiB,IAChB,kBAAA,GAAA,EAAA,UAAA;WACG;WAAI;WACH,kBAAC,QAAD;YAAM,WAAU;sBAAgB,EAAe,gBAAgB;YAAQ,CAAA;WACxE,EAAA,CAAA,GACD;UACF;WACA;;OAEL,IAAiB,IAChB,kBAAC,OAAD;QACE,WAAU;QACV,MAAK;QACL,iBAAe;QACf,iBAAe;QACf,iBAAe;QACf,cAAW;kBAEX,kBAAC,OAAD;SACE,WAAU;SACV,OAAO,EAAE,OAAO,GAAG,EAAS,IAAI;SAChC,CAAA;QACE,CAAA,GACJ;OAEJ,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAQ,WAAW,IAClB,kBAAC,IAAD;SACE,cAAa;SACb,OAAO,EAAa,UAAU,8BAA8B;SAC5D,aAAY;SACZ,WAAU;SACV,CAAA,GAEF,kBAAC,IAAD;SAAY,WAAU;mBACpB,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAQ,KAAK,MAAW;WACvB,IAAM,IAAQ,GAAY,EAAO,EAC3B,IAAQ,EAAO,cAAc,OAC7B,IAAU,EAAO,YAAY,EAAa,IAAI,EAAO,UAAU,GAAG;AACxE,kBACE,kBAAC,MAAD;YAEE,WAAU;sBAFZ;aAIE,kBAAC,QAAD;cACE,WAAU;cACV,eAAY;wBAEX,GAAS,EAAM;cACX,CAAA;aACP,kBAAC,OAAD;cAAK,WAAU;wBAAf,CACE,kBAAC,KAAD;eAAG,WAAU;yBAA0C;eAAU,CAAA,EACjE,kBAAC,KAAD;eAAG,WAAU;yBAAb;gBACG,GAAW,EAAO,WAAW;gBAAC;gBAAI,EAAO;gBACxC;iBACA;;aACN,kBAAC,OAAD;cAAK,WAAU;wBAAf;eACE,kBAAC,IAAD;gBAAO,SAAS,IAAQ,cAAc;gBAAW,WAAU;0BACxD,IAAQ,gBAAgB;gBACnB,CAAA;eACP,IACC,kBAAC,QAAD;gBAAM,WAAU;0BAAgD;gBAAe,CAAA,GAC7E;eACJ,kBAAC,GAAD;gBACE,WAAW,mBAAmB,EAAO,GAAG;gBACxC,cAAc,GAAe,EAAO;gBACpC,gBAAgB,GAAe,EAAO;gBACtC,CAAA;eACE;;aACH;cA5BE,EAAO,GA4BT;YAEP;UACC,CAAA;SACM,CAAA;QAEX,CAAA;OACN,kBAAC,GAAD;QACE,QAAQ,EAAkB;QAC1B,OAAO,EAAkB;QACzB,aAAa,EAAQ;QACrB,OAAO;QACP,QAAQ,EAAkB;QAC1B,QAAQ,EAAkB;QAC1B,WAAU;QACV,SAAS,EAAa;QACtB,CAAA;OACQ;QACR;OACF;QA/KN,kBAAC,GAAD;IAAW,WAAU;IAAQ,WAAU;cACrC,kBAAC,IAAD;KACE,cAAa;KACb,OAAM;KACN,aAAY;KACZ,WAAU;KACV,CAAA;IACQ,CAAA;GA2Kb,IACC,kBAAC,IAAD;IACE,MAAM;IACN,cAAc;IACd,SAAS;IACT,WAAW,GAAe,QAAQ;IAClC,SAAS;IACT,CAAA,GACA;GAEJ,kBAAC,IAAD;IACE,MAAM;IACN,cAAc;IACd,QAAQ;IACE;IACV,CAAA;GACE"}
|
|
1
|
+
{"version":3,"file":"KioskPage.js","names":[],"sources":["../../../../src/eventfullymanaged/pages/modules/KioskPage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n EmphasisPanel,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n Label,\n PagePurpose,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ScrollArea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n} from '@burdenoff/fe-libs/ui';\nimport {\n ArrowLeftFromLine,\n ArrowRightToLine,\n Camera,\n CameraOff,\n CloudOff,\n Keyboard,\n LogIn,\n Plus,\n QrCode,\n RefreshCw,\n ScanLine,\n} from 'lucide-react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport {\n useAttendeesQuery,\n useCheckInRecordsQuery,\n useCheckInStationsQuery,\n useCreateCheckInRecordMutation,\n useCreateCheckInStationMutation,\n useDeleteCheckInRecordMutation,\n useDeleteCheckInStationMutation,\n useEventSessionsQuery,\n useEventsQuery,\n useScanCheckInMutation,\n useUpdateCheckInRecordMutation,\n useUpdateCheckInStationMutation,\n} from '../../api/eventApi';\nimport { ActionMenu, Pagination, usePagination } from '../../components';\nimport { enqueuePendingScan } from '../../lib/offlineCheckInQueue';\nimport { describeError, mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\nimport { useOfflineCheckInSync } from '../../lib/useOfflineCheckInSync';\n\n// BOFF-4330 — a signed check-in token is \"<registrationId>.<64-hex-char HMAC>\".\n// Manual lookups (typed name/email/attendee id) never match this shape, so it\n// safely distinguishes a real QR scan from manual entry without extra state.\nconst CHECK_IN_TOKEN_PATTERN = /^[^.\\s]+\\.[0-9a-f]{64}$/i;\n\n// ---------------------------------------------------------------------------\n// BarcodeDetector — a built-in browser API (Chromium/Edge). No new dependency;\n// feature-detected so the scanner degrades gracefully to manual entry when the\n// API (or a camera) is unavailable.\n// ---------------------------------------------------------------------------\n\ninterface DetectedBarcode {\n rawValue: string;\n}\ninterface BarcodeDetectorLike {\n detect(source: CanvasImageSource): Promise<DetectedBarcode[]>;\n}\ninterface BarcodeDetectorCtor {\n new (options?: { formats: string[] }): BarcodeDetectorLike;\n}\ndeclare global {\n interface Window {\n BarcodeDetector?: BarcodeDetectorCtor;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Shared types\n// ---------------------------------------------------------------------------\n\ntype StationRow = {\n id: string;\n eventId?: string | null;\n name?: string | null;\n metadata?: Record<string, unknown> | null;\n};\n\ntype RecordRow = {\n id: string;\n eventId: string;\n stationId?: string | null;\n attendeeId?: string | null;\n registrationId?: string | null;\n method: string;\n status: string;\n direction: string;\n recordedAt: string;\n metadata?: Record<string, unknown> | null;\n};\n\nconst STATION_TYPES = ['DESK', 'GATE', 'SELF_SERVICE', 'MOBILE'] as const;\nconst CHECKIN_METHODS = ['QR', 'MANUAL'] as const;\nconst CHECKIN_DIRECTIONS = ['IN', 'OUT'] as const;\n\n/**\n * The stations list resolver projects a CheckInStation onto the generic\n * SimpleEntity shape (id/name/metadata) — it does NOT expose the `code`,\n * `location` or `isActive` columns. To keep create → list → edit lossless we\n * mirror those attributes into `metadata` on every write, so an edit opened from\n * a list row can rebuild the full required input without a by-id resolver.\n */\ntype StationMeta = {\n code?: string;\n location?: string;\n type?: string;\n isActive?: boolean;\n};\n\nfunction readStationMeta(metadata: Record<string, unknown> | null | undefined): StationMeta {\n if (!metadata || typeof metadata !== 'object') {\n return {};\n }\n const m = metadata as Record<string, unknown>;\n return {\n code: typeof m.code === 'string' ? m.code : undefined,\n location: typeof m.location === 'string' ? m.location : undefined,\n type: typeof m.type === 'string' ? m.type : undefined,\n isActive: typeof m.isActive === 'boolean' ? m.isActive : undefined,\n };\n}\n\nfunction slugCode(name: string): string {\n return (\n name\n .trim()\n .toUpperCase()\n .replace(/[^A-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 24) || 'STATION'\n );\n}\n\nfunction initials(label: string): string {\n const parts = label.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) {\n return '?';\n }\n if (parts.length === 1) {\n return parts[0].slice(0, 2).toUpperCase();\n }\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n}\n\nfunction formatTime(iso: string): string {\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });\n}\n\n// ===========================================================================\n// Camera QR scanner viewfinder\n// ===========================================================================\n\ninterface QrViewfinderProps {\n onDetected: (value: string) => void;\n}\n\nfunction QrViewfinder({ onDetected }: QrViewfinderProps) {\n const supported = typeof window !== 'undefined' && Boolean(window.BarcodeDetector);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const streamRef = useRef<MediaStream | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const [active, setActive] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const stop = useCallback(() => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (streamRef.current) {\n for (const track of streamRef.current.getTracks()) {\n track.stop();\n }\n streamRef.current = null;\n }\n if (videoRef.current) {\n videoRef.current.srcObject = null;\n }\n setActive(false);\n }, []);\n\n // Always release the camera when the component unmounts.\n useEffect(() => stop, [stop]);\n\n const start = useCallback(async () => {\n if (!supported || !window.BarcodeDetector) {\n return;\n }\n setError(null);\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n video: { facingMode: 'environment' },\n audio: false,\n });\n streamRef.current = stream;\n setActive(true);\n const video = videoRef.current;\n if (video) {\n video.srcObject = stream;\n await video.play().catch(() => undefined);\n }\n const detector = new window.BarcodeDetector({ formats: ['qr_code'] });\n intervalRef.current = setInterval(async () => {\n const el = videoRef.current;\n if (!el || el.readyState < 2) {\n return;\n }\n try {\n const results = await detector.detect(el);\n const hit = results.find((r) => r.rawValue.trim());\n if (hit) {\n onDetected(hit.rawValue.trim());\n stop();\n }\n } catch {\n // Transient decode frames can throw; ignore and keep polling.\n }\n }, 350);\n } catch {\n setError('Camera unavailable. Grant camera access or use manual lookup.');\n stop();\n }\n }, [onDetected, stop, supported]);\n\n return (\n <div className=\"relative aspect-square w-full overflow-hidden rounded-card border-2 border-accent-primary/70 bg-bg-sunken\">\n {/* Live camera feed (hidden until active). */}\n <video\n ref={videoRef}\n className={`h-full w-full object-cover transition-opacity duration-300 ${active ? 'opacity-100' : 'opacity-0'}`}\n muted\n playsInline\n aria-label=\"Attendee QR camera preview\"\n />\n\n {/* Corner brackets + scan affordance overlay. */}\n <div className=\"pointer-events-none absolute inset-0 p-5\">\n <div className=\"relative h-full w-full\">\n <span className=\"absolute left-0 top-0 h-10 w-10 rounded-tl-lg border-l-4 border-t-4 border-accent-primary\" />\n <span className=\"absolute right-0 top-0 h-10 w-10 rounded-tr-lg border-r-4 border-t-4 border-accent-primary\" />\n <span className=\"absolute bottom-0 left-0 h-10 w-10 rounded-bl-lg border-b-4 border-l-4 border-accent-primary\" />\n <span className=\"absolute bottom-0 right-0 h-10 w-10 rounded-br-lg border-b-4 border-r-4 border-accent-primary\" />\n {active ? <span className=\"absolute inset-x-6 top-1/2 h-0.5 animate-pulse bg-accent-primary/80\" /> : null}\n </div>\n </div>\n\n {/* Idle state. */}\n {!active ? (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-3 text-center\">\n <QrCode className=\"h-16 w-16 text-text-muted\" aria-hidden=\"true\" />\n <p className=\"text-lg font-semibold text-text-primary\">Scan attendee QR</p>\n {supported ? (\n <Button type=\"button\" size=\"sm\" variant=\"secondary\" onClick={() => void start()}>\n <Camera className=\"h-4 w-4\" />\n Start camera\n </Button>\n ) : (\n <p className=\"max-w-56 text-xs text-text-secondary\">\n Camera scanning isn't available in this browser — use manual lookup below.\n </p>\n )}\n {error ? <p className=\"max-w-56 text-xs text-status-danger-text\">{error}</p> : null}\n </div>\n ) : (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center justify-between gap-2 bg-bg-canvas/70 p-3 backdrop-blur\">\n <span className=\"flex items-center gap-1.5 text-xs font-medium text-text-primary\">\n <span className=\"h-2 w-2 animate-pulse rounded-full bg-status-success-text\" />\n Scanning…\n </span>\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={stop}>\n <CameraOff className=\"h-4 w-4\" />\n Stop\n </Button>\n </div>\n )}\n </div>\n );\n}\n\n// ===========================================================================\n// Segmented toggle (Method / Direction)\n// ===========================================================================\n\ninterface SegmentedProps<T extends string> {\n label: string;\n value: T;\n options: readonly { value: T; label: string; icon?: React.ComponentType<{ className?: string }> }[];\n onChange: (value: T) => void;\n}\n\nfunction Segmented<T extends string>({ label, value, options, onChange }: SegmentedProps<T>) {\n return (\n <div className=\"space-y-1.5\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">{label}</span>\n <div\n role=\"group\"\n aria-label={label}\n className=\"inline-flex rounded-input border border-border-default bg-bg-sunken p-0.5\"\n >\n {options.map((opt) => {\n const Icon = opt.icon;\n const selected = opt.value === value;\n return (\n <button\n key={opt.value}\n type=\"button\"\n aria-pressed={selected}\n onClick={() => onChange(opt.value)}\n className={`inline-flex items-center gap-1.5 rounded-[calc(var(--radius-input)-2px)] px-3 py-1.5 text-sm font-medium transition-colors ${\n selected\n ? 'bg-action-primary-bg text-action-primary-text shadow-elevation-1'\n : 'text-text-secondary hover:text-text-primary'\n }`}\n >\n {Icon ? <Icon className=\"h-4 w-4\" /> : null}\n {opt.label}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n\n// ===========================================================================\n// Station create / edit dialog\n// ===========================================================================\n\ntype StationFormState = {\n name: string;\n code: string;\n location: string;\n type: string;\n isActive: boolean;\n};\n\ninterface StationDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n eventId: string;\n eventName: string;\n /** Present when editing an existing station. */\n station?: StationRow;\n}\n\nfunction StationDialog({ open, onOpenChange, eventId, eventName, station }: StationDialogProps) {\n const isEdit = Boolean(station);\n const [createStation, { loading: creating }] = useCreateCheckInStationMutation();\n const [updateStation, { loading: updating }] = useUpdateCheckInStationMutation();\n\n const initial = useMemo<StationFormState>(() => {\n if (!station) {\n return { name: '', code: '', location: '', type: 'DESK', isActive: true };\n }\n const meta = readStationMeta(station.metadata);\n return {\n name: station.name ?? '',\n code: meta.code ?? slugCode(station.name ?? ''),\n location: meta.location ?? '',\n type: meta.type ?? 'DESK',\n isActive: meta.isActive ?? true,\n };\n }, [station]);\n\n const [form, setForm] = useState<StationFormState>(initial);\n // Reset the form to the active station whenever the dialog is (re)opened.\n const [seededFor, setSeededFor] = useState<string | null>(null);\n const seedKey = `${open ? 'open' : 'closed'}:${station?.id ?? 'new'}`;\n if (open && seededFor !== seedKey) {\n setSeededFor(seedKey);\n setForm(initial);\n }\n if (!open && seededFor !== null) {\n setSeededFor(null);\n }\n\n const onChange = <K extends keyof StationFormState>(field: K, value: StationFormState[K]) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n };\n\n const saving = creating || updating;\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const code = form.code.trim() || slugCode(form.name);\n const input = {\n eventId,\n name: form.name.trim(),\n code,\n location: form.location.trim() || null,\n isActive: form.isActive,\n kioskConfig: { type: form.type },\n // Mirror the write-only columns so the SimpleEntity list can rebuild them.\n metadata: { code, location: form.location.trim(), type: form.type, isActive: form.isActive },\n };\n\n try {\n if (isEdit && station) {\n const res = await updateStation({ variables: { id: station.id, input } });\n if (!mutationSucceeded(res, res.data?.updateCheckInStation?.id, 'Could not update station')) {\n return;\n }\n notify.success('Station updated', `“${input.name}” is now ${form.isActive ? 'active' : 'disabled'}.`);\n } else {\n const res = await createStation({ variables: { input } });\n if (!mutationSucceeded(res, res.data?.createCheckInStation?.id, 'Could not create station')) {\n return;\n }\n notify.success('Station created', `“${input.name}” is ready at ${eventName}.`);\n }\n onOpenChange(false);\n } catch (error) {\n notify.error('Could not save station', describeError(error));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{isEdit ? 'Edit check-in station' : 'New check-in station'}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n A station is a desk, gate or device where attendees scan in at {eventName}.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form id=\"station-form\" onSubmit={onSubmit} className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Name</span>\n <Input\n value={form.name}\n onChange={(e) => onChange('name', e.target.value)}\n placeholder=\"Main entrance\"\n required\n />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Code</span>\n <Input\n value={form.code}\n onChange={(e) => onChange('code', e.target.value)}\n placeholder=\"Auto from name\"\n />\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Location</span>\n <Input\n value={form.location}\n onChange={(e) => onChange('location', e.target.value)}\n placeholder=\"North lobby\"\n />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Type</span>\n <Select value={form.type} onValueChange={(value) => onChange('type', value)}>\n <SelectTrigger aria-label=\"Station type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATION_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {type.replace('_', ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <div className=\"flex items-center justify-between rounded-card border border-border-seam bg-bg-surface p-3\">\n <div>\n <Label htmlFor=\"station-active\" className=\"text-text-primary\">\n Active\n </Label>\n <p className=\"text-xs text-text-secondary\">Disabled stations stay configured but cannot accept scans.</p>\n </div>\n <Switch\n id=\"station-active\"\n checked={form.isActive}\n onCheckedChange={(checked) => onChange('isActive', checked)}\n aria-label=\"Station active\"\n />\n </div>\n </form>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)} disabled={saving}>\n Cancel\n </Button>\n <Button type=\"submit\" form=\"station-form\" disabled={saving}>\n {saving ? 'Saving…' : isEdit ? 'Save station' : 'Create station'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ===========================================================================\n// Check-in record edit dialog\n// ===========================================================================\n\ntype RecordFormState = {\n method: string;\n direction: string;\n status: string;\n stationId: string;\n attendeeId: string;\n};\n\ninterface RecordDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n record: RecordRow | null;\n stations: StationRow[];\n}\n\nfunction RecordDialog({ open, onOpenChange, record, stations }: RecordDialogProps) {\n const [updateRecord, { loading }] = useUpdateCheckInRecordMutation();\n\n const initial = useMemo<RecordFormState>(\n () => ({\n method: record?.method ?? 'MANUAL',\n direction: record?.direction ?? 'IN',\n status: record?.status ?? 'checked_in',\n stationId: record?.stationId ?? '',\n attendeeId: record?.attendeeId ?? '',\n }),\n [record]\n );\n const [form, setForm] = useState<RecordFormState>(initial);\n const [seededFor, setSeededFor] = useState<string | null>(null);\n const seedKey = `${open ? 'open' : 'closed'}:${record?.id ?? 'none'}`;\n if (open && seededFor !== seedKey) {\n setSeededFor(seedKey);\n setForm(initial);\n }\n if (!open && seededFor !== null) {\n setSeededFor(null);\n }\n\n const onChange = <K extends keyof RecordFormState>(field: K, value: RecordFormState[K]) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n };\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!record) {\n return;\n }\n const input = {\n eventId: record.eventId,\n attendeeId: form.attendeeId.trim() || null,\n registrationId: record.registrationId ?? null,\n stationId: form.stationId || null,\n method: form.method,\n direction: form.direction,\n status: form.status.trim() || 'checked_in',\n metadata: record.metadata ?? {},\n };\n try {\n const res = await updateRecord({ variables: { id: record.id, input } });\n if (!mutationSucceeded(res, res.data?.updateCheckInRecord?.id, 'Could not update record')) {\n return;\n }\n notify.success('Check-in updated');\n onOpenChange(false);\n } catch (error) {\n notify.error('Could not update record', describeError(error));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Edit check-in record</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Correct the direction, method or station for this scan.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form id=\"record-form\" onSubmit={onSubmit} className=\"space-y-4\">\n <label className=\"block space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Attendee ID</span>\n <Input value={form.attendeeId} onChange={(e) => onChange('attendeeId', e.target.value)} />\n </label>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Method</span>\n <Select value={form.method} onValueChange={(value) => onChange('method', value)}>\n <SelectTrigger aria-label=\"Method\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CHECKIN_METHODS.map((method) => (\n <SelectItem key={method} value={method}>\n {method}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Direction</span>\n <Select value={form.direction} onValueChange={(value) => onChange('direction', value)}>\n <SelectTrigger aria-label=\"Direction\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CHECKIN_DIRECTIONS.map((direction) => (\n <SelectItem key={direction} value={direction}>\n {direction}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Status</span>\n <Input value={form.status} onChange={(e) => onChange('status', e.target.value)} />\n </label>\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Station</span>\n <Select\n value={form.stationId || 'none'}\n onValueChange={(value) => onChange('stationId', value === 'none' ? '' : value)}\n >\n <SelectTrigger aria-label=\"Station\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">No station</SelectItem>\n {stations.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.name ?? s.id}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n </form>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button type=\"submit\" form=\"record-form\" disabled={loading}>\n {loading ? 'Saving…' : 'Save record'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ===========================================================================\n// Kiosk check-in panel (the hero workflow)\n// ===========================================================================\n\ninterface AttendeeLite {\n id: string;\n fullName: string;\n email?: string | null;\n}\n\ninterface CheckInPanelProps {\n eventId: string;\n eventName: string;\n stations: StationRow[];\n attendees: AttendeeLite[];\n activeStationId: string;\n onStationChange: (stationId: string) => void;\n onCheckedIn: () => void;\n}\n\nfunction CheckInPanel({\n eventId,\n eventName,\n stations,\n attendees,\n activeStationId,\n onStationChange,\n onCheckedIn,\n}: CheckInPanelProps) {\n const [scanValue, setScanValue] = useState('');\n const [method, setMethod] = useState<(typeof CHECKIN_METHODS)[number]>('QR');\n const [direction, setDirection] = useState<(typeof CHECKIN_DIRECTIONS)[number]>('IN');\n const [sessionId, setSessionId] = useState('');\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n const [createRecord, { loading }] = useCreateCheckInRecordMutation();\n const [scanCheckIn] = useScanCheckInMutation();\n const sessionsQuery = useEventSessionsQuery({ eventId, limit: 100, offset: 0 });\n const sessions = sessionsQuery.data?.eventSessions.items ?? [];\n\n // BOFF-4330 — offline-tolerant QR scan queue. A scan synced later (long\n // after this panel re-renders) still needs to refresh the live records/\n // counters, so `onCheckedIn` is passed as the sync-completion callback too.\n const { isOnline, pendingCount, syncNow } = useOfflineCheckInSync(scanCheckIn, onCheckedIn);\n\n const resolveAttendee = (raw: string): { attendeeId: string | null; label: string; matched: boolean } => {\n const value = raw.trim();\n if (!value) {\n return { attendeeId: null, label: 'attendee', matched: false };\n }\n if (value.includes('@')) {\n const match = attendees.find((a) => a.email?.toLowerCase() === value.toLowerCase());\n return { attendeeId: match?.id ?? null, label: match?.fullName ?? value, matched: Boolean(match) };\n }\n const byId = attendees.find((a) => a.id === value);\n return { attendeeId: value, label: byId?.fullName ?? `attendee ${value}`, matched: Boolean(byId) };\n };\n\n const onScanDetected = (value: string) => {\n setScanValue(value);\n setMethod('QR');\n notify.info('QR captured', 'Confirm the details and tap Check in.');\n inputRef.current?.focus();\n };\n\n /**\n * BOFF-4330 — kiosk QR scan path: the scanned value is a signed check-in\n * token, so it goes through `scanCheckIn` (server-side token verification)\n * rather than the raw-id admin path below. Offline (or a network failure\n * mid-request) never blocks the scan: it's persisted to the IndexedDB\n * queue with a freshly-minted `clientScanId` and synced automatically —\n * see `useOfflineCheckInSync`.\n */\n const submitTokenScan = async (token: string) => {\n const clientScanId = crypto.randomUUID();\n const scannedAt = new Date().toISOString();\n const queueEntry = {\n clientScanId,\n token,\n stationId: activeStationId || null,\n sessionId: sessionId || null,\n method: 'QR',\n direction,\n scannedAt,\n };\n\n const queueForLaterSync = async (reason: string) => {\n await enqueuePendingScan(queueEntry);\n notify.success('Saved on this device', reason);\n setScanValue('');\n inputRef.current?.focus();\n };\n\n if (typeof navigator !== 'undefined' && !navigator.onLine) {\n await queueForLaterSync(\n \"No connection right now — this check-in will sync automatically once you're back online.\"\n );\n return;\n }\n\n try {\n const res = await scanCheckIn({\n variables: {\n input: {\n token,\n stationId: activeStationId || null,\n sessionId: sessionId || null,\n method: 'QR',\n direction,\n recordedAt: scannedAt,\n clientScanId,\n },\n },\n });\n if (res.error) {\n notify.error('Could not record check-in', res.error.message);\n return;\n }\n if (!res.data?.scanCheckIn?.id) {\n notify.error('Could not record check-in', 'The server did not confirm the change.');\n return;\n }\n const activeStation = stations.find((s) => s.id === activeStationId);\n notify.success(\n `Checked ${direction === 'OUT' ? 'out' : 'in'}`,\n `Recorded via QR${activeStation?.name ? ` • ${activeStation.name}` : ''}.`\n );\n setScanValue('');\n inputRef.current?.focus();\n onCheckedIn();\n } catch {\n // Network-level failure (request never reached the gateway) — treat\n // exactly like starting offline rather than losing the scan.\n await queueForLaterSync(\"Connection dropped — this check-in will sync automatically once you're back online.\");\n }\n };\n\n const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const raw = scanValue.trim();\n\n if (method === 'QR' && CHECK_IN_TOKEN_PATTERN.test(raw)) {\n await submitTokenScan(raw);\n return;\n }\n\n const { attendeeId, label } = resolveAttendee(scanValue);\n if (scanValue.trim().includes('@') && !attendeeId) {\n notify.error('Attendee not found', `No attendee at this event matches “${scanValue.trim()}”.`);\n return;\n }\n const input = {\n eventId,\n attendeeId,\n stationId: activeStationId || null,\n method,\n direction,\n status: direction === 'OUT' ? 'checked_out' : 'checked_in',\n recordedAt: new Date().toISOString(),\n metadata: sessionId ? { sessionId } : {},\n };\n try {\n const res = await createRecord({ variables: { input } });\n if (!mutationSucceeded(res, res.data?.createCheckInRecord?.id, 'Could not record check-in')) {\n return;\n }\n const activeStation = stations.find((s) => s.id === activeStationId);\n notify.success(\n `${label} checked ${direction === 'OUT' ? 'out' : 'in'}`,\n `Recorded via ${method}${activeStation?.name ? ` • ${activeStation.name}` : ''}.`\n );\n setScanValue('');\n inputRef.current?.focus();\n onCheckedIn();\n } catch (error) {\n notify.error('Could not record check-in', describeError(error));\n }\n };\n\n return (\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-5 sm:p-6\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <ScanLine className=\"h-5 w-5 text-accent-primary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Kiosk mode</h2>\n </div>\n {!isOnline || pendingCount > 0 ? (\n <div className=\"flex items-center gap-2\">\n <Badge variant={isOnline ? 'secondary' : 'destructive'} className=\"flex items-center gap-1\">\n <CloudOff className=\"h-3 w-3\" aria-hidden=\"true\" />\n {isOnline ? 'Syncing…' : 'Offline'}\n {pendingCount > 0 ? ` · ${pendingCount} queued` : ''}\n </Badge>\n {isOnline && pendingCount > 0 ? (\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={syncNow}>\n <RefreshCw className=\"h-3.5 w-3.5\" />\n Sync now\n </Button>\n ) : null}\n </div>\n ) : null}\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Scan an attendee badge or look them up, set the direction, and check them into {eventName}.\n {pendingCount > 0 ? ' Scans queue on this device and sync automatically once you have a connection.' : ''}\n </p>\n\n <div className=\"mt-5\">\n <QrViewfinder onDetected={onScanDetected} />\n </div>\n\n <form onSubmit={onSubmit} className=\"mt-5 space-y-5\">\n <label className=\"block space-y-1.5\">\n <span className=\"flex items-center gap-1.5 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n <Keyboard className=\"h-3.5 w-3.5\" />\n Manual lookup\n </span>\n <Input\n ref={inputRef}\n value={scanValue}\n onChange={(e) => setScanValue(e.target.value)}\n placeholder=\"Enter name, email or attendee ID\"\n autoComplete=\"off\"\n className=\"h-12 text-base\"\n />\n </label>\n\n <div className=\"flex flex-wrap gap-5\">\n <Segmented\n label=\"Method\"\n value={method}\n onChange={setMethod}\n options={[\n { value: 'QR', label: 'QR', icon: QrCode },\n { value: 'MANUAL', label: 'Manual', icon: Keyboard },\n ]}\n />\n <Segmented\n label=\"Direction\"\n value={direction}\n onChange={setDirection}\n options={[\n { value: 'IN', label: 'In', icon: ArrowRightToLine },\n { value: 'OUT', label: 'Out', icon: ArrowLeftFromLine },\n ]}\n />\n <label className=\"space-y-1.5\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">Station</span>\n <Select value={activeStationId || 'none'} onValueChange={(v) => onStationChange(v === 'none' ? '' : v)}>\n <SelectTrigger aria-label=\"Station\" className=\"min-w-40\">\n <SelectValue placeholder=\"No station\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">No station</SelectItem>\n {stations.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.name ?? s.id}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <label className=\"space-y-1.5\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">Session</span>\n <Select value={sessionId || 'none'} onValueChange={(v) => setSessionId(v === 'none' ? '' : v)}>\n <SelectTrigger aria-label=\"Session\" className=\"min-w-40\">\n <SelectValue placeholder=\"Whole event\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">Whole event</SelectItem>\n {sessions.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.title}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n <Button type=\"submit\" size=\"lg\" disabled={loading || !scanValue.trim()} className=\"h-12 w-full text-base\">\n <LogIn className=\"h-5 w-5\" />\n {loading ? 'Recording…' : `Check ${direction === 'OUT' ? 'out' : 'in'}`}\n </Button>\n </form>\n </GlassCard>\n );\n}\n\n// ===========================================================================\n// Page\n// ===========================================================================\n\nconst PAGE_SIZE = 10;\nconst COUNTER_FETCH = 500;\n\nexport default function KioskPage() {\n const eventsQuery = useEventsQuery({ limit: 100, offset: 0 });\n const events = eventsQuery.data?.events.items ?? [];\n const [selectedEventId, setSelectedEventId] = useState('');\n const scopeEventId = selectedEventId || undefined;\n const selectedEvent = events.find((e) => e.id === selectedEventId);\n\n const [activeStationId, setActiveStationId] = useState('');\n const recordsPagination = usePagination({ pageSize: PAGE_SIZE, resetKey: selectedEventId });\n\n const stationsQuery = useCheckInStationsQuery({ eventId: scopeEventId, limit: 100, offset: 0 });\n const recordsQuery = useCheckInRecordsQuery({\n eventId: scopeEventId,\n limit: recordsPagination.limit,\n offset: recordsPagination.offset,\n });\n // Broad fetch powering the live \"checked in X / Y\" meter and per-station counts.\n const counterQuery = useCheckInRecordsQuery({ eventId: scopeEventId, limit: COUNTER_FETCH, offset: 0 });\n const attendeesQuery = useAttendeesQuery({ eventId: scopeEventId, limit: 200, offset: 0 });\n\n const stations = useMemo(\n () => (stationsQuery.data?.checkInStations.items ?? []) as StationRow[],\n [stationsQuery.data]\n );\n const records = (recordsQuery.data?.checkInRecords.items ?? []) as RecordRow[];\n const recordsTotal = recordsQuery.data?.checkInRecords.total ?? 0;\n const allRecords = useMemo(() => (counterQuery.data?.checkInRecords.items ?? []) as RecordRow[], [counterQuery.data]);\n const attendees = useMemo<AttendeeLite[]>(() => attendeesQuery.data?.attendees.items ?? [], [attendeesQuery.data]);\n const attendeesTotal = attendeesQuery.data?.attendees.total ?? 0;\n\n const attendeeNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const a of attendees) {\n map.set(a.id, a.fullName);\n }\n return map;\n }, [attendees]);\n\n const stationNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const s of stations) {\n map.set(s.id, s.name ?? s.id);\n }\n return map;\n }, [stations]);\n\n // Live counters derived from the broad records fetch — no fabricated numbers.\n const { checkedInCount, stationCounts } = useMemo(() => {\n const insideAttendees = new Set<string>();\n const anonInside = { count: 0 };\n const perStation = new Map<string, Set<string>>();\n // Replay records oldest→newest so the latest IN/OUT wins per attendee.\n const ordered = [...allRecords].sort((a, b) => new Date(a.recordedAt).getTime() - new Date(b.recordedAt).getTime());\n for (const r of ordered) {\n const key = r.attendeeId ?? '';\n if (r.direction === 'OUT') {\n if (key) {\n insideAttendees.delete(key);\n } else if (anonInside.count > 0) {\n anonInside.count -= 1;\n }\n } else {\n if (key) {\n insideAttendees.add(key);\n } else {\n anonInside.count += 1;\n }\n }\n if (r.stationId && r.direction !== 'OUT') {\n const set = perStation.get(r.stationId) ?? new Set<string>();\n set.add(r.id);\n perStation.set(r.stationId, set);\n }\n }\n const counts = new Map<string, number>();\n for (const [id, set] of perStation) {\n counts.set(id, set.size);\n }\n return { checkedInCount: insideAttendees.size + anonInside.count, stationCounts: counts };\n }, [allRecords]);\n\n const capacityTarget = attendeesTotal;\n const meterPct = capacityTarget > 0 ? Math.min(100, Math.round((checkedInCount / capacityTarget) * 100)) : 0;\n\n const [deleteStation] = useDeleteCheckInStationMutation();\n const [deleteRecord] = useDeleteCheckInRecordMutation();\n\n const [stationDialogOpen, setStationDialogOpen] = useState(false);\n const [editingStation, setEditingStation] = useState<StationRow | undefined>(undefined);\n const [recordDialogOpen, setRecordDialogOpen] = useState(false);\n const [editingRecord, setEditingRecord] = useState<RecordRow | null>(null);\n\n const openNewStation = () => {\n setEditingStation(undefined);\n setStationDialogOpen(true);\n };\n const openEditStation = (station: StationRow) => {\n setEditingStation(station);\n setStationDialogOpen(true);\n };\n const openEditRecord = (record: RecordRow) => {\n setEditingRecord(record);\n setRecordDialogOpen(true);\n };\n\n const onDeleteStation = async (station: StationRow) => {\n const res = await deleteStation({ variables: { id: station.id } });\n if (!mutationSucceeded(res, res.data?.deleteCheckInStation ? station.id : null, 'Could not delete station')) {\n return;\n }\n if (activeStationId === station.id) {\n setActiveStationId('');\n }\n notify.success('Station deleted', `“${station.name ?? station.id}” was removed.`);\n };\n\n const onDeleteRecord = async (record: RecordRow) => {\n const res = await deleteRecord({ variables: { id: record.id } });\n if (!mutationSucceeded(res, res.data?.deleteCheckInRecord ? record.id : null, 'Could not delete record')) {\n return;\n }\n notify.success('Check-in record deleted');\n };\n\n const refreshAfterCheckIn = () => {\n void recordsQuery.refetch();\n void counterQuery.refetch();\n };\n\n const recordLabel = (record: RecordRow): string => {\n if (record.attendeeId) {\n return attendeeNames.get(record.attendeeId) ?? `Attendee ${record.attendeeId.slice(0, 8)}`;\n }\n return 'Walk-in guest';\n };\n\n const hasEvent = Boolean(selectedEventId);\n\n return (\n <div className=\"space-y-6 p-6\">\n <PagePurpose>\n Kiosks are the front desk of your event. Each check-in station is a device or counter where attendees scan in,\n and check-in records are the live log of who arrived and when. Configure your stations before doors open, then\n check attendees in from this page and watch arrivals flow in on the day.\n </PagePurpose>\n\n <EmphasisPanel>\n <div className=\"flex flex-wrap items-start justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>Kiosk</GradientText> & Check-In\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Manage check-in stations and record attendee arrivals against a live backend.\n </p>\n </div>\n <div className=\"flex flex-wrap items-end gap-3\">\n <label className=\"space-y-1 text-sm\">\n <span className=\"font-medium text-text-primary\">Event</span>\n <Select value={selectedEventId || 'all'} onValueChange={(v) => setSelectedEventId(v === 'all' ? '' : v)}>\n <SelectTrigger aria-label=\"Event\" className=\"min-w-52\">\n <SelectValue placeholder=\"All events\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All events</SelectItem>\n {events.map((event) => (\n <SelectItem key={event.id} value={event.id}>\n {event.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n <Button type=\"button\" onClick={openNewStation} disabled={!hasEvent}>\n <Plus className=\"h-4 w-4\" />\n New station\n </Button>\n </div>\n </div>\n </EmphasisPanel>\n\n {!hasEvent ? (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"Select an event to open the kiosk\"\n description=\"Check-in stations and records belong to a specific event. Pick one above to start scanning attendees in.\"\n className=\"py-8\"\n />\n </GlassCard>\n ) : (\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-12\">\n {/* Left — kiosk scan panel */}\n <div className=\"lg:col-span-5\">\n <CheckInPanel\n eventId={selectedEventId}\n eventName={selectedEvent?.name ?? 'this event'}\n stations={stations}\n attendees={attendees}\n activeStationId={activeStationId}\n onStationChange={setActiveStationId}\n onCheckedIn={refreshAfterCheckIn}\n />\n </div>\n\n {/* Right — stations + live records */}\n <div className=\"space-y-6 lg:col-span-7\">\n {/* Stations chip strip */}\n <section>\n <h2 className=\"text-sm font-semibold uppercase tracking-wide text-text-secondary\">Stations</h2>\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {stations.map((station) => {\n const active = activeStationId === station.id;\n const count = stationCounts.get(station.id) ?? 0;\n return (\n <div\n key={station.id}\n className={`group inline-flex items-center gap-1.5 rounded-full border px-3 py-1.5 text-sm transition-colors ${\n active\n ? 'border-accent-primary bg-accent-primary/10 text-accent-primary'\n : 'border-border-default bg-bg-surface text-text-secondary hover:border-border-strong'\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={active}\n onClick={() => setActiveStationId(active ? '' : station.id)}\n className=\"inline-flex items-center gap-1.5 font-medium outline-none\"\n >\n {station.name ?? station.id}\n {count > 0 ? (\n <span className=\"rounded-full bg-bg-sunken px-1.5 py-0.5 text-xs tabular-nums text-text-secondary\">\n {count}\n </span>\n ) : null}\n </button>\n <ActionMenu\n ariaLabel={`Station ${station.name ?? station.id} actions`}\n entityName={station.name ?? undefined}\n onEdit={() => openEditStation(station)}\n onDelete={() => onDeleteStation(station)}\n />\n </div>\n );\n })}\n <button\n type=\"button\"\n onClick={openNewStation}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-dashed border-border-strong px-3 py-1.5 text-sm font-medium text-text-secondary transition-colors hover:border-accent-primary hover:text-accent-primary\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n New station\n </button>\n </div>\n {stationsQuery.loading && stations.length === 0 ? (\n <p className=\"mt-2 text-sm text-text-secondary\">Loading stations…</p>\n ) : null}\n </section>\n\n {/* Live records */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Check-In Records</h2>\n <p className=\"text-sm text-text-secondary\">\n Checked in{' '}\n <span className=\"text-lg font-bold tabular-nums text-text-primary\">\n {checkedInCount.toLocaleString()}\n </span>\n {capacityTarget > 0 ? (\n <>\n {' '}\n / <span className=\"tabular-nums\">{capacityTarget.toLocaleString()}</span>\n </>\n ) : null}\n </p>\n </div>\n\n {capacityTarget > 0 ? (\n <div\n className=\"mt-3 h-2 w-full overflow-hidden rounded-full bg-bg-sunken\"\n role=\"progressbar\"\n aria-valuenow={checkedInCount}\n aria-valuemin={0}\n aria-valuemax={capacityTarget}\n aria-label=\"Attendees checked in\"\n >\n <div\n className=\"h-full rounded-full bg-action-primary-bg transition-[width] duration-500\"\n style={{ width: `${meterPct}%` }}\n />\n </div>\n ) : null}\n\n <div className=\"mt-4\">\n {records.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={recordsQuery.loading ? 'Loading check-in records…' : 'No check-in records yet'}\n description=\"Arrivals recorded from this kiosk show up here, newest first.\"\n className=\"py-8\"\n />\n ) : (\n <ScrollArea className=\"max-h-[28rem] pr-3\">\n <ul className=\"space-y-2.5\">\n {records.map((record) => {\n const label = recordLabel(record);\n const isOut = record.direction === 'OUT';\n const station = record.stationId ? stationNames.get(record.stationId) : null;\n return (\n <li\n key={record.id}\n className=\"flex items-center gap-3 rounded-card border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] duration-200 hover:border-border-strong hover:shadow-elevation-1\"\n >\n <span\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent-primary/10 text-sm font-semibold text-accent-primary\"\n aria-hidden=\"true\"\n >\n {initials(label)}\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate font-medium text-text-primary\">{label}</p>\n <p className=\"mt-0.5 truncate text-sm text-text-secondary\">\n {formatTime(record.recordedAt)} • {record.method}\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Badge variant={isOut ? 'secondary' : 'success'} className=\"uppercase\">\n {isOut ? 'Checked out' : 'Checked in'}\n </Badge>\n {station ? (\n <span className=\"hidden text-sm text-text-secondary sm:inline\">{station}</span>\n ) : null}\n <ActionMenu\n ariaLabel={`Check-in record ${record.id} actions`}\n onEdit={() => openEditRecord(record)}\n onDelete={() => onDeleteRecord(record)}\n />\n </div>\n </li>\n );\n })}\n </ul>\n </ScrollArea>\n )}\n </div>\n <Pagination\n offset={recordsPagination.offset}\n limit={recordsPagination.limit}\n loadedCount={records.length}\n total={recordsTotal}\n onPrev={recordsPagination.prevPage}\n onNext={recordsPagination.nextPage}\n itemLabel=\"records\"\n loading={recordsQuery.loading}\n />\n </GlassCard>\n </div>\n </div>\n )}\n\n {selectedEventId ? (\n <StationDialog\n open={stationDialogOpen}\n onOpenChange={setStationDialogOpen}\n eventId={selectedEventId}\n eventName={selectedEvent?.name ?? 'this event'}\n station={editingStation}\n />\n ) : null}\n\n <RecordDialog\n open={recordDialogOpen}\n onOpenChange={setRecordDialogOpen}\n record={editingRecord}\n stations={stations}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegistrationPage.d.ts","sourceRoot":"","sources":["../../../../src/eventfullymanaged/pages/modules/RegistrationPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RegistrationPage.d.ts","sourceRoot":"","sources":["../../../../src/eventfullymanaged/pages/modules/RegistrationPage.tsx"],"names":[],"mappings":"AAgjBA,MAAM,CAAC,OAAO,UAAU,gBAAgB,4CAuEvC"}
|