Skip to content

Releases: afatyoo/Local-Wallet

1.3.1 - 2026-03-28

28 Mar 08:45

Choose a tag to compare

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 /register page 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 createdAt as 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_insights translation key. Changed English insights_title from "Where's My Money" to "Spending Insights" for better professionalism. Indonesian translations remain natural ("Kemana Uang Saya").

1.2.2 — 2026-03-26

26 Mar 07:00

Choose a tag to compare

1.2.2 — 2026-03-26

Fixed

  • 401 logout sync: When API returns 401, apiRequest now calls unauthorizedHandler which triggers authStore.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

26 Mar 07:00

Choose a tag to compare

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_management translation 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-limit to prevent brute-force attacks.
  • Security headers: Added helmet() middleware — sets Content-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_ORIGINS env var instead of allowing every origin (*).
  • Docker env passthrough: JWT_SECRET and ALLOWED_ORIGINS are now forwarded to the backend container in docker-compose.yml.
  • .env.example: Documents all required backend environment variables including JWT_SECRET and ALLOWED_ORIGINS.

Fixed

  • Auth middleware gap: authenticateToken middleware 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 userId ownership 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' when JWT_SECRET env var was not set. Server now crashes at startup with a clear error if the var is missing.
  • API header merge bug: apiRequest() spread ...options after the merged headers object, silently overwriting the Authorization: Bearer header on every request. Fixed by destructuring options.headers out 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 the exp claim locally — expired or malformed tokens are cleared on app load rather than waiting for a server rejection.
  • ApiUser.role type: Narrowed from string to 'admin' | 'user' to match the actual backend ENUM, fixing a TypeScript lint error in UserManagement.tsx.
  • UserManagement React import bug: Fixed React.useEffect usage without importing React in UserManagement.tsx; replaced with direct useEffect import.
  • 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 authStore persists the token and apiRequest attaches Authorization: Bearer header on every request. Backend register endpoint also returns a JWT token (login already did).

1.1.0 - 2025-03-25

25 Mar 10:19

Choose a tag to compare

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-MM for months, YYYY-MM-DD for 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 setSelectedMonth destructuring in Income.tsx and Expense.tsx which 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.f3 error 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

11 Mar 14:37
7f8b42d

Choose a tag to compare

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 --build

Open:

  • 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
  • .env file is required — never commit it to version control

📄 Documentation

See the full setup guide in README and README_DOCKER.