Commit Graph

291 Commits

Author SHA1 Message Date
Ulas 6f22ef8268 feat: list items get module accent border-left stripe
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 15:00:41 +02:00
Ulas 4ac9cd16d1 fix: add missing --module-accent declaration to calendar-page 2026-03-31 14:58:16 +02:00
Ulas 3bf2d2bbc0 feat: toolbar top-border stripe uses module accent colour 2026-03-31 14:54:10 +02:00
Ulas 7f41ee380a refactor: move --active-module-accent update into navigate() to avoid duplicate ROUTES.find
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 13:31:57 +02:00
Ulas 6a018867e0 feat: active nav tab uses module accent colour 2026-03-31 13:22:16 +02:00
Ulas cd017c4d0d fix: escape user input in shopping renderItem to prevent XSS 2026-03-31 12:53:00 +02:00
Ulas 0e035af492 feat: swipe gestures on shopping list items (toggle + delete) 2026-03-31 12:49:29 +02:00
Ulas 33bef8eb3f feat: wrap shopping items in swipe-row 2026-03-31 12:47:37 +02:00
Ulas dc2e874cb2 feat: add shopping swipe CSS (delete reveal, mobile button hide) 2026-03-31 12:46:26 +02:00
Ulas c74f482a0e refactor: move shared swipe CSS from tasks.css to layout.css
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:43:35 +02:00
Ulas fd94c58fea fix: hide FAB when virtual keyboard is open on mobile
Uses visualViewport resize event to detect keyboard state (viewport height
< 75% of window height). Sets body.keyboard-visible class; CSS hides
.fab and .page-fab via visibility:hidden on screens < 1024px.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:26:59 +02:00
Ulas 9446173247 fix: toast notifications no longer overlap bottom nav on mobile
Introduced --nav-bottom-height token (56px scroll + 12px dots indicator = 68px)
so that toast-container bottom and app-content padding-bottom both account for
the full nav-bottom height including the page-dots indicator.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:24:12 +02:00
Ulas 4fe4f6cb38 feat: BL-07–BL-10 — notes search, weather refresh, vCard import/export, PWA offline page
- Notes: client-side full-text search bar (filters title + content)
- Dashboard: weather refresh button + 30-min auto-refresh interval
- Contacts: vCard 3.0 export per contact (GET /:id/vcard); vCard import
  via file input with client-side parser (FN, TEL, EMAIL, ADR, NOTE, CATEGORIES)
- PWA: /offline.html served when network unavailable; cached in app-shell (sw v20)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:35:03 +02:00
Ulas d866d32336 feat: Apple CalDAV credentials form + connect/disconnect UI (BL-04)
Admin can now enter CalDAV URL, Apple-ID and app-specific password
directly in Settings; credentials are tested live before saving and
stored in sync_config (take precedence over .env); disconnect clears
DB-stored credentials without server restart. Auto-sync interval
(15 min, configurable via SYNC_INTERVAL_MINUTES) was already in place.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:27:07 +02:00
Ulas 6fd209ba5e feat: meals drag & drop between slots and days (BL-03)
Pointer Events-based drag & drop (touch + mouse compatible):
- Ghost element follows pointer; drops on empty slots move the meal,
  drops on occupied slots swap both meals via concurrent PUT requests
- prefers-reduced-motion: no ghost animation, interaction still works
- Suppress-click guard prevents accidental edit modal after drag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:23:39 +02:00
Ulas 6a860f2c13 feat(calendar): expand recurring events in GET /calendar and /upcoming
expandRecurringEvents() iterates from the event's original start date,
generating all occurrences within the requested window using the existing
nextOccurrence() service (max 1000 iterations). The SQL query is extended
to also fetch recurring events that started before the window. Event
duration is preserved across instances. Virtual instances carry
is_recurring_instance=1 and are shown with a repeat icon in the agenda
view. /upcoming expands across a 90-day forward window.

