/** * 📝 Tasks Store (Zustand) * Gerenciador de estado das tarefas */ import { create } from 'zustand'; import apiClient, { handleApiError } from '../api'; import { TasksState, Task, CreateTaskPayload, UpdateTaskPayload, TaskFilters, TasksListResponse, TaskStatsResponse, } from '../types'; interface TasksStore extends TasksState { // Ações fetchTasks: (filters?: TaskFilters) => Promise; fetchStats: () => Promise; createTask: (payload: CreateTaskPayload) => Promise; updateTask: (id: string, payload: UpdateTaskPayload) => Promise; deleteTask: (id: string) => Promise; setFilters: (filters: TaskFilters) => void; setError: (error: string | null) => void; setLoading: (loading: boolean) => void; clear: () => void; } /** * Criar store de tarefas */ export const useTasksStore = create((set, get) => ({ // Estado inicial tasks: [], stats: null, isLoading: false, error: null, filters: { completed: undefined, sortBy: 'created_at', order: 'desc', }, // ============================================================================ // AÇÕES // ============================================================================ /** * Buscar tarefas com filtros */ fetchTasks: async (filters?: TaskFilters) => { try { set({ isLoading: true, error: null }); if (filters) { set({ filters }); } const currentFilters = filters || get().filters; const params = new URLSearchParams(); if (currentFilters.completed !== undefined) { params.append('completed', String(currentFilters.completed)); } if (currentFilters.category) { params.append('category', currentFilters.category); } if (currentFilters.priority) { params.append('priority', currentFilters.priority); } if (currentFilters.sortBy) { params.append('sortBy', currentFilters.sortBy); } if (currentFilters.order) { params.append('order', currentFilters.order); } const url = `/tasks${params.toString() ? '?' + params.toString() : ''}`; const response = await apiClient.get(url); set({ tasks: response.data.data, isLoading: false, }); } catch (error) { const message = handleApiError(error); set({ error: message, isLoading: false, tasks: [] }); } }, /** * Buscar estatísticas */ fetchStats: async () => { try { const response = await apiClient.get('/tasks/stats'); set({ stats: response.data.data }); } catch (error) { console.error('Erro ao buscar estatísticas:', error); } }, /** * Criar tarefa */ createTask: async (payload: CreateTaskPayload) => { try { set({ isLoading: true, error: null }); const response = await apiClient.post<{ data: Task }>('/tasks', payload); const newTask = response.data.data; // Adicionar à lista set({ tasks: [newTask, ...get().tasks] }); // Atualizar stats se houver if (get().stats) { await get().fetchStats(); } return newTask; } catch (error) { const message = handleApiError(error); set({ error: message }); throw new Error(message); } finally { set({ isLoading: false }); } }, /** * Atualizar tarefa */ updateTask: async (id: string, payload: UpdateTaskPayload) => { try { set({ isLoading: true, error: null }); const response = await apiClient.patch<{ data: Task }>( `/tasks/${id}`, payload, ); const updatedTask = response.data.data; // Atualizar na lista set({ tasks: get().tasks.map((t) => (t.id === id ? updatedTask : t)), }); // Atualizar stats se houver if (get().stats) { await get().fetchStats(); } return updatedTask; } catch (error) { const message = handleApiError(error); set({ error: message }); throw new Error(message); } finally { set({ isLoading: false }); } }, /** * Deletar tarefa */ deleteTask: async (id: string) => { try { set({ isLoading: true, error: null }); await apiClient.delete(`/tasks/${id}`); // Remover da lista set({ tasks: get().tasks.filter((t) => t.id !== id) }); // Atualizar stats se houver if (get().stats) { await get().fetchStats(); } return true; } catch (error) { const message = handleApiError(error); set({ error: message }); return false; } finally { set({ isLoading: false }); } }, /** * Setar filtros */ setFilters: (filters: TaskFilters) => { set({ filters }); }, /** * Setar erro */ setError: (error: string | null) => { set({ error }); }, /** * Setar loading */ setLoading: (isLoading: boolean) => { set({ isLoading }); }, /** * Limpar estado */ clear: () => { set({ tasks: [], stats: null, isLoading: false, error: null, filters: { completed: undefined, sortBy: 'created_at', order: 'desc', }, }); }, })); // Hook customizado export const useTasks = () => { const store = useTasksStore(); return { tasks: store.tasks, stats: store.stats, isLoading: store.isLoading, error: store.error, filters: store.filters, fetchTasks: store.fetchTasks, fetchStats: store.fetchStats, createTask: store.createTask, updateTask: store.updateTask, deleteTask: store.deleteTask, setFilters: store.setFilters, }; };