58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
/**
|
|
* Local-storage draft persistence.
|
|
*
|
|
* Drafts are keyed by the form-filler's contact id so a single browser used
|
|
* for multiple co-ops (rare but possible) keeps each draft separate.
|
|
*
|
|
* We persist values + a timestamp. On load, if a draft is younger than
|
|
* MAX_DRAFT_AGE_MS, it overrides the server-side prefill. Otherwise it's
|
|
* discarded (stale drafts probably represent abandoned sessions, and the
|
|
* server-side prefill is fresher anyway).
|
|
*/
|
|
|
|
const MAX_DRAFT_AGE_MS = 1000 * 60 * 60 * 24 * 30; // 30 days
|
|
|
|
interface Draft {
|
|
values: Record<string, unknown>;
|
|
savedAt: string;
|
|
}
|
|
|
|
function key(cid: string): string {
|
|
return `coop-checkin:draft:${cid}`;
|
|
}
|
|
|
|
export function loadDraft(cid: string): Draft | null {
|
|
if (typeof window === "undefined") return null;
|
|
try {
|
|
const raw = window.localStorage.getItem(key(cid));
|
|
if (!raw) return null;
|
|
const parsed = JSON.parse(raw) as Draft;
|
|
if (Date.now() - new Date(parsed.savedAt).getTime() > MAX_DRAFT_AGE_MS) {
|
|
window.localStorage.removeItem(key(cid));
|
|
return null;
|
|
}
|
|
return parsed;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function saveDraft(cid: string, values: Record<string, unknown>): void {
|
|
if (typeof window === "undefined") return;
|
|
try {
|
|
const draft: Draft = { values, savedAt: new Date().toISOString() };
|
|
window.localStorage.setItem(key(cid), JSON.stringify(draft));
|
|
} catch {
|
|
// localStorage might be unavailable (private mode, quota). Silent ok.
|
|
}
|
|
}
|
|
|
|
export function clearDraft(cid: string): void {
|
|
if (typeof window === "undefined") return;
|
|
try {
|
|
window.localStorage.removeItem(key(cid));
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|