Closes BL-01.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:17:39 +02:00
Ulas 82e5b2cd85 feat(budget): auto-generate recurring entry instances per month
Adds schema migration v3 (recurrence_parent_id column + budget_recurrence_skipped
table). On every GET /api/v1/budget, the server checks all recurring originals
(is_recurring=1, no parent) and creates missing instances for the requested month
using the same day-of-month (clamped to the last day). Deleted instances are
recorded in budget_recurrence_skipped so they are not recreated on the next visit.
Generated instances are shown with a ↩ indicator in the transaction list.

Closes BL-05.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 10:13:37 +02:00
Ulas 26d3d12a22 feat(budget): add month-over-month comparison to summary cards
Each summary card (Einnahmen, Ausgaben, Saldo) now shows a trend line
comparing the current month to the previous one. The previous month's
summary is fetched in parallel via the existing /budget/summary endpoint,
so there is no extra round-trip latency. Positive deltas render in green
(▲), negative in red (▼), unchanged in neutral grey (—).

Closes BL-02.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 22:54:04 +02:00
Ulas 3e25339c86 fix: resolve event-listener leaks and CSS gaps found in code quality audit
- notes.js (Critical): move grid click listener from renderGrid() to
  render() — was re-registered on every save/pin/delete, causing
  multiple API calls per user action after several interactions
- dashboard.js (Major): introduce AbortController (_fabController) so
  the anonymous document click listener from initFab() is cancelled on
  each new render() cycle; also remove the redundant initFab() call on
  the skeleton render
- layout.css (Major): extend .label selector to include .form-label,
  covering usage in notes.js and settings.js without a mass-rename
- test-modal-utils.js (Major): 12 unit tests for wireBlurValidation,
  btnSuccess, btnError; registered as test:modal-utils in package.json
