- 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.
120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
'use client';
|
|
|
|
import { Task, TaskStatus } from '@/lib/types';
|
|
import { KanbanColumn } from './Column';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { CreateTaskForm } from '@/components/forms/CreateTaskForm';
|
|
import { CreateTaskData } from '@/clients/tasks-client';
|
|
import { useMemo, useState } from 'react';
|
|
|
|
interface KanbanBoardProps {
|
|
tasks: Task[];
|
|
onCreateTask?: (data: CreateTaskData) => Promise<Task | null>;
|
|
onDeleteTask?: (taskId: string) => Promise<void>;
|
|
loading?: boolean;
|
|
}
|
|
|
|
export function KanbanBoard({ tasks, onCreateTask, onDeleteTask, loading = false }: KanbanBoardProps) {
|
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
|
// Organiser les tâches par statut
|
|
const tasksByStatus = useMemo(() => {
|
|
const grouped = tasks.reduce((acc, task) => {
|
|
if (!acc[task.status]) {
|
|
acc[task.status] = [];
|
|
}
|
|
acc[task.status].push(task);
|
|
return acc;
|
|
}, {} as Record<TaskStatus, Task[]>);
|
|
|
|
return grouped;
|
|
}, [tasks]);
|
|
|
|
// Configuration des colonnes
|
|
const columns: Array<{
|
|
id: TaskStatus;
|
|
title: string;
|
|
color: string;
|
|
tasks: Task[];
|
|
}> = [
|
|
{
|
|
id: 'todo',
|
|
title: 'À faire',
|
|
color: 'gray',
|
|
tasks: tasksByStatus.todo || []
|
|
},
|
|
{
|
|
id: 'in_progress',
|
|
title: 'En cours',
|
|
color: 'blue',
|
|
tasks: tasksByStatus.in_progress || []
|
|
},
|
|
{
|
|
id: 'done',
|
|
title: 'Terminé',
|
|
color: 'green',
|
|
tasks: tasksByStatus.done || []
|
|
},
|
|
{
|
|
id: 'cancelled',
|
|
title: 'Annulé',
|
|
color: 'red',
|
|
tasks: tasksByStatus.cancelled || []
|
|
}
|
|
];
|
|
|
|
const handleCreateTask = async (data: CreateTaskData) => {
|
|
if (onCreateTask) {
|
|
await onCreateTask(data);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="h-full flex flex-col bg-slate-950">
|
|
{/* Header avec bouton nouvelle tâche */}
|
|
<div className="flex justify-between items-center p-6 pb-0">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-2 h-2 bg-cyan-400 rounded-full animate-pulse"></div>
|
|
<h2 className="text-lg font-mono font-bold text-slate-100 uppercase tracking-wider">
|
|
Kanban Board
|
|
</h2>
|
|
</div>
|
|
|
|
{onCreateTask && (
|
|
<Button
|
|
variant="primary"
|
|
onClick={() => setIsCreateModalOpen(true)}
|
|
disabled={loading}
|
|
>
|
|
+ Nouvelle tâche
|
|
</Button>
|
|
)}
|
|
</div>
|
|
|
|
{/* Board tech dark */}
|
|
<div className="flex-1 flex gap-6 overflow-x-auto p-6">
|
|
{columns.map((column) => (
|
|
<KanbanColumn
|
|
key={column.id}
|
|
id={column.id}
|
|
title={column.title}
|
|
color={column.color}
|
|
tasks={column.tasks}
|
|
onCreateTask={onCreateTask ? handleCreateTask : undefined}
|
|
onDeleteTask={onDeleteTask}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
{/* Modal de création */}
|
|
{onCreateTask && (
|
|
<CreateTaskForm
|
|
isOpen={isCreateModalOpen}
|
|
onClose={() => setIsCreateModalOpen(false)}
|
|
onSubmit={handleCreateTask}
|
|
loading={loading}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|