feat: enhance Kanban components with visibleStatuses prop
- Added `visibleStatuses` prop to `KanbanBoard`, `PrioritySwimlanesBoard`, `SwimlanesBase`, and `SwimlanesBoard` for improved column visibility control. - Updated `KanbanBoardContainer` to derive `visibleStatuses` from `useColumnVisibility`, allowing dynamic filtering of displayed statuses. - Refactored `KanbanFilters` to accept `hiddenStatuses` and `onToggleStatusVisibility` props, enabling better integration with column visibility management. - Cleaned up visibility logic across components to ensure consistent behavior and user experience.
This commit is contained in:
@@ -28,14 +28,15 @@ interface KanbanBoardProps {
|
|||||||
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
compactView?: boolean;
|
compactView?: boolean;
|
||||||
|
visibleStatuses?: TaskStatus[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function KanbanBoard({ tasks, onCreateTask, onDeleteTask, onEditTask, onUpdateTitle, onUpdateStatus, loading = false, compactView = false }: KanbanBoardProps) {
|
export function KanbanBoard({ tasks, onCreateTask, onDeleteTask, onEditTask, onUpdateTitle, onUpdateStatus, loading = false, compactView = false, visibleStatuses }: KanbanBoardProps) {
|
||||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||||
const [activeTask, setActiveTask] = useState<Task | null>(null);
|
const [activeTask, setActiveTask] = useState<Task | null>(null);
|
||||||
|
|
||||||
// Gestion de la visibilité des colonnes
|
// Gestion de la visibilité des colonnes (utilise les props si disponibles)
|
||||||
const { hiddenStatuses, toggleStatusVisibility, getVisibleStatuses } = useColumnVisibility();
|
const { getVisibleStatuses } = useColumnVisibility();
|
||||||
|
|
||||||
// Configuration des capteurs pour le drag & drop
|
// Configuration des capteurs pour le drag & drop
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
@@ -67,7 +68,9 @@ export function KanbanBoard({ tasks, onCreateTask, onDeleteTask, onEditTask, onU
|
|||||||
}, [tasksByStatus]);
|
}, [tasksByStatus]);
|
||||||
|
|
||||||
// Filtrer les colonnes visibles
|
// Filtrer les colonnes visibles
|
||||||
const visibleColumns = getVisibleStatuses(allColumns);
|
const visibleColumns = visibleStatuses ?
|
||||||
|
allColumns.filter(column => visibleStatuses.includes(column.id)) :
|
||||||
|
getVisibleStatuses(allColumns);
|
||||||
|
|
||||||
const handleCreateTask = async (data: CreateTaskData) => {
|
const handleCreateTask = async (data: CreateTaskData) => {
|
||||||
if (onCreateTask) {
|
if (onCreateTask) {
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import { EditTaskForm } from '@/components/forms/EditTaskForm';
|
|||||||
import { useTasksContext } from '@/contexts/TasksContext';
|
import { useTasksContext } from '@/contexts/TasksContext';
|
||||||
import { Task, TaskStatus } from '@/lib/types';
|
import { Task, TaskStatus } from '@/lib/types';
|
||||||
import { UpdateTaskData } from '@/clients/tasks-client';
|
import { UpdateTaskData } from '@/clients/tasks-client';
|
||||||
|
import { useColumnVisibility } from '@/hooks/useColumnVisibility';
|
||||||
|
import { getAllStatuses } from '@/lib/status-config';
|
||||||
|
|
||||||
export function KanbanBoardContainer() {
|
export function KanbanBoardContainer() {
|
||||||
const {
|
const {
|
||||||
@@ -25,6 +27,9 @@ export function KanbanBoardContainer() {
|
|||||||
tags
|
tags
|
||||||
} = useTasksContext();
|
} = useTasksContext();
|
||||||
|
|
||||||
|
const { hiddenStatuses, toggleStatusVisibility, getVisibleStatuses } = useColumnVisibility();
|
||||||
|
const allStatuses = getAllStatuses();
|
||||||
|
const visibleStatuses = getVisibleStatuses(allStatuses.map(s => ({ id: s.key }))).map(s => s.id);
|
||||||
const [editingTask, setEditingTask] = useState<Task | null>(null);
|
const [editingTask, setEditingTask] = useState<Task | null>(null);
|
||||||
|
|
||||||
const handleEditTask = (task: Task) => {
|
const handleEditTask = (task: Task) => {
|
||||||
@@ -59,6 +64,8 @@ export function KanbanBoardContainer() {
|
|||||||
<KanbanFilters
|
<KanbanFilters
|
||||||
filters={kanbanFilters}
|
filters={kanbanFilters}
|
||||||
onFiltersChange={setKanbanFilters}
|
onFiltersChange={setKanbanFilters}
|
||||||
|
hiddenStatuses={hiddenStatuses}
|
||||||
|
onToggleStatusVisibility={toggleStatusVisibility}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Section Objectifs Principaux */}
|
{/* Section Objectifs Principaux */}
|
||||||
@@ -82,6 +89,7 @@ export function KanbanBoardContainer() {
|
|||||||
onUpdateTitle={handleUpdateTitle}
|
onUpdateTitle={handleUpdateTitle}
|
||||||
onUpdateStatus={handleUpdateStatus}
|
onUpdateStatus={handleUpdateStatus}
|
||||||
compactView={kanbanFilters.compactView}
|
compactView={kanbanFilters.compactView}
|
||||||
|
visibleStatuses={visibleStatuses}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SwimlanesBoard
|
<SwimlanesBoard
|
||||||
@@ -91,6 +99,7 @@ export function KanbanBoardContainer() {
|
|||||||
onUpdateTitle={handleUpdateTitle}
|
onUpdateTitle={handleUpdateTitle}
|
||||||
onUpdateStatus={handleUpdateStatus}
|
onUpdateStatus={handleUpdateStatus}
|
||||||
compactView={kanbanFilters.compactView}
|
compactView={kanbanFilters.compactView}
|
||||||
|
visibleStatuses={visibleStatuses}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
@@ -103,6 +112,7 @@ export function KanbanBoardContainer() {
|
|||||||
onUpdateStatus={handleUpdateStatus}
|
onUpdateStatus={handleUpdateStatus}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
compactView={kanbanFilters.compactView}
|
compactView={kanbanFilters.compactView}
|
||||||
|
visibleStatuses={visibleStatuses}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useRef, useMemo } from 'react';
|
import { useState, useEffect, useRef, useMemo } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { TaskPriority } from '@/lib/types';
|
import { TaskPriority, TaskStatus } from '@/lib/types';
|
||||||
import { Button } from '@/components/ui/Button';
|
import { Button } from '@/components/ui/Button';
|
||||||
import { Input } from '@/components/ui/Input';
|
import { Input } from '@/components/ui/Input';
|
||||||
import { useTasksContext } from '@/contexts/TasksContext';
|
import { useTasksContext } from '@/contexts/TasksContext';
|
||||||
@@ -26,11 +26,17 @@ export interface KanbanFilters {
|
|||||||
interface KanbanFiltersProps {
|
interface KanbanFiltersProps {
|
||||||
filters: KanbanFilters;
|
filters: KanbanFilters;
|
||||||
onFiltersChange: (filters: KanbanFilters) => void;
|
onFiltersChange: (filters: KanbanFilters) => void;
|
||||||
|
hiddenStatuses?: Set<TaskStatus>;
|
||||||
|
onToggleStatusVisibility?: (status: TaskStatus) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function KanbanFilters({ filters, onFiltersChange }: KanbanFiltersProps) {
|
export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsHiddenStatuses, onToggleStatusVisibility }: KanbanFiltersProps) {
|
||||||
const { tags: availableTags, regularTasks } = useTasksContext();
|
const { tags: availableTags, regularTasks } = useTasksContext();
|
||||||
const { hiddenStatuses, toggleStatusVisibility } = useColumnVisibility();
|
const { hiddenStatuses: localHiddenStatuses, toggleStatusVisibility: localToggleStatusVisibility } = useColumnVisibility();
|
||||||
|
|
||||||
|
// Utiliser les props si disponibles, sinon utiliser l'état local
|
||||||
|
const hiddenStatuses = propsHiddenStatuses || localHiddenStatuses;
|
||||||
|
const toggleStatusVisibility = onToggleStatusVisibility || localToggleStatusVisibility;
|
||||||
const [isExpanded, setIsExpanded] = useState(false);
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
const [isSortExpanded, setIsSortExpanded] = useState(false);
|
const [isSortExpanded, setIsSortExpanded] = useState(false);
|
||||||
const [isSwimlaneModeExpanded, setIsSwimlaneModeExpanded] = useState(false);
|
const [isSwimlaneModeExpanded, setIsSwimlaneModeExpanded] = useState(false);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ interface PrioritySwimlanesoardProps {
|
|||||||
onUpdateTitle?: (taskId: string, newTitle: string) => Promise<void>;
|
onUpdateTitle?: (taskId: string, newTitle: string) => Promise<void>;
|
||||||
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
||||||
compactView?: boolean;
|
compactView?: boolean;
|
||||||
|
visibleStatuses?: TaskStatus[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PrioritySwimlanesBoard({
|
export function PrioritySwimlanesBoard({
|
||||||
@@ -20,7 +21,8 @@ export function PrioritySwimlanesBoard({
|
|||||||
onEditTask,
|
onEditTask,
|
||||||
onUpdateTitle,
|
onUpdateTitle,
|
||||||
onUpdateStatus,
|
onUpdateStatus,
|
||||||
compactView = false
|
compactView = false,
|
||||||
|
visibleStatuses
|
||||||
}: PrioritySwimlanesoardProps) {
|
}: PrioritySwimlanesoardProps) {
|
||||||
|
|
||||||
// Grouper les tâches par priorités et créer les données de swimlanes
|
// Grouper les tâches par priorités et créer les données de swimlanes
|
||||||
@@ -60,6 +62,7 @@ export function PrioritySwimlanesBoard({
|
|||||||
onUpdateTitle={onUpdateTitle}
|
onUpdateTitle={onUpdateTitle}
|
||||||
onUpdateStatus={onUpdateStatus}
|
onUpdateStatus={onUpdateStatus}
|
||||||
compactView={compactView}
|
compactView={compactView}
|
||||||
|
visibleStatuses={visibleStatuses}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -79,6 +79,7 @@ interface SwimlanesBaseProps {
|
|||||||
onUpdateTitle?: (taskId: string, newTitle: string) => Promise<void>;
|
onUpdateTitle?: (taskId: string, newTitle: string) => Promise<void>;
|
||||||
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
||||||
compactView?: boolean;
|
compactView?: boolean;
|
||||||
|
visibleStatuses?: TaskStatus[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SwimlanesBase({
|
export function SwimlanesBase({
|
||||||
@@ -89,16 +90,17 @@ export function SwimlanesBase({
|
|||||||
onEditTask,
|
onEditTask,
|
||||||
onUpdateTitle,
|
onUpdateTitle,
|
||||||
onUpdateStatus,
|
onUpdateStatus,
|
||||||
compactView = false
|
compactView = false,
|
||||||
|
visibleStatuses
|
||||||
}: SwimlanesBaseProps) {
|
}: SwimlanesBaseProps) {
|
||||||
const [activeTask, setActiveTask] = useState<Task | null>(null);
|
const [activeTask, setActiveTask] = useState<Task | null>(null);
|
||||||
const [collapsedSwimlanes, setCollapsedSwimlanes] = useState<Set<string>>(new Set());
|
const [collapsedSwimlanes, setCollapsedSwimlanes] = useState<Set<string>>(new Set());
|
||||||
|
|
||||||
// Gestion de la visibilité des colonnes
|
// Gestion de la visibilité des colonnes
|
||||||
const { hiddenStatuses, toggleStatusVisibility, getVisibleStatuses } = useColumnVisibility();
|
const { getVisibleStatuses } = useColumnVisibility();
|
||||||
const allStatuses = getAllStatuses();
|
const allStatuses = getAllStatuses();
|
||||||
const visibleStatuses = getVisibleStatuses(allStatuses.map(s => ({ id: s.key })))
|
const statusesToShow = visibleStatuses ||
|
||||||
.map(s => s.id);
|
getVisibleStatuses(allStatuses.map(s => ({ id: s.key }))).map(s => s.id);
|
||||||
|
|
||||||
// Configuration des sensors pour le drag & drop
|
// Configuration des sensors pour le drag & drop
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
@@ -161,9 +163,9 @@ export function SwimlanesBase({
|
|||||||
{/* Headers des colonnes visibles */}
|
{/* Headers des colonnes visibles */}
|
||||||
<div
|
<div
|
||||||
className={`grid gap-4 px-6 py-4 ml-8`}
|
className={`grid gap-4 px-6 py-4 ml-8`}
|
||||||
style={{ gridTemplateColumns: `repeat(${visibleStatuses.length}, minmax(0, 1fr))` }}
|
style={{ gridTemplateColumns: `repeat(${statusesToShow.length}, minmax(0, 1fr))` }}
|
||||||
>
|
>
|
||||||
{visibleStatuses.map(status => {
|
{statusesToShow.map(status => {
|
||||||
const statusConfig = allStatuses.find(s => s.key === status);
|
const statusConfig = allStatuses.find(s => s.key === status);
|
||||||
return (
|
return (
|
||||||
<div key={status} className="text-center">
|
<div key={status} className="text-center">
|
||||||
@@ -214,9 +216,9 @@ export function SwimlanesBase({
|
|||||||
{!isCollapsed && (
|
{!isCollapsed && (
|
||||||
<div
|
<div
|
||||||
className={`grid gap-4 p-4`}
|
className={`grid gap-4 p-4`}
|
||||||
style={{ gridTemplateColumns: `repeat(${visibleStatuses.length}, minmax(0, 1fr))` }}
|
style={{ gridTemplateColumns: `repeat(${statusesToShow.length}, minmax(0, 1fr))` }}
|
||||||
>
|
>
|
||||||
{visibleStatuses.map(status => {
|
{statusesToShow.map(status => {
|
||||||
const statusTasks = swimlane.tasks.filter(task => task.status === status);
|
const statusTasks = swimlane.tasks.filter(task => task.status === status);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ interface SwimlanesboardProps {
|
|||||||
onUpdateTitle?: (taskId: string, newTitle: string) => Promise<void>;
|
onUpdateTitle?: (taskId: string, newTitle: string) => Promise<void>;
|
||||||
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
||||||
compactView?: boolean;
|
compactView?: boolean;
|
||||||
|
visibleStatuses?: TaskStatus[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SwimlanesBoard({
|
export function SwimlanesBoard({
|
||||||
@@ -20,7 +21,8 @@ export function SwimlanesBoard({
|
|||||||
onEditTask,
|
onEditTask,
|
||||||
onUpdateTitle,
|
onUpdateTitle,
|
||||||
onUpdateStatus,
|
onUpdateStatus,
|
||||||
compactView = false
|
compactView = false,
|
||||||
|
visibleStatuses
|
||||||
}: SwimlanesboardProps) {
|
}: SwimlanesboardProps) {
|
||||||
const { tags: availableTags } = useTasksContext();
|
const { tags: availableTags } = useTasksContext();
|
||||||
|
|
||||||
@@ -80,6 +82,7 @@ export function SwimlanesBoard({
|
|||||||
onUpdateTitle={onUpdateTitle}
|
onUpdateTitle={onUpdateTitle}
|
||||||
onUpdateStatus={onUpdateStatus}
|
onUpdateStatus={onUpdateStatus}
|
||||||
compactView={compactView}
|
compactView={compactView}
|
||||||
|
visibleStatuses={visibleStatuses}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user