100 Commits

Author SHA1 Message Date
TehRiehlDeal 5a64cf649e Drill into category transactions by clicking the dashboard pie chart
Clicking a slice on the Spending by Category chart navigates to
/transactions?categoryId=<id>. The Transactions page reads that param as
its initial filter on mount (and strips it from the URL afterwards so
refreshes behave predictably, matching the existing `new=1` handling).

Also adds an explicit Category filter Select next to the existing
Account / Type filters so the user can change or clear the filter
in-page, and gives the pie slices a pointer cursor to signal they're
interactive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 15:17:27 -07:00
TehRiehlDeal e5bc486e77 Space balance chart points equidistantly instead of by real time
The previous fix gave each point a unique x-axis timestamp so the tooltip
could disambiguate same-day entries, but that caused real-time-scale
spacing: transactions clustered minutes apart became impossible to click
on individually. The desired behavior is equidistant slots for display,
with the x value only needing to be unique for tooltip hit-testing.

Switches the balance chart to a categorical x-axis keyed on the point's
array index (computed on the frontend after fetching). The tick formatter
looks up the date from the history array at that index so labels still
show the calendar date. Each point occupies its own evenly-spaced slot
and hover correctly identifies the specific point. The backend's now-
unused `timestamp` field is removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 10:51:43 -07:00
TehRiehlDeal 4f918fc14a Give each balance chart point a unique x-axis timestamp
Recharts picks one payload entry per x-axis value for its tooltip, so
when multiple transactions shared the same YYYY-MM-DD date, hovering any
of them surfaced only the first one's description — making the new
transaction-context tooltip misleading for same-day entries.

Each point now carries a millisecond `timestamp` (from the transaction's
createdAt for transaction-driven charts, or the valuation's date for
market-value charts, plus the request time for the "today" bookend).
The balance chart x-axis switches to a numeric time scale keyed on
timestamp, so same-day points sit at distinct x positions and hover
correctly identifies the specific point. The tooltip reads the date
from the point's payload instead of the x-axis label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 10:44:58 -07:00
TehRiehlDeal b6a3dba50e Theme chart tooltips and enrich balance chart with transaction context
Replaces the default white Recharts tooltip (which was jarring in dark
mode) with a themed ChartTooltip component that uses the popover /
foreground / muted-foreground tokens so it adapts to light and dark
themes. Applied to the Spending, Income vs Expense, Cash Flow, and
Balance over time charts for visual consistency.

The Balance over time tooltip now also includes, when the point
corresponds to a transaction, the transaction's description and the
signed balance change (green for inflow, red for outflow). The backend
endpoint was extended to return `description` and `change` alongside
each transaction point.

Also kills the mobile tap-highlight box and focus outline that Recharts
SVG elements render on tap — it was drawing a visible rectangle around
the hit region on touch devices. A short rule in index.css scoped to
.recharts-wrapper / .recharts-surface zeroes both.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 10:37:16 -07:00
TehRiehlDeal 89e7d7c647 Fix same-day ordering and off-by-one labels on balance chart
Two related bugs:

1. Same-day transactions were walked in arbitrary order. The balance-history
   endpoint ordered by `date desc` only; since all same-day transactions
   share a noon-UTC timestamp, Prisma returned them in an undefined order
   and the reverse walk could place income after expenses, making the chart
   dip below the pre-income balance. Adds `createdAt desc` as a secondary
   sort so the walk processes newest-inserted transactions first, which
   produces an oldest-first chart sequence that matches the order the user
   entered them.

2. Chart tick labels and tooltip headers were off by one day. The XAxis
   tickFormatter and Tooltip labelFormatter called `new Date("YYYY-MM-DD")`,
   which parses as midnight UTC — in timezones west of UTC this renders as
   the previous day. Swaps to local-component parsing (tick) and the
   existing `formatDate` helper (tooltip) so labels always match the stored
   calendar date.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 10:26:39 -07:00
TehRiehlDeal 69c9c1aecc Fix dashboard missing transactions on the end date of the range
Transactions are stored at noon UTC (per parseDateInput) so the calendar
date survives timezone shifts, but parseDateRange was constructing the
end boundary via `new Date("YYYY-MM-DD")`, which parses as midnight UTC.
A transaction dated "2026-04-30" (2026-04-30T12:00:00Z) therefore fell
AFTER the filter's `lte` boundary and was silently excluded from the
income/expense, spending-by-category, and cash-flow aggregations for any
range ending on that day.

