v1.1.0 Kalendarz i listy zakupów
All checks were successful
Build and Push Docker Images / build-and-push (push) Successful in 3m10s

Dodaje wspólny kalendarz wydarzeń grupy (zakres dat/godzin, cały dzień,
notatki, lokalizacja, uczestnicy z gospodarstwa + goście zewnętrzni)
oraz listy zakupów (wiele list, dodawanie/edycja/odznaczanie/usuwanie
produktów). Nowe tabele w schemacie SQLite są czysto addytywne
(CREATE TABLE IF NOT EXISTS), więc nie ruszają istniejących danych.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 23:26:00 +02:00
parent 350ccdbaf7
commit 9c39b33636
28 changed files with 1537 additions and 9 deletions

View File

@@ -8,6 +8,8 @@ A web app (PWA) for splitting expenses within a household — who paid what, who
- **Add expense** — large amount field, categories with icons, payer selection, three split modes: equally (among all members), exact amounts, or the full amount to one person.
- **History** — expense list with filters (month/category/payer), edit and delete.
- **Stats** — month-over-month expenses, comparison of household members' spending, category ranking.
- **Calendar** — a shared household calendar for planning events together: pick a date range or a specific day/time (or mark it all-day), add notes and a location, and choose who's involved (just you, everyone, or specific members) plus any number of external guests (name only, no account needed).
- **Shopping lists** — any number of named shopping lists per household; add/edit/delete items, check them off while shopping, rename or delete a whole list.
- **Multiple households** — a user can belong to several households at once and switch between them (Settings → "Your households"); each household can have any number of members, who join with the same invite code.
- **Settings** — switch and manage households (rename/change currency, remove a member, delete a household, invites), custom categories (rename/re-icon), light/dark/system theme, **language switcher (Polish/English)**, email notifications, CSV export.
- **Account** — email/password registration, login, rename, change password, password reminder/reset by email, account deletion.
@@ -43,7 +45,7 @@ whowhat/
│ ├── i18n.js # server-rendered translations (emails, CSV, default categories)
│ ├── db/ # schema.sql + better-sqlite3 connection
│ ├── middleware/auth.js # JWT verification
│ ├── routes/ # auth, households, categories, expenses, settlements, stats
│ ├── routes/ # auth, households, categories, expenses, settlements, stats, events, shoppingLists
│ └── utils/ # balance calculation, mailer (nodemailer), household helpers
└── frontend/
├── Dockerfile # multi-stage: build (node) -> serve (nginx)
@@ -51,8 +53,8 @@ whowhat/
├── vite.config.js # PWA config (manifest, service worker)
└── src/
├── i18n/ # I18nContext, per-namespace locale JSON files
├── pages/ # Dashboard, AddExpense, History, Stats, Settings, Login, Register, ...
├── components/ # BottomNav, charts, forms, Icon, Switch, LanguageSwitcher, ...
├── pages/ # Dashboard, AddExpense, History, Stats, Settings, Calendar, ShoppingLists, ShoppingListDetail, Login, Register, ...
├── components/ # BottomNav, charts, forms, EventFormModal, ShoppingListItemRow, Icon, Switch, LanguageSwitcher, ...
├── api/ # fetch client + React Query hooks
├── auth/ # auth context (JWT in localStorage)
├── household/ # active household context (list + switching)
@@ -116,6 +118,10 @@ The frontend's port `8856` is also published directly on the host — useful for
- `expenses` — expenses (amount, payer, category, date, split type)
- `expense_shares` — the final split of an expense across household members (always sums to the expense amount regardless of split type)
- `settlements` — settlement history ("Settle up")
- `events` — calendar events (title, notes, location, all-day flag, start/end)
- `event_attendees` — who's attending an event: either a `user_id` (household member) or a free-text `guest_name` for external guests
- `shopping_lists` — named shopping lists per household
- `shopping_list_items` — items on a list (name, quantity, checked state)
Per-person balance is computed as: `(amount they paid) (sum of their expense shares) (net settlements)`. For the "who owes whom" display, balances are simplified with a greedy algorithm (`backend/src/utils/balance.js: simplifyDebts`) that produces the minimum number of transfers to settle everyone (instead of a separate debt between every pair).
@@ -141,6 +147,8 @@ Error responses are `{ "error": "<code>" }`, where `<code>` is a stable snake_ca
| Expenses | `GET/POST/PUT/DELETE /expenses[/:id]` (filters: `month`, `categoryId`, `payerId`) |
| Settlements | `GET/POST /settlements` (POST immediately settles all simplified transfers) |
| Stats | `GET /stats/balance`, `/summary`, `/monthly`, `/export.csv` |
| Events | `GET/POST/PUT/DELETE /events[/:id]` |
| Shopping lists | `GET/POST/PUT/DELETE /shopping-lists[/:id]`, `POST/PUT/DELETE /shopping-lists/:id/items[/:itemId]` |
## Offline mode (PWA)