grantforge-api / frontend-react /src /utils /onboardingStorage.ts
GrantForge Bot
Deploy sha-565ad85979610064f6d1c18ab3b6404357d61073 — source build (no GHCR)
ce8f04a
Raw
History Blame Contribute Delete
2.31 kB
/** 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);
});
}