Commit Graph

42 Commits

Author SHA1 Message Date
48dd5a51bc Merge pull request 'Docs: backfill JSDoc, utility docs, and CLAUDE.md API/schema sections' (#6) from docs/backfill-missing-documentation into master
Reviewed-on: #6
2026-03-20 08:30:46 -07:00
11476086cd Docs: backfill JSDoc, utility docs, and CLAUDE.md API/schema sections
- Add JSDoc to paychecks.js helpers: buildVirtualPaychecks, generatePaychecks, fetchPaychecksForMonth
- Add JSDoc to financing.js helpers: remainingPeriods, calcPaymentAmount, enrichPlan
- Add JSDoc to validateBillFields (bills.js) and getAllConfig (config.js)
- Add JSDoc to ThemeProvider and useTheme in ThemeContext.jsx
- Add Database Schema reference table to CLAUDE.md
- Add complete API Endpoints reference section to CLAUDE.md covering all routes

Nightshift-Task: docs-backfill
Nightshift-Ref: https://github.com/marcus/nightshift
2026-03-20 02:54:45 -04:00
ccd0fb2155 Add component tests for Bills, Financing, Settings, MonthlySummary, AnnualOverview
62 client tests now passing across 8 test files. Handles duplicate text in
stat cards vs summary tables using getAllByText, and error states via ok:false
mock responses to trigger component-level error messages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:32:17 -04:00
bb2038c58c Add PaycheckView unit tests
Export ordinal/formatCurrency/formatPayDate for direct testing. Tests cover
pure function formatting, virtual/saved rendering, preview banner, error state,
month navigation (including year wrap), bill display, remaining balance, and
gross/net amounts. Uses vi.useFakeTimers({ toFake: ['Date'] }) to control
current date without faking setTimeout (which would break RTL's waitFor).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:19:58 -04:00
be410d7d88 Add one-time expenses, config, and summary route unit tests
one-time-expenses: POST validation (paycheck_id/name/amount), DELETE, PATCH paid toggle.
config: GET (defaults for missing keys), PUT (transaction, ignores unknown keys).
summary: GET monthly (zeros when no paychecks, full aggregates), GET annual (per-month breakdown).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:16:00 -04:00
666acb65fa Add financing route unit tests
Tests cover remainingPeriods pure function (single/split plans, boundary
cases), GET/POST/GET:id/PUT/DELETE /api/financing, and
PATCH /api/financing-payments/:id/paid including auto-close when fully paid.
Uses mid-month dates in pure function tests to avoid UTC timezone boundary issues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:10:44 -04:00
1106ec770c Add paychecks route unit tests
Tests cover GET /api/paychecks (virtual + saved), GET /api/paychecks/months,
POST /api/paychecks/generate, PATCH /api/paychecks/:id (gross/net),
PATCH /api/paycheck-bills/:id/amount, and PATCH /api/paycheck-bills/:id/paid
(paid toggle + amount_override locking).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:08:49 -04:00
d338283d8f Add missed migration for financing start_date column
This migration was part of the financing start_date feature (119d53c) but
was not staged by the previous agent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 21:04:12 -04:00
e9f5a48f2d Add unit testing infrastructure with Vitest
Set up Vitest for both server (Node + Supertest) and client (jsdom + React
Testing Library). Extract Express app into app.js for testability. Add example
tests covering bills validation, bills route CRUD, ThemeContext, and App nav
rendering. Update CLAUDE.md with testing docs and requirement to write tests
with features.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 21:03:29 -04:00
10f8debdf5 Clarify td approve requires a separate session, not just a sub-agent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:43:09 -04:00
6e771ad20b Fix variable bill amount lost on paid toggle; revert gross/net protection
- PATCH paycheck-bills/:id/paid: variable bills now preserve amount_override
  rather than overwriting it with b.amount (which may be null/0). Fixed bills
  continue to lock in b.amount on paid and clear on unpaid.
- generatePaychecks: revert gross/net protection — refresh always updates
  gross/net from current settings as originally intended.
- CLAUDE.md: remove gross/net protection note; add td approve sub-agent rule.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:41:57 -04:00
5aaa5cfed8 Fix timezone hazard in financing start_date guard
Replace new Date(date_string) + getFullYear/getMonth with direct string
parsing (split('-').map(Number)) so month comparisons are never shifted
by UTC offset. Affects both buildVirtualPaychecks and generatePaychecks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:39:47 -04:00
119d53c33a Add start_date to financing plans and protect paid paychecks from refresh
- Migration 004: adds start_date column to financing_plans (DEFAULT CURRENT_DATE)
- generatePaychecks: skips financing plans whose start_date is after the target month
- buildVirtualPaychecks: same start_date guard for virtual previews (already applied)
- generatePaychecks upsert: preserves gross/net when paycheck has any paid bills
- financing.js POST/PUT: accept and store start_date
- Financing.jsx: add Start Date field to create/edit form (defaults to today)
- CLAUDE.md: document start_date guard and paid-paycheck refresh protection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:37:37 -04:00
72c2e0a0c7 Enforce doc updates and single td commands per invocation in CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:30:07 -04:00
be827f6d92 Update CLAUDE.md with variable bills, lazy generation, and financing docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:29:07 -04:00
2d152f301d Add special financing feature
Data model:
- Migration 003: financing_plans and financing_payments tables
- Plans track total amount, due date, paycheck assignment (1, 2, or split)
- Payments linked to paycheck records, one per period

Payment calculation:
- Auto-calculated: (total - paid_so_far) / remaining_periods
- Split plans halve the per-period amount across both paychecks
- Recalculates each period as payments are made

Financing page (/financing):
- Create/edit/delete plans with name, amount, due date, paycheck assignment
- Progress bar showing paid vs total
- Overdue badge when past due with remaining balance
- Paid-off plans moved to a separate section

Paycheck view:
- New Financing section per column with payment checkbox
- Overdue badge on individual payments
- Running paid/total shown in bill meta
- Financing payments included in remaining balance calculation
- Auto-closes plan and reloads when fully paid off
- Lazy generation works: first interaction generates paycheck and payment records

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:28:09 -04:00
45383b80cf Add variable amount bills
- Migration 002: variable_amount boolean column on bills (default false)
- Bills form: 'Variable amount' checkbox; amount field becomes optional
  'Typical amount' when checked; table shows 'varies (~$X)' and a 〜 badge
- Paycheck view: variable bills show a pencil edit button to enter the
  month's actual amount, stored as amount_override on paycheck_bills
- New PATCH /api/paycheck-bills/:id/amount endpoint
- Lazy generation still works: setting an amount on a virtual paycheck
  generates it first then saves the override

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:14:08 -04:00
3bac852a40 Lazy paycheck generation, regenerate button, inline gross/net edit
- GET /api/paychecks returns virtual data (id: null) without writing to
  DB when no records exist for the month
- First interaction (bill toggle, OTE add, actual add) lazily calls
  POST /api/paychecks/generate to persist the paycheck
- New PATCH /api/paychecks/:id to update gross and net
- Regenerate/refresh button syncs gross/net from current Settings
- Inline pencil edit for gross/net on each paycheck column header
- 'preview' badge and info banner shown for unsaved months

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:06:41 -04:00
c132e1a5fe Update CLAUDE.md with theming, charts, and bill locking notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:59:14 -04:00
195a36c8a5 Add Recharts charts to Monthly Summary and Annual Overview
Monthly Summary:
- Spending breakdown donut (bills / variable / one-time)
- Variable spending by category bar chart
- Added actuals.by_category to /api/summary/monthly response

Annual Overview:
- Income vs. spending grouped bar chart
- Surplus/deficit bar chart (green/red per month)
- Stacked variable spending by category across all months
- New /api/summary/annual endpoint (single DB round trip for full year)
- AnnualOverview now uses /api/summary/annual instead of 12 parallel calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:58:50 -04:00
ea2ee9c5e6 Lock bill amount_override when marked paid, clear on unpaid
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:53:46 -04:00
00b55338af Fix pay_date NaN: parse DATE columns as strings in pg
pg returns DATE columns as JS Date objects which serialize to ISO
timestamps, causing split('-') to produce NaN for the day portion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:51:05 -04:00
db541b4147 Add modern UI with light/dark mode
- CSS custom properties design system with full light/dark themes
- ThemeContext with localStorage persistence and system preference detection
- Theme toggle button in nav (moon/sun icon)
- Modern Inter font, card-based layout, sticky nav
- All pages restyled with CSS classes instead of inline styles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:47:34 -04:00
16ba4166f2 Document td concurrency rule in CLAUDE.md and AGENTS.md
Sub-agents must never call td commands directly. Concurrent writes
from parallel agents corrupt the SQLite database. Only the
orchestrator manages td task lifecycle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:33:21 -04:00
3d41c623bc Fix dev compose: npm install on container startup
The ./server bind mount overwrites /app/server including node_modules
installed during the Docker build. Running npm install on startup
ensures deps are present after the volume mount.

Also reverts the node_modules named-volume workaround in favor of
this cleaner approach (requires node installed locally for non-Docker dev).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:27:52 -04:00
e98abe632a Fix dev compose: preserve node_modules via named volumes
Mounting ./server:/app/server overwrote the npm-installed node_modules
from the Docker build. Named volumes for server/client node_modules
shadow the bind mount so installed packages are preserved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:24:37 -04:00
6cf7f36f0e Add .dockerignore and fix stale build cache
.dockerignore prevents node_modules and dist from leaking into the
build context, which could silently overwrite npm-installed packages.
Forced no-cache rebuild confirms dotenv and all deps install cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:23:11 -04:00
0c39eec2a9 Fix build issues found during Docker validation
- Dockerfile: add COPY db/ /app/db/ so migrations are available at
  runtime (server/src/db.js requires ../../db/migrations at startup)
- vite.config.js: fix dev proxy port from 3001 to 3000 to match
  server's default PORT

Docker build passes; server starts and connects to DB correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:21:14 -04:00
35f9be4b02 Add monthly summary and annual overview (Phase 4)
Monthly summary:
- GET /api/summary/monthly returns income, bills, actuals, one-time
  expense totals and surplus/deficit for a given month
- MonthlySummary page shows stat cards and breakdown table

Annual overview:
- AnnualOverview page fetches all 12 months in parallel via Promise.all
- Year navigation, summary cards, monthly table with totals row
- Fix: normalize nested API response to flat fields expected by component

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:16:08 -04:00
22b1cfbe6b Add monthly summary view
GET /api/summary/monthly returns income, bills, actuals,
and one-time expense totals. Summary page shows stat cards
and a breakdown table with surplus/deficit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:15:25 -04:00
3d8cdc9068 Add annual overview page
Year-at-a-glance table with monthly income, bills, variable
spending, and surplus/deficit. Fetches all 12 months in parallel.
Summary cards show annual totals.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:15:08 -04:00
368786a9e1 Add one-time expenses UI and merge Phase 3 features
- One-time expenses: paid toggle, delete, and inline add form in
  paycheck columns (wired to POST/DELETE/PATCH /api/one-time-expenses)
- Variable spending actuals section with category select, amount,
  note, date fields; actuals included in remaining balance
- Both Phase 3 features fully integrated into PaycheckView

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:13:32 -04:00
17af71a7c7 Add variable expense actuals logging
API for expense categories and actuals with full CRUD.
Paycheck view shows actuals section and includes them in
remaining balance calculation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:12:25 -04:00
9ada36deda Add one-time expenses per paycheck
API for adding, removing, and marking one-time expenses paid.
Paycheck view supports inline add form and paid/delete actions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:12:07 -04:00
8a9844cf72 Add paycheck-centric main view
Two-column monthly view showing bills, amounts, paid status,
and remaining balance per paycheck. Month navigation included.
Also adds PATCH /api/paycheck-bills/:id/paid endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:09:51 -04:00
afe3895210 Add paycheck generation and retrieval API
Auto-generates paycheck records from config and active bills.
GET /api/paychecks auto-generates if month not yet created.
Idempotent generation preserves existing paid status.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:08:03 -04:00
0835b86c1a Add bills CRUD API and management UI
Full REST API for bill definitions with validation.
Bills page supports add, edit, toggle active, and delete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:06:43 -04:00
5f5f1111c5 Add config API and settings UI
GET/PUT /api/config for pay dates and amounts.
Settings page fetches and saves configuration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:04:33 -04:00
adebe10f52 Add PostgreSQL schema and migration runner
All tables per PRD data model with default config seeds.
Migration runner tracks applied migrations in DB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:03:57 -04:00
83abac52f6 Add Docker Compose project scaffold
Sets up the full monorepo structure with:
- Multi-stage Dockerfile (client-build + production stages)
- docker-compose.yml for production, docker-compose.dev.yml overlay for development
- Express server (port 3000) with pg pool, health route, and SPA static file serving
- React 18 + Vite client with react-router-dom v6, nav bar, and placeholder page components
- .env.example with PostgreSQL and app config
- Empty db/migrations/ directory for future migrations
- CLAUDE.md updated with development workflow commands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:02:17 -04:00
24d22ad850 Add agent workflow rules to CLAUDE.md
Document commit-per-task, documentation hygiene, and td lifecycle requirements
for all agents working in this repo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:57:48 -04:00
0a88bb3d12 Add project docs and initial configuration
- PRD.md: full product requirements for the budget app
- CLAUDE.md: repo guidance including td task management workflow
- AGENTS.md: session startup instructions
- .gitignore: comprehensive ignore rules for Node/React/Docker/editor artifacts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:56:20 -04:00