'use client'; import { create } from 'zustand'; import type { TaskWorklog } from '@/lib/task-worklog'; import { createTaskWorklogDomain, deleteTaskWorklogDomain, listTaskWorklogsDomain, } from '@/lib/domain-api'; import { scheduleSaveWithOptimisticRollback } from '@/lib/optimistic-persistence'; import { loadServerData, saveServerData, SERVER_DATA_CACHE_MS } from '@/lib/server-data'; let lastWorklogsFetchAt = 0; async function loadStored(): Promise { try { return await loadServerData('task-worklogs'); } catch {} return null; } interface TaskWorklogState { worklogs: TaskWorklog[]; loaded: boolean; fetchWorklogs: (options?: { force?: boolean }) => Promise; addWorklog: (data: Omit) => void; deleteWorklog: (id: string) => void; getActualHours: (taskId: string) => number; } export const useTaskWorklogStore = create((set, get) => ({ worklogs: [], loaded: false, fetchWorklogs: async (options) => { if (!options?.force && get().loaded && Date.now() - lastWorklogsFetchAt < SERVER_DATA_CACHE_MS) return; const cached = await listTaskWorklogsDomain().catch(loadStored); if (!options?.force && get().loaded && Date.now() - lastWorklogsFetchAt < SERVER_DATA_CACHE_MS) return; lastWorklogsFetchAt = Date.now(); set({ worklogs: cached ?? [], loaded: true }); }, addWorklog: (data) => { const previous = get().worklogs; const item: TaskWorklog = { ...data, id: `wl-${Date.now()}`, createdAt: new Date().toISOString(), }; const updated = [...previous, item]; set({ worklogs: updated, loaded: true }); scheduleSaveWithOptimisticRollback({ save: async () => { try { const created = await createTaskWorklogDomain(item); set({ worklogs: get().worklogs.map((worklog) => (worklog.id === item.id ? { ...item, ...created } : worklog)), loaded: true, }); } catch { await saveTaskWorklogsFallback(updated); } }, expected: updated, getCurrent: () => get().worklogs, rollback: () => set({ worklogs: previous, loaded: true }), }); }, deleteWorklog: (id) => { const previous = get().worklogs; const updated = previous.filter((w) => w.id !== id); set({ worklogs: updated, loaded: true }); scheduleSaveWithOptimisticRollback({ save: async () => { try { await deleteTaskWorklogDomain(id); } catch { await saveTaskWorklogsFallback(updated); } }, expected: updated, getCurrent: () => get().worklogs, rollback: () => set({ worklogs: previous, loaded: true }), }); }, getActualHours: (taskId) => { return get().worklogs .filter((w) => w.taskId === taskId) .reduce((sum, w) => sum + w.hours, 0); }, })); async function saveTaskWorklogsFallback(worklogs: TaskWorklog[]) { await saveServerData('task-worklogs', worklogs); }