Rebuilds parseDateRange to explicitly use UTC start-of-day for `gte` and
UTC end-of-day for `lte`, so any transaction on the endpoint day is now
included. Adds a regression test that asserts the Prisma filter range
covers noon UTC on the last day of the range.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 10:09:59 -07:00
TehRiehlDeal 3df88154e2 Fix blank advisor reply by priming a user turn on empty chat
Chat models (Ollama /api/chat) don't generate a reply when given only a
system message — they need a user turn to respond to. The new conversational
flow sent an empty messages array on "Get Advice", so Ollama received
only [system] and returned empty content, which rendered as a blank pill
in the UI. When the client message list is empty, inject a synthetic
opening-prompt user turn so the model always has something to reply to.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 18:53:51 -07:00
TehRiehlDeal 5e04bee05e Make AI advisor conversational and chat-capable
Fixes the "undefined category" bug in generated insights: the PII-strip
filter listed 'name' as sensitive, which wiped category labels like
"Groceries" out of the prompt before it reached the model. Category
names are user-defined labels, not PII, so they're removed from the
filter; a defensive `?? 'Uncategorized'` fallback guards against future
regressions.

The system prompt is rewritten as a friendly first-person persona that
grounds its replies in exact dollar amounts and a month-over-month
comparison (income, expenses, savings rate, top-3 categories for both
months) instead of the previous generic "3-5 numbered tips" format.

