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:
@@ -53,7 +53,11 @@ export function PrioritySwimlanesBoard({
|
|||||||
label: priority.label,
|
label: priority.label,
|
||||||
icon: priority.icon,
|
icon: priority.icon,
|
||||||
color: priority.color,
|
color: priority.color,
|
||||||
tasks: grouped[priority.key] || []
|
tasks: grouped[priority.key] || [],
|
||||||
|
context: {
|
||||||
|
type: 'priority' as const,
|
||||||
|
value: priority.key
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}, [tasks]);
|
}, [tasks]);
|
||||||
|
|
||||||
|
|||||||
@@ -5,23 +5,44 @@ import { Card } from '@/components/ui/Card';
|
|||||||
import { TagInput } from '@/components/ui/TagInput';
|
import { TagInput } from '@/components/ui/TagInput';
|
||||||
import { TaskStatus, TaskPriority } from '@/lib/types';
|
import { TaskStatus, TaskPriority } from '@/lib/types';
|
||||||
import { CreateTaskData } from '@/clients/tasks-client';
|
import { CreateTaskData } from '@/clients/tasks-client';
|
||||||
import { getAllPriorities, getPriorityConfig } from '@/lib/status-config';
|
import { getAllPriorities } from '@/lib/status-config';
|
||||||
|
|
||||||
interface QuickAddTaskProps {
|
interface QuickAddTaskProps {
|
||||||
status: TaskStatus;
|
status: TaskStatus;
|
||||||
onSubmit: (data: CreateTaskData) => Promise<void>;
|
onSubmit: (data: CreateTaskData) => Promise<void>;
|
||||||
onCancel: () => 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) {
|
export function QuickAddTask({ status, onSubmit, onCancel, swimlaneContext }: QuickAddTaskProps) {
|
||||||
const [formData, setFormData] = useState<CreateTaskData>({
|
// Fonction pour initialiser les données selon le contexte
|
||||||
title: '',
|
const getInitialFormData = (): CreateTaskData => {
|
||||||
description: '',
|
const baseData: CreateTaskData = {
|
||||||
status,
|
title: '',
|
||||||
priority: 'medium' as TaskPriority,
|
description: '',
|
||||||
tags: [],
|
status,
|
||||||
dueDate: undefined
|
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 [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [activeField, setActiveField] = useState<'title' | 'description' | 'tags' | 'date' | null>('title');
|
const [activeField, setActiveField] = useState<'title' | 'description' | 'tags' | 'date' | null>('title');
|
||||||
const titleRef = useRef<HTMLInputElement>(null);
|
const titleRef = useRef<HTMLInputElement>(null);
|
||||||
@@ -44,15 +65,8 @@ export function QuickAddTask({ status, onSubmit, onCancel }: QuickAddTaskProps)
|
|||||||
title: trimmedTitle
|
title: trimmedTitle
|
||||||
});
|
});
|
||||||
|
|
||||||
// Réinitialiser pour la prochaine tâche
|
// Réinitialiser pour la prochaine tâche (en gardant le contexte)
|
||||||
setFormData({
|
setFormData(getInitialFormData());
|
||||||
title: '',
|
|
||||||
description: '',
|
|
||||||
status,
|
|
||||||
priority: 'medium',
|
|
||||||
tags: [],
|
|
||||||
dueDate: undefined
|
|
||||||
});
|
|
||||||
setActiveField('title');
|
setActiveField('title');
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
titleRef.current?.focus();
|
titleRef.current?.focus();
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ function DroppableColumn({
|
|||||||
compactView,
|
compactView,
|
||||||
onCreateTask,
|
onCreateTask,
|
||||||
showQuickAdd,
|
showQuickAdd,
|
||||||
onToggleQuickAdd
|
onToggleQuickAdd,
|
||||||
|
swimlaneContext
|
||||||
}: {
|
}: {
|
||||||
status: TaskStatus;
|
status: TaskStatus;
|
||||||
tasks: Task[];
|
tasks: Task[];
|
||||||
@@ -46,6 +47,10 @@ function DroppableColumn({
|
|||||||
onCreateTask?: (data: CreateTaskData) => Promise<void>;
|
onCreateTask?: (data: CreateTaskData) => Promise<void>;
|
||||||
showQuickAdd?: boolean;
|
showQuickAdd?: boolean;
|
||||||
onToggleQuickAdd?: () => void;
|
onToggleQuickAdd?: () => void;
|
||||||
|
swimlaneContext?: {
|
||||||
|
type: 'tag' | 'priority';
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
}) {
|
}) {
|
||||||
const { setNodeRef } = useDroppable({
|
const { setNodeRef } = useDroppable({
|
||||||
id: status,
|
id: status,
|
||||||
@@ -76,6 +81,7 @@ function DroppableColumn({
|
|||||||
status={status}
|
status={status}
|
||||||
onSubmit={onCreateTask}
|
onSubmit={onCreateTask}
|
||||||
onCancel={onToggleQuickAdd || (() => {})}
|
onCancel={onToggleQuickAdd || (() => {})}
|
||||||
|
swimlaneContext={swimlaneContext}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
@@ -101,6 +107,10 @@ export interface SwimlaneData {
|
|||||||
icon?: string;
|
icon?: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
tasks: Task[];
|
tasks: Task[];
|
||||||
|
context?: {
|
||||||
|
type: 'tag' | 'priority';
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SwimlanesBaseProps {
|
interface SwimlanesBaseProps {
|
||||||
@@ -293,6 +303,9 @@ export function SwimlanesBase({
|
|||||||
|
|
||||||
const columnId = `${swimlane.key}-${status}`;
|
const columnId = `${swimlane.key}-${status}`;
|
||||||
|
|
||||||
|
// Utiliser le contexte défini dans la swimlane
|
||||||
|
const swimlaneContext = swimlane.context;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DroppableColumn
|
<DroppableColumn
|
||||||
key={columnId}
|
key={columnId}
|
||||||
@@ -305,6 +318,7 @@ export function SwimlanesBase({
|
|||||||
onCreateTask={onCreateTask ? (data) => handleQuickAdd(data, columnId) : undefined}
|
onCreateTask={onCreateTask ? (data) => handleQuickAdd(data, columnId) : undefined}
|
||||||
showQuickAdd={showQuickAdd[columnId] || false}
|
showQuickAdd={showQuickAdd[columnId] || false}
|
||||||
onToggleQuickAdd={() => toggleQuickAdd(columnId)}
|
onToggleQuickAdd={() => toggleQuickAdd(columnId)}
|
||||||
|
swimlaneContext={swimlaneContext}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -72,7 +72,11 @@ export function SwimlanesBoard({
|
|||||||
key: tagName,
|
key: tagName,
|
||||||
label: tagName,
|
label: tagName,
|
||||||
color: getTagColor(tagName),
|
color: getTagColor(tagName),
|
||||||
tasks: tagTasks
|
tasks: tagTasks,
|
||||||
|
context: tagName !== 'Sans tag' ? {
|
||||||
|
type: 'tag' as const,
|
||||||
|
value: tagName
|
||||||
|
} : undefined
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [tasks, availableTags]);
|
}, [tasks, availableTags]);
|
||||||
|
|||||||
Reference in New Issue
Block a user