Visual identity: Field Almanac — Fraunces+DM Sans, OKLCH cream/leaf/clay palette, paper texture, hand-drawn stage icons, draft auto-save, stage progress dots
This commit is contained in:
57
lib/draft.ts
Normal file
57
lib/draft.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user