Extracts the tab-bar UI into a reusable renderSubTabs() utility
(public/utils/sub-tabs.js + public/styles/sub-tabs.css) so all
sub-module navigation shares one implementation and visual style.
- Settings: replaces template-literal <nav class="settings-tabs">
with renderSubTabs(); tabs now show icon + label (pill-style),
group separators via separatorBefore, panel switching via onChange
- Kitchen: renderKitchenTabsBar() becomes a thin wrapper around
renderSubTabs(); kitchen-tabs.css keeps only layout adjustment rules
- CSS: kitchen-tab* rules removed from kitchen-tabs.css,
settings-tab-btn* rules removed from settings.css; both now
inherit from sub-tabs.css
- tokens.css: adds --sub-tabs-height (52px default;
kitchen overrides to --kitchen-tabs-height: 56px)
- test-browser-loader.mjs: resolves browser-absolute /utils/*.js
imports to public/ directory for Node test compatibility
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Open standards (CalDAV, CardDAV, ICS) now appear first in the Sync tab
under a dedicated "CalDAV & CardDAV" section, making self-hosted sync
options prominent. Cloud services (Google, Apple) move to a secondary
"Cloud-Dienste" section. Fixes raw <h2> heading in CalDAV card — now
uses consistent settings-card__title like all other cards.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: loadCalDAVAccounts and loadCardDAVAccounts were defined
inside the render function but called from bindIcsEvents (outside render),
causing ReferenceError when accessing Settings page.
Changes:
- Move loadCalDAVAccounts and loadCardDAVAccounts to top-level functions
- Add user parameter to both functions (no longer in render scope)
- Update all recursive calls to pass user parameter
- Move initial load code from bindIcsEvents to render function
Fixes the "loadCalDAVAccounts is not defined" error in v0.47.0.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add CalDAV accounts card to Settings page with:
* List of configured accounts showing URL and last sync
* Expandable calendar list with enable/disable checkboxes
* Sync Now, Refresh Calendars, and Delete actions per account
* Add Account modal with name, URL, username, password fields
- Add CalDAV target selector to event modal:
* Dropdown showing local and all enabled CalDAV calendars
* Grouped by account using optgroups
* Pre-selects current target when editing events
* Includes target_caldav_account_id and target_caldav_calendar_url in save
- Add CalDAV component styles to settings.css:
* Account cards with header, meta, and action sections
* Expandable calendar details with checkboxes and color dots
* Empty state for no accounts
- Add missing i18n keys for calendar enable/disable, refresh, delete confirm
- Load CalDAV targets async when modal opens
- Admin-only access to account management
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The PR changed dmy from dots to slashes, breaking existing users.
Revert dmy to dots (backward compat), add dmy_slash for DD/MM/YYYY.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
onSave(panel) is a setup hook, not a submit handler. Bind the form's
submit event inside it and call closeModal({ force: true }) on success.
Also add explicit submit/cancel buttons to the modal content.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a pencil-icon edit button to each ICS subscription row. Clicking it
opens a modal to update name, color, and shared visibility via PATCH
/calendar/subscriptions/:id. Adds updatedToast i18n key to all 15 locales.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Birthday date inputs in Settings (profile, new member, edit member) and
the Birthdays page were using type="text" with a custom mask, which
suppresses the native iOS date picker wheel. Switching to type="date"
with a plain ISO value restores the native picker while keeping the
existing parseDateInput / isDateInputValid logic intact.
Closes#98
Co-authored-by: Ulas Kalayci <ulas.kalayci@googlemail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Ukrainian (uk) locale to SUPPORTED_LOCALES and locale picker
- Add public/locales/uk.json (622 keys, full Ukrainian translation)
- Add UAH (Ukrainian Hryvnia) to SUPPORTED_CURRENCIES and VALID_CURRENCIES
- Add CATEGORY_I18N map and catLabel() in settings.js to translate default
shopping category names in the settings panel; rename and delete dialogs
now also use the translated name instead of the raw German DB string
- Align server VALID_CURRENCIES with frontend: add missing AED, BRL, INR, SAR
Co-Authored-By: baragoon <baragoon@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Six tabs (General, Meals, Budget, Shopping, Calendar, Account) replace
the flat single-page layout. Active tab persists via sessionStorage.
Calendar tab auto-activates on OAuth redirect. Tab bar is sticky.
All labels translated in de/en/es/it/sv.
- 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
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
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.
- 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
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>
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>
Dark Mode: Manueller Theme-Switch (System/Hell/Dunkel) in Einstellungen
mit localStorage-Persistenz und Flash-Prevention via data-theme Attribut.
RRULE UI: Wiederholungs-Formular in Aufgaben- und Kalender-Modals mit
Frequenz (Täglich/Wöchentlich/Monatlich), Intervall, Wochentag-Auswahl
und optionalem Enddatum. Backend-Routen für is_recurring/recurrence_rule
in POST/PUT erweitert. Repeat-Icon auf wiederkehrenden Einträgen.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>