commit 807ebc41a560a15e6dac6c810f16bf334cce1ae0 Author: Daniel Krähenbühl Date: Mon Apr 13 14:08:44 2026 +0200 release: Armarium v1.0.0 Full-stack personal finance application (Django + Angular 21). Backend: Django REST Framework, JWT auth, PostgreSQL, iCal feed, rate limiting. Frontend: Angular 21 standalone components, TailwindCSS, i18n (DE/FR/IT/EN), responsive mobile layout, dark/light mode, ApexCharts dashboard, Swiss holiday calendar with canton support. Co-Authored-By: Claude Sonnet 4.6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..747006d --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# ── Temporäre Upload-Ordner ─────────────────────────────────────────────────── +Logos_Armarium/ + +# ── Persönliche Entwicklungsnotizen (nicht für VCS) ────────────────────────── +backend/commands.md +backend/tasks.json + +# ── OS ──────────────────────────────────────────────────────────────────────── +.DS_Store +Thumbs.db + +# ── IDE ─────────────────────────────────────────────────────────────────────── +.idea/ +*.swp +*.swo + +# ── Claude Code (lokale Konfiguration) ─────────────────────────────────────── +.claude/ +.mcp.json diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8d4228e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,111 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +--- + +## [1.0.0] - 2026-04-13 + +### Added +- Branding: app renamed to "Armarium"; browser tab title updated +- Branding: `Logo_horizontal.svg` in navbar, `Logo_vertikal.svg` on login/register, `Icon.svg` as favicon +- Branding: navbar logo inverts colors in dark mode via `dark:invert` +- Responsive layout: mobile-first redesign across all pages +- Responsive layout: sidebar becomes a slide-in overlay drawer on mobile (hamburger in navbar) +- Responsive layout: mobile backdrop closes sidebar on outside click or navigation +- Responsive layout: main content padding reduced on mobile (`p-4 lg:p-8`), sidebar margin shifted to `lg:` breakpoint +- Responsive layout: tables (accounts, expenses, transactions) get `min-w` and `overflow-x-auto` for horizontal scroll on mobile +- Responsive layout: notifications panel becomes a full-width top drawer on mobile (`fixed top-[57px] left-0 right-0`), dropdown on desktop +- Responsive layout: desktop sidebar toggle button hidden on mobile (`hidden lg:flex`) +- Database: migrated from SQLite to PostgreSQL; connection configured via `.env` variables (`DB_NAME`, `DB_USER`, `DB_PASSWORD`, `DB_HOST`, `DB_PORT`) +- Database: added `psycopg2-binary` as PostgreSQL adapter; added `.env.example` for onboarding +- i18n: full 4-language support (DE/FR/IT/EN) via ngx-translate; translation files in `assets/i18n/` +- i18n: language selector in Profile settings, persisted to backend `Profile.language` field and `localStorage` +- i18n: browser language auto-detection on Login and Register pages +- i18n: `LanguageService` for centralised language init, detection and switching +- i18n: canton names translated per UI language via `canton_names` keys; ZH = "Zürich" (DE), "Zuerich" (EN), "Zurigo" (IT), "Zurich" (FR) +- Calendar year view: clicking a month card opens a modal with an enlarged month view +- Sidebar collapse toggle in navbar: sidebar can be collapsed to icon-only view and expanded again +- Collapsed sidebar: flyout submenus for Budgets and Accounts with backdrop to close on outside click +- Collapsed sidebar: tooltips on hover for all navigation icons +- Dark/Light mode toggle in navbar with sun/moon icons; preference persisted in localStorage (dark mode default) +- iCal feed: `GET /api/calendar/ical-url/` returns personal iCal feed URL per user +- iCal feed: `GET /api/calendar/ical///` serves `.ics` file with deadlines and expense due dates (HMAC-SHA256 token auth) +- Calendar: "Subscribe" button in header opens popup with iCal feed URL and copy button + +### Changed +- Calendar day detail: replaced bottom panel with a slide-in drawer from the right side +- All UI strings replaced with i18n translation keys (DE/FR/IT/EN) across all pages and components + +### Fixed +- Profile: canton and language selects not saving — replaced `[value]`/`(change)` with `[ngModel]`/`(ngModelChange)` for reliable Angular select binding +- Calendar: canton selector not reflecting the profile canton on load +- Sidebar collapse button was not wired to any action +- Sidebar flyout submenus were clipped inside collapsed sidebar due to `overflow-y-auto` +- iCal feed: removed unused `pytz` import that caused `ModuleNotFoundError` +- i18n: translations not loading due to `src/assets` missing from `angular.json` asset sources + +--- + +## [0.1.0] - 2026-03-08 + +### Added + +#### Backend (Django) +- Initialized Django project with `core` configuration app and `finance` app +- Configured SQLite3 as development database +- Integrated Django REST Framework with JWT authentication via `djangorestframework-simplejwt` +- Enabled JWT token blacklist for secure logout and token rotation +- Configured `django-cors-headers` to allow requests from Angular frontend (`localhost:4200`) +- Implemented rate limiting: 5/min (auth), 200/min (authenticated users), 20/min (anonymous) +- Configured environment variables via `python-dotenv` (SECRET_KEY, DEBUG, ALLOWED_HOSTS, CORS) +- Added media file handling for avatar image uploads + +#### Data Models +- `Account` – asset, expense, and revenue account types with balance tracking +- `Transaction` – double-entry bookkeeping with source and destination accounts +- `Budget` – 7 categories (fixed expenses, mobile/internet, subscriptions, leisure, tax reserves, insurance, loans) +- `Expense` – 10 categories with optional due date and notes +- `Profile` – user profile with avatar (image + color), name, email, and canton (all 26 Swiss cantons) +- `Deadline` – 5 types (tax, insurance, invoice, personal, other) + +#### REST API +- `POST /api/auth/register/` – user registration +- `POST /api/auth/token/` – JWT login +- `POST /api/auth/token/refresh/` – token refresh +- `POST /api/auth/logout/` – logout with token blacklist +- `POST /api/auth/password/` – password change +- `GET/POST/PUT/DELETE /api/accounts/` – account management +- `GET/POST/PUT/DELETE /api/transactions/` – transaction management +- `GET/POST/PUT/DELETE /api/budgets/` – budget management +- `GET/POST/PUT/DELETE /api/expenses/` – expense management +- `GET/POST/PUT/DELETE /api/deadlines/` – deadline management +- `GET/PUT/DELETE /api/profile/` – user profile with avatar upload + +#### Frontend (Angular) +- Initialized Angular 21.2 project using standalone component architecture +- Integrated Tailwind CSS v3.4 for utility-first styling +- Integrated Flowbite 4.0.1 as UI component library (initialized via `initFlowbite()` in shell) +- Integrated ApexCharts 3.46.0 for data visualization +- Added `typings.d.ts` for Flowbite TypeScript module declaration +- Implemented `ApiService` for all HTTP communication with the Django REST API +- Implemented `AuthService` for JWT token storage and management +- Implemented `authGuard` to protect routes requiring authentication +- Implemented `authInterceptor` to attach Bearer token to all outgoing requests and handle 401 errors +- Configured `SidebarService` for sidebar open/close state management + +#### Pages & Components +- Login and Register pages with JWT-based authentication +- Shell layout with responsive sidebar and navbar (user avatar, canton display) +- Dashboard with KPIs (total income, fixed costs, expenses, available balance, savings rate) and ApexCharts bar and donut charts +- Accounts page with full CRUD for asset, expense, and revenue accounts +- Budgets page with category grouping and budget suggestions per category +- Expenses page with category filtering and due date tracking +- Transactions page with double-entry transaction management +- Calendar page with year and month view, Swiss public holidays and school holidays by canton (2025–2026), expense due dates and personal deadlines +- Profile page with avatar upload, color selection, name, email, and canton selection diff --git a/backend b/backend new file mode 160000 index 0000000..980535b --- /dev/null +++ b/backend @@ -0,0 +1 @@ +Subproject commit 980535b2a4c75aa8ed02cc78d92c3e580b72925a diff --git a/frontend b/frontend new file mode 160000 index 0000000..e38e987 --- /dev/null +++ b/frontend @@ -0,0 +1 @@ +Subproject commit e38e9877c0ceaca4b9e32bc855c6601ce4ba4f5d diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..31b79d9 --- /dev/null +++ b/start.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +ROOT_DIR="$(cd "$(dirname "$0")" && pwd)" + +echo "Starting Django backend..." +cd "$ROOT_DIR/backend" +"$ROOT_DIR/backend/venv/bin/python3" manage.py runserver & +DJANGO_PID=$! + +echo "Starting Angular frontend..." +cd "$ROOT_DIR/frontend" +node ./node_modules/.bin/ng serve & +ANGULAR_PID=$! + +echo "" +echo "Both servers running." +echo " Django: http://localhost:8000" +echo " Angular: http://localhost:4200" +echo "" +echo "Press Ctrl+C to stop both." + +trap "echo ''; echo 'Stopping...'; kill $DJANGO_PID $ANGULAR_PID 2>/dev/null; exit 0" SIGINT SIGTERM + +wait