feat(ui): make task filter bar collapsible

This commit is contained in:
Gabriel Menezes 2026-10-09 09:45:55 -04:00
parent c4828a0a77
commit b05ff9651a

View file

@ -1,4 +1,5 @@
import { RefreshCw, Search } from 'lucide-react' import { useState } from 'react'
import { RefreshCw, Search, Filter, ChevronDown, ChevronUp } from 'lucide-react'
import { TASK_STATUS_LABELS, TASK_STATUS_OPTIONS, type TaskStatus } from '../types/task' import { TASK_STATUS_LABELS, TASK_STATUS_OPTIONS, type TaskStatus } from '../types/task'
import type { Project } from '../services/projectService' import type { Project } from '../services/projectService'
import type { Category } from '../types/category' import type { Category } from '../types/category'
@ -36,9 +37,17 @@ export function TaskFilterBar({
isLoading, isLoading,
onRefresh, onRefresh,
}: TaskFilterBarProps) { }: TaskFilterBarProps) {
const [isExpanded, setIsExpanded] = useState(false)
const update = (partial: Partial<TaskFilters>) => const update = (partial: Partial<TaskFilters>) =>
onFiltersChange({ ...filters, ...partial }) onFiltersChange({ ...filters, ...partial })
const activeFiltersCount =
(filters.projectIds?.length || 0) +
(filters.statuses?.length || 0) +
(filters.categoryIds?.length || 0) +
(filters.userIds?.length || 0)
return ( return (
<div className="flex flex-col gap-4 rounded-2xl border border-border-soft bg-surface p-4 shadow-sm"> <div className="flex flex-col gap-4 rounded-2xl border border-border-soft bg-surface p-4 shadow-sm">
<div className="flex flex-col gap-3 lg:flex-row lg:items-center"> <div className="flex flex-col gap-3 lg:flex-row lg:items-center">
@ -56,18 +65,39 @@ export function TaskFilterBar({
/> />
</div> </div>
{onRefresh && ( <div className="flex items-center gap-2">
<button <button
onClick={onRefresh} onClick={() => setIsExpanded(!isExpanded)}
className="flex h-11 w-11 items-center justify-center rounded-xl bg-app-bg text-text-muted transition-all hover:bg-surface-muted hover:text-brand" className={`flex h-11 items-center gap-2 rounded-xl px-4 text-sm font-medium transition-all ${
title="Recarregar" isExpanded || activeFiltersCount > 0
? 'bg-brand/10 text-brand'
: 'bg-app-bg text-text-muted hover:bg-surface-muted hover:text-brand'
}`}
> >
<RefreshCw size={18} className={isLoading ? 'animate-spin' : ''} /> <Filter size={18} />
<span className="hidden sm:inline">Filtros</span>
{activeFiltersCount > 0 && (
<span className="flex h-5 min-w-5 items-center justify-center rounded-full bg-brand text-xs text-white">
{activeFiltersCount}
</span>
)}
{isExpanded ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
</button> </button>
)}
{onRefresh && (
<button
onClick={onRefresh}
className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-app-bg text-text-muted transition-all hover:bg-surface-muted hover:text-brand"
title="Recarregar"
>
<RefreshCw size={18} className={isLoading ? 'animate-spin' : ''} />
</button>
)}
</div>
</div> </div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4"> {isExpanded && (
<div className="grid grid-cols-1 gap-4 border-t border-border-soft pt-4 sm:grid-cols-2 lg:grid-cols-4">
{projects.length > 0 && ( {projects.length > 0 && (
<MultiSelectDropdown <MultiSelectDropdown
label="Projetos" label="Projetos"
@ -143,7 +173,8 @@ export function TaskFilterBar({
)} )}
</div> </div>
)} )}
</div> </div>
)}
</div> </div>
) )
} }