Releases: afatyoo/Local-Wallet
Releases · afatyoo/Local-Wallet
1.3.1 - 2026-03-28
Added
- Admin password reset: Administrators can now change user passwords directly from the User Management page via an inline modal (Key icon button). This allows admins to reset passwords for any user except themselves.
Changed
- Registration flow moved: User registration is now only available through the User Management page as an inline modal for admins. The standalone
/registerpage has been removed. Non-admin users can no longer self-register; only administrators can create new user accounts. - User Management modal localized: The "Add New User" modal in User Management page is now in English with improved styling (glass-card effect, smooth animations).
- Created At display fixed: Fixed bug where user creation dates were not displaying correctly due to timezone issues. Backend now returns
createdAtas a date string (YYYY-MM-DD) based on the server's local timezone. Frontend displays it in DD/MM/YYYY format, ensuring the date matches what the server shows regardless of the client's timezone. - Insights page translations improved: Fixed hardcoded "Insights" section title by adding
insights_insightstranslation key. Changed Englishinsights_titlefrom "Where's My Money" to "Spending Insights" for better professionalism. Indonesian translations remain natural ("Kemana Uang Saya").
1.2.2 — 2026-03-26
1.2.2 — 2026-03-26
Fixed
- 401 logout sync: When API returns 401,
apiRequestnow callsunauthorizedHandlerwhich triggersauthStore.logout()to ensure frontend state matches the cleared localStorage. Prevents "Access Token Required" errors on retry after token expiry.
1.2.1 — 2026-03-26
1.2.1 — 2026-03-26
Added
- User Management page: Added a new page for managing users with the ability to view, update, and delete users.
- User Management navigation: Added a navigation link to the User Management page in the sidebar.
- User Management i18n: Added translation keys for the User Management page in all 12 locale files.
- Admin-only User Management nav: Added "User Management" sidebar link (ShieldCheck icon) visible only to admin users. Non-admin users do not see this menu item.
- i18n for User Management: Added
nav_user_managementtranslation key to all 12 locale files (ID, EN, ES, FR, DE, PT, RU, AR, HI, ZH, JA, KO). - Default admin user: On Docker startup, a default admin account (username:
admin, password:admin) is automatically created if it doesn't already exist. - Rate limiting: Global limit (100 req/15 min) + aggressive auth limit (5 req/15 min) via
express-rate-limitto prevent brute-force attacks. - Security headers: Added
helmet()middleware — setsContent-Security-Policy,X-Frame-Options,X-Content-Type-Options, and 8+ other headers automatically. - Input validation: Required-field checks, date/month format validation (
YYYY-MM-DD/YYYY-MM), and minimum password length (6 chars) on all endpoints. - HTML sanitization: All text inputs are stripped of HTML tags before reaching the database.
- CORS restriction: CORS now reads
ALLOWED_ORIGINSenv var instead of allowing every origin (*). - Docker env passthrough:
JWT_SECRETandALLOWED_ORIGINSare now forwarded to the backend container indocker-compose.yml. .env.example: Documents all required backend environment variables includingJWT_SECRETandALLOWED_ORIGINS.
Fixed
- Auth middleware gap:
authenticateTokenmiddleware was missing from all CRUD routes (income, expense, budget, savings, bills, bill-payments, admin). Any unauthenticated request could previously read or modify any user's data. - Ownership verification: Added
userIdownership check on every CRUD endpoint — a logged-in user can no longer read or modify another user's records (returns 403). - Hardcoded JWT secret: Backend previously fell back to the literal string
'your_jwt_secret'whenJWT_SECRETenv var was not set. Server now crashes at startup with a clear error if the var is missing. - API header merge bug:
apiRequest()spread...optionsafter the mergedheadersobject, silently overwriting theAuthorization: Bearerheader on every request. Fixed by destructuringoptions.headersout before the spread. - Auto-logout on 401: Frontend now clears the persisted session and returns a user-friendly message when the server responds with 401.
- JWT expiry check:
checkSession()now decodes the JWT payload and checks theexpclaim locally — expired or malformed tokens are cleared on app load rather than waiting for a server rejection. ApiUser.roletype: Narrowed fromstringto'admin' | 'user'to match the actual backend ENUM, fixing a TypeScript lint error inUserManagement.tsx.- UserManagement React import bug: Fixed
React.useEffectusage without importingReactinUserManagement.tsx; replaced with directuseEffectimport. - JWT auth token not sent: Fixed "Access Token Required" error on User Management and all protected API endpoints. Root cause: frontend never stored or sent the JWT token from login/register. Now
authStorepersists the token andapiRequestattachesAuthorization: Bearerheader on every request. Backend register endpoint also returns a JWT token (login already did).
1.1.0 - 2025-03-25
1.1.0 - 2025-03-25
Added
- Auto-switch to latest month: When viewing Income or Expense pages with "All Period" selected, the app automatically switches to the most recent month with data (prevents blank screens).
- Improved dummy data seeding: New seed script (
backend/seed-dummy-data.mjs) that clears existing data and populates realistic test data with correct date formats (YYYY-MMfor months,YYYY-MM-DDfor dates). - Docker port configuration: MySQL exposed on port 3307 to avoid conflicts with local MySQL installations.
- Excel export: Added ability to export financial reports to Excel (XLSX) format alongside PDF. Excel reports include multiple sheets: Summary, Income, Expenses, Budget, and Category Breakdown.
Fixed
- Month filter bug: Fixed mismatch between seed data format (
MM/YYYY) and frontend expectations (YYYY-MM), causing income/expense filters to return empty results. - ReferenceError: Added missing
setSelectedMonthdestructuring inIncome.tsxandExpense.tsxwhich caused blank pages when auto-switch triggered. - Date format consistency: All seeded dates now use ISO format compatible with frontend date inputs and month filtering.
- PDF generation error: Fixed
Invalid argument passed to jsPDF.f3error by using hex color strings instead of RGB arrays and ensuring jsPDF 2.5.1 + jspdf-autotable 3.5.13 compatibility. - Report UI localization: Changed report page UI and generated PDFs to use English as default language for better internationalization.
v1.0.0 - Initial Release Local Wallet
My Local Wallet is a simple yet powerful personal finance tracker built with React + TypeScript (frontend) and Node.js + Express + MySQL (backend).
Track your income, expenses, budgets, savings, and recurring bills all in one place, with charts, insights, and export/import support.
✨ What's Included
🔐 Authentication
- Register & Login with passwords hashed using bcrypt
📊 Dashboard
- Income vs expense summary
- Balance overview
- Recent transactions
💵 Income & 💸 Expenses
- Full CRUD operations
- Categories & payment methods
🎯 Budgets
- Per category and per month budget tracking
🐷 Savings / Investments
- Track savings goals and investment progress
📅 Bills (Recurring)
- Manage recurring bills with payment history
📈 Insights & Heatmap
- Visualize spending patterns over time
🧾 Reports
- Export reports to PDF
- Export / Import data as JSON for backup and restore
💱 Multi-Currency Display
- Base currency: IDR
- Display in IDR, USD, EUR, GBP, SGD, JPY, and more
- Automatic conversion using latest exchange rates (cached, with manual refresh)
- Falls back gracefully when offline
🌐 Multi-Language (i18n)
- Base language: Indonesian (id)
- Supported: EN, ES, FR, DE, PT, RU, AR, HI, 中文, 日本語, 한국어
- Auto-sync and auto-translate new/changed keys (hash-based, avoids unnecessary work)
- Optional LibreTranslate via Docker for free auto-translation
🧱 Tech Stack
| Layer | Stack |
|---|---|
| Frontend | React 18, TypeScript, Vite, Tailwind, shadcn/ui, Zustand, React Router |
| Charts | Recharts |
| PDF Export | jsPDF + jspdf-autotable |
| Backend | Node.js, Express, mysql2, bcryptjs, uuid |
| Container | Docker + Docker Compose (Nginx frontend + reverse-proxy /api) |
🚀 Quick Start (Docker — recommended)
cp .env.example .env
# Edit .env with your MySQL credentials
docker compose up -d --buildOpen:
- Frontend:
http://localhost:3000 - Backend health:
http://localhost:3000/api/health
🧑💻 Local Development (no Docker)
# Backend
cd backend && npm install
MYSQL_HOST=127.0.0.1 MYSQL_USER=root MYSQL_PASSWORD=your_password MYSQL_DATABASE=finance_db npm run dev
# Frontend (new terminal)
npm install
export VITE_API_URL="http://localhost:3001/api"
npm run dev🔐 Security Notes
- Passwords are hashed with bcrypt before storage
- For production: change DB passwords and run behind HTTPS (Nginx / Caddy / Traefik)
- Default CORS is enabled on the backend
📝 Notes
- All monetary amounts are stored in IDR, then converted for display
- Exchange rates are cached to minimize API calls; falls back to last-known rates if offline
.envfile is required — never commit it to version control
📄 Documentation
See the full setup guide in README and README_DOCKER.