// ── Zustand Store for Routines ──────────────────────────────── import { create } from 'zustand'; import { persist, createJSONStorage } from 'zustand/middleware'; import type { Routine, CreateRoutineParams } from './routines'; import { createRoutine, startRoutine, pauseRoutine, resumeRoutine, completeCurrentStep, skipCurrentStep, cancelRoutine, instantiateTemplate, getBuiltInTemplates, shouldStepComplete, } from './routines'; import { enqueueRoutineChange, enqueueRoutineDeleteChange, isSyncEnabled } from './platform-sync'; export interface RoutineStore { routines: Routine[]; templates: Routine[]; // CRUD addRoutine: (params: CreateRoutineParams) => Routine; addTemplate: (params: CreateRoutineParams) => Routine; removeRoutine: (id: string) => void; removeTemplate: (id: string) => void; // State transitions start: (id: string) => void; pause: (id: string) => void; resume: (id: string) => void; completeStep: (id: string) => void; skipStep: (id: string) => void; cancel: (id: string) => void; // Template startFromTemplate: (templateId: string) => Routine | null; // Tick — auto-advance steps tickRoutines: (now: number) => void; // Helpers getRoutine: (id: string) => Routine | undefined; getActiveRoutine: () => Routine | undefined; } function updateRoutine(routines: Routine[], id: string, updater: (r: Routine) => Routine): Routine[] { return routines.map((r) => (r.id === id ? updater(r) : r)); } export const useRoutineStore = create()( persist( (set, get) => ({ routines: [], templates: getBuiltInTemplates(), addRoutine: (params) => { const routine = createRoutine(params); set((s) => ({ routines: [...s.routines, routine] })); if (isSyncEnabled()) enqueueRoutineChange(routine, 'create'); return routine; }, addTemplate: (params) => { const template = createRoutine({ ...params, isTemplate: true }); set((s) => ({ templates: [...s.templates, template] })); return template; }, removeRoutine: (id) => { set((s) => ({ routines: s.routines.filter((r) => r.id !== id) })); if (isSyncEnabled()) enqueueRoutineDeleteChange(id); }, removeTemplate: (id) => { set((s) => ({ templates: s.templates.filter((r) => r.id !== id) })); }, start: (id) => { set((s) => ({ routines: updateRoutine(s.routines, id, startRoutine) })); const updated = get().routines.find((r) => r.id === id); if (updated && isSyncEnabled()) enqueueRoutineChange(updated, 'update'); }, pause: (id) => { set((s) => ({ routines: updateRoutine(s.routines, id, pauseRoutine) })); const updated = get().routines.find((r) => r.id === id); if (updated && isSyncEnabled()) enqueueRoutineChange(updated, 'update'); }, resume: (id) => { set((s) => ({ routines: updateRoutine(s.routines, id, resumeRoutine) })); const updated = get().routines.find((r) => r.id === id); if (updated && isSyncEnabled()) enqueueRoutineChange(updated, 'update'); }, completeStep: (id) => { set((s) => ({ routines: updateRoutine(s.routines, id, completeCurrentStep) })); const updated = get().routines.find((r) => r.id === id); if (updated && isSyncEnabled()) enqueueRoutineChange(updated, 'update'); }, skipStep: (id) => { set((s) => ({ routines: updateRoutine(s.routines, id, skipCurrentStep) })); const updated = get().routines.find((r) => r.id === id); if (updated && isSyncEnabled()) enqueueRoutineChange(updated, 'update'); }, cancel: (id) => { set((s) => ({ routines: updateRoutine(s.routines, id, cancelRoutine) })); const updated = get().routines.find((r) => r.id === id); if (updated && isSyncEnabled()) enqueueRoutineChange(updated, 'update'); }, startFromTemplate: (templateId) => { const template = get().templates.find((t) => t.id === templateId); if (!template) return null; const routine = startRoutine(instantiateTemplate(template)); set((s) => ({ routines: [...s.routines, routine] })); if (isSyncEnabled()) enqueueRoutineChange(routine, 'create'); return routine; }, tickRoutines: (now) => { const { routines } = get(); let changed = false; const updated = routines.map((r) => { if (r.status === 'active' && shouldStepComplete(r, now)) { changed = true; return completeCurrentStep(r); } return r; }); if (changed) set({ routines: updated }); }, getRoutine: (id) => get().routines.find((r) => r.id === id), getActiveRoutine: () => get().routines.find((r) => r.status === 'active' || r.status === 'paused'), }), { name: 'chronomind-routines', storage: createJSONStorage(() => { if (typeof window === 'undefined') { return { getItem: () => null, setItem: () => {}, removeItem: () => {} }; } return localStorage; }), partialize: (state) => ({ routines: state.routines, templates: state.templates }), } ) );