Commit Graph

975 Commits

Author SHA1 Message Date
Alexander 2087970f46 fix: clear build warnings across svelte components
Resolves 16 vite-plugin-svelte warnings: state_referenced_locally
(wrap prop reads in untrack), two a11y issues (ConfirmDialog tabindex
+ key handler, meal entry role/list), and nine unused CSS selectors.
Bump to 1.40.2.
2026-04-21 11:22:08 +02:00
Alexander 38824cc054 fix(faith): calendar-slug language swap + gate detail to 1962
- LanguageSelector: add kalender/calendar/calendarium mappings so swapping
  language from /glaube/kalender/... produces /faith/calendar/... instead
  of the broken /faith/kalender/... URL.
- HeroCard: move margin-bottom off the anchor so the plain (1969) variant
  keeps the same bottom spacing as the linked (1962) variant.
- Calendar overview: omit detail href on 1969 so the hover chevron /
  hover elevation don't appear when no detail page exists.
- Detail route: 404 any /detail/... under the 1969 rite — only 1962 has
  day-detail pages.
2026-04-21 11:10:32 +02:00
Alexander 57cd16085c feat(faith): Bible fallback for 1962 propers with propers view toggle
- Auto-fill missing vernacular propers from Allioli (DE) or DRB (EN)
  when the 1962 missal bundle lacks a translation, mapped per Latin slot
  via romcal's scriptureRef blocks (compound refs split 1-to-1 when
  segment count matches slot count).
- Strip Psalm superscriptions and trailing periods so lookups parse and
  Bible text aligns with the Latin antiphon.
- Localize the section reference header (Marc → Mk, Vulgate→Hebrew
  psalm shift for DE) instead of showing raw Latin.
- Add Latin / Parallel / Vernacular view toggle with localStorage
  persistence; hide Allioli/DRB badge in Latin-only view.
- Latin column now takes primary text color; vernacular secondary,
  matching the Prayer.svelte convention.
2026-04-21 11:01:45 +02:00
Alexander 845e2eefa3 faith: use identical hero card for details and calendar overview 2026-04-21 09:57:08 +02:00
Alexander fd4753905e refactor(ui): drop redundant page headers, rework measure profile UX
Removes decorative route-label h1s across fitness, recipe and cospend
pages — replaced with sr-only h1s for assistive tech and a shared
.sr-only utility in app.css. On the measure page, the tucked-away
profile chip becomes a dismissible setup banner that only appears
when sex/height/birth year are missing, with a permanent "Edit profile"
link at the foot of the page.
2026-04-21 09:15:32 +02:00
Alexander 415bad6c23 fix(fitness): split empty-state hints on stats page
Macro split now always renders (faded rings + hint when no food logged),
and the calorie balance hint distinguishes missing demographics/weight
from missing food-log data with a warning style.
2026-04-21 08:54:35 +02:00
Alexander d93006a319 refactor(ui): SaveFab shares ActionButton shell
ActionButton now renders as <a> (href) or <button> (onclick), so
SaveFab wraps it to inherit the shake/hover/focus behavior already
used by AddButton/EditButton. Body-parts review replaces its inline
save button with SaveFab for consistency.
2026-04-21 08:48:26 +02:00
Alexander c45585baa5 feat(fitness): body-part cards link to per-part history pages
Latest measurements render as a 3x3 card grid (vertical mobile,
horizontal on ≥768px) linking to `/fitness/{measure}/{history}/{part}`
with summary stats + chart. Slugs localize (hals, oberschenkel, …)
when on the German route.
2026-04-21 08:32:08 +02:00
Alexander 2b1a415ab6 perf(faith): warm liturgical cache + fix 1962 rendering
CI / update (push) Successful in 3m59s
Pre-compute romcal year maps on server boot for current + next civil year
across en/de/la in each rite's default diocese, non-blocking so startup is
unaffected.

