import { create } from 'zustand'; import { Project } from '../entities/Project'; import { Area } from '../entities/Area'; import { Note } from '../entities/Note'; import { Task } from '../entities/Task'; import { Tag } from '../entities/Tag'; import { InboxItem } from '../entities/InboxItem'; interface NotesStore { notes: Note[]; isLoading: boolean; isError: boolean; hasLoaded: boolean; setNotes: (notes: Note[]) => void; setLoading: (isLoading: boolean) => void; setError: (isError: boolean) => void; loadNotes: () => Promise; } interface AreasStore { areas: Area[]; isLoading: boolean; isError: boolean; hasLoaded: boolean; setAreas: (areas: Area[]) => void; setLoading: (isLoading: boolean) => void; setError: (isError: boolean) => void; loadAreas: () => Promise; } interface ProjectsStore { projects: Project[]; currentProject: Project | null; isLoading: boolean; isError: boolean; setProjects: (projects: Project[]) => void; setCurrentProject: (project: Project | null) => void; setLoading: (isLoading: boolean) => void; setError: (isError: boolean) => void; } interface TagsStore { tags: Tag[]; isLoading: boolean; isError: boolean; hasLoaded: boolean; setTags: (tags: Tag[]) => void; setLoading: (isLoading: boolean) => void; setError: (isError: boolean) => void; loadTags: (forceReload?: boolean) => Promise; getTags: () => Tag[]; refreshTags: () => Promise; addNewTags: (newTagNames: string[]) => void; } interface TasksStore { tasks: Task[]; isLoading: boolean; isError: boolean; setTasks: (tasks: Task[]) => void; setLoading: (isLoading: boolean) => void; setError: (isError: boolean) => void; loadTasks: (query?: string) => Promise; createTask: (taskData: Task) => Promise; updateTask: (taskId: number, taskData: Task) => Promise; deleteTask: (taskId: number) => Promise; toggleTaskCompletion: (taskId: number) => Promise; toggleTaskToday: (taskId: number) => Promise; loadTaskById: (taskId: number) => Promise; loadTaskByUid: (uid: string) => Promise; loadSubtasks: (parentTaskId: number) => Promise; addTask: (task: Task) => void; removeTask: (taskId: number) => void; updateTaskInStore: (updatedTask: Task) => void; } interface InboxStore { inboxItems: InboxItem[]; isLoading: boolean; isError: boolean; setInboxItems: (inboxItems: InboxItem[]) => void; addInboxItem: (inboxItem: InboxItem) => void; updateInboxItem: (inboxItem: InboxItem) => void; removeInboxItem: (id: number) => void; setLoading: (isLoading: boolean) => void; setError: (isError: boolean) => void; } interface StoreState { notesStore: NotesStore; areasStore: AreasStore; projectsStore: ProjectsStore; tagsStore: TagsStore; tasksStore: TasksStore; inboxStore: InboxStore; } export const useStore = create((set: any) => ({ notesStore: { notes: [], isLoading: false, isError: false, hasLoaded: false, setNotes: (notes) => set((state) => ({ notesStore: { ...state.notesStore, notes } })), setLoading: (isLoading) => set((state) => ({ notesStore: { ...state.notesStore, isLoading }, })), setError: (isError) => set((state) => ({ notesStore: { ...state.notesStore, isError } })), loadNotes: async () => { const state = useStore.getState(); if (state.notesStore.isLoading) return; const { fetchNotes } = await import('../utils/notesService'); set((state) => ({ notesStore: { ...state.notesStore, isLoading: true, isError: false, }, })); try { const notes = await fetchNotes(); set((state) => ({ notesStore: { ...state.notesStore, notes, isLoading: false, hasLoaded: true, }, })); } catch (error) { console.error('loadNotes: Failed to load notes:', error); set((state) => ({ notesStore: { ...state.notesStore, isError: true, isLoading: false, hasLoaded: true, }, })); } }, }, areasStore: { areas: [], isLoading: false, isError: false, hasLoaded: false, setAreas: (areas) => set((state) => ({ areasStore: { ...state.areasStore, areas } })), setLoading: (isLoading) => set((state) => ({ areasStore: { ...state.areasStore, isLoading }, })), setError: (isError) => set((state) => ({ areasStore: { ...state.areasStore, isError } })), loadAreas: async () => { const state = useStore.getState(); if (state.areasStore.isLoading) return; const { fetchAreas } = await import('../utils/areasService'); set((state) => ({ areasStore: { ...state.areasStore, isLoading: true, isError: false, }, })); try { const areas = await fetchAreas(); set((state) => ({ areasStore: { ...state.areasStore, areas, isLoading: false, hasLoaded: true, }, })); } catch (error) { console.error('loadAreas: Failed to load areas:', error); set((state) => ({ areasStore: { ...state.areasStore, isError: true, isLoading: false, hasLoaded: true, }, })); } }, }, projectsStore: { projects: [], currentProject: null, isLoading: false, isError: false, setProjects: (projects) => set((state) => ({ projectsStore: { ...state.projectsStore, projects }, })), setCurrentProject: (currentProject) => set((state) => ({ projectsStore: { ...state.projectsStore, currentProject }, })), setLoading: (isLoading) => set((state) => ({ projectsStore: { ...state.projectsStore, isLoading }, })), setError: (isError) => set((state) => ({ projectsStore: { ...state.projectsStore, isError }, })), }, tagsStore: { tags: [], isLoading: false, isError: false, hasLoaded: false, setTags: (tags) => set((state) => ({ tagsStore: { ...state.tagsStore, tags } })), setLoading: (isLoading) => set((state) => ({ tagsStore: { ...state.tagsStore, isLoading } })), setError: (isError) => set((state) => ({ tagsStore: { ...state.tagsStore, isError } })), loadTags: async (forceReload = false) => { const state = useStore.getState(); if (state.tagsStore.isLoading) return; // Skip loading if already loaded and not forcing reload if (state.tagsStore.hasLoaded && !forceReload) return; const { fetchTags } = await import('../utils/tagsService'); set((state) => ({ tagsStore: { ...state.tagsStore, isLoading: true, isError: false, }, })); try { const tags = await fetchTags(); set((state) => ({ tagsStore: { ...state.tagsStore, tags, isLoading: false, hasLoaded: true, }, })); } catch (error) { console.error('loadTags: Failed to load tags:', error); set((state) => ({ tagsStore: { ...state.tagsStore, isError: true, isLoading: false, hasLoaded: true, }, })); } }, getTags: (): Tag[] => { const state: StoreState = useStore.getState(); // Auto-load tags if not loaded yet if (!state.tagsStore.hasLoaded && !state.tagsStore.isLoading) { state.tagsStore.loadTags(); } return state.tagsStore.tags; }, refreshTags: async () => { const state = useStore.getState(); return state.tagsStore.loadTags(true); }, addNewTags: (newTagNames: string[]) => { const state = useStore.getState(); const existingTagNames = state.tagsStore.tags.map( (tag: Tag) => tag.name ); const tagsToAdd = newTagNames .filter((name) => !existingTagNames.includes(name)) .map((name) => ({ name, id: Date.now() + Math.random() })); // Temporary ID if (tagsToAdd.length > 0) { set((state) => ({ tagsStore: { ...state.tagsStore, tags: [...state.tagsStore.tags, ...tagsToAdd], }, })); } }, }, tasksStore: { tasks: [], isLoading: false, isError: false, setTasks: (tasks) => set((state) => ({ tasksStore: { ...state.tasksStore, tasks } })), setLoading: (isLoading) => set((state) => ({ tasksStore: { ...state.tasksStore, isLoading }, })), setError: (isError) => set((state) => ({ tasksStore: { ...state.tasksStore, isError } })), loadTasks: async (query = '') => { const { fetchTasks } = await import('../utils/tasksService'); set((state) => ({ tasksStore: { ...state.tasksStore, isLoading: true, isError: false, }, })); try { const { tasks } = await fetchTasks(query); set((state) => ({ tasksStore: { ...state.tasksStore, tasks, isLoading: false, }, })); } catch (error) { console.error('loadTasks: Failed to load tasks:', error); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true, isLoading: false, }, })); } }, createTask: async (taskData) => { const { createTask } = await import('../utils/tasksService'); try { const newTask = await createTask(taskData); set((state) => ({ tasksStore: { ...state.tasksStore, tasks: [newTask, ...state.tasksStore.tasks], }, })); return newTask; } catch (error) { console.error('createTask: Failed to create task:', error); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true }, })); throw error; } }, updateTask: async (taskId, taskData) => { const { updateTask } = await import('../utils/tasksService'); try { const updatedTask = await updateTask(taskId, taskData); set((state) => ({ tasksStore: { ...state.tasksStore, tasks: state.tasksStore.tasks.map((task) => task.id === taskId ? updatedTask : task ), }, })); return updatedTask; } catch (error) { console.error('updateTask: Failed to update task:', error); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true }, })); throw error; } }, deleteTask: async (taskId) => { const { deleteTask } = await import('../utils/tasksService'); try { await deleteTask(taskId); set((state) => ({ tasksStore: { ...state.tasksStore, tasks: state.tasksStore.tasks.filter( (task) => task.id !== taskId ), }, })); } catch (error) { console.error('deleteTask: Failed to delete task:', error); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true }, })); throw error; } }, toggleTaskCompletion: async (taskId) => { const { toggleTaskCompletion } = await import( '../utils/tasksService' ); try { const updatedTask = await toggleTaskCompletion(taskId); set((state) => ({ tasksStore: { ...state.tasksStore, tasks: state.tasksStore.tasks.map((task) => task.id === taskId ? updatedTask : task ), }, })); return updatedTask; } catch (error) { console.error( 'toggleTaskCompletion: Failed to toggle task completion:', error ); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true }, })); throw error; } }, toggleTaskToday: async (taskId) => { const { toggleTaskToday } = await import('../utils/tasksService'); try { const updatedTask = await toggleTaskToday(taskId); set((state) => ({ tasksStore: { ...state.tasksStore, tasks: state.tasksStore.tasks.map((task) => task.id === taskId ? updatedTask : task ), }, })); return updatedTask; } catch (error) { console.error( 'toggleTaskToday: Failed to toggle task today status:', error ); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true }, })); throw error; } }, loadTaskById: async (taskId) => { const { fetchTaskById } = await import('../utils/tasksService'); try { const task = await fetchTaskById(taskId); set((state) => ({ tasksStore: { ...state.tasksStore, tasks: state.tasksStore.tasks.some( (t) => t.id === taskId ) ? state.tasksStore.tasks.map((t) => t.id === taskId ? task : t ) : [task, ...state.tasksStore.tasks], }, })); return task; } catch (error) { console.error('loadTaskById: Failed to load task:', error); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true }, })); throw error; } }, loadTaskByUid: async (uid) => { const { fetchTaskByUid } = await import('../utils/tasksService'); try { const task = await fetchTaskByUid(uid); set((state) => ({ tasksStore: { ...state.tasksStore, tasks: state.tasksStore.tasks.some((t) => t.uid === uid) ? state.tasksStore.tasks.map((t) => t.uid === uid ? task : t ) : [task, ...state.tasksStore.tasks], }, })); return task; } catch (error) { console.error('loadTaskByUid: Failed to load task:', error); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true }, })); throw error; } }, loadSubtasks: async (parentTaskId) => { const { fetchSubtasks } = await import('../utils/tasksService'); try { const subtasks = await fetchSubtasks(parentTaskId); set((state) => ({ tasksStore: { ...state.tasksStore, tasks: [ ...state.tasksStore.tasks.filter( (task) => task.parent_task_id !== parentTaskId ), ...subtasks, ], }, })); return subtasks; } catch (error) { console.error('loadSubtasks: Failed to load subtasks:', error); set((state) => ({ tasksStore: { ...state.tasksStore, isError: true }, })); throw error; } }, addTask: (task) => set((state) => ({ tasksStore: { ...state.tasksStore, tasks: [task, ...state.tasksStore.tasks], }, })), removeTask: (taskId) => set((state) => ({ tasksStore: { ...state.tasksStore, tasks: state.tasksStore.tasks.filter( (task) => task.id !== taskId ), }, })), updateTaskInStore: (updatedTask) => set((state) => ({ tasksStore: { ...state.tasksStore, tasks: state.tasksStore.tasks.map((task) => task.id === updatedTask.id ? { ...task, ...updatedTask, // Explicitly preserve subtasks data subtasks: updatedTask.subtasks || updatedTask.Subtasks || task.subtasks || task.Subtasks || [], Subtasks: updatedTask.subtasks || updatedTask.Subtasks || task.subtasks || task.Subtasks || [], } : task ), }, })), }, inboxStore: { inboxItems: [], isLoading: false, isError: false, setInboxItems: (inboxItems) => set((state) => ({ inboxStore: { ...state.inboxStore, inboxItems }, })), addInboxItem: (inboxItem) => set((state) => ({ inboxStore: { ...state.inboxStore, inboxItems: [inboxItem, ...state.inboxStore.inboxItems], }, })), updateInboxItem: (inboxItem) => set((state) => ({ inboxStore: { ...state.inboxStore, inboxItems: state.inboxStore.inboxItems.map((item) => item.id === inboxItem.id ? inboxItem : item ), }, })), removeInboxItem: (id) => set((state) => ({ inboxStore: { ...state.inboxStore, inboxItems: state.inboxStore.inboxItems.filter( (item) => item.id !== id ), }, })), setLoading: (isLoading) => set((state) => ({ inboxStore: { ...state.inboxStore, isLoading }, })), setError: (isError) => set((state) => ({ inboxStore: { ...state.inboxStore, isError }, })), }, }));