- Created firstTime utility for detecting first-time users - Functions: isFirstTime, markAsNotFirstTime, isOnboardingCompleted, markOnboardingCompleted - Uses localStorage to persist state across sessions - Graceful error handling with logger warnings - SSR-safe (returns false on server) - Can be integrated with Onboarding component - Action 10.4.1.4 complete
120 lines
3.5 KiB
TypeScript
120 lines
3.5 KiB
TypeScript
import { logger } from '@/utils/logger';
|
|
|
|
/**
|
|
* First Time Detection Utility
|
|
* Action 10.4.1.4: Add "first time" detection
|
|
*
|
|
* Provides utilities to detect first-time users and track onboarding completion
|
|
* Uses localStorage to persist state across sessions
|
|
*/
|
|
|
|
const FIRST_TIME_KEY = 'veza_first_time';
|
|
const ONBOARDING_COMPLETED_KEY = 'veza_onboarding_completed';
|
|
|
|
/**
|
|
* Check if this is the user's first time using the application
|
|
* @returns True if first time, false otherwise
|
|
*/
|
|
export function isFirstTime(): boolean {
|
|
if (typeof window === 'undefined') {
|
|
// Server-side rendering - assume not first time
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const value = localStorage.getItem(FIRST_TIME_KEY);
|
|
// If the key doesn't exist, it's the first time
|
|
return value === null;
|
|
} catch (error) {
|
|
logger.warn('Error checking first time status', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
});
|
|
// On error, assume not first time to avoid showing onboarding repeatedly
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mark the user as no longer first-time
|
|
* This should be called after the user has completed onboarding or interacted with the app
|
|
*/
|
|
export function markAsNotFirstTime(): void {
|
|
if (typeof window === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
localStorage.setItem(FIRST_TIME_KEY, 'false');
|
|
logger.debug('User marked as not first-time');
|
|
} catch (error) {
|
|
logger.warn('Error marking user as not first-time', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if onboarding has been completed
|
|
* @returns True if onboarding was completed, false otherwise
|
|
*/
|
|
export function isOnboardingCompleted(): boolean {
|
|
if (typeof window === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const value = localStorage.getItem(ONBOARDING_COMPLETED_KEY);
|
|
return value === 'true';
|
|
} catch (error) {
|
|
logger.warn('Error checking onboarding completion status', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
});
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mark onboarding as completed
|
|
* This should be called when the user completes the onboarding flow
|
|
*/
|
|
export function markOnboardingCompleted(): void {
|
|
if (typeof window === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
localStorage.setItem(ONBOARDING_COMPLETED_KEY, 'true');
|
|
// Also mark as not first-time when onboarding is completed
|
|
markAsNotFirstTime();
|
|
logger.debug('Onboarding marked as completed');
|
|
} catch (error) {
|
|
logger.warn('Error marking onboarding as completed', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reset first-time detection (useful for testing or admin purposes)
|
|
* This will make the user appear as first-time again
|
|
*/
|
|
export function resetFirstTimeDetection(): void {
|
|
if (typeof window === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
localStorage.removeItem(FIRST_TIME_KEY);
|
|
localStorage.removeItem(ONBOARDING_COMPLETED_KEY);
|
|
logger.debug('First-time detection reset');
|
|
} catch (error) {
|
|
logger.warn('Error resetting first-time detection', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
});
|
|
}
|
|
}
|