feat: enhance Kanban functionality and update TODO.md
- Completed the creation and validation forms for tasks in the Kanban board, improving task management capabilities. - Integrated new task creation and deletion functionalities in the `KanbanBoard` and `KanbanColumn` components. - Added quick task addition feature in `Column` component for better user experience. - Updated `TaskCard` to support task deletion with a new button. - Marked several tasks as completed in `TODO.md` to reflect the progress on Kanban features. - Updated TypeScript types to include 'manual' as a new task source.
This commit is contained in:
154
hooks/useTasks.ts
Normal file
154
hooks/useTasks.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { tasksClient, TaskFilters, CreateTaskData, UpdateTaskData } from '@/clients/tasks-client';
|
||||
import { Task } from '@/lib/types';
|
||||
|
||||
interface UseTasksState {
|
||||
tasks: Task[];
|
||||
stats: {
|
||||
total: number;
|
||||
completed: number;
|
||||
inProgress: number;
|
||||
todo: number;
|
||||
completionRate: number;
|
||||
};
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
interface UseTasksActions {
|
||||
refreshTasks: () => Promise<void>;
|
||||
createTask: (data: CreateTaskData) => Promise<Task | null>;
|
||||
updateTask: (data: UpdateTaskData) => Promise<Task | null>;
|
||||
deleteTask: (taskId: string) => Promise<void>;
|
||||
setFilters: (filters: TaskFilters) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook pour la gestion des tâches
|
||||
*/
|
||||
export function useTasks(
|
||||
initialFilters?: TaskFilters,
|
||||
initialData?: { tasks: Task[]; stats: UseTasksState['stats'] }
|
||||
): UseTasksState & UseTasksActions {
|
||||
const [state, setState] = useState<UseTasksState>({
|
||||
tasks: initialData?.tasks || [],
|
||||
stats: initialData?.stats || {
|
||||
total: 0,
|
||||
completed: 0,
|
||||
inProgress: 0,
|
||||
todo: 0,
|
||||
completionRate: 0
|
||||
},
|
||||
loading: false,
|
||||
error: null
|
||||
});
|
||||
|
||||
const [filters, setFilters] = useState<TaskFilters>(initialFilters || {});
|
||||
|
||||
/**
|
||||
* Récupère les tâches depuis l'API
|
||||
*/
|
||||
const refreshTasks = useCallback(async () => {
|
||||
setState(prev => ({ ...prev, loading: true, error: null }));
|
||||
|
||||
try {
|
||||
const response = await tasksClient.getTasks(filters);
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
tasks: response.data,
|
||||
stats: response.stats,
|
||||
loading: false
|
||||
}));
|
||||
} catch (error) {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
loading: false,
|
||||
error: error instanceof Error ? error.message : 'Erreur inconnue'
|
||||
}));
|
||||
}
|
||||
}, [filters]);
|
||||
|
||||
/**
|
||||
* Crée une nouvelle tâche
|
||||
*/
|
||||
const createTask = useCallback(async (data: CreateTaskData): Promise<Task | null> => {
|
||||
setState(prev => ({ ...prev, loading: true, error: null }));
|
||||
|
||||
try {
|
||||
const response = await tasksClient.createTask(data);
|
||||
|
||||
// Rafraîchir la liste après création
|
||||
await refreshTasks();
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
loading: false,
|
||||
error: error instanceof Error ? error.message : 'Erreur lors de la création'
|
||||
}));
|
||||
return null;
|
||||
}
|
||||
}, [refreshTasks]);
|
||||
|
||||
/**
|
||||
* Met à jour une tâche
|
||||
*/
|
||||
const updateTask = useCallback(async (data: UpdateTaskData): Promise<Task | null> => {
|
||||
setState(prev => ({ ...prev, loading: true, error: null }));
|
||||
|
||||
try {
|
||||
const response = await tasksClient.updateTask(data);
|
||||
|
||||
// Rafraîchir la liste après mise à jour
|
||||
await refreshTasks();
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
loading: false,
|
||||
error: error instanceof Error ? error.message : 'Erreur lors de la mise à jour'
|
||||
}));
|
||||
return null;
|
||||
}
|
||||
}, [refreshTasks]);
|
||||
|
||||
/**
|
||||
* Supprime une tâche
|
||||
*/
|
||||
const deleteTask = useCallback(async (taskId: string): Promise<void> => {
|
||||
setState(prev => ({ ...prev, loading: true, error: null }));
|
||||
|
||||
try {
|
||||
await tasksClient.deleteTask(taskId);
|
||||
|
||||
// Rafraîchir la liste après suppression
|
||||
await refreshTasks();
|
||||
} catch (error) {
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
loading: false,
|
||||
error: error instanceof Error ? error.message : 'Erreur lors de la suppression'
|
||||
}));
|
||||
throw error; // Re-throw pour que l'UI puisse gérer l'erreur
|
||||
}
|
||||
}, [refreshTasks]);
|
||||
|
||||
// Charger les tâches au montage et quand les filtres changent
|
||||
useEffect(() => {
|
||||
refreshTasks();
|
||||
}, [refreshTasks]);
|
||||
|
||||
return {
|
||||
...state,
|
||||
refreshTasks,
|
||||
createTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
setFilters
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user