Also fixes several 1962-rite rendering bugs: commemorations previously
leaked 1969-shape ids (e.g. andrew_apostle) next to proper 1962 sancti;
station church names came through unresolved because RomcalConfig's
internal i18next has no bundle loaded; season names arrived as raw keys
(advent.season) for the same reason. All three now resolve locally via
the shipped 1962 bundle with Latin as fallback. ClassIV ferias get a
small dot on the grid.
2026-04-21 08:04:20 +02:00
Alexander dd612f6535 fix(fitness): persist activityType when picking GPS activity
The active-workout activity picker updated local state + workout.name
but never synced workout.activityType, so every hiking/walking/cycling
workout was saved with an inner exercise of 'running'. That silently
applied the wrong kcal model — running Minetti for hiking/walking
(~43% overestimate) and running instead of the cycling physics model
(large overestimate for cycling).

Adds an activityType setter on the workout store and invokes it from
selectActivity() so the saved session's exercise matches the picked
activity.
2026-04-21 07:54:31 +02:00
Alexander dca2fa6d51 fix(fitness): exclude 0-kcal days from calorie balance stats
Average calorie balance was comparing logged-day intake against all-day
expenditure, producing a spurious deficit on weeks with untracked days.
Now restrict both sides to days with non-zero logged intake so the
subtraction compares apples to apples.
2026-04-21 07:46:41 +02:00
Alexander 53f803c04c fix(fitness): only show projected kcal on future days in nutrition
Past and today return projectedExercise=null, so the estimate no longer
appears on days where the user could have just skipped a workout. Also
skips the WorkoutSchedule lookup when not needed.
2026-04-21 07:45:22 +02:00
Alexander 9093e0fe51 perf: add Server-Timing, split fitness bundle, tighten DB queries
- Add `timing` handle in hooks.server.ts emitting Server-Timing headers
  and expose `locals.timing.mark/measure` for per-load instrumentation.
- Drop dead `getEnrichedExerciseById` fallback in fitness detail page —
  server load already 404s via errorWithVerse, so the client no longer
  pulls exercisedb-raw.json (~760KB) into the detail bundle.
- Add `{ createdBy: 1, nextExecutionDate: -1 }` index on RecurringPayment
  for user-scoped list queries.
- Narrow populate projections in cospend/debts (title/date/category on
  userSplits, _id only on allRelatedSplits) to cut payload + hydration.
- Parallelize today's sessions + WorkoutSchedule lookup in the nutrition
  page load via Promise.all; add `.lean()` + `.select('templateId')` to
  the lastScheduled query.
2026-04-21 07:37:10 +02:00
Alexander 58b3d4b478 fix(fitness): fit body-parts wizard to viewport and tint thigh SVG
CI / update (push) Successful in 1m6s
Cap shell height to viewport minus header so the bottombar stays visible,
allow the stage to scroll internally, and swap the thigh diagram to a
mask-tinted SVG that tracks the text-primary color across themes.
2026-04-20 23:03:43 +02:00
Alexander ad154bf914 fix(errors): surface Bible verses on section error pages
SvelteKit's handleError hook is skipped for expected `error()` throws,
so verses set there never reached `$page.error` for server-thrown 404s
and auth denials. Introduce `errorWithVerse()` in `$lib/server/errorQuote`
that fetches a random verse first, then throws `error(status, body)`
with `{ message, bibleQuote, lang }`, making the quote available in
every `SectionError`. Convert all page load throws (catchalls, layout
validators, calendar, prayers, recipes, fitness, cospend, admin) and
hooks.server auth gates to the helper. Add `src/error.html` as a
branded last-resort fallback.
2026-04-20 22:39:39 +02:00
Alexander fbd09fbdae refactor(errors): redesign error pages in editorial style
Replace the emoji/gradient card with an editorial layout: small lucide
glyph, oversized error code, hairline-divided serif bible quote.

