ST-1230: Sorteerstate en -logica toevoegen aan IdeaList (#126)

* feat(ideas): STATUS_SORT_ORDER + sorteerstate (ST-cmotjj9uf000104l5i70so19b)

- Voeg STATUS_SORT_ORDER toe: workflow-volgorde map (draft→plan_failed)
- Zet standaard sortDir op 'desc' conform AC (code aflopend bij laden)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(ideas): sorted useMemo + tabel-render koppelen (ST-cmotjj9uf000104l5i70so19b)

- Voeg sorted useMemo toe na filtered: locale-aware sort met STATUS_SORT_ORDER
- Ideeën zonder product sorteren achteraan bij oplopende productsortering
- Vervang filtered.length/filtered.map door sorted in tabel-render

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-06 07:24:20 +02:00 committed by GitHub
parent 6015357905
commit a28f0249e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -70,6 +70,11 @@ const STATUS_FILTERS: { value: IdeaStatusApi; label: string }[] = [
{ value: 'plan_failed', label: 'Plan mislukt' },
]
const STATUS_SORT_ORDER: Record<IdeaStatusApi, number> = {
draft: 0, grilling: 1, grilled: 2, planning: 3,
plan_ready: 4, planned: 5, grill_failed: 6, plan_failed: 7,
}
function SortHeader({
col,
label,
@ -113,7 +118,7 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
// Sort state
const [sortKey, setSortKey] = useState<SortKey>('code')
const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc')
const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')
// Create-form state
const [showCreate, setShowCreate] = useState(false)
@ -149,6 +154,26 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
})
}, [ideas, search, productFilter, statusFilter, sortKey, sortDir])
const sorted = useMemo(() => {
return [...filtered].sort((a, b) => {
let cmp = 0
if (sortKey === 'code') {
cmp = (a.code ?? '').localeCompare(b.code ?? '', 'nl', { numeric: true })
} else if (sortKey === 'title') {
cmp = a.title.localeCompare(b.title, 'nl')
} else if (sortKey === 'product') {
const aN = a.product?.name ?? ''
const bN = b.product?.name ?? ''
if (!aN && bN) return sortDir === 'asc' ? 1 : -1
if (aN && !bN) return sortDir === 'asc' ? -1 : 1
cmp = aN.localeCompare(bN, 'nl')
} else {
cmp = (STATUS_SORT_ORDER[a.status] ?? 99) - (STATUS_SORT_ORDER[b.status] ?? 99)
}
return sortDir === 'asc' ? cmp : -cmp
})
}, [filtered, sortKey, sortDir])
function handleSort(col: SortKey) {
if (sortKey === col) {
setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))
@ -311,7 +336,7 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
)}
{/* Tabel */}
{filtered.length === 0 ? (
{sorted.length === 0 ? (
<p className="text-sm text-muted-foreground py-8 text-center">
{ideas.length === 0
? 'Nog geen ideeën — start hierboven met "Nieuw idee".'
@ -329,7 +354,7 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
</TableRow>
</TableHeader>
<TableBody>
{filtered.map((idea) => {
{sorted.map((idea) => {
const badge = getIdeaStatusBadge(API_TO_DB[idea.status])
return (
<TableRow