'use client'; import { create } from 'zustand'; import { formatLocalDate } from '@/lib/format'; import { type WorkActivity, type WorkActivityDraft } from '@/lib/work-activity'; import { makeProgressNoteActivity, type ProgressNoteActivityInput } from '@/lib/work-activity-factory'; import { createWorkActivityDomain, deleteWorkActivityDomain, listWorkActivitiesDomain, } from '@/lib/domain-api'; import { scheduleSaveWithOptimisticRollback } from '@/lib/optimistic-persistence'; import { SERVER_DATA_CACHE_MS } from '@/lib/server-data'; interface WorkActivityState { activities: WorkActivity[]; loaded: boolean; fetchActivities: (options?: { force?: boolean }) => Promise; addActivity: (data: WorkActivityDraft) => WorkActivity; addProgressNote: (data: ProgressNoteActivityInput) => WorkActivity; deleteActivity: (id: string) => void; } let lastActivitiesFetchAt = 0; function createActivityId(): string { return `act-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`; } export const useWorkActivityStore = create((set, get) => ({ activities: [], loaded: false, fetchActivities: async (options) => { if (!options?.force && get().loaded && Date.now() - lastActivitiesFetchAt < SERVER_DATA_CACHE_MS) return; const cached = await listWorkActivitiesDomain().catch(() => []); if (!options?.force && get().loaded && Date.now() - lastActivitiesFetchAt < SERVER_DATA_CACHE_MS) return; lastActivitiesFetchAt = Date.now(); set({ activities: cached ?? [], loaded: true }); }, addActivity: (data) => { const previous = get().activities; const now = new Date(); const item: WorkActivity = { ...data, id: createActivityId(), date: data.date ?? formatLocalDate(now), occurredAt: data.occurredAt ?? now.toISOString(), }; const updated = [...previous, item]; set({ activities: updated, loaded: true }); scheduleSaveWithOptimisticRollback({ save: async () => { const created = await createWorkActivityDomain(item); set({ activities: get().activities.map((activity) => (activity.id === item.id ? { ...item, ...created } : activity)), loaded: true, }); }, expected: updated, getCurrent: () => get().activities, rollback: () => set({ activities: previous, loaded: true }), }); return item; }, addProgressNote: (data) => { return get().addActivity(makeProgressNoteActivity(data)); }, deleteActivity: (id) => { const previous = get().activities; const updated = previous.filter((activity) => activity.id !== id); set({ activities: updated, loaded: true }); scheduleSaveWithOptimisticRollback({ save: async () => { await deleteWorkActivityDomain(id); }, expected: updated, getCurrent: () => get().activities, rollback: () => set({ activities: previous, loaded: true }), }); }, }));