Commit Graph

140 Commits

Author SHA1 Message Date
Ulas Kalayci 7b04d5a48a fix: resolve design token violations and locale bug
- Add --color-warning-translucent and --color-soon tokens to tokens.css
- Replace hardcoded font-size 1.4rem with var(--text-xl) in dashboard.css
- Replace hardcoded rgba color with var(--color-warning-translucent)
- Remove duplicate .task-item__meta--overdue rule
- Fix hardcoded 'de-DE' locale: use formatTime() from i18n.js
- Fix formatDueDate: don't show time (23:59) when no due_time is set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 23:38:56 +02:00
Konrad M. 9f092ff633 fix(dashboard): FAB shortcut opens add modal directly on target page
After navigating to tasks/calendar/shopping/notes via FAB, the page's
primary add-button is programmatically clicked so the new-item modal
opens without a second tap. FAB container right-margin doubled to avoid
overlap with the browser's edge-swipe gesture zone.
2026-04-21 22:18:14 +02:00
Konrad M. eede4a9708 fix(dashboard): flatten header; replace greeting with date+time; split overdue/soon chips
Header shows current date and time instead of user name + separate date line.
urgentCount replaced by overdueCount (overdue tasks) and dueSoonCount (due today/soon),
each with a distinct chip color. formatDueDate updated to accept due_time and return
accurate overdue/soon states against the current moment.
dashboard grid expands to 4 columns at 1280px instead of 1440px.
2026-04-21 22:18:14 +02:00
Konrad M. 8f36c359aa fix(dashboard): fix widget nav button on iOS; lift header above backdrop-filter
widgetHeader replaces <a href> with <button type="button"> so iOS Safari
does not intercept the touch event before the JS click handler fires.
widget__header gets position: relative; z-index: 2 to appear above the
backdrop-filter ::after pseudo-element stacking context.
2026-04-21 22:18:14 +02:00
Konrad M. c6c02f0f30 fix(dashboard): show external calendar name and location in upcoming events
Imports fmtLocation; renderUpcomingEvents adds event-item__cal span for
cal_name and shows location with normalized ICS escapes via fmtLocation().
Event color dot gets filter: saturate(0.4) to match calendar view style.
2026-04-21 22:18:14 +02:00
Konrad M. e729bc9c4e fix(layout): refactor page transition animations; expand sidebar at 1440px
Page-in animations drop 'forwards' fill mode — a .page-transition base class
(opacity:0) serves as the initial state, and .page-transition--in-{left,right}
force opacity:1 after the animation ends, preventing a flash-back-to-invisible
on some WebKit versions. Sidebar expands at 1440px instead of 1280px.
Glass desktop toolbar loses the rounded card border in favour of a flat
accent-top-border + bottom border consistent with other module headers.
2026-04-21 22:18:14 +02:00
Konrad M. 68645d2483 fix(layout): prevent horizontal overflow in modals, sheets, and input fields
Modal overlay gets overflow: hidden; sheet scroll container gets overflow-x: hidden
to stop content bleed on narrow viewports. Inputs get min-width: 0 and
box-sizing: border-box so they cannot overflow two-column grid containers.
2026-04-21 22:18:14 +02:00
Konrad M. 28e2ca6b01 fix(pwa): fix bottom nav safe-area padding causing extra gap on iOS
pwa.css safe-area padding-bottom rule and body::after fill-overlay commented out.
glass.css nav-bottom uses margin-bottom: 0 instead; --hidden state uses
translateY(100%) + negative margin so the bar disappears without leaving a gap.
layout.css removes redundant padding-bottom from .nav-bottom rule.
2026-04-21 22:18:14 +02:00
Konrad M. 879485c588 feat(ui): add module accent top border to shopping and budget page headers
Adds border-top: 3px solid var(--module-accent) to .list-tabs-bar
and .budget-nav, matching the visual style of other module toolbars.
2026-04-21 22:18:14 +02:00
Konrad M. ab35d6fb93 fix(reminders): use minmax grid columns to prevent field overflow 2026-04-21 22:18:14 +02:00
Konrad M. 88a1a78743 fix(tasks): reorder toolbar buttons; wrap list in tasks-body; remove flex-wrap on mobile
group-mode toggle moved before view toggle in markup order.
Filter panel, task list, and FAB wrapped in .tasks-body for scroll containment.
tasks-toolbar flex-wrap removed — actions stay on one line on narrow screens.
2026-04-21 22:18:14 +02:00
Konrad M. bf1df5d8e0 fix(calendar): constrain allday-cell width; change agenda event indicator to full-height bar
allday-cell gets min-width: 0; overflow: hidden so long event titles
no longer stretch week-view column widths beyond their grid allocation.
Agenda event color dot replaced by a 3px full-height left bar matching
the dashboard upcoming-events style (align-items: stretch on parent).
2026-04-21 22:18:14 +02:00
Serhiy Bobrov 0b54fe255b feat: add recipes module with CRUD functionality and integrate with meals
- Implemented new recipes page with UI for managing recipes.
- Added REST API routes for recipes including create, read, update, and delete operations.
- Introduced database schema for recipes and recipe ingredients.
- Updated meals to link with recipes, allowing meals to reference specific recipes.
- Enhanced validation for recipe-related fields in meals.
- Added styles for the recipes page and components.
2026-04-21 14:15:39 +02:00
ulsklyc d1ec7367a0 fix(auth): resolve post-login navigate race condition and add version display (#68) (#70)
Root cause: when auth.me() failed during initial navigation, the catch block
called navigate('/login') without clearing _pendingLoginRedirect. The outer
finally then fired a second concurrent navigate('/login'), which held
isNavigating=true while running. If the user submitted the login form (or
iCloud Keychain autofilled credentials) before the second navigation
completed, navigate('/', user) was silently blocked by the isNavigating guard —
login appeared to succeed but the app never advanced to the dashboard.

Fix: clear _pendingLoginRedirect in the catch block so the finally handler
does not spawn the duplicate navigation.

Also adds a GET /api/v1/version endpoint (no auth required) and shows the
version on the login page, so users can verify their PWA has received the
latest cached JS.

Resolves #68

Co-authored-by: Ulas Kalayci <ulas.kalayci@googlemail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 08:19:53 +02:00
Ulas Kalayci 4f7b73cf81 chore: release v0.20.32
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 12:05:40 +02:00
Ulas Kalayci ecd4453b71 chore: release v0.20.31
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 11:02:00 +02:00
Ulas Kalayci 66f4cda41b chore: release v0.20.30
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 10:53:56 +02:00
Ulas Kalayci 24dca4ed19 chore: release v0.20.29
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 10:50:55 +02:00
Ulas Kalayci 09b339e5f9 fix: use CSS media query as authoritative dark mode source for system preference 2026-04-20 10:37:24 +02:00
Ulas Kalayci e48d249fbe chore: release v0.20.24
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 10:05:12 +02:00
Ulas Kalayci aae895d704 feat: filter panel + english category keys
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 09:50:55 +02:00
Ulas Kalayci b867917995 feat: kanban touch drag, swipe undo, dashboard task deep-link
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 09:44:50 +02:00
Ulas Kalayci c8e20b22c8 chore: release v0.20.21
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:36:07 +02:00
Ulas Kalayci 87be39364d chore: release v0.20.20
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:17:30 +02:00
Ulas Kalayci 40fc080c3a chore: release v0.20.19 2026-04-20 07:09:07 +02:00
Ulas Kalayci 18c90653d4 refactor: dark-mode token deduplication via private-variable indirection (v0.20.17)
All tokens with dark-mode overrides gain a private --_name counterpart in :root.
Public tokens (--color-*, --module-*, --glass-* etc.) become stable var(--_name)
references. Both dark blocks now only override compact private tokens — no more
manual two-block sync for every future colour change.

Also removes the redundant --color-surface-2 dark override (already auto-derived
via var(--neutral-50)). No visual change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 06:53:08 +02:00
Ulas Kalayci e89f4259bc chore: complete colour-redesign follow-up — PWA theme sync, glass tokens, print normalisation (v0.20.16)
- index.html: theme-color #2563EB → #4F46E5 (Indigo-600)
- oikos-install-prompt.js: CSS fallback #2554C7 → #4338CA; #fff → var(--color-text-on-accent)
- tokens.css: add --glass-inset-{soft,base,medium,elevated,strong} tokens
- glass.css: replace 9 inset rgba() literals with --glass-inset-* token refs
- tasks.css: replace 1 inset rgba() literal with --glass-inset-base
- layout.css: normalise @media print shorthand hex to six-digit notation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 22:22:30 +02:00
Ulas Kalayci c567ff17e4 chore: release v0.20.15 — colour redesign + nav-badge visibility fix
Bundles the Indigo accent migration, module-colour decoupling, WCAG
contrast improvements and nav-badge base-style relocation into one
release. See CHANGELOG.md [0.20.15] for full details.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 22:16:07 +02:00
Ulas Kalayci 888cd05437 fix: move nav-badge styles to layout.css so badge stays visible on all pages
The .nav-badge base styles (background, size, color) were defined in tasks.css,
which is dynamically unloaded when navigating away from /tasks. This caused the
overdue badge in the nav to become invisible on every other page, even though
the badge element remained in the DOM.

Also refactors subtask checkbox icon to use a CSS class instead of inline styles.

Resolves #56

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 22:10:06 +02:00
Ulas Kalayci 847eaf6927 fix: remove executable bit from layout.css 2026-04-19 18:07:21 +02:00
Ulas Kalayci d656ad8bfc fix: use space token for nav-badge offset instead of hardcoded -4px 2026-04-19 18:06:38 +02:00
Ulas Kalayci 573ba52f63 fix: anchor overdue badge to icon via runtime wrapper (#56)
Root cause: the badge was `position: absolute` relative to the entire
`.nav-item`, which stretches to `flex: 1` on mobile (up to ~75 px wide).
With `right: 4px` the badge sat far from the icon on the bottom bar and
overlapped label text in the expanded desktop sidebar.

Fix: `updateOverdueBadge()` now wraps the nav icon in a
`.nav-item__icon-wrap` span (created once, reused on subsequent calls).
The badge is appended there instead of to the nav item root.

CSS changes:
- Remove `.nav-item .nav-badge` positional override
- Add `.nav-item__icon-wrap { position: relative; display: inline-flex }`
- Add `.nav-item__icon-wrap .nav-badge { position: absolute; top: -4px; right: -4px }`

The badge now consistently overlays the top-right corner of the icon
across all nav layouts (mobile column, collapsed sidebar row, expanded
sidebar row with label).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 17:26:12 +02:00
ulsklyc ccb41a056e fix: position overdue nav-badge absolutely to avoid flex layout distortion (closes #56) (#57)
The nav-badge was appended as an in-flow flex child, breaking nav-item
layout: on mobile (column flex) it appeared below the label, on desktop
sidebar (row flex + justify-content:center) it was pushed far right via
margin-left:auto. Fix positions it absolutely within the nav-item and
uses DOM API instead of insertAdjacentHTML per project convention.

Co-authored-by: Ulas Kalayci <ulas.kalayci@googlemail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 13:30:32 +02:00
Ulas Kalayci 3c2a2fe6e9 fix: resolve modal header scroll-behind issue on iOS PWA (closes #50)
position: sticky on .modal-panel__header failed on iOS WebKit when the
scroll container had padding-top applied (drag-handle spacing). Restructured
modal layout: .modal-panel is now a flex-column with overflow:hidden and
.modal-panel__body handles scrolling (overflow-y:auto, flex:1). The header
is a non-scrolled flex sibling, so it stays visible without sticky. Updated
swipe-to-close to read .modal-panel__body scroll position.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 07:19:42 +02:00
Ulas 66816a4f88 fix: resolve iOS PWA bottom space and keyboard zoom issues
- pwa.css: body::after now uses var(--glass-bg) matching the nav's glass
  background exactly; z-index lowered to z-nav-1 so the nav renders
  on top in the overlap area (safe-area padding), removing the visible
  color mismatch that appeared as empty space
- router.js: add iOS focusin/focusout handlers that temporarily set
  maximum-scale=1 on input focus to prevent WKWebView auto-zoom;
  restores original viewport content 150ms after blur so manual
  zoom remains available for accessibility
2026-04-16 15:35:03 +02:00
Ulas 5bd80b1333 fix: reduce page transition lag on Android (closes #48)
Two causes of ~1s navigation delay fixed:

1. glass.css Section 19 was extending the page-in animation from 0.20s
   to 0.30s using spring easing. Reverted to 0.20s in / 0.12s out.

2. During transitions, dozens of backdrop-filter layers (widgets, cards,
   inputs, toolbars) were composited simultaneously for both the outgoing
   and incoming page, overloading mid-range Android GPUs.
   Added html.navigating class: router.js sets it at transition start,
   glass.css overrides all app-content backdrop-filters to none while
   active, animationend removes it once the in-animation completes.
2026-04-16 13:50:38 +02:00
Ulas a7ac7d105c fix: remove will-change from nav-bottom and add iOS height fallback
will-change: transform on a position:relative flex child causes iOS WebKit
to composite the element at an incorrect position - creating a visible gap
below the nav bar. Remove it; CSS transform transitions use hardware
acceleration automatically on modern iOS without this hint.

Add -webkit-fill-available before 100dvh on .app-shell as a fallback for
iOS WebKit versions where 100dvh is computed slightly smaller than the
actual WKWebView height.
2026-04-16 12:48:43 +02:00
Ulas 51f211d72a fix: resolve iOS PWA bottom nav positioning via flex layout
Switch .nav-bottom from position: fixed to a flex child of .app-shell.
With position: fixed and will-change: transform (used for the hide/show
animation), iOS compositor layers can misplace the element. As a flex
child (position: relative; flex-shrink: 0) at the end of a height: 100dvh
container the nav is guaranteed to sit flush at the physical screen bottom.

Remove padding-bottom clearance from .app-content, .tasks-page and
.dashboard - no longer needed since the nav no longer overlaps the
content area.
2026-04-16 09:59:16 +02:00
Ulas fc8a4ce046 fix: match nav-bottom blur style in safe-area body::after on iOS PWA 2026-04-16 09:19:04 +02:00
Ulas e384ae1037 feat: add reminders for tasks and calendar events (closes #13)
- DB migration #8: reminders table (entity_type, entity_id, remind_at, dismissed, created_by)
- REST API: GET /pending, GET /?entity, POST /, PATCH /:id/dismiss, DELETE
- Client polling module (reminders.js): 60s interval, toast + Browser Notification API
- Tasks: enable reminder with custom date/time in edit modal
- Calendar: reminder offset selector (at time / 15min / 1h / 1d before)
- Bell badge shows pending count; reminders auto-dismiss after 30s or on user action
- SW shell cache updated to include reminders.js + reminders.css
- 11 new DB tests covering CRUD, pending query, dismiss, upsert, cascade delete, constraints
2026-04-15 11:40:24 +02:00
Ulas d16919ef7c feat: per-ingredient category selection for shopping list transfer (closes #33)
When adding ingredients in the meal editor, each ingredient now has a
category dropdown. Categories are stored on the ingredient and applied
automatically when transferring to the shopping list, so items appear
pre-grouped by category without manual re-sorting.
2026-04-15 07:11:49 +02:00
Ulas d6d2c41bfa fix: eliminate black gap below bottom nav in iOS PWA standalone mode
iOS reserves the home indicator area outside the CSS viewport, leaving
a black strip below the bottom navigation. A fixed body::after pseudo-
element now fills this zone with the surface color. Also added explicit
background-color on body for consistent rendering.
2026-04-14 23:02:06 +02:00
Ulas f988ab348f fix: improve accessibility and tokenize remaining hardcoded CSS values
- FAB focus ring: double-ring pattern replacing invisible #fff outline
- forced-colors media query for Windows High Contrast Mode
- New tokens: --color-accent-secondary, --content-max-width-narrow, --cal-hour-height
- Apple sync logo uses semantic tokens for correct dark mode inversion
- Sidebar logo gradient references token instead of hardcoded #7C5CFC
2026-04-14 18:05:19 +02:00
Ulas 8f96e066f3 feat: customizable dashboard layout (#32)
Users can now show/hide widgets and reorder them via a settings button
in the greeting header. Configuration is persisted server-side in
sync_config (dashboard_widgets key) and shared across all family members.

- Greeting widget gets a settings icon button opening a customize modal
- Modal lists all widgets (tasks, calendar, shopping, meals, notes,
  weather) with toggle switches and up/down reorder buttons
- Reset to default layout available in the modal
- GET /preferences now returns dashboard_widgets; PUT accepts it
- All 10 locales updated with new i18n keys
2026-04-14 08:04:26 +02:00
Ulas 6f532e45ec feat: Liquid Glass Phase 4 - vibrancy, module tint, deeper glass penetration
Dashboard widgets, task cards, note items, meal slots, form inputs,
toolbars, and FAB actions now use semi-transparent glass backgrounds
with backdrop-filter blur. Each surface gets a subtle module accent
color tint via color-mix gradient overlay. App background uses a
radial accent gradient for ambient vibrancy.

New tokens: --glass-bg-card, --glass-bg-input, --glass-bg-toolbar,
--glass-tint-strength with full dark mode and accessibility overrides.
2026-04-14 07:35:59 +02:00
Ulas 3bc926d766 fix: iOS PWA bottom nav shifting up in standalone mode
In iOS WebKit standalone (home screen) mode, position:fixed elements
move with the page when the body itself becomes scrollable - unlike
regular Safari where fixed elements stay pinned. The root cause was
body having min-height: 100dvh without overflow: hidden, which allowed
body scroll to occur when content overflowed.

Fix: html and body are now overflow: hidden with fixed height (100% / 100dvh)
so all scrolling is confined to .app-content. Service worker bumped to
shell-v30 to force re-download of reset.css on installed PWAs.
2026-04-13 22:17:31 +02:00
Ulas 5a2bc5cdb1 fix: Safari < 18 glass UI - webkit backdrop-filter @supports fallback
- All @supports checks extended to include or (-webkit-backdrop-filter: blur(1px))
  so Safari < 18 (which only recognizes the -webkit- prefix) no longer skips
  the entire @supports block and receives no glass styles at all
- Non-blur glass styles (background-color, border, box-shadow) moved outside
  @supports blocks - always active on all browsers regardless of blur support
- Capsule buttons, specular highlights, glass borders and shadows now visible
  on all devices, blur effects added on top where supported
2026-04-13 22:02:23 +02:00
Ulas 37a783b9c7 fix: resolve CSS load-order conflicts between glass.css and module stylesheets
- dashboard.css: move .widget glass styles (shadow, border, ::before highlight)
  directly here since module CSS loads after glass.css and would override it
- tasks.css: move .filter-chip--active glass state and fix .priority-badge
  border-radius to use --radius-glass-chip (capsule) instead of --radius-xs
- glass.css: remove dead .sticky-header rule (class not used in HTML) and
  remove duplicate .widget rules now handled by dashboard.css
2026-04-13 21:12:09 +02:00
Ulas 2a2249182e feat: Phase 3 - Micro-Interactions + Polish
glass.css - Phase 3 Ergänzungen:

Nav Auto-Hide (Section 18):
- .nav-bottom: will-change: transform + transition für smooth slide
- .nav-bottom--hidden: translateY(100% + safe-area) + pointer-events: none

Modal Spring-Entrance (Section 19):
- Desktop: glass-modal-scale-in mit --ease-glass (spring overshoot)
  0.32s, scale(0.90) → scale(1) + translateY(8px) → 0
- Mobile: glass-sheet-in, sanfterer Slide (40% statt 100%) + opacity ramp
- Beide Animationen ersetzen die linearen layout.css-Varianten

Seitentransitionen (Section 20):
- In-Animationen: 0.30s mit --ease-glass statt 0.20s ease
- Out-Animationen: 0.14s mit --ease-out (schnell raus, langsam rein)

List-Stagger (Section 21):
- 0.28s + --ease-glass für physikalisch plausibleren Erscheinungseffekt

Focus-Ring (Section 22):
- transition auf outline-offset + box-shadow für sanften Focus-Pop

Skeleton Shimmer (Section 23):
- 105° Gradient mit glass-highlight-Tint statt flat-grey
- Hellerer Mittelpunkt simuliert Lichtreflexion

FAB Attention Pulse (Section 24):
- Einmaliger Ring-Expand 0.6s nach Erscheinen (fab-ring-pulse)
- Kombinierte animation-Deklaration mit fab-in

Accessibility (Section 25):
- prefers-reduced-motion deaktiviert alle Phase-3-Animationen

router.js:
- initNavHideOnScroll(): scroll-Listener auf #main-content
  versteckt .nav-bottom beim Runterscrollen (+ 4px Hysterese)
  zeigt wieder beim Hochscrollen (- 4px) oder bei < 10px
  nur aktiv bei < 1024px (Mobile/Tablet, kein Desktop)
- wird in renderAppShell() nach initBottomNavSwipe() aufgerufen
2026-04-13 17:11:38 +02:00
Ulas d27216203f feat: Phase 2 - Glass Modul-Komponenten
glass.css - Phase 2 Ergänzungen:

Form-Inputs:
- Glass-Border (--glass-border-subtle) + verbesserter Focus-Ring
  mit color-mix-basiertem Glow statt einfacher box-shadow
- Modal-Inputs: explizit --color-surface-2 als Hintergrund

Sticky Headers:
- backdrop-filter auf --blur-sm + saturate(160%) mit Glass-Tokens
- Hintergrund 80% opak statt 90% für mehr sichtbaren Blur-Effekt
- Glass-Border unten

Toasts:
- --radius-glass-card (20px) statt --radius-sm
- Standard-Toast: Dark-Glass mit backdrop-filter
- Farbige Toasts: specular inset-highlight

Filter-Chips:
- Inaktiv: --glass-border-subtle
- Aktiv: Glass backdrop-filter + Accent-Tint + specular highlight

Priority Badges:
- Capsule-Radius (--radius-glass-chip)
- 1px semi-transparente Farb-Border

Toggle Switch:
- Specular Highlight + Gegenlicht auf Thumb via inset box-shadow
- Animation verwendet --transition-glass Easing

Dashboard Widgets:
- Glass-Border + --glass-shadow-sm
- Specular ::before Highlight-Linie oben

FAB-Backdrop (Dashboard):
- blur(4px) + 18% Dimming statt 25%

contacts.css, notes.css, shopping.css:
- Search-Inputs direkt auf Glass-Tokens migriert
  (--radius-glass-button, --glass-border-subtle, Glass-Focus-Ring)
2026-04-13 17:05:19 +02:00