feat: drag-and-drop reorder for budget categories and items (#479)

Add reordering support for budget categories and line items within
categories. Changes persist via new DB table (budget_category_order)
and existing sort_order column. Live sync via WebSocket budget:reordered
event. Use Map instead of plain objects for category grouping to
preserve insertion order with numeric category names.
This commit is contained in:
Maurice
2026-04-09 19:21:43 +02:00
parent 1f3e27765a
commit 5c0d819fc1
7 changed files with 293 additions and 24 deletions
+20
View File
@@ -864,6 +864,26 @@ function runMigrations(db: Database.Database): void {
for (const d of matchingDays) ins.run(r.id, d.id, r.day_plan_position);
}
},
// Migration: Budget category ordering
() => {
db.exec(`
CREATE TABLE IF NOT EXISTS budget_category_order (
trip_id INTEGER NOT NULL REFERENCES trips(id) ON DELETE CASCADE,
category TEXT NOT NULL,
sort_order INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (trip_id, category)
);
`);
// Seed existing categories with alphabetical order
const rows = db.prepare('SELECT DISTINCT trip_id, category FROM budget_items ORDER BY trip_id, category').all() as { trip_id: number; category: string }[];
const ins = db.prepare('INSERT OR IGNORE INTO budget_category_order (trip_id, category, sort_order) VALUES (?, ?, ?)');
let lastTripId = -1;
let idx = 0;
for (const r of rows) {
if (r.trip_id !== lastTripId) { lastTripId = r.trip_id; idx = 0; }
ins.run(r.trip_id, r.category, idx++);
}
},
];
if (currentVersion < migrations.length) {