Commit Graph

78 Commits

Author SHA1 Message Date
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 62bb3546a8 chore: bump version to 0.20.3 2026-04-16 09:20:25 +02:00
Ulas 9ef9680e82 chore: bump version to 0.20.2 2026-04-16 08:17:06 +02:00
Ulas dfd809c284 chore: bump version to 0.20.1 2026-04-15 18:16:56 +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 44d1b88e3d fix: resolve iOS forbidden errors by delivering CSRF token in response body
iOS Safari (especially PWA/standalone mode) unreliably exposes cookies
via document.cookie, causing CSRF token mismatch on state-changing
requests. The CSRF token is now included in /auth/login and /auth/me
response bodies and stored in-memory on the client. Cookie remains as
fallback. Retry mechanism also improved to read token from response
body and handle expired sessions.
2026-04-14 18:53:42 +02:00
Ulas b152d0e53f feat: add arm64 Docker image support (closes #44)
Add QEMU and multi-platform build (linux/amd64 + linux/arm64) to
GitHub Actions workflow, enabling self-hosting on Raspberry Pi and
other ARM64 devices.
2026-04-14 18:45:31 +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 e33c792083 chore: release v0.19.1 - iOS PWA forbidden fix 2026-04-14 17:38:38 +02:00
Ulas 8af730e9cf feat: add Japanese, Arabic, Hindi, Portuguese locales + new currencies
- 4 new locale files (ja, ar, hi, pt) with 567 keys each - full coverage
- Japanese (日本語): Hiragana/Kanji script
- Arabic (العربية): RTL-ready text
- Hindi (हिन्दी): Devanagari script
- Portuguese (Português): Brazilian Portuguese
- SUPPORTED_LOCALES updated in i18n.js (10 → 14 locales)
- LOCALE_LABELS updated in oikos-locale-picker.js
- New currencies: AED, BRL, INR, SAR added to budget settings
- Service Worker v31: new locale files pre-cached in APP_SHELL
- Docs: README, SPEC.md, BACKLOG.md, CHANGELOG.md updated
2026-04-14 10:28:17 +02:00
Ulas 3f387b616e fix: default TRUST_PROXY to 1 for Docker+reverse-proxy setups (#46)
With the previous default of 'loopback', Express ignored X-Forwarded-Proto
headers from Caddy/nginx when running in Docker (bridge IP, not loopback).
This caused req.secure=false, which made express-session silently drop the
session cookie on login - resulting in a 401 on every subsequent request.

Changing the default to 1 (trust one proxy hop) fixes this for all standard
Docker+reverse-proxy deployments without requiring manual configuration.
2026-04-14 09:04:06 +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 35186ca87f fix: change SameSite=Strict to SameSite=Lax for session and CSRF cookies (#46)
Safari's ITP blocks Strict cookies on certain navigations (direct URL entry,
reverse proxy context), resulting in a 401 on login even with valid credentials.
Lax is safe: CSRF attacks are prevented by the double-submit token and the
HTTPS-only secure flag. Firefox and Chrome were unaffected.
2026-04-13 21:36:35 +02:00
Ulas bd21a890e9 chore: release v0.17.1 - glass CSS load-order fixes 2026-04-13 21:13:17 +02:00
Ulas 70cf691f56 chore: release v0.17.0 - Liquid Glass redesign
Bump version to 0.17.0, update CHANGELOG with full Phase 0-3 glass layer
changes, and update SPEC.md design system documentation with glass tokens,
glass.css layer architecture, and corrected color token values.
2026-04-13 17:19:05 +02:00
Ulas 2dc8984c3e feat(shopping): custom categories - add, rename, delete and reorder (#26)
- New DB table shopping_categories (migration v5) seeds 9 default
  categories with Lucide icons and sort_order
- Backend CRUD routes: GET/POST/PUT/DELETE /shopping/categories
  plus PATCH /shopping/categories/reorder
- Category validation now uses DB instead of hardcoded constant;
  items of deleted category are moved to the next available one
- Frontend shopping page loads categories from API, dropdown and
  grouping reflect custom order dynamically
- Settings -> Shopping section: list categories with up/down buttons,
  click-to-rename, delete with confirmation; add new categories inline
- i18n keys added in de/en/sv/it
2026-04-05 17:24:06 +02:00
Ulas cde511da1d docs: update README, installation guide and GitHub Pages
- README: GHCR badge, Kanban quick-status buttons and configurable
  currency mentioned in highlights
- installation.md: Option A (pre-built image, no clone) as primary path,
  Option B (build from source) as alternative; Updates section updated;
  SQLCipher troubleshooting tip added
- index.html: Get Started block now shows pre-built image path;
  task and budget feature cards updated (EN + DE translations)
2026-04-05 16:29:12 +02:00
Ulas 7292b14945 feat(docker): use pre-built GHCR image in docker-compose by default (#25)
docker-compose.yml now references ghcr.io/ulsklyc/oikos:latest so users
can start the app with a single 'docker compose up' without cloning or
building locally. The build: . entry is retained for contributors who
want to build from source with --build.

README Quick Start updated to document both the no-clone path (curl
docker-compose + .env.example) and the build-from-source path.
2026-04-05 16:20:24 +02:00
Ulas 19a7161307 feat(tasks): add quick-status button to kanban cards (#24)
Adds a small button on each kanban card that cycles the task status
(open → in_progress → done → open) without requiring drag-and-drop.
Useful for touch devices and kiosk browsers (e.g. Fully Kiosk Browser)
where drag-and-drop is unavailable. All four locales updated.
2026-04-05 16:16:46 +02:00
Ulas 31a9538518 chore: bump version to 0.11.6 2026-04-05 14:47:12 +02:00
Ulas a8275f5ec9 chore: bump version to 0.11.5 2026-04-05 13:50:03 +02:00
Ulas 014873f516 chore: bump version to 0.11.4 2026-04-05 13:24:17 +02:00
Ulas 3a6ae4a64a feat(i18n): add Swedish (sv) translation and Italian as explicit language option (#19)
Swedish translation contributed by @olsson82 (PR #19), integrated with
minor corrections (dayShortSunday: Sun → Sön, amountLabel aligned with
v0.11.2, new v0.11.2 currency keys added).

Italian was already supported server-side but is now explicitly listed
in the locale picker alongside German, English, and Swedish.
2026-04-05 12:01:16 +02:00
Ulas 446b9b1388 feat(budget): configurable currency in settings (#20)
Add household-wide currency preference for the budget section.
Users can select from 13 currencies (EUR, USD, GBP, SEK, NOK, DKK,
CHF, PLN, CZK, HUF, JPY, AUD, CAD) in Settings → Budget.

- preferences API (GET/PUT) now includes currency field
- budget page loads currency from preferences on render
- formatAmount() uses locale-aware Intl.NumberFormat with chosen currency
- settings page gains a Budget section with a currency select
- all three locales (de, en, it) updated with new i18n keys
2026-04-05 11:55:38 +02:00
Ulas 212a8bdb0a fix(dashboard): filter todayMeals by visible_meal_types preference (#14)
The dashboard meal widget was showing all meal types regardless of the
household meal visibility settings configured in Settings > Meal Plan.

Root cause: the todayMeals SQL query in dashboard.js did not read
visible_meal_types from sync_config. The Meals page applied this filter
client-side, but the dashboard API returned unfiltered data.

Fix: read visible_meal_types from sync_config before the query and inject
the active types as IN (?) placeholders. Falls back to all four types when
no preference is stored.
2026-04-05 03:12:01 +02:00
Ulas 0940afc170 chore(release): v0.11.0
Bump version and update CHANGELOG for release v0.11.0.
2026-04-05 03:09:06 +02:00
Ulas 08159ec8b4 feat(meals): customizable meal type visibility in Settings (#14)
Users can now toggle which meal types (breakfast, lunch, dinner, snack)
are displayed in the meal planner via a new Settings section. Preference
is stored household-wide in sync_config and applied as a filter on the
meals page. Includes preferences API, i18n (DE/EN/IT), and Settings UI.
2026-04-04 22:51:57 +02:00
Ulas 0421b540cd feat(tasks): persist view mode and support ?view=kanban URL parameter
View mode (list/kanban) is now saved to localStorage and restored on
page load. URL parameter ?view=kanban takes precedence, enabling tablet
kiosk setups to default to Kanban view. Toggle buttons reflect the
active view correctly on initial render.

Closes #17
2026-04-04 22:34:29 +02:00
Ulas 2c36fa0307 feat(tasks): add optional "none" priority level for tasks without urgency
New tasks default to "none" priority instead of "medium". Tasks with no
priority hide the badge in list and dashboard views, reducing visual noise
for routine items. Includes DB migration v4 and i18n keys (de, en, it).

Closes #15
2026-04-04 22:13:51 +02:00
Ulas 2508473265 fix(pwa): fix UI overlap, scroll bleed and wrong nav height on iOS
Three root causes fixed:

1. Double safe-area padding: pwa.css set padding-top/bottom on body
   globally, but page containers already account for safe-area-inset
   in their height calculations. Removed body vertical padding (kept
   only in standalone media query for padding-top).

2. Wrong nav token: all page containers used --nav-height-mobile (56px)
   instead of --nav-bottom-height (68px = 56px scroll + 12px dots),
   causing 12px of content to render behind the bottom nav.

3. Scroll bleed: fixed-height page containers lacked overflow:hidden,
   allowing scroll events to propagate to the body. Added
   overscroll-behavior-y:contain on app-content globally.

Fixes #16
2026-04-04 22:02:19 +02:00
Ulas 7eb06ed905 fix(modal): replace native prompt() with custom modal dialogs
Native browser prompt() is unreliable on mobile browsers and PWAs,
often requiring multiple clicks to close. Replace all prompt() calls
with custom promptModal() and selectModal() functions that use the
existing modal system with proper focus management and animations.

Affected pages: shopping (create/rename list), tasks (add subtask),
meals (choose shopping list).

Fixes #12
2026-04-04 21:31:50 +02:00
Ulas c93be9049c feat(dashboard): add shopping list widget
Show shopping lists with open items directly on the dashboard.
Each list displays a progress bar, the first few unchecked items,
and a "+N more" overflow indicator. Widget only appears when there
are lists with open items.

Backend: new shoppingLists query in /api/v1/dashboard (up to 3 lists,
6 open items each). Frontend: renderShoppingLists() widget following
existing widget pattern. CSS: compact list/progress/item styles.
i18n: shoppingMore key added to de/en/it.

Requested in discussion #9
2026-04-04 14:30:31 +02:00
Ulas 47b34c4829 fix(modal): add fallback timer for mobile close animation
On mobile, closeModal() relies on the CSS animationend event to call
_doClose(). When the animation does not fire (prefers-reduced-motion,
tab switch, browser quirk), the modal stays stuck and the user cannot
dismiss it. A 300ms fallback timer now guarantees cleanup runs.

Reported in discussion #9
2026-04-04 14:16:00 +02:00
Ulas 597c2602aa fix(i18n): translate category names in tasks and budget displays
Category group headers in tasks and bar chart labels / transaction meta
in budget were showing raw German database keys instead of going through
CATEGORY_LABELS() i18n mapping.

Closes #11
2026-04-04 14:08:41 +02:00
Ulas 6454c1fc9f chore: bump version to v0.7.5 and update changelog 2026-04-04 07:27:42 +02:00
Ulas 1c7b77401d chore: bump version to v0.7.4 and update changelog 2026-04-04 06:51:38 +02:00
Ulas 364d029950 fix(ux): prevent iOS auto-zoom on inputs + lazy-load page CSS
Increase font-size to 16px on mobile for shopping quick-add inputs,
notes search, and contacts search. Desktop breakpoint restores compact
sizes. Move 9 page-specific stylesheets from index.html to on-demand
loading in router.js, reducing initial CSS payload.
2026-04-04 06:39:45 +02:00
Ulas 70c1291ae7 fix(a11y): skip-link target, priority labels, greeting tokens
- Rename #page-content to #main-content so skip-to-content link
  targets the semantic <main> landmark
- Add sr-only priority labels to dashboard task items for screen
  readers (WCAG 1.4.1 color-not-only)
- Replace hardcoded hex in greeting gradient with accent tokens
  so dark mode themes the banner correctly
- Replace hardcoded gap: 2px with --space-0h token
- Bump version to 0.7.2
2026-04-04 06:31:21 +02:00
Ulas 6bc4c46f03 fix(security): eliminate XSS vectors and restore zoom accessibility
- Extract shared esc() utility (public/utils/html.js) replacing 8
  duplicate escHtml() functions across all page modules
- Apply HTML escaping to all user-controlled data in innerHTML
  templates: titles, names, locations, descriptions, colors, notes
  content, weather data, autocomplete suggestions
- Remove user-scalable=no and maximum-scale=1 from viewport meta
  tag, restoring pinch-to-zoom for WCAG 1.4.4 compliance
- Bump version to 0.7.1
2026-04-04 06:25:28 +02:00
Ulas 9b21a72d40 chore: release v0.7.0 - audit remediation
Bump version to 0.7.0 and add CHANGELOG entry covering all
audit findings: bcrypt upgrade, ESM migration, session secret
hardening, structured logging, documentation translations,
and repository cleanup.
2026-04-04 01:22:39 +02:00
Ulas b139eea623 refactor(esm): migrate server and tests from CommonJS to ESM
Convert all server/, test, and setup files from require()/module.exports
to import/export syntax. Activate ESM globally via "type": "module" in
package.json and load dotenv via --import dotenv/config in npm scripts.
2026-04-03 23:11:20 +02:00
Ulas ae8fbdd465 fix(deps): upgrade bcrypt 5.1.1->6.0.0 and patch path-to-regexp ReDoS
Resolves all 5 npm audit vulnerabilities (4 high in tar via
node-pre-gyp, 1 high path-to-regexp ReDoS). bcrypt 6 replaces
node-pre-gyp with prebuildify, removing 46 transitive packages.
2026-04-03 21:58:28 +02:00
Ulas 614a496256 docs: translate package.json description and .env.example to English
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 21:54:31 +02:00
Ulas 3d2604bab9 fix(security): address critical and high findings from security audit
Fix stored XSS in tasks (titles/subtasks) and settings (member list)
by applying escHtml(). Harden trust proxy to loopback default, add
OAuth state parameter for Google Calendar CSRF protection, sanitize
CSV export against formula injection, invalidate sessions on user
deletion, restrict usernames to alphanumeric chars, and require admin
role for calendar sync triggers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 17:28:36 +02:00