/** Versioned onboarding tour persistence (driver.js). Bump to re-show tours. */ export const ONBOARDING_VERSION = 2; export type OnboardingTourId = 'dashboard' | 'wizard' | 'workspace'; const STORAGE_KEY = 'grantforge_onboarding'; type OnboardingPayload = { version: number; tours: Partial>; }; const LEGACY_KEYS: Record = { dashboard: 'has_seen_tour_dashboard', wizard: 'has_seen_tour_wizard', workspace: 'has_seen_tour_workspace', }; function readPayload(): OnboardingPayload { try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) { return { version: ONBOARDING_VERSION, tours: {} }; } const parsed = JSON.parse(raw) as OnboardingPayload; return { version: parsed.version ?? 0, tours: parsed.tours ?? {}, }; } catch { return { version: 0, tours: {} }; } } function writePayload(payload: OnboardingPayload): void { localStorage.setItem(STORAGE_KEY, JSON.stringify(payload)); } /** Remove legacy keys; version bump in storage resets tour completion. */ export function migrateLegacyOnboardingKeys(): void { const payload = readPayload(); if (payload.version !== ONBOARDING_VERSION) { writePayload({ version: ONBOARDING_VERSION, tours: {} }); } (Object.values(LEGACY_KEYS) as string[]).forEach((key) => { localStorage.removeItem(key); }); } export function hasSeenTour(tourId: OnboardingTourId): boolean { migrateLegacyOnboardingKeys(); const payload = readPayload(); if (payload.version !== ONBOARDING_VERSION) { return false; } return Boolean(payload.tours[tourId]); } export function markTourSeen(tourId: OnboardingTourId): void { migrateLegacyOnboardingKeys(); const payload = readPayload(); payload.version = ONBOARDING_VERSION; payload.tours[tourId] = true; writePayload(payload); } export function resetTour(tourId: OnboardingTourId): void { migrateLegacyOnboardingKeys(); const payload = readPayload(); payload.version = ONBOARDING_VERSION; delete payload.tours[tourId]; writePayload(payload); } export function resetAllTours(): void { writePayload({ version: ONBOARDING_VERSION, tours: {} }); (Object.values(LEGACY_KEYS) as string[]).forEach((key) => { localStorage.removeItem(key); }); }