Extract shared ErrorView + SectionError components and a bilingual
string helper. Add +error.svelte at each section root (faith, recipes,
fitness, tasks, cospend) so errors render inside the correct layout and
inherit the section-specific header/nav. Catch-all [...rest]/+page.ts
stubs route unmatched URLs through the section layout so the right
error page catches them.
2026-04-20 19:54:33 +02:00
Alexander 97e8734709 fix(fitness): read .value off rendered pending point in body-parts chart legend
The raw series has `pending: number | null`, but the rendered series stores
pending as `{ x, y, value }` for SVG placement. Legend labels were calling
`.toFixed(1)` directly on the object, crashing as soon as a pending value
existed (i.e. whenever the user typed a measurement).
2026-04-20 16:51:32 +02:00
Alexander 3aa8f38f92 fix(faith): locate romcal root by walking up from main entry
romcal's package.json is not listed in its exports map, so
require.resolve('romcal/package.json') throws ERR_PACKAGE_PATH_NOT_EXPORTED
under Node's strict exports enforcement. Resolve the main entry instead
and walk up until we find the package.json belonging to romcal itself.
2026-04-20 16:50:12 +02:00
Alexander f447520aaa fix(faith): resolve 1962 bundles via createRequire and add deploy pre-push hook
CI / update (push) Successful in 1m27s
romcal's 1962 bundle files live outside the package's exports map and were
being loaded via a cwd-relative path. Under systemd the server runs with
cwd /usr/share/webapps/homepage/dist/, so node_modules/romcal/... resolved
against dist/ and hit ERR_MODULE_NOT_FOUND. Switch to createRequire +
require.resolve('romcal/package.json') so the bundle path is anchored to
the actual package root regardless of cwd.

Also track scripts/hooks/pre-push which runs scripts/deploy.sh after a
master push to origin. Git has no native post-push hook; pre-push is the
closest client-side equivalent — if deploy fails the push is aborted.
Install with: ln -sf ../../scripts/hooks/pre-push .git/hooks/pre-push
2026-04-20 16:44:59 +02:00
Alexander 9c119b8df2 feat(fitness): add guided body-parts measurement wizard
New /fitness/measure/body-parts route with step-by-step tape-measure
flow, per-step tips, L/R paired inputs, inline history chart, and
review-before-save summary. Measure page replaces the old body-parts
accordion with a launch button. Fitness layout goes full-bleed and
hides the site footer for this route via a :has() attribute selector,
and the desktop 3-column grid now extends rail and side panel up past
the floating nav while the middle column compensates with padding.
2026-04-20 16:28:09 +02:00
Alexander b2b69301aa feat(fitness): add how-to-measure hints to body-parts form
Inline italic captions under each single-sided input (neck, shoulders,
chest, waist, hips) and row-spanning captions with a primary accent bar
under each paired row (biceps, forearms, thighs, calves) — one tip per
pair, not per side. EN + DE copy.
2026-04-20 13:42:31 +02:00
Alexander e9010b9e13 fix(fitness): save and recall paired L/R body measurements
Schema uses flat keys (leftBicep, rightBicep, leftForearm, ...), but
create/edit forms built nested objects (biceps: {left, right}), which
Mongoose silently stripped — so paired parts never persisted. The
latest-measurements endpoint also wraps the body-parts doc in
{value, date}; the display path skipped the .value hop, hiding every
body-part field. Switch client to flat keys end-to-end.
2026-04-20 13:22:34 +02:00
Alexander 8e0b1d7b96 feat(faith): enrich ring with next-year wedge, feast pill, and LY-aware navigation
- Reserve an angular gap in the ring and render a clickable green triangle
  that jumps to Advent I of the following liturgical year; on hover the
  center numeral previews the upcoming LY in a muted color.
- Show the liturgical year (not civil) in the ring center so Advent 2025
  already reads 2026, and promote the selected arc to the top of the
  SVG paint order so its highlighted border is never clipped by neighbors.
- Lift the selected-season glow by mixing the season tint with the
  foreground color so purple stays visible on dark backgrounds and white
  on light backgrounds.
- On feast-dot hover, pop a colored SVG pill with the short date and feast
  name, tracked by ISO so it auto-clears when the dot is unmounted by
  navigation.
- Server now derives the liturgical year from the selected date, shifting
  yearMap forward when the URL civil date lies past Advent I of that year
  so clicks on Dec 25 no longer select the prior post-Pentecost cycle.
- Add data-sveltekit-keepfocus on ring anchors to avoid the focus-scroll
  jump after client-side navigation.
2026-04-20 13:14:55 +02:00
Alexander e37d41b180 feat(faith): adopt flat-id romcal fork and simplify 1962 calendar rendering
Switch the romcal dependency to AlexBocken/romcal (monorepo fork with
collapsed bucket prefixes) and strip the runtime prefix-fallback chain
from liturgicalCalendar.ts — name/propers lookups now use a single
flat id. The 1962 data model shrinks to just what the rendering uses
(commem {id,name}, detail carrying propers as {key, la[], local[]})
and the detail + overview pages drop the rubrics/octave/properSource
fields that never got wired in.
2026-04-18 22:28:48 +02:00
Alexander e036588795 feat(faith): animate ring rotation and restyle calendar month/detail
- Rotate the ring smoothly to put the selected day under a static vertical
  needle pin; pivot uses a shortest-arc Tween, respects prefers-reduced-motion,
  and falls back to today when no selection. Pin + bar cross-fade color in
  lockstep (650ms cubicOut) to the selected day's liturgical color (gold when
  selected == today).
