docs: update BACKLOG, SPEC, README, and CONTRIBUTING to v0.41.0

- BACKLOG: added completed entries for v0.38.2–v0.41.0 (loans, widget sizes,
  date formats, birthday badge, calendar improvements, typography, reminders)
- SPEC: added Budget Loans and Budget Loan Payments data-model tables; updated
  Budget module description with Loans tab and API; updated Dashboard with
  widget size presets; corrected Settings tab count from 8 to 9
- README: Budget feature row now mentions the loans tracker
- CONTRIBUTING: added test:kitchen-tabs and test:setup to individual suite list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ulas Kalayci
2026-05-01 20:16:26 +02:00
parent 6eae4bae24
commit 3b02cb1aee
4 changed files with 49 additions and 2 deletions
+16
View File
@@ -103,3 +103,19 @@ New suggestion? → [Open an issue](https://github.com/ulsklyc/oikos/issues/new?
| - | UX: `friendlyError()` helper — unhandled promise rejections show status-code-aware messages instead of raw error text | v0.36.0 | | - | UX: `friendlyError()` helper — unhandled promise rejections show status-code-aware messages instead of raw error text | v0.36.0 |
| - | Date input: default format changed to DMY with dot separator; dot-separated dates accepted everywhere | v0.36.1 | | - | Date input: default format changed to DMY with dot separator; dot-separated dates accepted everywhere | v0.36.1 |
| - | Microinteraction long loops: FAB entry animation stops after 5 views; keyboard shortcut hint hides after first use; success toasts suppressed after 50 saves; empty-state CTA delayed fade-in | v0.38.0 | | - | Microinteraction long loops: FAB entry animation stops after 5 views; keyboard shortcut hint hides after first use; success toasts suppressed after 50 saves; empty-state CTA delayed fade-in | v0.38.0 |
| - | Calendar: recurring events with `FREQ=WEEKLY;INTERVAL=N;BYDAY` now correctly skip N1 weeks between occurrences | v0.38.2 |
| - | Dashboard portrait mode on mobile: horizontal scrollbar and overflow bugs fixed | v0.38.3 / v0.38.4 |
| - | Settings: 24-hour / AM·PM time format toggle, persisted globally; calendar remembers last selected view | v0.39.0 |
| - | Swedish (sv) translation completed by @olsson82; i18n gap-fill for 13 non-German locales | v0.39.1 |
| - | Budget date picker: native `type="date"` input on iOS and Android instead of plain text field | v0.39.2 |
| - | Budget loans tracker: instalment-based loans, per-payment records, remaining balance, auto-close when paid off (PR #117 by @rafaelfoster) | v0.40.0 |
| - | Dashboard: configurable widget sizes via named presets (Tiny, Narrow, Standard, Large, Full), persisted in user preferences | v0.40.0 |
| - | Settings: four additional date formats — MM.DD.YYYY, YYYY.MM.DD, YYYY/MM/DD, DD/MM/YYYY | v0.40.0 |
| - | Typography: tighter letter-spacing on page/modal titles, `text-wrap: balance`; warm-tinted shadows; larger button radius (--radius-md); module-accent empty-state icons; sentence-case search section labels | v0.40.1 |
| - | Tabular figures: `font-variant-numeric: tabular-nums` on all numeric displays (budget, weather, dashboard, calendar) | v0.40.1 |
| - | Birthdays: nav badge when any family member has a birthday within the next 3 days | v0.41.0 |
| - | Tasks: up to three recently-used filter chips, persisted in localStorage | v0.41.0 |
| - | Calendar: live keyword search in the icon picker; icons grouped into labelled categories | v0.41.0 |
| - | Calendar: repeat indicator icon on recurring events in month and week views | v0.41.0 |
| - | Calendar: 3-day week view on screens narrower than 640 px | v0.41.0 |
| - | Forms: required-field asterisk via `.required-marker` CSS class; enlarged modal drag-handle hit area (44 px); budget tab minimum height 40 px | v0.41.0 |
+1
View File
@@ -55,6 +55,7 @@ npm run test:meals && npm run test:calendar && npm run test:ncb
npm run test:reminders && npm run test:dashboard && npm run test:api npm run test:reminders && npm run test:dashboard && npm run test:api
npm run test:ics-parser && npm run test:ics-sub npm run test:ics-parser && npm run test:ics-sub
npm run test:modal-utils && npm run test:ux-utils npm run test:modal-utils && npm run test:ux-utils
npm run test:kitchen-tabs && npm run test:setup
``` ```
Tests use the Node.js built-in test runner with in-memory SQLite (`--experimental-sqlite`). No running server or database required — tests import route handlers directly. Tests use the Node.js built-in test runner with in-memory SQLite (`--experimental-sqlite`). No running server or database required — tests import route handlers directly.
+1 -1
View File
@@ -54,7 +54,7 @@ The goal is a single, private place for everything that keeps a household runnin
| **Recipes** | Create, duplicate, and scale reusable recipes. Pre-fill meal slots from a recipe or save any meal as a recipe. | | **Recipes** | Create, duplicate, and scale reusable recipes. Pre-fill meal slots from a recipe or save any meal as a recipe. |
| **Calendar** | Two-way sync with Google Calendar (OAuth) and Apple iCloud (CalDAV). Subscribe to any public ICS/webcal URL with per-subscription color and visibility. Overlapping timed events render side-by-side. Events support file attachments (images, PDFs, Office documents). | | **Calendar** | Two-way sync with Google Calendar (OAuth) and Apple iCloud (CalDAV). Subscribe to any public ICS/webcal URL with per-subscription color and visibility. Overlapping timed events render side-by-side. Events support file attachments (images, PDFs, Office documents). |
| **Documents** | Upload and manage family files (PDF, images, Office documents up to 5 MB). Grid/list view, drag-and-drop upload, 14 category tags (medical, school, identity, finance, and more), per-document visibility (family, selected members, private), archive and download. | | **Documents** | Upload and manage family files (PDF, images, Office documents up to 5 MB). Grid/list view, drag-and-drop upload, 14 category tags (medical, school, identity, finance, and more), per-document visibility (family, selected members, private), archive and download. |
| **Budget** | Track income and expenses with recurring entries, monthly trends, and CSV export. 35 predefined categories plus custom ones. Supports 15 currencies. | | **Budget** | Track income and expenses with recurring entries, monthly trends, and CSV export. 35 predefined categories plus custom ones. Supports 15 currencies. Loans tab for instalment-based loan tracking with per-payment history and automatic paid-off detection. |
| **Notes & Contacts** | Colored sticky notes with Markdown support. Contact directory with vCard import/export. | | **Notes & Contacts** | Colored sticky notes with Markdown support. Contact directory with vCard import/export. |
| **Birthdays** | Birthday tracker with automatic annual calendar events, age display, profile photos, and 1-day-before reminders. | | **Birthdays** | Birthday tracker with automatic annual calendar events, age display, profile photos, and 1-day-before reminders. |
| **Reminders** | Time-based reminders on tasks and calendar events. In-app notification badge. | | **Reminders** | Time-based reminders on tasks and calendar events. In-app notification badge. |
+31 -1
View File
@@ -281,6 +281,32 @@ Allowlist for `visibility = 'restricted'` documents — only listed users can se
| user_id | INTEGER | FK → Users (CASCADE delete), NOT NULL | | user_id | INTEGER | FK → Users (CASCADE delete), NOT NULL |
| PRIMARY KEY | | (document_id, user_id) | | PRIMARY KEY | | (document_id, user_id) |
### Budget Loans
Instalment-based loans with per-payment tracking. Active loans show remaining balance and due months; paid-off loans are automatically closed.
| Column | Type | Constraint |
|--------|------|-----------|
| title | TEXT | NOT NULL |
| borrower | TEXT | NOT NULL |
| total_amount | REAL | NOT NULL CHECK(> 0) |
| installment_count | INTEGER | NOT NULL CHECK(> 0) |
| start_month | TEXT | YYYY-MM, NOT NULL |
| notes | TEXT | nullable |
| status | TEXT | 'active' (default) or 'paid' |
| created_by | INTEGER | FK → Users (CASCADE delete), NOT NULL |
### Budget Loan Payments
Individual payment records for a budget loan. Each installment number is unique per loan.
| Column | Type | Constraint |
|--------|------|-----------|
| loan_id | INTEGER | FK → Budget Loans (CASCADE delete), NOT NULL |
| installment_number | INTEGER | NOT NULL CHECK(> 0), UNIQUE per loan |
| amount | REAL | NOT NULL CHECK(> 0) |
| paid_date | TEXT | DATE, NOT NULL |
| budget_entry_id | INTEGER | FK → Budget Entries (SET NULL on delete), nullable |
| created_by | INTEGER | FK → Users (CASCADE delete), NOT NULL |
### Sync Config ### Sync Config
Key-value table for OAuth tokens and CalDAV credentials. Key-value table for OAuth tokens and CalDAV credentials.
@@ -306,6 +332,8 @@ Responsive grid: 1 column on mobile, 2 on tablet, 3 on desktop.
- Pinboard preview: 23 pinned notes - Pinboard preview: 23 pinned notes
- FAB (quick actions): + Task, + Event, + Shopping list item, + Note - FAB (quick actions): + Task, + Event, + Shopping list item, + Note
**Widget sizes:** each widget has a configurable size using named presets (Tiny, Narrow, Standard, Large, Full) that map to `columns × rows` in the CSS grid. Sizes are persisted in user preferences and survive page reloads.
Skeleton loading instead of spinners. Clicking any widget navigates to that module. Skeleton loading instead of spinners. Clicking any widget navigates to that module.
### Tasks (`/tasks`) ### Tasks (`/tasks`)
@@ -428,7 +456,7 @@ User management and app configuration. Logged-in users only.
- **Language:** System (follows `navigator.language`), German, English, Spanish, French, Italian, Swedish, Greek, Russian, Turkish, Chinese, Japanese, Arabic, Hindi, Portuguese - via `oikos-locale-picker` web component; switch without page reload - **Language:** System (follows `navigator.language`), German, English, Spanish, French, Italian, Swedish, Greek, Russian, Turkish, Chinese, Japanese, Arabic, Hindi, Portuguese - via `oikos-locale-picker` web component; switch without page reload
- **API Tokens (admin):** create named Bearer / X-API-Key tokens for external integrations; the full token value is shown only once immediately after creation; tokens can be revoked at any time; support optional expiry and track last-used timestamp - **API Tokens (admin):** create named Bearer / X-API-Key tokens for external integrations; the full token value is shown only once immediately after creation; tokens can be revoked at any time; support optional expiry and track last-used timestamp
- **Backup Management (admin):** download the current database as a file (`GET /api/v1/backup/database`) or restore from a backup file (`POST /api/v1/backup/restore`, drag-and-drop supported). Validates that the uploaded file is a valid Oikos database. A rollback copy is created automatically before restore. - **Backup Management (admin):** download the current database as a file (`GET /api/v1/backup/database`) or restore from a backup file (`POST /api/v1/backup/restore`, drag-and-drop supported). Validates that the uploaded file is a valid Oikos database. A rollback copy is created automatically before restore.
- **Tab navigation:** Settings is organized in eight tabs (General, Meals, Budget, Shopping, Calendar, Family, API Tokens, Account). Admin-only tabs: Family, API Tokens, Backup. Sticky tab bar, active tab persists in sessionStorage, Calendar tab auto-activates after OAuth callbacks. - **Tab navigation:** Settings is organized in nine tabs (General, Meals, Budget, Shopping, Calendar, Family, API Tokens, Backup, Account). Admin-only tabs: Family, API Tokens, Backup. Sticky tab bar, active tab persists in sessionStorage, Calendar tab auto-activates after OAuth callbacks.
- **Family management (admin):** assign a `family_role` (Dad, Mom, Parent, Child, Grandparent, Relative, Other) to each user, and set per-member phone, email, and birthday — automatically synced to Contacts and Birthdays. Displayed in the family member list and profile views. - **Family management (admin):** assign a `family_role` (Dad, Mom, Parent, Child, Grandparent, Relative, Other) to each user, and set per-member phone, email, and birthday — automatically synced to Contacts and Birthdays. Displayed in the family member list and profile views.
- **Profile picture:** users can upload a personal avatar (PNG/JPEG/WebP/GIF, ≤ 5 MB), stored as a Base64 data URL in `avatar_data`. Displayed alongside display name across the app. - **Profile picture:** users can upload a personal avatar (PNG/JPEG/WebP/GIF, ≤ 5 MB), stored as a Base64 data URL in `avatar_data`. Displayed alongside display name across the app.
- **App info:** version, license - **App info:** version, license
@@ -445,7 +473,9 @@ User management and app configuration. Logged-in users only.
- Recurring entries - Recurring entries
- Monthly comparison (current vs. previous month) - Monthly comparison (current vs. previous month)
- CSV export includes a subcategory column and English column headers - CSV export includes a subcategory column and English column headers
- **Loans tab:** create instalment-based loans (borrower, total amount, number of instalments, start month); record individual payments; remaining balance and due months shown automatically; paid-off loans marked as closed; filter budget transactions by loan
- API: `GET /api/v1/budget/categories`, `GET /api/v1/budget/categories/:key/subcategories` (optional `?lang=` localisation), `POST /api/v1/budget/categories`, `POST /api/v1/budget/categories/:key/subcategories` - API: `GET /api/v1/budget/categories`, `GET /api/v1/budget/categories/:key/subcategories` (optional `?lang=` localisation), `POST /api/v1/budget/categories`, `POST /api/v1/budget/categories/:key/subcategories`
- Loans API: `GET /api/v1/budget/loans`, `POST /api/v1/budget/loans`, `GET /api/v1/budget/loans/:id`, `PUT /api/v1/budget/loans/:id`, `DELETE /api/v1/budget/loans/:id`, `GET /api/v1/budget/loans/:id/payments`, `POST /api/v1/budget/loans/:id/payments`, `DELETE /api/v1/budget/loans/:id/payments/:paymentId`
### Birthdays (`/birthdays`) ### Birthdays (`/birthdays`)