/** * Shared utility for reordering budget table rows. * Recursively moves subtotal (parent) rows below their children * at every depth level when "subtotals on bottom" is enabled. * * The generic constraint only requires the two fields the algorithm actually * reads (`is_parent`, `depth`) so it works for both the budget rows (required * `is_parent`) and the Compare `CategoryDelta` rows (optional `is_parent`). */ export function reorderRows< T extends { is_parent?: boolean; depth?: number }, >(rows: T[], subtotalsOnTop: boolean): T[] { if (subtotalsOnTop) return rows; function reorderGroup(groupRows: T[], parentDepth: number): T[] { const result: T[] = []; let currentParent: T | null = null; let currentChildren: T[] = []; for (const row of groupRows) { if (row.is_parent && (row.depth ?? 0) === parentDepth) { // Flush previous group if (currentParent) { result.push(...reorderGroup(currentChildren, parentDepth + 1), currentParent); currentChildren = []; } currentParent = row; } else if (currentParent) { currentChildren.push(row); } else { result.push(row); } } // Flush last group if (currentParent) { result.push(...reorderGroup(currentChildren, parentDepth + 1), currentParent); } return result; } return reorderGroup(rows, 0); }