首页布局优化前
This commit is contained in:
128
desktop/src/lib/use-onboarding.ts
Normal file
128
desktop/src/lib/use-onboarding.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* useOnboarding - Hook for detecting and managing first-time user onboarding
|
||||
*
|
||||
* Determines if user needs to go through the onboarding wizard.
|
||||
* Stores completion status in localStorage.
|
||||
*/
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
|
||||
const ONBOARDING_COMPLETED_KEY = 'zclaw-onboarding-completed';
|
||||
const USER_PROFILE_KEY = 'zclaw-user-profile';
|
||||
|
||||
export interface UserProfile {
|
||||
userName: string;
|
||||
userRole?: string;
|
||||
completedAt: string;
|
||||
}
|
||||
|
||||
export interface OnboardingState {
|
||||
isNeeded: boolean;
|
||||
isLoading: boolean;
|
||||
userProfile: UserProfile | null;
|
||||
markCompleted: (profile: Omit<UserProfile, 'completedAt'>) => void;
|
||||
resetOnboarding: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to manage first-time user onboarding
|
||||
*
|
||||
* Usage:
|
||||
* ```tsx
|
||||
* const { isNeeded, isLoading, markCompleted } = useOnboarding();
|
||||
*
|
||||
* if (isNeeded) {
|
||||
* return <OnboardingWizard onComplete={markCompleted} />;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function useOnboarding(): OnboardingState {
|
||||
const [isNeeded, setIsNeeded] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [userProfile, setUserProfile] = useState<UserProfile | null>(null);
|
||||
|
||||
// Check onboarding status on mount
|
||||
useEffect(() => {
|
||||
try {
|
||||
const completed = localStorage.getItem(ONBOARDING_COMPLETED_KEY);
|
||||
const profileStr = localStorage.getItem(USER_PROFILE_KEY);
|
||||
|
||||
if (completed === 'true' && profileStr) {
|
||||
const profile = JSON.parse(profileStr) as UserProfile;
|
||||
setUserProfile(profile);
|
||||
setIsNeeded(false);
|
||||
} else {
|
||||
// No onboarding record - first time user
|
||||
setIsNeeded(true);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[useOnboarding] Failed to check onboarding status:', err);
|
||||
setIsNeeded(true);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Mark onboarding as completed
|
||||
const markCompleted = useCallback((profile: Omit<UserProfile, 'completedAt'>) => {
|
||||
const fullProfile: UserProfile = {
|
||||
...profile,
|
||||
completedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
try {
|
||||
localStorage.setItem(ONBOARDING_COMPLETED_KEY, 'true');
|
||||
localStorage.setItem(USER_PROFILE_KEY, JSON.stringify(fullProfile));
|
||||
setUserProfile(fullProfile);
|
||||
setIsNeeded(false);
|
||||
console.log('[useOnboarding] Onboarding completed for user:', profile.userName);
|
||||
} catch (err) {
|
||||
console.error('[useOnboarding] Failed to save onboarding status:', err);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Reset onboarding (for testing or user request)
|
||||
const resetOnboarding = useCallback(() => {
|
||||
try {
|
||||
localStorage.removeItem(ONBOARDING_COMPLETED_KEY);
|
||||
localStorage.removeItem(USER_PROFILE_KEY);
|
||||
setUserProfile(null);
|
||||
setIsNeeded(true);
|
||||
console.log('[useOnboarding] Onboarding reset');
|
||||
} catch (err) {
|
||||
console.error('[useOnboarding] Failed to reset onboarding:', err);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return {
|
||||
isNeeded,
|
||||
isLoading,
|
||||
userProfile,
|
||||
markCompleted,
|
||||
resetOnboarding,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stored user profile without hook (for use outside React components)
|
||||
*/
|
||||
export function getStoredUserProfile(): UserProfile | null {
|
||||
try {
|
||||
const profileStr = localStorage.getItem(USER_PROFILE_KEY);
|
||||
if (profileStr) {
|
||||
return JSON.parse(profileStr) as UserProfile;
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[useOnboarding] Failed to get user profile:', err);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if onboarding is completed (for use outside React components)
|
||||
*/
|
||||
export function isOnboardingCompleted(): boolean {
|
||||
return localStorage.getItem(ONBOARDING_COMPLETED_KEY) === 'true';
|
||||
}
|
||||
|
||||
export default useOnboarding;
|
||||
Reference in New Issue
Block a user