Initial commit: Wallet App - FastAPI backend with React frontend for personal finance tracking

This commit is contained in:
RemTools
2026-09-04 08:37:14 +00:00 Unverified
commit d7b52f24d2
39572 changed files with 1617122 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
WDNVO5uZextBLwTuVVcVlg3E3bqvhb7QPR_5wQ_KbrY=
+1
View File
@@ -0,0 +1 @@
gAAAAABqmoGFZN-ddAdnsypsJdMCZj_PcD2h7p-6c-i46ANNcwUK74Gm8QVCD7UUkeJBn7BZPoy7O0c9AM3Uo7_9xwxa5iQk2q6U65gEGQFLo13NbY6ZtJY3dl8iFWe6hXCOJCPL8qicM7aOevywSY6plS9o8H23C05P00mu7fZxn7h79xOJnZ4RNZn1loo04jcR73qPdV6NmMQS_UDaD9oRwmi0AyUF23wHO75kygCTxQ_ywXpctR-0WEYajU8VpPZI66IK-YMUM4GMP8QTPKoCnDFBHKk4cBbuVj_1ahAvZFiivQc87Mn7w4czbO9c7udNIv7lZx_Lcs42GVZ7Zqv_w1fKjG0CYHKF1linlLoOrIXcNYnjFOzfzbPbOAc6hPGgq3Xr6NHDJe0hVzyVviUHPdj_gvhPDcmt6RIjx-t7WXTepZ0KisU9Z6qh-Ba9h_F98eAroxvGYE0aX0rbV43gnWDVhnOUNPNIP0vjJ-hfaQqkMqUf87mAyJ2pM8V_AycW3JIbT0yp
+7
View File
@@ -0,0 +1,7 @@
{
"engine": "sqlite",
"schema": "",
"status": "sqlite_fallback",
"host": "vibecoder-postgres",
"provisioned_at": "2026-09-04T08:29:56.995619+00:00"
}
+17
View File
@@ -0,0 +1,17 @@
# Project Database State
- **Engine**: `sqlite`
- **Status**: `sqlite_fallback`
- **Schema**: `—`
- **Host**: `vibecoder-postgres`
- **Last provisioned**: 2026-09-04T08:29:56.995619+00:00
_Credentials are stored encrypted in `database.enc` (key: `.dbsecret`)._
_This folder is never exposed to the user file or chat stream._
## Operation history (most recent last)
- `2026-09-04T08:29:56.995720+00:00` **provision_start** project_uuid=ebf1c40f-6e4e-4675-859d-529df9ee89d7, target_schema=app_78dc3392_ebf1
- `2026-09-04T08:29:57.006621+00:00` **resolve_user_db** configured=True, host=vibecoder-postgres
- `2026-09-04T08:29:57.012280+00:00` **ping** host=vibecoder-postgres, reachable=False
- `2026-09-04T08:29:57.012957+00:00` **provision_done** engine=sqlite, status=sqlite_fallback, schema=, host=vibecoder-postgres
+4
View File
@@ -0,0 +1,4 @@
{"ts": "2026-09-04T08:29:56.995720+00:00", "action": "provision_start", "project_uuid": "ebf1c40f-6e4e-4675-859d-529df9ee89d7", "target_schema": "app_78dc3392_ebf1"}
{"ts": "2026-09-04T08:29:57.006621+00:00", "action": "resolve_user_db", "configured": true, "host": "vibecoder-postgres"}
{"ts": "2026-09-04T08:29:57.012280+00:00", "action": "ping", "host": "vibecoder-postgres", "reachable": false}
{"ts": "2026-09-04T08:29:57.012957+00:00", "action": "provision_done", "engine": "sqlite", "status": "sqlite_fallback", "schema": "", "host": "vibecoder-postgres"}
+56
View File
@@ -0,0 +1,56 @@
# VibeCoder Project: app-78dc3392
- UUID: ebf1c40f-6e4e-4675-859d-529df9ee89d7
## Files
- `tasks.md`
- `.remtools/bash/20260904-073715-0004.log`
- `.remtools/bash/20260904-073537-0002.log`
- `.remtools/bash/20260904-073535-0001.log`
- `.remtools/bash/20260904-073722-0005.log`
- `.remtools/bash/20260904-073829-0006.log`
- `.remtools/bash/20260904-073641-0003.log`
- `frontend/index.html`
- `frontend/package.json`
- `frontend/package-lock.json`
- `frontend/tsconfig.json`
- `frontend/vite.config.ts`
- `frontend/src/main.tsx`
- `frontend/src/App.tsx`
- `frontend/src/theme.ts`
- `frontend/src/services/api.ts`
- `frontend/src/services/auth.ts`
- `frontend/src/services/mockData.ts`
- `frontend/src/services/dataSource.ts`
- `frontend/src/pages/Register.tsx`
- `frontend/src/pages/Dashboard.tsx`
- `frontend/src/pages/Login.tsx`
- `frontend/src/pages/EntryForm.tsx`
- `frontend/src/pages/EntriesList.tsx`
- `frontend/dist/index.html`
- `frontend/dist/assets/index-DmuSdnn_.js`
- `backend/requirements.txt`
- `backend/seed_demo.py`
- `backend/.ruff_cache/.gitignore`
- `backend/.ruff_cache/CACHEDIR.TAG`
- `backend/.ruff_cache/0.15.15/14492034624820516455`
- `backend/.ruff_cache/0.15.15/12188829397567061770`
- `backend/app/__init__.py`
- `backend/app/schemas.py`
- `backend/app/auth.py`
- `backend/app/models.py`
- `backend/app/database.py`
- `backend/app/main.py`
- `backend/app/routes/__init__.py`
- `backend/app/routes/health.py`
- `backend/app/routes/wallet.py`
- `backend/app/routes/items.py`
- `backend/app/routes/auth.py`
- `.vibecoder/db_history.jsonl`
- `.vibecoder/database.enc`
- `.vibecoder/.dbsecret`
- `.vibecoder/plan.md`
- `.vibecoder/database.json`
- `.vibecoder/database.md`
## History
- Sessions: 0
+116
View File
@@ -0,0 +1,116 @@
# Wallet App — MVP Plan
## What We're Building
A personal finance wallet app where you can log income transactions, view your total balance on a dashboard, and see a complete history of all entries. The app requires login (so each user has their own data) and persists everything to SQLite.
**For the user:** Sign up or log in → see your total balance at a glance → add new income entries → review all transactions in a table.
## How It Works
1. **Auth Pages** (Sign Up / Log In)
- User creates an account or logs in with email + password
- Session token stored in browser; backend validates on each request
- Redirects to dashboard on success
2. **Dashboard**
- Shows **Total Balance** (sum of all income entries for this user)
- Quick link to add a new entry
- Link to view full transaction history
3. **Wallet Entry Page**
- Form to add a new income entry: amount, description, date
- Submit creates the entry and returns to dashboard
4. **Transaction Table**
- Lists all income entries (newest first)
- Columns: Date, Description, Amount, Running Balance
- Shows overall savings (total balance) at the top
## Key Decisions & Why
- **React frontend** (you chose it): modern, component-based, easy to extend
- **FastAPI backend**: lightweight, fast, great for JSON APIs
- **SQLite database**: no external DB needed, data lives in `./data/app.db`
- **Session-based auth**: simple, stateful; user logs in once per browser
- **Income only** (you chose it): simpler schema, no expense tracking yet
- **Total balance metric** (you chose it): single number, easy to understand
## Assumptions & Defaults
- Email + password auth (no OAuth, no 2FA)
- One user per session (no multi-user dashboard)
- Amounts are decimal (e.g., 1234.56)
- Dates default to today when adding an entry
- No edit/delete of past entries (read-only history)
- No categories or tags
## Out of Scope
- Expense tracking (only income)
- Recurring transactions
- Budget alerts
- Export to CSV
- Mobile app (web only)
- Dark mode
---
## Technical Detail
### Frontend (React)
**Screens:**
1. **Login** (`/login`) — email, password, submit, link to sign up
2. **Sign Up** (`/signup`) — email, password, confirm password, submit, link to login
3. **Dashboard** (`/`) — total balance card, "Add Entry" button, link to history
4. **Add Entry** (`/add`) — form (amount, description, date), submit button, cancel
5. **History** (`/history`) — table of all entries, total balance header
**State & Flow:**
- React Context or simple state for auth token + current user
- Redirect to `/login` if not authenticated
- Fetch dashboard data on mount
- Form submission posts to backend, then redirects
### Backend (FastAPI)
**Data Model:**
```
User
- id (int, PK)
- email (str, unique)
- password_hash (str)
- created_at (datetime)
Entry
- id (int, PK)
- user_id (int, FK → User)
- amount (Decimal)
- description (str)
- date (date)
- created_at (datetime)
```
**Endpoints:**
- `POST /auth/signup` — create user, return token
- `POST /auth/login` — validate email/password, return token
- `POST /auth/logout` — clear session (optional, browser can just delete token)
- `GET /dashboard` — return total balance for logged-in user
- `POST /entries` — create new income entry
- `GET /entries` — list all entries for logged-in user (paginated or all)
**Auth:**
- Password hashed with bcrypt
- Session token (JWT or simple session ID) in cookie or Authorization header
- Middleware checks token on protected routes
**Database:**
- SQLite at `./data/app.db`
- Migrations run on startup (SQLAlchemy ORM)
### Data Source
- User input only (no external APIs)
- All data stored locally in SQLite
### Stack
- **Frontend:** React 18, React Router, Fetch API
- **Backend:** FastAPI, SQLAlchemy ORM, Pydantic, bcrypt
- **Database:** SQLite
- **Template:** `fastapi-react` (pinned dependencies, known to build)
## Scope
Depth: MVP. Something they could actually use: the core flow end to end, real persisted data, auth ONLY if the app is meaningless without it, sensible empty and error states. No test suite, no roles, no CI.