feat: redesign task filter bar UI

This commit is contained in:
Gabriel Menezes 2026-10-08 10:22:49 -04:00
parent b399992dc5
commit ec9cf347ec

View file

@ -1,8 +1,7 @@
import { Filter, RefreshCw, Search } from 'lucide-react' import { RefreshCw, Search } 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'
import { MultiSelectChips } from './MultiSelectChips'
import { CategoryIcon } from './CategoryIcon' import { CategoryIcon } from './CategoryIcon'
import { MultiSelectDropdown } from './MultiSelectDropdown' import { MultiSelectDropdown } from './MultiSelectDropdown'
import type { TaskFilters } from './taskFilters' import type { TaskFilters } from './taskFilters'
@ -68,39 +67,65 @@ export function TaskFilterBar({
)} )}
</div> </div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
{projects.length > 0 && ( {projects.length > 0 && (
<div className="flex items-center gap-2"> <MultiSelectDropdown
<Filter size={16} className="shrink-0 text-text-muted" /> label="Projetos"
<span className="text-[10px] font-black uppercase tracking-widest text-text-muted whitespace-nowrap">Projetos</span> allLabel="Todos os projetos"
<MultiSelectChips
options={projects.map((p) => ({ options={projects.map((p) => ({
value: p.id, value: p.id,
label: p.name, label: p.name,
color: p.color ?? undefined,
icon: p.icon ? <CategoryIcon iconName={p.icon} size={14} /> : undefined, icon: p.icon ? <CategoryIcon iconName={p.icon} size={14} /> : undefined,
}))} }))}
selected={filters.projectIds} selected={filters.projectIds}
onChange={(projectIds) => update({ projectIds })} onChange={(projectIds) => update({ projectIds })}
/> />
</div>
)} )}
<div className="flex items-center gap-2"> <MultiSelectDropdown
<Filter size={16} className="shrink-0 text-text-muted" /> label="Status"
<span className="text-[10px] font-black uppercase tracking-widest text-text-muted whitespace-nowrap">Status</span> allLabel="Todos os status"
<MultiSelectChips
options={TASK_STATUS_OPTIONS.map((s) => ({ options={TASK_STATUS_OPTIONS.map((s) => ({
value: s, value: s,
label: TASK_STATUS_LABELS[s], label: TASK_STATUS_LABELS[s],
color: STATUS_CHIP_COLORS[s], icon: (
<div
className="h-3 w-3 shrink-0 rounded-full"
style={{ backgroundColor: STATUS_CHIP_COLORS[s] }}
/>
),
}))} }))}
selected={filters.statuses} selected={filters.statuses}
onChange={(statuses) => update({ statuses })} onChange={(statuses) => update({ statuses })}
/> />
</div>
{categories.length > 0 && (
<MultiSelectDropdown
label="Categorias"
allLabel="Todas as categorias"
options={categories.map((c) => ({
value: c.id,
label: c.name,
icon: <CategoryIcon iconName={c.icon} size={14} />,
}))}
selected={filters.categoryIds}
onChange={(categoryIds) => update({ categoryIds })}
/>
)}
{assignees.length > 0 && ( {assignees.length > 0 && (
<div className="grid gap-2"> <div className="flex flex-col gap-2">
<MultiSelectDropdown
label="Funcionário"
allLabel="Todos os funcionários"
options={assignees.map((assignee) => ({
value: assignee.id,
label: assignee.name,
icon: <UserAvatar name={assignee.name} photo={assignee.photo} size="sm" />,
}))}
selected={filters.userIds}
onChange={(userIds) => update({ userIds })}
/>
{currentUserId !== undefined && ( {currentUserId !== undefined && (
<label className="flex cursor-pointer items-center gap-2 self-start"> <label className="flex cursor-pointer items-center gap-2 self-start">
<input <input
@ -116,36 +141,9 @@ export function TaskFilterBar({
</span> </span>
</label> </label>
)} )}
<MultiSelectDropdown
label="Funcionario"
allLabel="Todos os funcionarios"
options={assignees.map((assignee) => ({
value: assignee.id,
label: assignee.name,
icon: <UserAvatar name={assignee.name} photo={assignee.photo} size="sm" />,
}))}
selected={filters.userIds}
onChange={(userIds) => update({ userIds })}
/>
</div> </div>
)} )}
{categories.length > 0 && (
<div className="flex items-center gap-2">
<Filter size={16} className="shrink-0 text-text-muted" />
<span className="text-[10px] font-black uppercase tracking-widest text-text-muted whitespace-nowrap">Categorias</span>
<MultiSelectChips
options={categories.map((c) => ({
value: c.id,
label: c.name,
color: c.color,
icon: <CategoryIcon iconName={c.icon} size={14} />,
}))}
selected={filters.categoryIds}
onChange={(categoryIds) => update({ categoryIds })}
/>
</div> </div>
)}
</div> </div>
) )
} }