- notes.js (Minor): add btnError() shake feedback to save error handler
- calendar.js (Minor): add popup.isConnected guard to closePopup so
  the listener self-removes correctly after navigation without a click

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 22:26:49 +02:00
Ulas 36de5fa477 feat: merge UX polish v0.2.0 (14 tasks, 4 layers) 2026-03-30 22:02:03 +02:00
Ulas 0ac2769fac feat: blur-triggered inline validation and submit button feedback
Task 13: wireBlurValidation() activates error/valid state on required
fields after blur. Task 14: btnSuccess() shows a checkmark for 700ms
then closes the modal; btnError() triggers a shake animation on failure.
Both wired into the tasks form submit handler.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 21:22:36 +02:00
Ulas 1684215da8 feat: bottom sheet modal on mobile with swipe-to-close and Enter-key form navigation
- Add sheet drag handle (::before pseudo-element) and closing animation (sheet-out keyframe) for mobile < 768px in layout.css
- Add prefers-reduced-motion support disabling all modal animations
- Refactor closeModal() to extract _doClose() and play slide-out animation on mobile before removing the overlay
- Add _wireSheetSwipe() for touch drag-to-dismiss (threshold 80px)
- Extend trapFocus() Enter handler: advances focus through inputs/selects and triggers primary button on last field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 21:19:25 +02:00
Ulas b9ec36611d feat: consistent vibration feedback via vibrate() utility across modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 21:18:44 +02:00
Ulas 499ce2cd29 feat: delay install prompt, reset counter on dismiss, scroll inputs into view
- Install prompt now waits for 2 interactions before showing
- Dismiss duration reduced from 30d to 7d
- Interaction counter reset on dismiss (clean slate after 7d)
- Virtual keyboard: focused inputs scroll into view in modals (300ms delay)
2026-03-30 21:16:36 +02:00
Ulas e3e0b8081b feat: scroll focused inputs into view on virtual keyboard open 2026-03-30 17:31:09 +02:00
Ulas 4eacba2edd feat: delay install prompt until 2 interactions, reduce dismiss to 7 days
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:30:05 +02:00
Ulas 168cd387b4 fix: remove stale .meals-empty CSS, add .meal-slot--empty rule 2026-03-30 17:28:04 +02:00
Ulas 0eab480a0e style: unify all empty states to shared .empty-state class across all modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:25:13 +02:00
Ulas eb0ac95e1d fix: scope stagger selector to #budget-list in budget.js 2026-03-30 17:21:53 +02:00
Ulas bc6e759b79 feat: staggered fade-in for list items across all modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:19:33 +02:00
Ulas f4eb567219 feat: add stagger() and vibrate() UX utilities with tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:14:15 +02:00
Ulas 20792e9894 fix: sync ROUTE_ORDER with nav order, guard against navigation race condition
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:11:53 +02:00
Ulas bc3f855fa9 feat: directional slide-x page transitions in router
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:08:49 +02:00
Ulas 0dbea82a22 fix: wire page-fab and fab-main to module-accent token 2026-03-30 17:02:05 +02:00
Ulas 194728bbe9 style: tie FAB colors to per-module accent tokens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 16:55:33 +02:00
Ulas 624f3ab763 style: unify card padding to 16px across all modules 2026-03-30 16:43:05 +02:00
Ulas d1bbc9c8bb Fix inconsistent text alignment in meal cards
Force left-alignment at every level: meal-slot container, meal-card,
title, meta, and actions. Use align-self: stretch and explicit
text-align: left to prevent any parent from overriding alignment.
Left-aligned text is the correct UX choice for small scannable cards.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 16:20:12 +02:00
Ulas d3becbcf13 Remove global min-size touch target rule from pwa.css
The blanket 44px min-height/min-width on all buttons, links, and
checkboxes conflicted with the existing token-based touch target
system (--target-sm/md/lg + ::before pseudo-element expansion).
This caused oversized checkboxes in calendar (all-day toggle),
budget (recurring), and other form controls across all modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 15:57:33 +02:00
Ulas 26a42d001b Fix oversized task checkboxes and inconsistent meal text alignment
Exclude small buttons (task checkboxes, action buttons, color swatches)
from the 44px min-size rule in pwa.css — they already expand touch area
via ::before pseudo-elements. Force consistent left-alignment on meal
card titles, ingredients, and type labels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 15:51:28 +02:00
Ulas 41e88e0acf Add PWA native feel: manifest, meta tags, install prompt, SW optimization, dynamic theme-color
Configure manifest.json with scope, maskable icons, and categories. Add iOS/Android
meta tags for standalone behavior. Create pwa.css for native touch/scroll handling
and safe area insets. Add oikos-install-prompt Web Component with Chrome install
flow and iOS guidance. Optimize service worker with network-first navigation and
expanded precache (v19). Add dynamic theme-color per route and modal overlay dimming
in standalone mode. Generate placeholder icons via sharp script.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 15:35:01 +02:00
Ulas 8e01d4c749 Add theme-adaptive screenshots to README and fix manifest icons
Replace old screenshots with new mobile/tablet variants in light and dark
mode. README now uses <picture> elements with prefers-color-scheme so
screenshots automatically match the viewer's GitHub theme. Split manifest
icon purpose field into separate "any" and "maskable" entries per PWA spec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 00:42:24 +01:00
Ulas cb8b108d3c fix: Notizen-Toolbar erweitert + Essen-Widget 2×2-Grid auf Desktop
Pinnwand: Pflichtfeld-Stern entfernt, Markdown-Hinweis ergänzt,
Formatierungs-Toolbar um Unterstreichen, Durchgestrichen, Überschrift,
nummerierte Liste, Checkliste, Link, Code, Zitat und Trennlinie erweitert.
Dashboard: Essen-Widget nutzt ab Desktop 2×2-Layout statt 4×1 für
bessere Lesbarkeit der Mahlzeiten-Labels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 15:31:50 +01:00
Ulas 2f0b0c05ec feat: Notizen — automatische Textkontrastfarbe + Formatierungs-Toolbar
Kontrastproblem: Titel, Inhalt und Footer-Elemente der Notizkarten
überschrieben die Inline-Textfarbe mit festen Token-Werten. Jetzt
erben alle Elemente die adaptiv berechnete Farbe (dunkel auf hellen
Karten, hell auf dunklen).

