fix: display level 4+ categories under their parent in dashboard (#23) #28
No reviewers
Labels
No labels
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#28
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/simpl-resultat-23-dashboard-category-ordering"
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 #23
Summary
buildSubGrouprecursive to support arbitrary nesting depth (was hardcoded to 3 levels max)Files changed
src/services/budgetService.ts— RecursivebuildSubGroup, tree-order sort, removed broken flat sortsrc/shared/types/index.ts—depthtype changed from0|1|2tonumbersrc/components/reports/BudgetVsActualTable.tsx— Support depth 3+ paddingsrc/components/budget/BudgetTable.tsx— Type constraint updatesrc/components/dashboard/CategoryPieChart.tsx— Removed legend, reduced heightsrc/pages/DashboardPage.tsx— 3-column grid layoutCHANGELOG.md/CHANGELOG.fr.md— Changelog entriesReviewer automatique — needs-fix
La logique récursive dans budgetService.ts semble correcte pour la construction de l'arbre, mais reorderRows() dans BudgetVsActualTable et BudgetTable ne gère que depth 0-1 pour le réordonnancement des sous-totaux — ce qui casse le toggle 'subtotals on bottom' pour les niveaux 2+. Aucun test n'est ajouté pour cette refonte significative. La suppression complète de la légende du PieChart va au-delà de ce que l'issue demandait.
Suggestions de simplification
lg:col-span-1(ligne 130) est la valeur par défaut dans une grille CSS et peut être supprimée — elle n'a aucun effet.Problèmes détectés
(child.depth ?? 0) === 0et=== 1). Avec la nouvelle profondeur arbitraire, un parent de depth 2+ ne sera jamais reconnu comme sub-parent → quand subtotalsOnTop=false, les sous-totaux de niveau 2+ resteront en haut de leur groupe au lieu d'être déplacés en bas. Il faut rendre cette logique récursive ou au minimum gérer tous les niveaux de depth.numbermais la logique de reorderRows (identique) ne gère toujours que depth 0 et 1. Le BudgetTable a probablement une copie de la même fonction — les deux doivent être corrigées ensemble.pl-20). Toutes les profondeurs 3, 4, 5... auront la même indentation. Pour supporter réellement une profondeur arbitraire, utiliser un padding calculé dynamiquement serait plus cohérent :style={{ paddingLeft: depth * 24 + 12 }}ou équivalent Tailwind.Reviewer automatique — needs-fix
La récursion dans reorderRows et buildSubGroup est correcte et résout l'issue #23. Cependant, la suppression du tri alphabétique des enfants dans budgetService.ts est une régression potentielle, le styling des parents intermédiaires depth 2+ est ignoré, et aucun test n'a été ajouté malgré le signalement en round 1.
Suggestions de simplification
depth >= 3 ? "pl-20"plafonne l'indentation visuelle à un seul niveau pour toutes les profondeurs >= 3. Si on supporte une profondeur arbitraire, calculer dynamiquement le padding :pl-${8 + depth * 6}ou utiliser un style inlinepaddingLeft: ${depth * 1.5}rem.Problèmes détectés
allChildRows.sort(...)a été entièrement supprimé. L'ancien code triait les enfants alphabétiquement avec '(direct)' en premier. Maintenant l'ordre dépend de l'ordre d'itération dechildrenretourné parchildrenByParent, qui est l'ordre d'insertion dans la boucle ligne 237 — donc l'ordre brut deallCategories. Si cet ordre n'est pas garanti stable (ex: requête SQL sans ORDER BY), l'affichage sera non-déterministe. Au minimum, trierchildrenparsort_orderpuisnameavant d'itérer, comme le faisait implicitement l'ancien code.isIntermediateParentest toujours codé en dur àdepth === 1. Avec le support de profondeurs arbitraires, les parents à depth 2+ ne recevront pas le styling intermédiaire (bold atténué, etc.). Devrait êtreisParent && depth > 0ouisParent && depth >= 1.buildSubtotalreçoitleafRows(ligne 399) filtré par!r.is_parent, mais dansbuildSubGroup(ligne 357) il reçoit aussileafRowsfiltré localement. Si un sous-groupe contient un row '(direct)' avec le mêmecategory_idque le parent, ce row sera compté à la fois dans le subtotal du sous-groupe ET dans le subtotal du groupe parent — risque de double-comptage. Vérifier avec un scénario où un parent intermédiaireis_inputablea aussi des enfants inputables.buildSubGroupetreorderRowsest non triviale — un test avec 4 niveaux de profondeur (le cas exact de l'issue) est indispensable pour éviter les régressions. Ajouter au minimum : (1) test buildSubGroup avec depth 0→3, (2) test reorderRows avec subtotalsOnTop=false et depth 3+, (3) test que les montants des subtotals ne double-comptent pas.Reviewer automatique — needs-fix
La refactorisation récursive résout correctement l'issue #23 et la déduplication de reorderRows est bienvenue. Cependant, le subtotal des parents intermédiaires ne comptabilise que les feuilles directes et ignore les sous-totaux imbriqués, ce qui peut produire des montants incorrects pour les hiérarchies profondes. La légende cachée par défaut (opacity-0) dégrade l'UX en rendant les catégories invisibles sans interaction.
Suggestions de simplification
depthPaddingClass(depth: number, isParent: boolean)ou au minimum une constante partagée pour éviter la divergence entre les deux.Problèmes détectés
childRows.filter(r => !r.is_parent)récupère toutes les feuilles de l'arbre aplati, ce qui est correct pour la somme MAIS seulement si chaque feuille n'apparaît qu'une fois dans childRows. Vérifier que les feuilles d'un sous-sous-groupe (depth 3+) ne sont pas comptées en double quand elles remontent via buildSubGroup récursif. Le même pattern est utilisé ligne 402 pour le top-level — même risque.opacity-0 pointer-events-nonepar défaut et ne s'affiche qu'au survol du graphique. L'issue demandait 'afficher seulement les étiquettes quand on survole le graph' — ce qui se réfère aux labels sur le graphique, pas à la légende entière. Cacher la légende par défaut rend impossible l'identification des catégories sans interaction. Suggestion : garder la légende visible en permanence et utiliser le tooltip de Recharts (déjà implémenté) pour les valeurs détaillées au survol, ou afficher les labels directement sur les slices au hover.Reviewer automatique — needs-simplify
La refactorisation récursive est correcte et résout l'issue #23. Les problèmes des rounds précédents (subtotals multi-niveaux, tri alphabétique, légende PieChart) sont tous corrigés. La déduplication de reorderRows dans un utilitaire partagé est bienvenue. Reste l'absence persistante de tests unitaires et quelques simplifications possibles.
Suggestions de simplification
depthPaddingClass(depth: number): stringdans un fichier partagé (ou à côté de reorderRows) pour éviter cette duplication.isChartHoveredcontrôle l'affichage des pourcentages dans la légende. Comme la légende est positionnée SOUS le chart (pas à l'intérieur du div onMouseEnter/Leave), survoler la légende elle-même ne déclenche pas isChartHovered — les pourcentages disparaissent quand l'utilisateur survole les noms de catégories. Envisager de remonter le onMouseEnter/Leave au conteneur parent englobant chart + légende, ou d'afficher les pourcentages en permanence (plus simple et plus accessible).