import { create } from "zustand"; import { persist } from "zustand/middleware"; import { appConfig } from "@/app.config"; import type { GuideDialogState } from "../types/dialog.types"; const getDialogKey = (courseId: string, dialogId: string) => `${courseId}:${dialogId}`; const getInitialState = () => ({ open: false, courseId: null, dialogId: null, steps: [], current: 0, showOnce: true, }); export const useDialogStore = create()( persist( (set, get) => ({ ...getInitialState(), completedDialogMap: {}, startDialog: ({ courseId, dialogId, steps, showOnce = true, initialStep = 0, }) => { if (steps.length === 0) return; const key = getDialogKey(courseId, dialogId); if (showOnce && get().completedDialogMap[key]) { return; } set({ open: true, courseId, dialogId, steps, current: Math.min(Math.max(initialStep, 0), steps.length - 1), showOnce, }); }, closeDialog: () => { set(getInitialState()); }, nextStep: () => { const { current, steps, finishDialog } = get(); if (current >= steps.length - 1) { finishDialog(); return; } set({ current: current + 1 }); }, prevStep: () => { const { current } = get(); set({ current: Math.max(current - 1, 0) }); }, setStep: (index) => { const { steps } = get(); if (steps.length === 0) return; set({ current: Math.min(Math.max(index, 0), steps.length - 1) }); }, selectOption: (optionId) => { const { current, steps, setStep, finishDialog, nextStep } = get(); const step = steps[current]; const option = step?.options?.find((item) => item.id === optionId); if (!option) return; if (option.finish) { finishDialog(); return; } if (option.nextId) { const nextIndex = steps.findIndex( (item) => item.id === option.nextId, ); if (nextIndex >= 0) { setStep(nextIndex); return; } } nextStep(); }, finishDialog: () => { const { courseId, dialogId, completedDialogMap } = get(); if (!courseId || !dialogId) { set(getInitialState()); return; } const key = getDialogKey(courseId, dialogId); set({ ...getInitialState(), completedDialogMap: { ...completedDialogMap, [key]: true, }, }); }, skipDialog: () => { get().finishDialog(); }, resetDialog: (courseId, dialogId) => { const key = getDialogKey(courseId, dialogId); const { [key]: _removed, ...rest } = get().completedDialogMap; const isCurrentDialog = get().courseId === courseId && get().dialogId === dialogId; set({ ...(isCurrentDialog ? getInitialState() : {}), completedDialogMap: rest, }); }, }), { name: `${appConfig.storage.prefix}-dialog-storage`, partialize: (state) => ({ completedDialogMap: state.completedDialogMap, }), }, ), );