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:
@@ -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
|
||||
});
|
||||
};
|
||||
|
||||
const handleSwimlaneModeChange = (mode: 'tags' | 'priority') => {
|
||||
// Cycle entre les 3 modes : Normal → Par tags → Par priorité → Normal
|
||||
if (!filters.swimlanesByTags) {
|
||||
// Normal → Par tags
|
||||
onFiltersChange({
|
||||
...filters,
|
||||
swimlanesByTags: true,
|
||||
swimlanesMode: mode
|
||||
swimlanesMode: 'tags'
|
||||
});
|
||||
setIsSwimlaneModeExpanded(false);
|
||||
} 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 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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user