Formatierungs-Toolbar: Fett, Kursiv und Liste als Buttons über dem
Textfeld im Editor. Fügt Markdown-Syntax ein, unterstützt Selektion
und Tastaturkürzel (Strg+B, Strg+I). Markdown-Rendering bleibt
unverändert.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 09:05:28 +01:00
Ulas cacec64777 fix: Dashboard-Widgets zeigen jetzt alle offenen Aufgaben und neueste Notizen
Aufgaben-Widget zeigte nur high/urgent Tasks mit Fälligkeit ≤48h,
Pinnwand-Widget nur explizit gepinnte Notizen. Neue Einträge waren
dadurch im Dashboard unsichtbar.

- Aufgaben: alle offenen Tasks (sortiert nach Priorität), Limit 5
- Notizen: neueste 3 (gepinnte zuerst, dann nach Aktualisierung)
- Greeting-Chip zählt weiterhin nur high/urgent Tasks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 23:30:00 +01:00
Ulas 31b9760bc3 fix: SW-Cache-Version bumpen + fetch cache:no-store für API-Aufrufe
Dashboard-Widgets aktualisierten nicht, weil der Service Worker die
alte router.js aus dem Cache servierte (stale-while-revalidate).
Cache-Version v15→v16 erzwingt Invalidierung aller gecachten Dateien.
Zusätzlich fetch cache:no-store auf allen API-Aufrufen als Absicherung.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 23:24:11 +01:00
Ulas a7214f81e6 fix: 4 Bugs behoben — Dark-Mode Inputs, Essensplan, Dashboard-Refresh, Mengenfeld
1. Dark Mode: .form-input hatte kein Styling, Browser-Default führte zu
   weißem Text auf weißem Hintergrund. Jetzt mit .input zusammengefasst.
2. Essensplan: DATE_RE fehlte im Import (ReferenceError), db.transaction()
   wurde doppelt aufgerufen (3 Stellen).
3. Dashboard: Router-Guard verhinderte Re-Render bei Rücknavigation,
   Widgets zeigten veraltete Daten.
4. Einkaufsliste: Mengenfeld hatte abweichende Hintergrundfarbe und
   überdimensionierte min-height.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 23:13:15 +01:00
Ulas d69c5a0413 feat: Wetter-Widget responsive über volle Breite im Desktop-Dashboard
Auf Desktop wird das Wetter-Widget über allen anderen Widgets platziert
mit horizontalem Layout (aktuelles Wetter links, Vorhersage rechts).
Vorhersagezeitraum skaliert mit Bildschirmbreite: 3 Tage (Mobil),
4 Tage (Tablet), 5 Tage (Desktop/Wide).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 15:20:55 +01:00
ulsklyc e4760473a7 fix: Login-Seite zentriert + Hero-Bereich mit Tagline über dem Formular
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 14:29:31 +01:00
ulsklyc 5a2e2d3c48 a11y: prefers-reduced-motion Fix (Redesign Phase H)
- animation-duration/transition-duration: 0.01ms → 0s (kein Flicker)
- animation-delay: 0s hinzugefügt
- animation-iteration-count entfernt (unnötig bei duration 0s)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 13:51:58 +01:00
ulsklyc 4cd3299f38 a11y: --text-2xs Token entfernt, 12px Minimum (Redesign Phase G)
- --text-2xs (11px) aus tokens.css gelöscht
- Alle 8 Referenzen → --text-xs (12px) migriert:
  Nav-Labels, Badges, Event-Time, Meal-Slots, Avatare
- 12px Mindestgröße für alle sichtbaren Texte (Mobile-PWA-Lesbarkeit)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 13:50:31 +01:00