feat: add search functionality and due date filter toggle in DesktopControls

- Implemented a debounced search input for filtering tasks, enhancing user experience with smooth input handling.
- Added a toggle button for filtering tasks by due date, improving task visibility options.
- Updated layout for better responsiveness and integrated new input components for a cleaner UI.
This commit is contained in:
Julien Froidefond
2025-09-26 08:44:05 +02:00
parent a5199a8302
commit 2e9cc4e667

View File

@@ -1,6 +1,8 @@
'use client'; 'use client';
import { useState, useEffect, useRef, useCallback } from 'react';
import { Button } from '@/components/ui/Button'; import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { JiraQuickFilter } from '@/components/kanban/JiraQuickFilter'; import { JiraQuickFilter } from '@/components/kanban/JiraQuickFilter';
import { TfsQuickFilter } from '@/components/kanban/TfsQuickFilter'; import { TfsQuickFilter } from '@/components/kanban/TfsQuickFilter';
import { FontSizeToggle } from '@/components/ui/FontSizeToggle'; import { FontSizeToggle } from '@/components/ui/FontSizeToggle';
@@ -35,11 +37,64 @@ export function DesktopControls({
onFiltersChange, onFiltersChange,
onCreateTask, onCreateTask,
}: DesktopControlsProps) { }: DesktopControlsProps) {
// État local pour la recherche pour une saisie fluide
const [localSearch, setLocalSearch] = useState(kanbanFilters.search || '');
const searchTimeoutRef = useRef<number | undefined>(undefined);
// Fonction debouncée pour mettre à jour les filtres
const debouncedSearchChange = useCallback((search: string) => {
if (searchTimeoutRef.current) {
window.clearTimeout(searchTimeoutRef.current);
}
searchTimeoutRef.current = window.setTimeout(() => {
onFiltersChange({ ...kanbanFilters, search: search || undefined });
}, 300);
}, [kanbanFilters, onFiltersChange]);
const handleSearchChange = (search: string) => {
setLocalSearch(search);
debouncedSearchChange(search);
};
// Synchroniser l'état local quand les filtres changent de l'extérieur
useEffect(() => {
setLocalSearch(kanbanFilters.search || '');
}, [kanbanFilters.search]);
// Nettoyer le timeout au démontage
useEffect(() => {
return () => {
if (searchTimeoutRef.current) {
window.clearTimeout(searchTimeoutRef.current);
}
};
}, []);
const handleDueDateFilterToggle = () => {
onFiltersChange({
...kanbanFilters,
showWithDueDate: !kanbanFilters.showWithDueDate
});
};
return ( return (
<div className="bg-[var(--card)]/30 border-b border-[var(--border)]/30"> <div className="bg-[var(--card)]/30 border-b border-[var(--border)]/30 w-full">
<div className="container mx-auto px-6 py-2"> <div className="w-full px-6 py-2">
<div className="flex items-center justify-between w-full"> {/* Layout responsive : deux lignes sur tablette, une ligne sur desktop */}
<div className="flex flex-col lg:flex-row lg:items-center gap-4 lg:gap-0 w-full">
{/* Section gauche : Recherche + Boutons principaux */}
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
{/* Champ de recherche */}
<div className="flex-1 min-w-0">
<Input
type="text"
value={localSearch}
onChange={(e) => handleSearchChange(e.target.value)}
placeholder="Rechercher des tâches..."
className="bg-[var(--card)] border-[var(--border)] w-full"
/>
</div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
onClick={onToggleFilters} onClick={onToggleFilters}
@@ -68,8 +123,25 @@ export function DesktopControls({
</svg> </svg>
Objectifs Objectifs
</button> </button>
<button
onClick={handleDueDateFilterToggle}
className={`flex items-center justify-center px-3 py-1.5 rounded-md transition-all mr-4 ${
kanbanFilters.showWithDueDate
? 'bg-[var(--cyan)]/20 text-[var(--cyan)] border border-[var(--cyan)]/30'
: 'bg-[var(--card)] text-[var(--muted-foreground)] border border-[var(--border)] hover:border-[var(--cyan)]/50'
}`}
title={kanbanFilters.showWithDueDate ? "Afficher toutes les tâches" : "Afficher seulement les tâches avec date de fin"}
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 002 2v12a2 2 0 002 2z" />
</svg>
</button>
</div> </div>
</div>
{/* Section droite : Raccourcis + Bouton Nouvelle tâche */}
<div className="flex items-center justify-between lg:justify-start gap-4">
<div className="flex items-center gap-2 border-l border-[var(--border)] pl-4"> <div className="flex items-center gap-2 border-l border-[var(--border)] pl-4">
{/* Raccourcis Jira */} {/* Raccourcis Jira */}
<JiraQuickFilter <JiraQuickFilter
@@ -124,20 +196,20 @@ export function DesktopControls({
{/* Font Size Toggle */} {/* Font Size Toggle */}
<FontSizeToggle /> <FontSizeToggle />
</div> </div>
</div>
{/* Bouton d'ajout de tâche */} {/* Bouton d'ajout de tâche */}
<Button <Button
variant="primary" variant="primary"
onClick={onCreateTask} size="sm"
className="flex items-center gap-2" onClick={onCreateTask}
> className="flex items-center gap-2"
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> >
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" /> <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
</svg> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
Nouvelle tâche </svg>
</Button> Nouvelle tâche
</Button>
</div>
</div> </div>
</div> </div>
</div> </div>