Files
Investidor-V2/resources/js/hooks/use-interest-draft.ts
T
2026-11-15 18:56:39 +02:00

74 lines
2.7 KiB
TypeScript

import { useEffect, useState } from 'react';
import { newSubmissionKey } from '@/lib/portal-api';
export function useInterestDraft<T>(name: string, initial: T) {
const storage = 'investemoz-interest:' + name;
const read = () => {
try {
const value = JSON.parse(sessionStorage.getItem(storage) ?? 'null');
if (value?.form && typeof value.key === 'string')
return { ...value, storage } as {
form: T;
key: string;
storage: string;
};
} catch {
/* unavailable storage leaves the current form usable */
}
return { form: initial, key: newSubmissionKey(), storage };
};
const [draft, setDraft] = useState(read);
// Inertia can reuse this component for a different opportunity. Never write
// the previous opportunity's answers into the new opportunity's storage key.
if (draft.storage !== storage) setDraft(read());
useEffect(() => {
if (draft.storage !== storage) return;
try {
sessionStorage.setItem(storage, JSON.stringify(draft));
} catch {}
}, [storage, draft]);
const setForm = (value: T | ((old: T) => T)) =>
setDraft((old) => ({
...old,
form:
typeof value === 'function'
? (value as (old: T) => T)(old.form)
: value,
}));
return {
form: draft.form,
setForm,
key: draft.key,
clear: () => {
try {
sessionStorage.removeItem(storage);
sessionStorage.removeItem('investemoz-participation-identity');
} catch {
/* Storage failure must not turn a confirmed submission into an error. */
}
},
authenticate: () => {
const identity = draft.form as {
name?: string;
fullName?: string;
email?: string;
};
try {
sessionStorage.setItem(
'investemoz-participation-identity',
JSON.stringify({
name: identity.fullName ?? identity.name ?? '',
email: identity.email ?? '',
}),
);
sessionStorage.setItem(storage, JSON.stringify(draft));
} catch {
/* Authentication remains available when browser persistence is blocked. */
}
window.location.assign(
'/participar/entrar?return=' +
encodeURIComponent(location.pathname + location.search),
);
},
};
}