Extracts all German UI strings from public/pages/, public/components/,
and public/router.js into 482 i18n keys organized by module prefix.
English translations added for all keys.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Discussions links for questions at top and bottom of CONTRIBUTING.md.
Update security reporting to reference GitHub Private Vulnerability Reporting.
Customize Discussions #2 welcome post with project-specific content.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delete orphaned Python screenshot generators, social-preview template,
and duplicate icon files in public/assets/ (superseded by public/icons/).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Geometric house icon on blue gradient rounded square (SVG).
Replaces shields.io badge placeholder in README hero section.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restructure README with compelling hero section, "Why Oikos?" philosophy
section, two-column feature grid, tablet screenshot gallery, and streamlined
quick start. Add GitHub Private Vulnerability Reporting link to SECURITY.md.
Include social preview HTML template for GitHub social card generation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
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>
- 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>
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>
- 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>