export type PendingCheckout = { packageId: number | null; checkoutSessionId?: string | null; startedAt: number; }; export const PENDING_CHECKOUT_TTL_MS = 1000 * 60 * 30; export const CHECKOUT_STORAGE_KEY = 'admin.billing.checkout.pending.v1'; export function isCheckoutExpired( pending: PendingCheckout, now = Date.now(), ttl = PENDING_CHECKOUT_TTL_MS, ): boolean { return now - pending.startedAt > ttl; } export function loadPendingCheckout( now = Date.now(), ttl = PENDING_CHECKOUT_TTL_MS, ): PendingCheckout | null { if (typeof window === 'undefined') { return null; } try { const raw = window.sessionStorage.getItem(CHECKOUT_STORAGE_KEY); if (! raw) { return null; } const parsed = JSON.parse(raw) as PendingCheckout; if (typeof parsed?.startedAt !== 'number') { return null; } const packageId = typeof parsed.packageId === 'number' && Number.isFinite(parsed.packageId) ? parsed.packageId : null; const checkoutSessionId = typeof parsed.checkoutSessionId === 'string' ? parsed.checkoutSessionId : null; if (now - parsed.startedAt > ttl) { return null; } return { packageId, checkoutSessionId, startedAt: parsed.startedAt, }; } catch { return null; } } export function storePendingCheckout(next: PendingCheckout | null): void { if (typeof window === 'undefined') { return; } try { if (! next) { window.sessionStorage.removeItem(CHECKOUT_STORAGE_KEY); } else { window.sessionStorage.setItem(CHECKOUT_STORAGE_KEY, JSON.stringify(next)); } } catch { // Ignore storage errors. } } export function shouldClearPendingCheckout( pending: PendingCheckout, activePackageId: number | null, now = Date.now(), ttl = PENDING_CHECKOUT_TTL_MS, ): boolean { if (isCheckoutExpired(pending, now, ttl)) { return true; } if (pending.packageId && activePackageId && pending.packageId === activePackageId) { return true; } return false; }