Adds a stateless POST /advisor/chat endpoint that accepts the full
client-held message history and replies with the next assistant turn,
rebuilding the financial context on every call. The dashboard card
becomes a mini-chat: user/assistant bubbles, follow-up input, and a
restart button, with auto-scroll to the latest message.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:54:44 -07:00
TehRiehlDeal b5647dca11 Add cash-flow card and range selector to dashboard
Adds a new /aggregations/cash-flow endpoint that reports money entering
and leaving liquid accounts (CHECKING/SAVINGS/CASH) over a period.
Defining outflows as "reduces a liquid account" naturally counts
credit-card and loan payments as outflows while excluding the original
credit-card swipes (which don't touch cash until paid), avoiding
double-counting. Dashboard gains a shared range selector (This month,
Last 30d, Last 90d, YTD) controlling the summary cards, spending, and
the new cash-flow card.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 07:42:29 -07:00
TehRiehlDeal fdcbe2611d Add CASH/INVESTMENT/RETIREMENT account types with market-value tracking
Extends AccountType enum and counts all three new types as assets in net
worth. For STOCK/INVESTMENT/RETIREMENT accounts, adds an AccountValuation
model and /accounts/:id/valuations endpoints so users can log periodic
balance snapshots; the balance-history chart uses those snapshots for
market-value accounts instead of reconstructing from transactions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 22:05:11 -07:00
TehRiehlDeal d04686c1da Fix off-by-one date bug by parsing/displaying dates timezone-independently 2026-04-16 16:17:07 -07:00
TehRiehlDeal bc599ebb5a Auto-update account balances for all transaction types (INCOME/EXPENSE/TRANSFER) 2026-04-16 16:09:27 -07:00
TehRiehlDeal 78c337cfe1 Add balance-over-time chart to account detail page 2026-04-16 16:03:04 -07:00
TehRiehlDeal 4154066a37 Replace popup-based receipt viewer with inline modal 2026-04-16 15:47:11 -07:00
TehRiehlDeal 3fac8a806d Make receipt paperclip clickable to view the file in a new tab 2026-04-16 15:42:15 -07:00
TehRiehlDeal 9cb483a733 Add receiptPath to transaction DTO so it isn't stripped by ValidationPipe 2026-04-16 15:37:08 -07:00
TehRiehlDeal 5c4ced1e20 Add edit transaction support via reusable TransactionForm component 2026-04-16 15:34:51 -07:00
TehRiehlDeal 474e181360 Add quick-transaction floating button on dashboard 2026-04-16 15:26:38 -07:00
TehRiehlDeal a359c54d50 Fix modal overflow with long filenames and tall forms 2026-04-16 15:22:40 -07:00
TehRiehlDeal ea7efddee1 Persist session across refresh and add Stay Logged In toggle 2026-04-16 15:15:49 -07:00
TehRiehlDeal cfc7624493 Add PWA support with service worker, manifest, and install icons 2026-04-16 15:09:23 -07:00
TehRiehlDeal 0afe0763dd Preserve negative sign when formatting currency 2026-04-16 14:49:14 -07:00
TehRiehlDeal 6bda259e99 Fix net worth to subtract liabilities instead of summing all balances 2026-04-16 14:43:16 -07:00
TehRiehlDeal ddf5c544c1 Add clickable account details page and drag-and-drop reordering 2026-04-16 14:37:10 -07:00
TehRiehlDeal 154682de5b Fix Select display to show labels instead of raw values 2026-04-16 14:26:54 -07:00
TehRiehlDeal 172845dc4d Invert transfer balance direction for liability accounts (credit, loan) 2026-04-16 14:19:53 -07:00
TehRiehlDeal e63eed9d90 Add transfer support: source → destination accounts with atomic balance updates 2026-04-16 14:11:30 -07:00
TehRiehlDeal 6b2e8d7626 Update page title, meta tags, and favicon with emerald TRB logo 2026-04-16 13:52:19 -07:00
TehRiehlDeal c2d67953ba Add mobile-responsive layout, dark mode toggle, and emerald color scheme 2026-04-16 13:46:48 -07:00
TehRiehlDeal 1da33a845d Fix query param type coercion and default date ranges for aggregations 2026-04-12 21:24:05 -07:00
TehRiehlDeal e16acc6950 Enable CORS and add /api global route prefix 2026-04-12 21:18:54 -07:00
TehRiehlDeal 026351b5a4 Downgrade Prisma to v6 for Docker compatibility 2026-04-12 21:13:31 -07:00
TehRiehlDeal 43d6a18aba Fix production build errors (type imports, Prisma constructor, TS6 compat, Recharts types) 2026-04-12 20:59:27 -07:00
TehRiehlDeal 37f8e2e7c3 Replace Anthropic API with local Ollama for AI advisor 2026-04-12 17:36:34 -07:00
TehRiehlDeal 17de171d26 Remove Plaid integration 2026-04-12 17:13:33 -07:00
TehRiehlDeal be7aab8959 Add dashboard with Recharts, AI advisor, and Plaid Connect page 2026-04-12 17:03:52 -07:00
TehRiehlDeal a40ecb1983 Add Zustand stores and CRUD pages for accounts, categories, and transactions 2026-04-12 17:03:45 -07:00
TehRiehlDeal f0b0078a51 Add Supabase auth integration, API client, and login/signup pages 2026-04-12 17:03:36 -07:00
TehRiehlDeal 6a95771237 Scaffold React frontend with Vite, TailwindCSS, and ShadCN UI 2026-04-12 17:03:26 -07:00
TehRiehlDeal 6987a50474 Add AI financial advisor with Claude and PII stripping 2026-04-12 17:03:06 -07:00
TehRiehlDeal 8c844e0122 Add Plaid integration for external account linking 2026-04-12 17:03:06 -07:00
TehRiehlDeal ecb3012e95 Add financial aggregation endpoints 2026-04-12 17:02:58 -07:00
TehRiehlDeal 9afd31f741 Add local filesystem receipt upload service 2026-04-12 17:02:58 -07:00
TehRiehlDeal 8bb4498f70 Add Accounts, Categories, and Transactions CRUD modules 2026-04-12 17:02:51 -07:00
TehRiehlDeal 413b4aa733 Add AES-256-GCM field-level encryption service and interceptor 2026-04-12 17:02:43 -07:00
TehRiehlDeal 7eecdaff69 Add Supabase Auth guard, service, and CurrentUser decorator 2026-04-12 17:02:35 -07:00
TehRiehlDeal 448b33996b Add Prisma schema, migrations, and PrismaModule 2026-04-12 17:02:25 -07:00
TehRiehlDeal f2cdb9f967 Scaffold NestJS backend with ValidationPipe and config 2026-04-12 17:02:17 -07:00
TehRiehlDeal 9a9fed9ffb Add project plan and TODO checklist 2026-04-12 17:01:46 -07:00
TehRiehlDeal c98d1a98f2 Initialize pnpm monorepo with Docker Compose for PostgreSQL 2026-04-12 17:01:37 -07:00