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.
This commit is contained in:
Julien Froidefond
2025-09-15 11:53:47 +02:00
parent 07cd3bde3b
commit c627d1abd3
4 changed files with 58 additions and 22 deletions

View File

@@ -53,7 +53,11 @@ export function PrioritySwimlanesBoard({
label: priority.label,
icon: priority.icon,
color: priority.color,
tasks: grouped[priority.key] || []
tasks: grouped[priority.key] || [],
context: {
type: 'priority' as const,
value: priority.key
}
}));
}, [tasks]);

View File

@@ -5,23 +5,44 @@ import { Card } from '@/components/ui/Card';
import { TagInput } from '@/components/ui/TagInput';
import { TaskStatus, TaskPriority } from '@/lib/types';
import { CreateTaskData } from '@/clients/tasks-client';
import { getAllPriorities, getPriorityConfig } from '@/lib/status-config';
import { getAllPriorities } from '@/lib/status-config';
interface QuickAddTaskProps {
status: TaskStatus;
onSubmit: (data: CreateTaskData) => Promise<void>;
onCancel: () => void;
// Contexte pour les swimlanes
swimlaneContext?: {
type: 'tag' | 'priority';
value: string; // nom du tag ou clé de la priorité
};
}
export function QuickAddTask({ status, onSubmit, onCancel }: QuickAddTaskProps) {
const [formData, setFormData] = useState<CreateTaskData>({
title: '',
description: '',
status,
priority: 'medium' as TaskPriority,
tags: [],
dueDate: undefined
});
export function QuickAddTask({ status, onSubmit, onCancel, swimlaneContext }: QuickAddTaskProps) {
// Fonction pour initialiser les données selon le contexte
const getInitialFormData = (): CreateTaskData => {
const baseData: CreateTaskData = {
title: '',
description: '',
status,
priority: 'medium' as TaskPriority,
tags: [],
dueDate: undefined
};
// Pré-remplir selon le contexte de swimlane
if (swimlaneContext) {
if (swimlaneContext.type === 'tag' && swimlaneContext.value !== 'Sans tag') {
baseData.tags = [swimlaneContext.value];
} else if (swimlaneContext.type === 'priority') {
baseData.priority = swimlaneContext.value as TaskPriority;
}
}
return baseData;
};
const [formData, setFormData] = useState<CreateTaskData>(getInitialFormData());
const [isSubmitting, setIsSubmitting] = useState(false);
const [activeField, setActiveField] = useState<'title' | 'description' | 'tags' | 'date' | null>('title');
const titleRef = useRef<HTMLInputElement>(null);
@@ -44,15 +65,8 @@ export function QuickAddTask({ status, onSubmit, onCancel }: QuickAddTaskProps)
title: trimmedTitle
});
// Réinitialiser pour la prochaine tâche
setFormData({
title: '',
description: '',
status,
priority: 'medium',
tags: [],
dueDate: undefined
});
// Réinitialiser pour la prochaine tâche (en gardant le contexte)
setFormData(getInitialFormData());
setActiveField('title');
setIsSubmitting(false);
titleRef.current?.focus();

View File

@@ -35,7 +35,8 @@ function DroppableColumn({
compactView,
onCreateTask,
showQuickAdd,
onToggleQuickAdd
onToggleQuickAdd,
swimlaneContext
}: {
status: TaskStatus;
tasks: Task[];
@@ -46,6 +47,10 @@ function DroppableColumn({
onCreateTask?: (data: CreateTaskData) => Promise<void>;
showQuickAdd?: boolean;
onToggleQuickAdd?: () => void;
swimlaneContext?: {
type: 'tag' | 'priority';
value: string;
};
}) {
const { setNodeRef } = useDroppable({
id: status,
@@ -76,6 +81,7 @@ function DroppableColumn({
status={status}
onSubmit={onCreateTask}
onCancel={onToggleQuickAdd || (() => {})}
swimlaneContext={swimlaneContext}
/>
) : (
<button
@@ -101,6 +107,10 @@ export interface SwimlaneData {
icon?: string;
color?: string;
tasks: Task[];
context?: {
type: 'tag' | 'priority';
value: string;
};
}
interface SwimlanesBaseProps {
@@ -293,6 +303,9 @@ export function SwimlanesBase({
const columnId = `${swimlane.key}-${status}`;
// Utiliser le contexte défini dans la swimlane
const swimlaneContext = swimlane.context;
return (
<DroppableColumn
key={columnId}
@@ -305,6 +318,7 @@ export function SwimlanesBase({
onCreateTask={onCreateTask ? (data) => handleQuickAdd(data, columnId) : undefined}
showQuickAdd={showQuickAdd[columnId] || false}
onToggleQuickAdd={() => toggleQuickAdd(columnId)}
swimlaneContext={swimlaneContext}
/>
);
})}

View File

@@ -72,7 +72,11 @@ export function SwimlanesBoard({
key: tagName,
label: tagName,
color: getTagColor(tagName),
tasks: tagTasks
tasks: tagTasks,
context: tagName !== 'Sans tag' ? {
type: 'tag' as const,
value: tagName
} : undefined
};
});
}, [tasks, availableTags]);