feat: add monthly budget tracker to dashboard#18
Merged
Merged
Conversation
Adds BudgetSettings/BudgetRepo interface, SqliteBudgetRepo implementation, migration v3 creating the budget_settings table, wires repo into createSqliteRepos, and updates all test stubs to satisfy the Repos interface. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renders a Budget$ row in the stats bar showing pace badge (ahead/over/on-track), remaining amount+%, and reset date. Wired into both page and stats routes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Allow async handle() in RouteHandler interface (backward-compatible) - Implement createBudgetRoute: GET 404/200, POST 200/400 with validation - Wire budget route in dashboard/index.ts before stats route - Update routes.test.ts to await handle() calls for TS compatibility Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Gear button in header opens a dialog with amount, work-day toggles (Mo–So, German labels), and period-start-day input. openBudgetModal() loads existing budget via GET /api/budget; saveBudget() POSTs and calls refresh(). Tests assert gear-btn, budget-modal, and day-toggle elements are present in rendered HTML. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
POST /api/budget now rejects amount < 0 or non-finite, workDays > 127, and periodStartDay outside 1-28 with 400. saveBudget() checks res.ok and catches network errors, showing inline error instead of silently closing the modal on failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Center modal with margin:auto on dialog element - Replace gear icon with credit-card SVG + "Budget" label - Period row: compact layout (one line) with dynamic hint below showing "ends last day of month" or "ends Nth of next month" - Fix resetDate to use periodStartDay instead of hardcoded day 1 - Add test: periodStartDay=5 produces resetDate on day 5 of next month Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
budget_settingsSQLite table (single-row) to persist monthly budget amount, work-day bitmask, and period start daycalcBudgetStatus()prorates budget by elapsed work days and returns pace delta, remaining amount, and reset dateOverall$stats bar:[Budget$] [▲/▼/● pace] $X left · Y% Resets Aug 1GET /POST /api/budgetendpoints to read/write settings⚙in dashboard header opens a<dialog>modal with amount input, work-day toggles (Mo–So), and period start fieldTest plan
⚙next to "took Xms" — modal opens[Budget$]row appears belowOverall$with correct pace label (ahead/on-track/over)▼ overbadge in orange🤖 Generated with Claude Code