- Split the overview into an inline hero (selected day) and a dedicated
  /detail/{yyyy}/{mm}/{dd} route that opens on hero click; drop the old
  inline detail block.
- Restyle the month grid to a minimalist card-grid: taupe feria fills,
  rounded cells, gold today-ring + dot, Roman-numeral rank badges, and
  equal-width columns via minmax(0, 1fr) so long feast names no longer
  stretch a column.
- Default the calendar view to the ring, reorder the view switcher
  (ring first), and match hero-card color transition to the ring timing.
- Extract shared calendar types to $lib/calendarTypes.ts and server helpers
  to $lib/server/liturgicalCalendar.ts so the overview + detail routes share
  one source of truth. Bump romcal dep to the dev branch, alias the Swiss
  1969 bundle so its exports resolve.
- Bump version to 1.35.0.
2026-04-18 17:54:41 +02:00
Alexander 2970dc0451 feat(faith): render 1962 Mass propers with scripture refs and Bible fallback
Show propers text for each 1962 celebration with scripture reference pills
grouping each block. When a translated proper is missing, fall back to the
local-language Bible (Douay-Rheims for en, Allioli for de), showing a note
above the translated column. Handles multi-segment refs (e.g. "Ps 118:85;
118:46") with inherited book/chapter, and shifts Vulgate→Hebrew psalm
numbering for Allioli.

Also restructures date navigation as folder-based optional params
(/yyyy/mm/dd) with the rite forced as a required path segment so day/month
navigation stays within the active rite.
2026-04-14 22:44:03 +02:00
Alexander 3a2e2a9408 feat(faith): show accuracy disclaimer on 1962 calendar and bump romcal
Add a small banner on the 1962 rite view noting that day-to-day data is
still being verified and that local proper calendars (diocese, order,
national feasts) are not yet layered on top of the general Roman
calendar. Bump the romcal dep to AlexBocken/romcal1962#e4731a8 for the
Holy Week / Easter Octave name fixes and the Pentecost-season color fix
(ordinary-time Sundays are now Green, not White/Red).
2026-04-13 18:56:43 +02:00
Alexander af0f50abb6 feat(stickers): expand blobcat catalog with Tirifto set and drop mismatched art
Replace four tastytea-style SVGs (blanket, hammer, teapot, heart_tastytea)
whose 800px viewBox clashed with the 33.866666 viewBox of the rest, and add
the full Tirifto gutkato_ set. Catalog grows from 54 to 113 positive stickers
(new foods/drinks, rose and cat colors, professions, cute expressions, signs).
2026-04-13 18:56:25 +02:00
Alexander a0ac5215c4 feat(faith): add calendar tile to faith landing and soften rite wording
Adds a calendar tile to the /faith (glaube/fides) LinksGrid linking to the
liturgical calendar. Homepage description and WIP body reference the "older
rite" / "alten Ritus" rather than "Tridentine" to avoid loaded connotations;
subtitle labels keep the neutral Ordinary/Extraordinary Form terminology.
2026-04-13 11:39:11 +02:00
Alexander 21c8c196df feat(faith): add liturgical calendar with 1969/1962 rite toggle
Adds `/faith/calendar`, `/glaube/kalender`, `/fides/calendarium` route backed by
romcal v3 + @romcal/calendar.general-roman with native EN/DE/LA locales. Month
grid, today hero, and day detail panel use liturgical colors from the rubric.

Header gets a segmented 1969/1962 pill toggle; selecting 1962 shows a WIP
placeholder (Tridentine calendar data not yet wired up).
2026-04-13 10:55:04 +02:00
Alexander 7ee5f7d183 fix(rosary): trigger haptic on pointerup so iOS Safari vibrates
WebKit's hidden <input type="checkbox" switch> haptic trick is gated on
tap-completion, not tap-start. Firing on pointerdown ran the programmatic
click() before iOS committed to "this is a tap" so the switch-toggle
haptic was suppressed. pointerup lands inside iOS's tap-completion
window — still earlier than click (no movement filter, no 300ms wait).
Android native bridge path is unaffected.
2026-04-13 10:54:07 +02:00
Alexander 4dba5ea4fd feat(nutrition): reactive quick-log recents and favorites
Derive recents from current-day entries merged with historical
server data so logging a food updates the quick-log bar instantly.
FoodSearch now emits onfavoritechange so toggling a heart keeps
the quick-log favorites tab in sync without reloading.
2026-04-13 09:52:31 +02:00
Alexander 465bd9b25a feat(fitness): replace ExercisePicker dropdowns with icon pills
Align muscle group and equipment filters in the exercise picker
with the rest of the fitness UI — horizontal pill scrollers, multi-
select, with Lucide icons for each equipment type.
2026-04-13 09:52:25 +02:00
Alexander 3876e6d384 feat(nutrition): change meal of logged food via edit pills or drag-and-drop
Edit mode now shows a pill row (breakfast/lunch/dinner/snack with their
icons) beneath the grams input so the entry can be moved to another meal.
Food cards are also draggable; dropping onto a different meal section
optimistically moves the entry (rolls back on API error). Desktop/pointer
only — touch devices use the pill row.
2026-04-13 09:34:47 +02:00
Alexander 7c3e90933d feat(fitness): support repeat groups in interval training templates
Allow users to nest steps inside a repeat group (e.g. "5×: 30s sprint,
60s recovery") when building GPS interval templates. Groups are tagged
{ type: 'group', repeat, steps } alongside flat { type: 'step' } entries
and capped at one nesting level. Entries are expanded into a flat list
before handing off to the native Android TTS/interval service, so the
runtime state machine is unchanged.
2026-04-13 09:17:55 +02:00
Alexander 0ef8ee38c5 feat(fitness): classify exercises by type and redesign filter UI
Distinguish stretches, strength, cardio, and plyometric exercises
with a curated `exerciseType` field that overrides mislabels in
ExerciseDB for the hand-curated stretch set. Surface the type as
pills on the detail page and as a filter toggle on the list page.

Replace the muscle-group and equipment dropdowns with horizontally
scrolling pill rows; equipment pills carry Lucide icons, and the
type toggle shows a flexed-bicep / person / layers glyph. Selected
muscle groups hoist to the front of the scroller.
2026-04-13 08:59:12 +02:00
Alexander 4692bf9bf7 feat(recipes): redesign cake-form and baking info with collapsible card pattern
Viewer: cake-form adjust now collapses into a summary trigger with live
factor badge; shape picker replaced with icon-only tiles that flex to
fill the row; numeric inputs gain inline cm suffix; restore-default link
appears when user deviates from the default. Editor: default-Backform
config mirrors the same card + tile pattern (adds "none" tile), plus
inline cm suffixes. Baking info row in instruction editor becomes a
click-to-reveal card with summary chips, mode presets, and editable
fields behind the chevron.
2026-04-12 21:46:51 +02:00
Alexander f108e9ceaa feat: align recipe edit page with viewer design
Replace CardAdd with EditTitleImgParallax so /rezepte/edit/[name]
mirrors the hero-parallax layout of /rezepte/[name]. Add Lucide icons
and a width-constrained info-card grid to CreateStepList's additional
info section. Refactor the English translation view to use semantic
theme vars, side-by-side German/English field comparison, and a card
aesthetic matching the rest of the site.

Fix portions binding bug where the shared portions store was being
written by both language ingredient lists. CreateIngredientList now
accepts a bindable portions prop; the English list uses it with
useStore=false to stay isolated from the German value.
2026-04-12 21:22:53 +02:00
Alexander 69c2e05462 feat: add tactile haptic feedback to rosary prayer cards
Every prayer card now vibrates on tap — non-decade cards advance to the
next section, decade cards increment the Ave Maria counter with auto-scroll
at 10. Two profiles (bead vs card) give distinct tactile feel; the 10th
bead fires the heavier card haptic to mark decade completion.

Native Android path via AndroidBridge.forceVibrate uses VibrationAttributes
USAGE_ACCESSIBILITY so vibration bypasses silent / Do-Not-Disturb inside
the Tauri app. Browser falls back to the web-haptics npm package. Haptic
fires on pointerdown with touch-action: manipulation for near-zero tap
latency; state change stays on click so scroll gestures don't advance.

- Remove CounterButton (whole card is now the tap target)
- Replace emoji with Lucide BookOpen icon, restyle citation as an
  understated inline typographic link (no background chip)
- Drop decade min-height leftover from the pre-auto-advance layout

Bumps site to 1.27.0 and Tauri app to 0.5.0 (new Android capability).
2026-04-12 20:15:40 +02:00
Alexander cfd1d953fb fix: adjust LinksGrid nth-child offsets for earlier, more frequent color pops
Shift pop-b and pop-c selectors so accent colors appear sooner in the
grid and the light/white pop-c repeats more frequently (every 5th
instead of every 7th item).
2026-04-11 21:34:23 +02:00
Alexander a8f07ad800 feat: add chat.bocken.org link to homepage links grid 2026-04-11 19:39:32 +02:00
Alexander db1cd76bb6 feat: add hold timer for timed exercises with full sync support
- Play/Stop button replaces checkmark for duration-only exercises
- Green countdown bar with auto-completion and rest timer chaining
- Display duration in seconds (SEC) instead of minutes for holds
- ActiveWorkout model now preserves distance/duration fields on sync
- Hold timer state syncs across devices via SSE
- Workout summary shows per-set hold times for duration exercises
- Template diff compares and displays duration changes correctly
2026-04-11 17:40:58 +02:00
Alexander c80827b41e fix: add 15 stretching exercises to exercise database
Exercises used by the Day 6 stretching template were only in
exercisedb-map.ts but missing from exercises.ts, causing the
template detail to show raw IDs instead of proper names.
2026-04-11 16:14:34 +02:00
Alexander 1434580c3f feat: record cadence from step detector during GPS workouts
Use Android TYPE_STEP_DETECTOR sensor in LocationForegroundService to
count steps in a 15s rolling window. Cadence (spm) is computed at each
GPS point and stored alongside lat/lng/altitude/speed. Session detail
page shows cadence chart when data is available.

No additional permissions required — step detector is not a restricted
sensor. Gracefully skipped on devices without the sensor.
2026-04-11 15:28:27 +02:00
Alexander 4ae3793c06 feat: add elevation chart and gain/loss stats to GPS workout detail 2026-04-11 15:17:34 +02:00
Alexander 079e14c605 feat: add template library for browsing and adding defaults
Replace auto-seed with a browsable template library. Users can
selectively add built-in templates to their collection via a
BookOpen icon or the empty-state prompt. Each library template
tracks its origin via libraryId to prevent duplicates.

- Extract default templates to shared $lib/data/defaultTemplates.ts
- Add GET/POST /api/fitness/templates/library endpoint
- Add library modal with add/added state per template
- Keep seed endpoint as fallback (imports from shared data)
2026-04-11 15:02:58 +02:00
Alexander 9f5263a0a5 feat: add Day 6 stretching template to seed defaults
Full-body stretching session (~30 min) covering all major muscle
groups with 15 bodyweight exercises: neck, shoulders, chest, back,
spine, hips, hamstrings, quads, glutes, calves, and arms.
Each exercise has 2 sets of 60-90s holds with 15s rest.
2026-04-11 13:17:05 +02:00
Alexander b895088ad8 feat: project exercise kcal from next scheduled template
When no workout is logged for the day, look up the next template
in the schedule rotation and show the kcal from its most recent
session as a projection. Tappable toggle includes/excludes it
from the calorie goal, ring, and macro bars for meal planning.
2026-04-11 13:11:32 +02:00
Alexander d4af6ff5ff fix: increase shopping icon sizes for better visibility
List icons: 44→56px desktop, 36→48px mobile.
Icon picker modal: 42→56px grid cells.
2026-04-11 10:19:17 +02:00
Alexander 45c6be21a1 fix: sync runtime shopping catalog with source catalog
shoppingCatalog.json was missing all 22 new entries (11 icons
with aliases) added to catalog.json, so new icons like stroh80
were never matched at runtime.
2026-04-11 10:14:32 +02:00