fix(reports): render category combobox in hierarchical DFS order (#126) #134
No reviewers
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#134
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-126-category-combobox-presentation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #126
Root cause
The by-category report (
/reports/category) pulls categories viagetAllCategoriesWithCounts()(insrc/services/categoryService.ts), whose SQL ends withORDER BY c.sort_order, c.name. That is a global sort — two distinct roots that sharesort_order=1would be followed by their respective sub-trees, all bucketed by depth-agnosticsort_order. The combobox was then applying an indent proportional to each row'sdepth, producing exactly what the user reported: indentation that doesn't follow the visual order, and parents / children from different sub-trees sitting side by side.Fix
sortHierarchical(categories, resolveName)exported fromsrc/components/shared/CategoryCombobox.tsx. It re-orders the flat list into a DFS walk: for each group of siblings (sameparent_id), sort bysort_orderascending then localized display name, then emit the parent immediately followed by its whole sub-tree.useMemokeyed on(categories, displayName)and uses the ordered list both for rendering and for the accent-insensitive filter.Coverage
src/components/shared/CategoryCombobox.test.ts— 7 unit tests onsortHierarchical:sort_order+ name tiebreak on siblings,Verification
npx tsc --noEmit— cleannpx vitest run— 23 files / 338 tests passnpm run build— greenChangelog
Entry added under
## [Unreleased] / ### Fixedin bothCHANGELOG.mdandCHANGELOG.fr.md.Scope note
The fix is isolated to
CategoryCombobox(consumer-side sort) rather than changing the SQL query. That keeps other callers ofgetAllCategoriesWithCountsunaffected and avoids coupling the SQL to a specific presentation order.🤖 Generated with Claude Code
Self-review — APPROVE
Verdict: APPROVE.
Correctness
sortHierarchicalgroups byparent_id, sorts each sibling bucket by(sort_order, localized name), then emits a DFS walk from roots. Parent always precedes its descendants, each sub-tree stays contiguous.visitedset.No regression
categoriestoorderedCategories— already-filtered items keep the correct parent-first order.computeDepthsand indent rendering are untouched; depths are keyed oncat.idso reordering is transparent to the indent logic.totalItems,highlightIndex) uses the reorderedfilteredlist seamlessly.CategoryCombobox(TransactionFilterBar,TransactionTable,SplitAdjustmentModal) get the same DFS re-order for free; if their input was already ordered the idempotence guarantee applies.i18n
displayName(which already resolvesi18n_keyviat(...)withnamefallback).Changelog
CHANGELOG.md—## [Unreleased] / ### Fixedentry with (#126). ✓CHANGELOG.fr.md—## [Non publié] / ### Corrigéentry with (#126). ✓CI gates
npx tsc --noEmit— cleannpx vitest run— 23 files / 338 tests pass (including the 7 new helper tests)npm run build— greenScope
categoryService.getAllCategoriesWithCountsis untouched, avoiding coupling the service to any specific ordering.Ready to merge.