feat(ui): make task filter bar collapsible
This commit is contained in:
parent
c4828a0a77
commit
b05ff9651a
1 changed files with 40 additions and 9 deletions
|
|
@ -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>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
onClick={() => setIsExpanded(!isExpanded)}
|
||||||
|
className={`flex h-11 items-center gap-2 rounded-xl px-4 text-sm font-medium transition-all ${
|
||||||
|
isExpanded || activeFiltersCount > 0
|
||||||
|
? 'bg-brand/10 text-brand'
|
||||||
|
: 'bg-app-bg text-text-muted hover:bg-surface-muted hover:text-brand'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
|
||||||
{onRefresh && (
|
{onRefresh && (
|
||||||
<button
|
<button
|
||||||
onClick={onRefresh}
|
onClick={onRefresh}
|
||||||
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 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"
|
title="Recarregar"
|
||||||
>
|
>
|
||||||
<RefreshCw size={18} className={isLoading ? 'animate-spin' : ''} />
|
<RefreshCw size={18} className={isLoading ? 'animate-spin' : ''} />
|
||||||
</button>
|
</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"
|
||||||
|
|
@ -144,6 +174,7 @@ export function TaskFilterBar({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue