diff --git a/TODO.md b/TODO.md index 42eba662..68f83ba9 100644 --- a/TODO.md +++ b/TODO.md @@ -11,7 +11,7 @@ Order = impact. Font items + app.html preload intentionally skipped. - [x] 5. Replace redundant `locals.auth()` with `locals.session` across all routes (68 files, 107 sites — loaders, actions, API endpoints) - [x] 6. Stream fitness stats loader — muscleHeatmap, nutritionStats, periods, sharedPeriods now stream via `{#await}`. `stats` still awaited (too many chart $deriveds depend on it) - [x] 7. Muscle-heatmap endpoint — add projection + O(1) bucket math. Overview already had a projection; set-subfield narrowing was attempted but reverted (returned malformed sets). Timeseries cap not feasible: totals are lifetime-scoped. -- [ ] 8. Calendar payload trim — drop `name` from `yearDays`, pre-filter `feastDots` server-side +- [x] 8. Calendar payload trim — `yearDays` narrowed to `{iso, color}` (needle lookup only), new pre-filtered `feastDots` array carries feast-specific metadata. Also fixed a stray double `locals.session ?? (locals.session ?? …)` in both calendar page loaders. - [ ] 9. History sessions endpoint — slim exercise payload for list view - [ ] 10. `Cache-Control` headers on stable API endpoints (all_brief, calendar, exercises metadata) - [ ] 11. Search — debounce 200 ms + server-side pre-normalized `_searchKey` diff --git a/package.json b/package.json index 1972bf5f..65385e74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.46.21", + "version": "1.46.22", "private": true, "type": "module", "scripts": { diff --git a/src/lib/calendarTypes.ts b/src/lib/calendarTypes.ts index a6a9d80e..c5857622 100644 --- a/src/lib/calendarTypes.ts +++ b/src/lib/calendarTypes.ts @@ -16,14 +16,23 @@ export interface CalendarDay { rite1962?: Rite1962Detail; } -// Compact per-day shape returned for the full year so the ring / month-grid -// overview views can render without refetching. Kept small on purpose. +// Compact per-day shape returned for the full window of the liturgical year. +// Kept to the bare minimum needed client-side: the ring needs a color for the +// needle on the selected day (which may be a ferial with no rank metadata), +// everything else goes through the separate `feastDots` array. export interface YearDay { + iso: string; + color: string; // primary color key (WHITE/RED/...) +} + +// Pre-filtered list of days that render a feast dot on the ring — rank > feria +// — with the metadata the ring and side panel need for each. Sent alongside +// YearDay so clients don't have to filter 365 entries themselves. +export interface FeastDot { iso: string; name: string; rank: string; - color: string; // primary color key (WHITE/RED/...) - seasonKey: string | null; + color: string; } export interface SeasonArc { diff --git a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.server.ts b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.server.ts index 6baeb45f..bce04cc9 100644 --- a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.server.ts +++ b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.server.ts @@ -13,16 +13,17 @@ import { type Diocese1969, type Rite } from '../../../../calendarI18n'; -import { seasonColorFor } from '../../../../calendarColors'; +import { rankDotSize, seasonColorFor } from '../../../../calendarColors'; import { getYear, getYear1962, isoFor } from '$lib/server/liturgicalCalendar'; -import type { CalendarDay, SeasonArc, YearDay } from '$lib/calendarTypes'; +import type { CalendarDay, FeastDot, SeasonArc, YearDay } from '$lib/calendarTypes'; export type { CalendarDay, + FeastDot, ProperSection, Rite1962Commem, Rite1962Detail, @@ -234,14 +235,25 @@ export const load: PageServerLoad = async ({ params, url, locals, fetch }) => { } } - const yearDays: YearDay[] = sortedYear.map((d, i) => ({ + // `yearDays` only carries what the ring's needle-color lookup needs for any + // day (feast or ferial). Feast metadata (name, rank) moves into `feastDots` + // below so the client can iterate it directly without filtering 365 entries. + const yearDays: YearDay[] = sortedYear.map((d) => ({ iso: d.iso, - name: d.name, - rank: d.rank, - color: d.colorKeys[0] ?? 'GREEN', - seasonKey: filledSeasons[i] + color: d.colorKeys[0] ?? 'GREEN' })); + const feastDots: FeastDot[] = []; + for (const d of sortedYear) { + if (rankDotSize(d.rank) === 0) continue; + feastDots.push({ + iso: d.iso, + name: d.name, + rank: d.rank, + color: d.colorKeys[0] ?? 'GREEN' + }); + } + const seasonArcs: SeasonArc[] = []; let cur: SeasonArc | null = null; for (let i = 0; i < sortedYear.length; i++) { @@ -282,6 +294,7 @@ export const load: PageServerLoad = async ({ params, url, locals, fetch }) => { month, monthDays, yearDays, + feastDots, seasonArcs, windowStart, windowEnd, @@ -291,6 +304,6 @@ export const load: PageServerLoad = async ({ params, url, locals, fetch }) => { todayIso, selected: selectedEntry, selectedIso, - session: locals.session ?? (locals.session ?? await locals.auth()) + session: locals.session ?? await locals.auth() }; }; diff --git a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.svelte b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.svelte index 466ef4a7..12115f3e 100644 --- a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.svelte +++ b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.svelte @@ -28,6 +28,7 @@ const month = $derived(data.month); const monthDays = $derived(data.monthDays); const yearDays = $derived(data.yearDays); + const feastDots = $derived(data.feastDots); const seasonArcs = $derived(data.seasonArcs); const today = $derived(data.today); const todayIso = $derived(data.todayIso); @@ -267,6 +268,7 @@ {year} {liturgicalYear} {yearDays} + {feastDots} {seasonArcs} {todayIso} {selectedIso} diff --git a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/RingView.svelte b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/RingView.svelte index da1ac5ac..33da570a 100644 --- a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/RingView.svelte +++ b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/RingView.svelte @@ -1,5 +1,5 @@