Files
towercontrol/components/kanban/SwimlanesBoard.tsx
Julien Froidefond c627d1abd3 feat: enhance Kanban components with swimlane context support
- Added `context` prop to `PrioritySwimlanesBoard`, `SwimlanesBoard`, and `DroppableColumn` to provide swimlane context for task creation.
- Updated `QuickAddTask` to pre-fill form data based on the swimlane context, improving user experience during task addition.
- Enhanced task handling in `SwimlanesBoard` to include context for tags, ensuring better organization and task management.
2025-09-15 11:53:47 +02:00

99 lines
2.9 KiB
TypeScript

'use client';
import { Task, TaskStatus } from '@/lib/types';
import { CreateTaskData } from '@/clients/tasks-client';
import { useMemo } from 'react';
import { useTasksContext } from '@/contexts/TasksContext';
import { SwimlanesBase, SwimlaneData } from './SwimlanesBase';
interface SwimlanesboardProps {
tasks: Task[];
onCreateTask?: (data: CreateTaskData) => Promise<Task | null>;
onDeleteTask?: (taskId: string) => Promise<void>;
onEditTask?: (task: Task) => void;
onUpdateTitle?: (taskId: string, newTitle: string) => Promise<void>;
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
compactView?: boolean;
visibleStatuses?: TaskStatus[];
loading?: boolean;
}
export function SwimlanesBoard({
tasks,
onCreateTask,
onDeleteTask,
onEditTask,
onUpdateTitle,
onUpdateStatus,
compactView = false,
visibleStatuses,
loading = false
}: SwimlanesboardProps) {
const { tags: availableTags } = useTasksContext();
// Grouper les tâches par tags et créer les données de swimlanes
const swimlanesData = useMemo((): SwimlaneData[] => {
const grouped: { [tagName: string]: Task[] } = {};
// Ajouter une catégorie pour les tâches sans tags
grouped['Sans tag'] = [];
tasks.forEach(task => {
if (!task.tags || task.tags.length === 0) {
grouped['Sans tag'].push(task);
} else {
task.tags.forEach(tagName => {
if (!grouped[tagName]) {
grouped[tagName] = [];
}
grouped[tagName].push(task);
});
}
});
// Convertir en format SwimlaneData et trier
return Object.entries(grouped)
.sort(([a, tasksA], [b, tasksB]) => {
// Mettre "Sans tag" à la fin
if (a === 'Sans tag') return 1;
if (b === 'Sans tag') return -1;
// Trier par nombre de tâches (décroissant)
return tasksB.length - tasksA.length;
})
.map(([tagName, tagTasks]) => {
// Obtenir la couleur du tag
const getTagColor = (name: string) => {
if (name === 'Sans tag') return '#64748b'; // slate-500
const tag = availableTags.find(t => t.name === name);
return tag?.color || '#64748b';
};
return {
key: tagName,
label: tagName,
color: getTagColor(tagName),
tasks: tagTasks,
context: tagName !== 'Sans tag' ? {
type: 'tag' as const,
value: tagName
} : undefined
};
});
}, [tasks, availableTags]);
return (
<SwimlanesBase
tasks={tasks}
title="Swimlanes par Tag"
swimlanes={swimlanesData}
onCreateTask={onCreateTask}
onDeleteTask={onDeleteTask}
onEditTask={onEditTask}
onUpdateTitle={onUpdateTitle}
onUpdateStatus={onUpdateStatus}
compactView={compactView}
visibleStatuses={visibleStatuses}
loading={loading}
/>
);
}