@burdenoff/microfe-eventfullymanaged 2026.723.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
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { listPendingScans as e, markPendingScanFailed as t, removePendingScan as n } from "./offlineCheckInQueue.js";
|
|
2
|
+
import { useCallback as r, useEffect as i, useRef as a, useState as o } from "react";
|
|
3
|
+
//#region src/eventfullymanaged/lib/useOfflineCheckInSync.ts
|
|
4
|
+
var s = 2e4;
|
|
5
|
+
function c(e) {
|
|
6
|
+
return {
|
|
7
|
+
token: e.token,
|
|
8
|
+
stationId: e.stationId,
|
|
9
|
+
sessionId: e.sessionId,
|
|
10
|
+
method: e.method,
|
|
11
|
+
direction: e.direction,
|
|
12
|
+
recordedAt: e.scannedAt,
|
|
13
|
+
clientScanId: e.clientScanId
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function l(l, u) {
|
|
17
|
+
let [d, f] = o(() => typeof navigator > "u" || navigator.onLine), [p, m] = o(0), h = a(!1), g = r(() => {
|
|
18
|
+
e().then((e) => m(e.length));
|
|
19
|
+
}, []), _ = r(async () => {
|
|
20
|
+
if (!h.current) {
|
|
21
|
+
h.current = !0;
|
|
22
|
+
try {
|
|
23
|
+
let r = await e();
|
|
24
|
+
for (let e of r) try {
|
|
25
|
+
let r = await l({ variables: { input: c(e) } });
|
|
26
|
+
if (r.error) {
|
|
27
|
+
await t(e.clientScanId, r.error.message);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (!r.data?.scanCheckIn?.id) {
|
|
31
|
+
await t(e.clientScanId, "The server did not confirm the sync.");
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
await n(e.clientScanId), u?.(e);
|
|
35
|
+
} catch (n) {
|
|
36
|
+
let r = n instanceof Error ? n.message : "Network error";
|
|
37
|
+
await t(e.clientScanId, r);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
} finally {
|
|
41
|
+
h.current = !1, g();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}, [
|
|
45
|
+
l,
|
|
46
|
+
u,
|
|
47
|
+
g
|
|
48
|
+
]), v = r(() => {
|
|
49
|
+
_();
|
|
50
|
+
}, [_]);
|
|
51
|
+
return i(() => {
|
|
52
|
+
if (g(), _(), typeof window > "u") return;
|
|
53
|
+
let e = () => {
|
|
54
|
+
f(!0), _();
|
|
55
|
+
}, t = () => f(!1);
|
|
56
|
+
window.addEventListener("online", e), window.addEventListener("offline", t);
|
|
57
|
+
let n = setInterval(() => {
|
|
58
|
+
(typeof navigator > "u" || navigator.onLine) && _();
|
|
59
|
+
}, s);
|
|
60
|
+
return () => {
|
|
61
|
+
window.removeEventListener("online", e), window.removeEventListener("offline", t), clearInterval(n);
|
|
62
|
+
};
|
|
63
|
+
}, []), {
|
|
64
|
+
isOnline: d,
|
|
65
|
+
pendingCount: p,
|
|
66
|
+
syncNow: v,
|
|
67
|
+
refreshPendingCount: g
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { l as useOfflineCheckInSync };
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=useOfflineCheckInSync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOfflineCheckInSync.js","names":[],"sources":["../../../src/eventfullymanaged/lib/useOfflineCheckInSync.ts"],"sourcesContent":["/**\n * useOfflineCheckInSync — drains the offline QR check-in queue (BOFF-4330).\n * @module eventfullymanaged/lib\n *\n * Wires the IndexedDB queue (`offlineCheckInQueue.ts`) to the\n * `eventfullyManagedScanCheckIn` mutation: replays every queued scan with its\n * original `clientScanId` (so the backend's idempotency guarantee makes a\n * repeat sync safe), on three triggers —\n * 1. once on mount (covers \"kiosk was reloaded with a full queue\"),\n * 2. immediately when the browser fires `online` (connectivity just came\n * back),\n * 3. periodically while online, in case the network is flaky rather than\n * fully down (a per-request failure shouldn't wait for a full\n * online/offline cycle to retry).\n *\n * A scan whose sync attempt throws (network failure — still offline, or the\n * request never reached the gateway) stops the drain for this pass so we\n * don't burn through the whole queue against a dead connection; a scan that\n * gets a real GraphQL error back (e.g. an invalid/forged token) is marked\n * failed and skipped so one bad entry can't block the rest of a healthy\n * queue — the operator can inspect/discard it from the pending list.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { listPendingScans, markPendingScanFailed, removePendingScan, type PendingScan } from './offlineCheckInQueue';\n\nconst RETRY_INTERVAL_MS = 20_000;\n\ntype ScanCheckInMutate = (options: {\n variables: { input: Record<string, unknown> };\n}) => Promise<{ data?: { scanCheckIn?: { id?: string } | null } | null; error?: { message: string } | null }>;\n\nexport interface OfflineCheckInSyncState {\n /** Live `navigator.onLine` state (assumes online in non-browser test environments). */\n isOnline: boolean;\n /** How many scans are currently queued, waiting to sync. */\n pendingCount: number;\n /** Manually kick a sync pass (e.g. a \"Retry now\" button). */\n syncNow: () => void;\n /** Refresh `pendingCount` from IndexedDB without triggering a sync. */\n refreshPendingCount: () => void;\n}\n\nfunction toInputVariables(scan: PendingScan): Record<string, unknown> {\n return {\n token: scan.token,\n stationId: scan.stationId,\n sessionId: scan.sessionId,\n method: scan.method,\n direction: scan.direction,\n recordedAt: scan.scannedAt,\n clientScanId: scan.clientScanId,\n };\n}\n\nexport function useOfflineCheckInSync(\n scanCheckIn: ScanCheckInMutate,\n onSynced?: (scan: PendingScan) => void\n): OfflineCheckInSyncState {\n const [isOnline, setIsOnline] = useState(() => typeof navigator === 'undefined' || navigator.onLine);\n const [pendingCount, setPendingCount] = useState(0);\n const syncingRef = useRef(false);\n\n const refreshPendingCount = useCallback(() => {\n void listPendingScans().then((scans) => setPendingCount(scans.length));\n }, []);\n\n const drainQueue = useCallback(async () => {\n if (syncingRef.current) return;\n syncingRef.current = true;\n try {\n const pending = await listPendingScans();\n for (const scan of pending) {\n try {\n const res = await scanCheckIn({ variables: { input: toInputVariables(scan) } });\n if (res.error) {\n await markPendingScanFailed(scan.clientScanId, res.error.message);\n continue;\n }\n if (!res.data?.scanCheckIn?.id) {\n await markPendingScanFailed(scan.clientScanId, 'The server did not confirm the sync.');\n continue;\n }\n await removePendingScan(scan.clientScanId);\n onSynced?.(scan);\n } catch (err) {\n // Network-level failure (still offline, gateway unreachable) — stop\n // this pass; the next online/interval trigger retries from here.\n const message = err instanceof Error ? err.message : 'Network error';\n await markPendingScanFailed(scan.clientScanId, message);\n break;\n }\n }\n } finally {\n syncingRef.current = false;\n refreshPendingCount();\n }\n }, [scanCheckIn, onSynced, refreshPendingCount]);\n\n const syncNow = useCallback(() => {\n void drainQueue();\n }, [drainQueue]);\n\n useEffect(() => {\n refreshPendingCount();\n // Covers the kiosk being reloaded with scans still queued from a prior\n // offline stretch — don't wait for an `online` event that may never\n // fire again if the device was already online when it reloaded.\n void drainQueue();\n\n if (typeof window === 'undefined') return;\n const handleOnline = () => {\n setIsOnline(true);\n void drainQueue();\n };\n const handleOffline = () => setIsOnline(false);\n window.addEventListener('online', handleOnline);\n window.addEventListener('offline', handleOffline);\n\n const interval = setInterval(() => {\n if (typeof navigator === 'undefined' || navigator.onLine) {\n void drainQueue();\n }\n }, RETRY_INTERVAL_MS);\n\n return () => {\n window.removeEventListener('online', handleOnline);\n window.removeEventListener('offline', handleOffline);\n clearInterval(interval);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- drainQueue is stable enough (only scanCheckIn identity churns across renders); re-subscribing on every mutate identity change would tear down/rebuild the interval constantly.\n }, []);\n\n return { isOnline, pendingCount, syncNow, refreshPendingCount };\n}\n"],"mappings":";;;AA0BA,IAAM,IAAoB;AAiB1B,SAAS,EAAiB,GAA4C;AACpE,QAAO;EACL,OAAO,EAAK;EACZ,WAAW,EAAK;EAChB,WAAW,EAAK;EAChB,QAAQ,EAAK;EACb,WAAW,EAAK;EAChB,YAAY,EAAK;EACjB,cAAc,EAAK;EACpB;;AAGH,SAAgB,EACd,GACA,GACyB;CACzB,IAAM,CAAC,GAAU,KAAe,QAAe,OAAO,YAAc,OAAe,UAAU,OAAO,EAC9F,CAAC,GAAc,KAAmB,EAAS,EAAE,EAC7C,IAAa,EAAO,GAAM,EAE1B,IAAsB,QAAkB;AACvC,KAAkB,CAAC,MAAM,MAAU,EAAgB,EAAM,OAAO,CAAC;IACrE,EAAE,CAAC,EAEA,IAAa,EAAY,YAAY;AACrC,SAAW,SACf;KAAW,UAAU;AACrB,OAAI;IACF,IAAM,IAAU,MAAM,GAAkB;AACxC,SAAK,IAAM,KAAQ,EACjB,KAAI;KACF,IAAM,IAAM,MAAM,EAAY,EAAE,WAAW,EAAE,OAAO,EAAiB,EAAK,EAAE,EAAE,CAAC;AAC/E,SAAI,EAAI,OAAO;AACb,YAAM,EAAsB,EAAK,cAAc,EAAI,MAAM,QAAQ;AACjE;;AAEF,SAAI,CAAC,EAAI,MAAM,aAAa,IAAI;AAC9B,YAAM,EAAsB,EAAK,cAAc,uCAAuC;AACtF;;AAGF,KADA,MAAM,EAAkB,EAAK,aAAa,EAC1C,IAAW,EAAK;aACT,GAAK;KAGZ,IAAM,IAAU,aAAe,QAAQ,EAAI,UAAU;AACrD,WAAM,EAAsB,EAAK,cAAc,EAAQ;AACvD;;aAGI;AAER,IADA,EAAW,UAAU,IACrB,GAAqB;;;IAEtB;EAAC;EAAa;EAAU;EAAoB,CAAC,EAE1C,IAAU,QAAkB;AAC3B,KAAY;IAChB,CAAC,EAAW,CAAC;AAgChB,QA9BA,QAAgB;AAOd,MANA,GAAqB,EAIhB,GAAY,EAEb,OAAO,SAAW,IAAa;EACnC,IAAM,UAAqB;AAEpB,GADL,EAAY,GAAK,EACZ,GAAY;KAEb,UAAsB,EAAY,GAAM;AAE9C,EADA,OAAO,iBAAiB,UAAU,EAAa,EAC/C,OAAO,iBAAiB,WAAW,EAAc;EAEjD,IAAM,IAAW,kBAAkB;AACjC,IAAI,OAAO,YAAc,OAAe,UAAU,WAC3C,GAAY;KAElB,EAAkB;AAErB,eAAa;AAGX,GAFA,OAAO,oBAAoB,UAAU,EAAa,EAClD,OAAO,oBAAoB,WAAW,EAAc,EACpD,cAAc,EAAS;;IAGxB,EAAE,CAAC,EAEC;EAAE;EAAU;EAAc;EAAS;EAAqB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KioskPage.d.ts","sourceRoot":"","sources":["../../../../src/eventfullymanaged/pages/modules/KioskPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"KioskPage.d.ts","sourceRoot":"","sources":["../../../../src/eventfullymanaged/pages/modules/KioskPage.tsx"],"names":[],"mappings":"AAsEA,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AACD,UAAU,mBAAmB;IAC3B,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CAC/D;AACD,UAAU,mBAAmB;IAC3B,KAAK,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,mBAAmB,CAAC;CAC5D;AACD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,eAAe,CAAC,EAAE,mBAAmB,CAAC;KACvC;CACF;AAo4BD,MAAM,CAAC,OAAO,UAAU,SAAS,4CA0XhC"}
|