refactor phase 7-8
This commit is contained in:
@@ -1,28 +1,84 @@
|
||||
/**
|
||||
* Onboarding Store (Zustand)
|
||||
* Manages welcome/guide screen state and dismissal
|
||||
* Syncs with backend UserSettings for cross-device persistence
|
||||
*/
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import { fetchUserSetting, createUserSetting, updateUserSetting } from '../services/api';
|
||||
|
||||
interface OnboardingState {
|
||||
isGuideDismissed: boolean;
|
||||
isGuideVisible: boolean;
|
||||
isLoading: boolean;
|
||||
lastSyncedAt: Date | null;
|
||||
|
||||
// Actions
|
||||
dismissGuide: () => void;
|
||||
dismissGuide: () => Promise<void>;
|
||||
showGuide: () => void;
|
||||
toggleGuide: () => void;
|
||||
loadFromBackend: () => Promise<void>;
|
||||
syncToBackend: (dismissed: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
const GUIDE_SETTING_KEY = 'workflow_guide_dismissed';
|
||||
|
||||
export const useOnboardingStore = create<OnboardingState>()(
|
||||
persist<OnboardingState>(
|
||||
(set) => ({
|
||||
(set, get) => ({
|
||||
isGuideDismissed: false,
|
||||
isGuideVisible: false,
|
||||
isLoading: false,
|
||||
lastSyncedAt: null,
|
||||
|
||||
loadFromBackend: async () => {
|
||||
set({ isLoading: true });
|
||||
try {
|
||||
const setting = await fetchUserSetting(GUIDE_SETTING_KEY);
|
||||
const dismissed = setting.value?.dismissed === true;
|
||||
set({
|
||||
isGuideDismissed: dismissed,
|
||||
isGuideVisible: !dismissed,
|
||||
lastSyncedAt: new Date(),
|
||||
isLoading: false
|
||||
});
|
||||
} catch (error: any) {
|
||||
// 404 means setting doesn't exist yet - that's fine, use local state
|
||||
if (error.status !== 404) {
|
||||
console.warn('Failed to load guide dismissal from backend:', error);
|
||||
}
|
||||
set({ isLoading: false });
|
||||
}
|
||||
},
|
||||
|
||||
syncToBackend: async (dismissed: boolean) => {
|
||||
try {
|
||||
const data = { value: { dismissed, dismissed_at: new Date().toISOString() } };
|
||||
try {
|
||||
await updateUserSetting(GUIDE_SETTING_KEY, data);
|
||||
} catch (error: any) {
|
||||
// If setting doesn't exist, create it
|
||||
if (error.status === 404) {
|
||||
await createUserSetting({ key: GUIDE_SETTING_KEY, value: data.value });
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
set({ lastSyncedAt: new Date() });
|
||||
} catch (error) {
|
||||
console.warn('Failed to sync guide dismissal to backend:', error);
|
||||
// Don't throw - local state is still updated
|
||||
}
|
||||
},
|
||||
|
||||
dismissGuide: async () => {
|
||||
set({ isGuideDismissed: true, isGuideVisible: false });
|
||||
// Sync to backend asynchronously
|
||||
await get().syncToBackend(true);
|
||||
},
|
||||
|
||||
dismissGuide: () => set({ isGuideDismissed: true, isGuideVisible: false }),
|
||||
showGuide: () => set({ isGuideVisible: true }),
|
||||
|
||||
toggleGuide: () => set((state) => ({ isGuideVisible: !state.isGuideVisible })),
|
||||
}),
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user