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:
@@ -1,6 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { JiraQuickFilter } from '@/components/kanban/JiraQuickFilter';
|
||||
import { TfsQuickFilter } from '@/components/kanban/TfsQuickFilter';
|
||||
import { FontSizeToggle } from '@/components/ui/FontSizeToggle';
|
||||
@@ -35,11 +37,64 @@ export function DesktopControls({
|
||||
onFiltersChange,
|
||||
onCreateTask,
|
||||
}: 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 (
|
||||
<div className="bg-[var(--card)]/30 border-b border-[var(--border)]/30">
|
||||
<div className="container mx-auto px-6 py-2">
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<div className="bg-[var(--card)]/30 border-b border-[var(--border)]/30 w-full">
|
||||
<div className="w-full px-6 py-2">
|
||||
{/* 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">
|
||||
{/* 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">
|
||||
<button
|
||||
onClick={onToggleFilters}
|
||||
@@ -68,8 +123,25 @@ export function DesktopControls({
|
||||
</svg>
|
||||
Objectifs
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
{/* 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">
|
||||
{/* Raccourcis Jira */}
|
||||
<JiraQuickFilter
|
||||
@@ -125,19 +197,19 @@ export function DesktopControls({
|
||||
<FontSizeToggle />
|
||||
</div>
|
||||
|
||||
{/* Bouton d'ajout de tâche */}
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
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>
|
||||
Nouvelle tâche
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Bouton d'ajout de tâche */}
|
||||
<Button
|
||||
variant="primary"
|
||||
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>
|
||||
Nouvelle tâche
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user