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 hiddenStatuses = propsHiddenStatuses || new Set(preferences.columnVisibility.hiddenStatuses);
|
||||||
const toggleStatusVisibility = onToggleStatusVisibility || toggleColumnVisibility;
|
const toggleStatusVisibility = onToggleStatusVisibility || toggleColumnVisibility;
|
||||||
const [isSortExpanded, setIsSortExpanded] = useState(false);
|
const [isSortExpanded, setIsSortExpanded] = useState(false);
|
||||||
const [isSwimlaneModeExpanded, setIsSwimlaneModeExpanded] = useState(false);
|
|
||||||
const isMobile = useIsMobile(768); // Tailwind md breakpoint
|
const isMobile = useIsMobile(768); // Tailwind md breakpoint
|
||||||
const sortDropdownRef = useRef<HTMLDivElement>(null);
|
const sortDropdownRef = useRef<HTMLDivElement>(null);
|
||||||
const swimlaneModeDropdownRef = useRef<HTMLDivElement>(null);
|
|
||||||
const sortButtonRef = useRef<HTMLButtonElement>(null);
|
const sortButtonRef = useRef<HTMLButtonElement>(null);
|
||||||
const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });
|
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)) {
|
if (sortDropdownRef.current && !sortDropdownRef.current.contains(event.target as Node)) {
|
||||||
setIsSortExpanded(false);
|
setIsSortExpanded(false);
|
||||||
}
|
}
|
||||||
if (swimlaneModeDropdownRef.current && !swimlaneModeDropdownRef.current.contains(event.target as Node)) {
|
|
||||||
setIsSwimlaneModeExpanded(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSortExpanded || isSwimlaneModeExpanded) {
|
if (isSortExpanded) {
|
||||||
document.addEventListener('mousedown', handleClickOutside);
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||||
}
|
}
|
||||||
}, [isSortExpanded, isSwimlaneModeExpanded]);
|
}, [isSortExpanded]);
|
||||||
|
|
||||||
// Handler pour la recherche avec debounce intégré
|
// Handler pour la recherche avec debounce intégré
|
||||||
const handleSearchChange = (search: string) => {
|
const handleSearchChange = (search: string) => {
|
||||||
@@ -87,30 +82,31 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
|
|||||||
|
|
||||||
|
|
||||||
const handleSwimlanesToggle = () => {
|
const handleSwimlanesToggle = () => {
|
||||||
onFiltersChange({
|
// Cycle entre les 3 modes : Normal → Par tags → Par priorité → Normal
|
||||||
...filters,
|
if (!filters.swimlanesByTags) {
|
||||||
swimlanesByTags: !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) => {
|
const handleSortChange = (sortKey: string) => {
|
||||||
onFiltersChange({
|
onFiltersChange({
|
||||||
@@ -186,23 +182,6 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
|
|||||||
}
|
}
|
||||||
</ToggleButton>
|
</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>
|
</ControlGroup>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -331,35 +310,6 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
|
|||||||
document.body
|
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>
|
</ControlPanel>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user