Spaces:
Running
Running
| /** 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<Record<OnboardingTourId, boolean>>; | |
| }; | |
| const LEGACY_KEYS: Record<OnboardingTourId, string> = { | |
| 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); | |
| }); | |
| } | |