- 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.
99 lines
2.9 KiB
TypeScript
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}
|
|
/>
|
|
);
|
|
} |