c912afd46a
Extends the previous loader-only sweep across the full tree: every remaining `await locals.auth()` now falls back through `locals.session ?? await locals.auth()`, so the hook's cached result is reused. 68 files, 107 sites touched — loaders, form actions, and API endpoints across cospend / tasks / fitness / faith / recipe / admin. hooks.server.ts is intentionally left alone since it's the originating call that populates locals.session in the first place.
136 lines
4.1 KiB
TypeScript
136 lines
4.1 KiB
TypeScript
import { mysteryVerseDataDe, mysteryVerseDataEn } from '$lib/data/mysteryVerseData';
|
|
import { getLiturgicalSeason } from '$lib/js/easter.svelte';
|
|
import type { PageServerLoad, Actions } from './$types';
|
|
|
|
interface StreakData {
|
|
length: number;
|
|
lastPrayed: string | null;
|
|
}
|
|
|
|
const validMysteries = ['freudenreich', 'schmerzhaften', 'glorreichen', 'lichtreichen'] as const;
|
|
|
|
const seasonalMysteryMap: Record<string, string> = {
|
|
eastertide: 'glorreichen',
|
|
lent: 'schmerzhaften',
|
|
};
|
|
|
|
function getMysteryForWeekday(date: Date, includeLuminous: boolean): string {
|
|
const dayOfWeek = date.getDay();
|
|
|
|
if (includeLuminous) {
|
|
const schedule: Record<number, string> = {
|
|
0: 'glorreichen',
|
|
1: 'freudenreich',
|
|
2: 'schmerzhaften',
|
|
3: 'glorreichen',
|
|
4: 'lichtreichen',
|
|
5: 'schmerzhaften',
|
|
6: 'freudenreich'
|
|
};
|
|
return schedule[dayOfWeek];
|
|
} else {
|
|
const schedule: Record<number, string> = {
|
|
0: 'glorreichen',
|
|
1: 'freudenreich',
|
|
2: 'schmerzhaften',
|
|
3: 'glorreichen',
|
|
4: 'freudenreich',
|
|
5: 'schmerzhaften',
|
|
6: 'glorreichen'
|
|
};
|
|
return schedule[dayOfWeek];
|
|
}
|
|
}
|
|
|
|
export const load: PageServerLoad = async ({ url, fetch, locals, params }) => {
|
|
const session = locals.session ?? await locals.auth();
|
|
|
|
// Read toggle/mystery state from URL search params (for no-JS progressive enhancement)
|
|
const luminousParam = url.searchParams.get('luminous');
|
|
const latinParam = url.searchParams.get('latin');
|
|
const mysteryParam = url.searchParams.get('mystery');
|
|
const imagesParam = url.searchParams.get('images');
|
|
|
|
const hasUrlLuminous = luminousParam !== null;
|
|
const hasUrlLatin = latinParam !== null;
|
|
const hasUrlMystery = mysteryParam !== null;
|
|
const hasUrlImages = imagesParam !== null;
|
|
|
|
const initialLuminous = hasUrlLuminous ? luminousParam !== '0' : true;
|
|
const initialLatin = hasUrlLatin ? latinParam !== '0' : true;
|
|
const initialShowImages = hasUrlImages ? imagesParam !== '0' : true;
|
|
|
|
const todaysMystery = getMysteryForWeekday(new Date(), initialLuminous);
|
|
const season = getLiturgicalSeason();
|
|
const seasonalMystery = season ? seasonalMysteryMap[season] ?? null : null;
|
|
const defaultMystery = seasonalMystery ?? todaysMystery;
|
|
|
|
let initialMystery = (validMysteries as readonly string[]).includes(mysteryParam ?? '')
|
|
? mysteryParam!
|
|
: defaultMystery;
|
|
|
|
// If luminous is off and luminous mystery was selected, fall back
|
|
if (!initialLuminous && initialMystery === 'lichtreichen') {
|
|
initialMystery = defaultMystery;
|
|
}
|
|
|
|
// Fetch streak data for logged-in users via API route
|
|
let streakData: StreakData | null = null;
|
|
if (session?.user?.nickname) {
|
|
try {
|
|
const res = await fetch('/api/glaube/rosary-streak');
|
|
if (res.ok) {
|
|
streakData = await res.json();
|
|
}
|
|
} catch {
|
|
// Server unavailable, client will use localStorage
|
|
}
|
|
}
|
|
|
|
return {
|
|
mysteryDescriptions: params.faithLang === 'glaube' ? mysteryVerseDataDe : mysteryVerseDataEn,
|
|
streakData,
|
|
isLoggedIn: !!session?.user?.nickname,
|
|
initialMystery,
|
|
todaysMystery,
|
|
initialLuminous,
|
|
initialLatin,
|
|
hasUrlMystery,
|
|
hasUrlLuminous,
|
|
hasUrlLatin,
|
|
initialShowImages,
|
|
hasUrlImages
|
|
};
|
|
};
|
|
|
|
export const actions: Actions = {
|
|
pray: async ({ locals, fetch }) => {
|
|
const session = locals.session ?? await locals.auth();
|
|
if (!session?.user?.nickname) {
|
|
return { success: false };
|
|
}
|
|
|
|
const res = await fetch('/api/glaube/rosary-streak');
|
|
const current = res.ok ? await res.json() : { length: 0, lastPrayed: null };
|
|
|
|
const today = new Date().toISOString().split('T')[0];
|
|
if (current.lastPrayed === today) {
|
|
return { success: true, alreadyPrayed: true };
|
|
}
|
|
|
|
const yesterday = new Date();
|
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
const yesterdayStr = yesterday.toISOString().split('T')[0];
|
|
|
|
const newLength = current.lastPrayed === yesterdayStr ? current.length + 1 : 1;
|
|
|
|
await fetch('/api/glaube/rosary-streak', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ length: newLength, lastPrayed: today })
|
|
});
|
|
|
|
return { success: true };
|
|
}
|
|
};
|