feat: enhance column visibility toggle with task counts
- Added `tasks` prop to `ColumnVisibilityToggle` for displaying task counts per status. - Updated `KanbanFilters` to calculate and show counts for priorities and tags, improving filter visibility. - Integrated task counts into UI elements for better user feedback on task distribution across statuses, priorities, and tags.
This commit is contained in:
@@ -134,6 +134,7 @@ export function KanbanBoard({ tasks, onCreateTask, onDeleteTask, onEditTask, onU
|
|||||||
<ColumnVisibilityToggle
|
<ColumnVisibilityToggle
|
||||||
hiddenStatuses={hiddenStatuses}
|
hiddenStatuses={hiddenStatuses}
|
||||||
onToggleStatus={toggleStatusVisibility}
|
onToggleStatus={toggleStatusVisibility}
|
||||||
|
tasks={tasks}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,33 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { TaskStatus } from '@/lib/types';
|
import { useMemo } from 'react';
|
||||||
|
import { Task, TaskStatus } from '@/lib/types';
|
||||||
import { getAllStatuses } from '@/lib/status-config';
|
import { getAllStatuses } from '@/lib/status-config';
|
||||||
|
|
||||||
interface ColumnVisibilityToggleProps {
|
interface ColumnVisibilityToggleProps {
|
||||||
hiddenStatuses: Set<TaskStatus>;
|
hiddenStatuses: Set<TaskStatus>;
|
||||||
onToggleStatus: (status: TaskStatus) => void;
|
onToggleStatus: (status: TaskStatus) => void;
|
||||||
|
tasks: Task[];
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ColumnVisibilityToggle({
|
export function ColumnVisibilityToggle({
|
||||||
hiddenStatuses,
|
hiddenStatuses,
|
||||||
onToggleStatus,
|
onToggleStatus,
|
||||||
|
tasks,
|
||||||
className = ""
|
className = ""
|
||||||
}: ColumnVisibilityToggleProps) {
|
}: ColumnVisibilityToggleProps) {
|
||||||
const statuses = getAllStatuses();
|
const statuses = getAllStatuses();
|
||||||
|
|
||||||
|
// Calculer les compteurs pour chaque statut
|
||||||
|
const statusCounts = useMemo(() => {
|
||||||
|
const counts: Record<string, number> = {};
|
||||||
|
statuses.forEach(status => {
|
||||||
|
counts[status.key] = tasks.filter(task => task.status === status.key).length;
|
||||||
|
});
|
||||||
|
return counts;
|
||||||
|
}, [tasks, statuses]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`flex items-center gap-2 ${className}`}>
|
<div className={`flex items-center gap-2 ${className}`}>
|
||||||
<span className="text-sm font-mono font-medium text-slate-400">
|
<span className="text-sm font-mono font-medium text-slate-400">
|
||||||
@@ -32,7 +44,7 @@ export function ColumnVisibilityToggle({
|
|||||||
}`}
|
}`}
|
||||||
title={hiddenStatuses.has(statusConfig.key) ? `Afficher ${statusConfig.label}` : `Masquer ${statusConfig.label}`}
|
title={hiddenStatuses.has(statusConfig.key) ? `Afficher ${statusConfig.label}` : `Masquer ${statusConfig.label}`}
|
||||||
>
|
>
|
||||||
{hiddenStatuses.has(statusConfig.key) ? '👁️🗨️' : '👁️'} {statusConfig.label}
|
{hiddenStatuses.has(statusConfig.key) ? '👁️🗨️' : '👁️'} {statusConfig.label} ({statusCounts[statusConfig.key] || 0})
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState, useEffect, useRef } 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 } from '@/lib/types';
|
||||||
import { Button } from '@/components/ui/Button';
|
import { Button } from '@/components/ui/Button';
|
||||||
@@ -26,7 +26,7 @@ interface KanbanFiltersProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function KanbanFilters({ filters, onFiltersChange }: KanbanFiltersProps) {
|
export function KanbanFilters({ filters, onFiltersChange }: KanbanFiltersProps) {
|
||||||
const { tags: availableTags } = useTasksContext();
|
const { tags: availableTags, tasks } = useTasksContext();
|
||||||
const [isExpanded, setIsExpanded] = useState(false);
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
const [isSortExpanded, setIsSortExpanded] = useState(false);
|
const [isSortExpanded, setIsSortExpanded] = useState(false);
|
||||||
const sortDropdownRef = useRef<HTMLDivElement>(null);
|
const sortDropdownRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -113,10 +113,29 @@ export function KanbanFilters({ filters, onFiltersChange }: KanbanFiltersProps)
|
|||||||
|
|
||||||
const activeFiltersCount = (filters.tags?.length || 0) + (filters.priorities?.length || 0) + (filters.search ? 1 : 0);
|
const activeFiltersCount = (filters.tags?.length || 0) + (filters.priorities?.length || 0) + (filters.search ? 1 : 0);
|
||||||
|
|
||||||
|
// Calculer les compteurs pour les priorités
|
||||||
|
const priorityCounts = useMemo(() => {
|
||||||
|
const counts: Record<string, number> = {};
|
||||||
|
getAllPriorities().forEach(priority => {
|
||||||
|
counts[priority.key] = tasks.filter(task => task.priority === priority.key).length;
|
||||||
|
});
|
||||||
|
return counts;
|
||||||
|
}, [tasks]);
|
||||||
|
|
||||||
|
// Calculer les compteurs pour les tags
|
||||||
|
const tagCounts = useMemo(() => {
|
||||||
|
const counts: Record<string, number> = {};
|
||||||
|
availableTags.forEach(tag => {
|
||||||
|
counts[tag.name] = tasks.filter(task => task.tags?.includes(tag.name)).length;
|
||||||
|
});
|
||||||
|
return counts;
|
||||||
|
}, [tasks, availableTags]);
|
||||||
|
|
||||||
const priorityOptions = getAllPriorities().map(priorityConfig => ({
|
const priorityOptions = getAllPriorities().map(priorityConfig => ({
|
||||||
value: priorityConfig.key,
|
value: priorityConfig.key,
|
||||||
label: priorityConfig.label,
|
label: priorityConfig.label,
|
||||||
color: priorityConfig.color
|
color: priorityConfig.color,
|
||||||
|
count: priorityCounts[priorityConfig.key] || 0
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -270,7 +289,7 @@ export function KanbanFilters({ filters, onFiltersChange }: KanbanFiltersProps)
|
|||||||
className="w-2 h-2 rounded-full"
|
className="w-2 h-2 rounded-full"
|
||||||
style={{ backgroundColor: getPriorityColorHex(priority.color) }}
|
style={{ backgroundColor: getPriorityColorHex(priority.color) }}
|
||||||
/>
|
/>
|
||||||
{priority.label}
|
{priority.label} ({priority.count})
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -297,7 +316,7 @@ export function KanbanFilters({ filters, onFiltersChange }: KanbanFiltersProps)
|
|||||||
className="w-2 h-2 rounded-full"
|
className="w-2 h-2 rounded-full"
|
||||||
style={{ backgroundColor: tag.color }}
|
style={{ backgroundColor: tag.color }}
|
||||||
/>
|
/>
|
||||||
{tag.name}
|
{tag.name} ({tagCounts[tag.name] || 0})
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ export function SwimlanesBoard({
|
|||||||
<ColumnVisibilityToggle
|
<ColumnVisibilityToggle
|
||||||
hiddenStatuses={hiddenStatuses}
|
hiddenStatuses={hiddenStatuses}
|
||||||
onToggleStatus={toggleStatusVisibility}
|
onToggleStatus={toggleStatusVisibility}
|
||||||
|
tasks={tasks}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user