refactor: simplify swimlane mode handling in KanbanFilters

- Removed swimlane mode toggle and dropdown, streamlining the swimlane mode functionality.
- Updated `handleSwimlanesToggle` to cycle through swimlane modes directly, enhancing clarity and usability.
- Cleaned up unused state and refs related to swimlane mode, improving component performance and maintainability.
This commit is contained in:
Julien Froidefond
2025-09-28 21:55:56 +02:00
parent 0fcd4d68c1
commit 5a3d825b8e

View File

@@ -32,10 +32,8 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
const hiddenStatuses = propsHiddenStatuses || new Set(preferences.columnVisibility.hiddenStatuses);
const toggleStatusVisibility = onToggleStatusVisibility || toggleColumnVisibility;
const [isSortExpanded, setIsSortExpanded] = useState(false);
const [isSwimlaneModeExpanded, setIsSwimlaneModeExpanded] = useState(false);
const isMobile = useIsMobile(768); // Tailwind md breakpoint
const sortDropdownRef = useRef<HTMLDivElement>(null);
const swimlaneModeDropdownRef = useRef<HTMLDivElement>(null);
const sortButtonRef = useRef<HTMLButtonElement>(null);
const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });
@@ -45,16 +43,13 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
if (sortDropdownRef.current && !sortDropdownRef.current.contains(event.target as Node)) {
setIsSortExpanded(false);
}
if (swimlaneModeDropdownRef.current && !swimlaneModeDropdownRef.current.contains(event.target as Node)) {
setIsSwimlaneModeExpanded(false);
}
}
if (isSortExpanded || isSwimlaneModeExpanded) {
if (isSortExpanded) {
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}
}, [isSortExpanded, isSwimlaneModeExpanded]);
}, [isSortExpanded]);
// Handler pour la recherche avec debounce intégré
const handleSearchChange = (search: string) => {
@@ -87,30 +82,31 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
const handleSwimlanesToggle = () => {
onFiltersChange({
...filters,
swimlanesByTags: !filters.swimlanesByTags
});
// Cycle entre les 3 modes : Normal → Par tags → Par priorité → Normal
if (!filters.swimlanesByTags) {
// Normal → Par tags
onFiltersChange({
...filters,
swimlanesByTags: true,
swimlanesMode: 'tags'
});
} else if (filters.swimlanesMode === 'tags') {
// Par tags → Par priorité
onFiltersChange({
...filters,
swimlanesByTags: true,
swimlanesMode: 'priority'
});
} else {
// Par priorité → Normal
onFiltersChange({
...filters,
swimlanesByTags: false,
swimlanesMode: undefined
});
}
};
const handleSwimlaneModeChange = (mode: 'tags' | 'priority') => {
onFiltersChange({
...filters,
swimlanesByTags: true,
swimlanesMode: mode
});
setIsSwimlaneModeExpanded(false);
};
const handleSwimlaneModeToggle = (event: React.MouseEvent<HTMLButtonElement>) => {
const button = event.currentTarget;
const rect = button.getBoundingClientRect();
setDropdownPosition({
top: rect.bottom + window.scrollY + 4,
left: rect.left + window.scrollX
});
setIsSwimlaneModeExpanded(!isSwimlaneModeExpanded);
};
const handleSortChange = (sortKey: string) => {
onFiltersChange({
@@ -186,23 +182,6 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
}
</ToggleButton>
{/* Bouton pour changer le mode des swimlanes */}
{filters.swimlanesByTags && (
<Button
variant="ghost"
onClick={handleSwimlaneModeToggle}
className="flex items-center gap-1 px-2"
>
<svg
className={`w-3 h-3 transition-transform ${isSwimlaneModeExpanded ? 'rotate-180' : ''}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</Button>
)}
</ControlGroup>
)}
@@ -331,35 +310,6 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
document.body
)}
{/* Dropdown des modes swimlanes rendu via portail pour éviter les problèmes de z-index - masqué sur mobile */}
{!isMobile && isSwimlaneModeExpanded && typeof window !== 'undefined' && createPortal(
<div
ref={swimlaneModeDropdownRef}
className="fixed bg-[var(--card)] border border-[var(--border)] rounded-lg shadow-xl z-[9999] min-w-[140px]"
style={{
top: dropdownPosition.top,
left: dropdownPosition.left,
}}
>
<button
onClick={() => handleSwimlaneModeChange('tags')}
className={`w-full px-3 py-2 text-left text-xs hover:bg-[var(--card-hover)] transition-colors flex items-center gap-2 first:rounded-t-lg ${
(!filters.swimlanesMode || filters.swimlanesMode === 'tags') ? 'bg-[var(--card-hover)] text-[var(--primary)]' : 'text-[var(--muted-foreground)]'
}`}
>
🏷 Par tags
</button>
<button
onClick={() => handleSwimlaneModeChange('priority')}
className={`w-full px-3 py-2 text-left text-xs hover:bg-[var(--card-hover)] transition-colors flex items-center gap-2 last:rounded-b-lg ${
filters.swimlanesMode === 'priority' ? 'bg-[var(--card-hover)] text-[var(--primary)]' : 'text-[var(--muted-foreground)]'
}`}
>
🎯 Par priorité
</button>
</div>,
document.body
)}
</ControlPanel>
);
}