feat(ideas): vervang inline statuschips door IdeasFilterPopover met user-settings persistentie
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b8eb724d17
commit
e398b84930
1 changed files with 26 additions and 28 deletions
|
|
@ -12,6 +12,10 @@ import { useMemo, useState, useTransition } from 'react'
|
|||
import { useRouter } from 'next/navigation'
|
||||
import { Plus, ArrowUp, ArrowDown, ArrowUpDown } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
|
||||
import { useUserSettingsStore } from '@/stores/user-settings/store'
|
||||
import { IdeasFilterPopover } from '@/components/ideas/ideas-filter-popover'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
|
@ -122,7 +126,11 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
|
|||
// Filter state
|
||||
const [search, setSearch] = useState('')
|
||||
const [productFilter, setProductFilter] = useState<string>('all')
|
||||
const [statusFilter, setStatusFilter] = useState<Set<IdeaStatusApi>>(new Set())
|
||||
const filterStatuses = useUserSettingsStore(useShallow(
|
||||
(s) => s.entities.settings.views?.ideasList?.filterStatuses ?? []))
|
||||
const setPref = useUserSettingsStore((s) => s.setPref)
|
||||
const statusFilter = useMemo(() => new Set(filterStatuses), [filterStatuses])
|
||||
const [filterPopoverOpen, setFilterPopoverOpen] = useState(false)
|
||||
|
||||
// Sort state
|
||||
const [sortKey, setSortKey] = useState<SortKey>('code')
|
||||
|
|
@ -197,12 +205,14 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
|
|||
}
|
||||
|
||||
function toggleStatus(s: IdeaStatusApi) {
|
||||
setStatusFilter((prev) => {
|
||||
const next = new Set(prev)
|
||||
if (next.has(s)) next.delete(s)
|
||||
else next.add(s)
|
||||
return next
|
||||
})
|
||||
const next = filterStatuses.includes(s)
|
||||
? filterStatuses.filter((v) => v !== s)
|
||||
: [...filterStatuses, s]
|
||||
void setPref(['views', 'ideasList', 'filterStatuses'], next)
|
||||
}
|
||||
|
||||
function clearStatusFilter() {
|
||||
void setPref(['views', 'ideasList', 'filterStatuses'], [])
|
||||
}
|
||||
|
||||
function handleCreate() {
|
||||
|
|
@ -289,6 +299,15 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
|
|||
))}
|
||||
</select>
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<IdeasFilterPopover
|
||||
open={filterPopoverOpen}
|
||||
onOpenChange={setFilterPopoverOpen}
|
||||
statusOptions={STATUS_FILTERS}
|
||||
selected={statusFilter}
|
||||
onToggle={toggleStatus}
|
||||
onClear={clearStatusFilter}
|
||||
activeFilterCount={statusFilter.size}
|
||||
/>
|
||||
<DemoTooltip show={isDemo}>
|
||||
<Button
|
||||
size="sm"
|
||||
|
|
@ -313,27 +332,6 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Status-chips als multi-select filter */}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{STATUS_FILTERS.map((s) => {
|
||||
const active = statusFilter.has(s.value)
|
||||
return (
|
||||
<button
|
||||
key={s.value}
|
||||
type="button"
|
||||
onClick={() => toggleStatus(s.value)}
|
||||
className={`rounded-full border px-2.5 py-0.5 text-xs transition-colors ${
|
||||
active
|
||||
? 'bg-primary text-on-primary border-primary'
|
||||
: 'bg-background text-muted-foreground border-input hover:bg-muted'
|
||||
}`}
|
||||
>
|
||||
{s.label}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Snel idee form — geen product-dropdown */}
|
||||
{showQuick && (
|
||||
<div className="rounded-md border border-input bg-surface-container p-4 space-y-3">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue