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.
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "homepage",
|
"name": "homepage",
|
||||||
"version": "1.37.0",
|
"version": "1.37.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+145
@@ -0,0 +1,145 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#5E81AC" />
|
||||||
|
<link rel="icon" href="/favicon.svg" />
|
||||||
|
<title>%sveltekit.status% — Error</title>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
try {
|
||||||
|
var t = localStorage.getItem('theme');
|
||||||
|
if (t === 'light' || t === 'dark') document.documentElement.dataset.theme = t;
|
||||||
|
} catch (_) {}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg: #f8f6f1;
|
||||||
|
--text: #2a2a2a;
|
||||||
|
--text-muted: #555;
|
||||||
|
--text-dim: #777;
|
||||||
|
--border: #ddd;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--bg: #000;
|
||||||
|
--text: #e5e5e5;
|
||||||
|
--text-muted: #aaa;
|
||||||
|
--text-dim: #888;
|
||||||
|
--border: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:root[data-theme='light'] {
|
||||||
|
--bg: #f8f6f1;
|
||||||
|
--text: #2a2a2a;
|
||||||
|
--text-muted: #555;
|
||||||
|
--text-dim: #777;
|
||||||
|
--border: #ddd;
|
||||||
|
}
|
||||||
|
:root[data-theme='dark'] {
|
||||||
|
--bg: #000;
|
||||||
|
--text: #e5e5e5;
|
||||||
|
--text-muted: #aaa;
|
||||||
|
--text-dim: #888;
|
||||||
|
--border: #333;
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
font-family: Helvetica, Arial, 'Noto Sans', sans-serif;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
padding: clamp(3rem, 10vh, 8rem) 1.5rem 4rem;
|
||||||
|
}
|
||||||
|
article {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 640px;
|
||||||
|
}
|
||||||
|
.eyebrow {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-dim);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.code {
|
||||||
|
font-size: clamp(7rem, 22vw, 14rem);
|
||||||
|
font-weight: 200;
|
||||||
|
line-height: 0.9;
|
||||||
|
letter-spacing: -0.05em;
|
||||||
|
color: var(--text);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
font-variant-numeric: lining-nums tabular-nums;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: clamp(1.5rem, 3vw, 2rem);
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
font-size: 1.0625rem;
|
||||||
|
line-height: 1.55;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin: 0;
|
||||||
|
max-width: 44ch;
|
||||||
|
}
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 1.75rem;
|
||||||
|
margin: 2.25rem 0 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.link {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-decoration: none;
|
||||||
|
position: relative;
|
||||||
|
transition: color 200ms ease;
|
||||||
|
}
|
||||||
|
.link::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: -2px;
|
||||||
|
height: 1px;
|
||||||
|
background: currentColor;
|
||||||
|
opacity: 0.35;
|
||||||
|
transition: opacity 200ms ease;
|
||||||
|
}
|
||||||
|
.link:hover {
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.link:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<article>
|
||||||
|
<div class="eyebrow">Error</div>
|
||||||
|
<div class="code" aria-hidden="true">%sveltekit.status%</div>
|
||||||
|
<h1 class="title">%sveltekit.error.message%</h1>
|
||||||
|
<p class="description">
|
||||||
|
An unexpected error occurred while rendering this page.
|
||||||
|
</p>
|
||||||
|
<nav class="actions">
|
||||||
|
<a class="link" href="/">Homepage</a>
|
||||||
|
<a class="link" href="javascript:history.back()">Go back</a>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+27
-53
@@ -1,10 +1,10 @@
|
|||||||
import type { Handle, HandleServerError } from "@sveltejs/kit"
|
import type { Handle, HandleServerError } from "@sveltejs/kit"
|
||||||
import { redirect } from "@sveltejs/kit"
|
import { redirect } from "@sveltejs/kit"
|
||||||
import { error } from "@sveltejs/kit"
|
|
||||||
import { sequence } from "@sveltejs/kit/hooks"
|
import { sequence } from "@sveltejs/kit/hooks"
|
||||||
import * as auth from "./auth"
|
import * as auth from "./auth"
|
||||||
import { initializeScheduler } from "./lib/server/scheduler"
|
import { initializeScheduler } from "./lib/server/scheduler"
|
||||||
import { dbConnect } from "./utils/db"
|
import { dbConnect } from "./utils/db"
|
||||||
|
import { errorWithVerse, getRandomVerse } from "$lib/server/errorQuote"
|
||||||
|
|
||||||
// Initialize database connection on server startup
|
// Initialize database connection on server startup
|
||||||
console.log('🚀 Server starting - initializing database connection...');
|
console.log('🚀 Server starting - initializing database connection...');
|
||||||
@@ -21,27 +21,26 @@ await dbConnect().then(() => {
|
|||||||
async function authorization({ event, resolve }: Parameters<Handle>[0]) {
|
async function authorization({ event, resolve }: Parameters<Handle>[0]) {
|
||||||
const session = await event.locals.auth();
|
const session = await event.locals.auth();
|
||||||
event.locals.session = session;
|
event.locals.session = session;
|
||||||
|
const { fetch, url } = event;
|
||||||
|
|
||||||
// Protect rezepte routes
|
// Protect rezepte routes
|
||||||
if (event.url.pathname.startsWith('/rezepte/edit') || event.url.pathname.startsWith('/rezepte/add')) {
|
if (url.pathname.startsWith('/rezepte/edit') || url.pathname.startsWith('/rezepte/add')) {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
// Preserve the original URL the user was trying to access
|
const callbackUrl = encodeURIComponent(url.pathname + url.search);
|
||||||
const callbackUrl = encodeURIComponent(event.url.pathname + event.url.search);
|
|
||||||
redirect(303, `/login?callbackUrl=${callbackUrl}`);
|
redirect(303, `/login?callbackUrl=${callbackUrl}`);
|
||||||
}
|
}
|
||||||
else if (!session.user?.groups?.includes('rezepte_users')) {
|
else if (!session.user?.groups?.includes('rezepte_users')) {
|
||||||
error(403, {
|
await errorWithVerse(fetch, url.pathname, 403,
|
||||||
message: 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich. Falls du glaubst, dass dies ein Fehler ist, wende dich bitte an Alexander.'
|
'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich. Falls du glaubst, dass dies ein Fehler ist, wende dich bitte an Alexander.');
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protect cospend routes and API endpoints
|
// Protect cospend routes and API endpoints
|
||||||
if (event.url.pathname.startsWith('/cospend') || event.url.pathname.startsWith('/expenses') || event.url.pathname.startsWith('/api/cospend')) {
|
if (url.pathname.startsWith('/cospend') || url.pathname.startsWith('/expenses') || url.pathname.startsWith('/api/cospend')) {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
// Allow share-token access to shopping list routes
|
// Allow share-token access to shopping list routes
|
||||||
const isShoppingRoute = event.url.pathname.startsWith('/cospend/list') || event.url.pathname.startsWith('/expenses/list') || event.url.pathname.startsWith('/api/cospend/list');
|
const isShoppingRoute = url.pathname.startsWith('/cospend/list') || url.pathname.startsWith('/expenses/list') || url.pathname.startsWith('/api/cospend/list');
|
||||||
const shareToken = event.url.searchParams.get('token');
|
const shareToken = url.searchParams.get('token');
|
||||||
if (isShoppingRoute && shareToken) {
|
if (isShoppingRoute && shareToken) {
|
||||||
const { validateShareToken } = await import('$lib/server/shoppingAuth');
|
const { validateShareToken } = await import('$lib/server/shoppingAuth');
|
||||||
if (await validateShareToken(shareToken)) {
|
if (await validateShareToken(shareToken)) {
|
||||||
@@ -50,49 +49,42 @@ async function authorization({ event, resolve }: Parameters<Handle>[0]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For API routes, return 401 instead of redirecting
|
// For API routes, return 401 instead of redirecting
|
||||||
if (event.url.pathname.startsWith('/api/cospend')) {
|
if (url.pathname.startsWith('/api/cospend')) {
|
||||||
error(401, {
|
await errorWithVerse(fetch, url.pathname, 401,
|
||||||
message: 'Anmeldung erforderlich. Du musst angemeldet sein, um auf diesen Bereich zugreifen zu können.'
|
'Anmeldung erforderlich. Du musst angemeldet sein, um auf diesen Bereich zugreifen zu können.');
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// For page routes, redirect to login
|
// For page routes, redirect to login
|
||||||
const callbackUrl = encodeURIComponent(event.url.pathname + event.url.search);
|
const callbackUrl = encodeURIComponent(url.pathname + url.search);
|
||||||
redirect(303, `/login?callbackUrl=${callbackUrl}`);
|
redirect(303, `/login?callbackUrl=${callbackUrl}`);
|
||||||
}
|
}
|
||||||
else if (!session.user?.groups?.includes('cospend')) {
|
else if (!session.user?.groups?.includes('cospend')) {
|
||||||
error(403, {
|
await errorWithVerse(fetch, url.pathname, 403,
|
||||||
message: 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich. Falls du glaubst, dass dies ein Fehler ist, wende dich bitte an Alexander.'
|
'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich. Falls du glaubst, dass dies ein Fehler ist, wende dich bitte an Alexander.');
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protect tasks routes and API endpoints
|
// Protect tasks routes and API endpoints
|
||||||
if (event.url.pathname.startsWith('/tasks') || event.url.pathname.startsWith('/api/tasks')) {
|
if (url.pathname.startsWith('/tasks') || url.pathname.startsWith('/api/tasks')) {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
if (event.url.pathname.startsWith('/api/tasks')) {
|
if (url.pathname.startsWith('/api/tasks')) {
|
||||||
error(401, {
|
await errorWithVerse(fetch, url.pathname, 401, 'Anmeldung erforderlich.');
|
||||||
message: 'Anmeldung erforderlich.'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const callbackUrl = encodeURIComponent(event.url.pathname + event.url.search);
|
const callbackUrl = encodeURIComponent(url.pathname + url.search);
|
||||||
redirect(303, `/login?callbackUrl=${callbackUrl}`);
|
redirect(303, `/login?callbackUrl=${callbackUrl}`);
|
||||||
}
|
}
|
||||||
else if (!session.user?.groups?.includes('task_users')) {
|
else if (!session.user?.groups?.includes('task_users')) {
|
||||||
error(403, {
|
await errorWithVerse(fetch, url.pathname, 403,
|
||||||
message: 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich. Falls du glaubst, dass dies ein Fehler ist, wende dich bitte an Alexander.'
|
'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich. Falls du glaubst, dass dies ein Fehler ist, wende dich bitte an Alexander.');
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protect fitness routes and API endpoints
|
// Protect fitness routes and API endpoints
|
||||||
if (event.url.pathname.startsWith('/fitness') || event.url.pathname.startsWith('/api/fitness')) {
|
if (url.pathname.startsWith('/fitness') || url.pathname.startsWith('/api/fitness')) {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
if (event.url.pathname.startsWith('/api/fitness')) {
|
if (url.pathname.startsWith('/api/fitness')) {
|
||||||
error(401, {
|
await errorWithVerse(fetch, url.pathname, 401, 'Authentication required.');
|
||||||
message: 'Authentication required.'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const callbackUrl = encodeURIComponent(event.url.pathname + event.url.search);
|
const callbackUrl = encodeURIComponent(url.pathname + url.search);
|
||||||
redirect(303, `/login?callbackUrl=${callbackUrl}`);
|
redirect(303, `/login?callbackUrl=${callbackUrl}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,32 +93,14 @@ async function authorization({ event, resolve }: Parameters<Handle>[0]) {
|
|||||||
return resolve(event);
|
return resolve(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bible verse functionality for error pages
|
|
||||||
async function getRandomVerse(fetch: typeof globalThis.fetch, pathname: string): Promise<{ text: string; reference: string } | null> {
|
|
||||||
const isEnglish = pathname.startsWith('/faith/') || pathname.startsWith('/recipes/');
|
|
||||||
const endpoint = isEnglish ? '/api/faith/bibel/zufallszitat' : '/api/glaube/bibel/zufallszitat';
|
|
||||||
try {
|
|
||||||
const response = await fetch(endpoint);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
return await response.json();
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error getting random verse:', err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const handleError: HandleServerError = async ({ error, event, status, message }) => {
|
export const handleError: HandleServerError = async ({ error, event, status, message }) => {
|
||||||
console.error('Error occurred:', { error, status, message, url: event.url.pathname });
|
console.error('Error occurred:', { error, status, message, url: event.url.pathname });
|
||||||
|
|
||||||
// Add Bible verse to error context
|
|
||||||
const bibleQuote = await getRandomVerse(event.fetch, event.url.pathname);
|
|
||||||
|
|
||||||
|
const bibleQuote = await getRandomVerse(event.fetch, event.url.pathname);
|
||||||
const isEnglish = event.url.pathname.startsWith('/faith/') || event.url.pathname.startsWith('/recipes/');
|
const isEnglish = event.url.pathname.startsWith('/faith/') || event.url.pathname.startsWith('/recipes/');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: message,
|
message,
|
||||||
bibleQuote,
|
bibleQuote,
|
||||||
lang: isEnglish ? 'en' : 'de'
|
lang: isEnglish ? 'en' : 'de'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
type Fetch = typeof globalThis.fetch;
|
||||||
|
|
||||||
|
function detectLang(pathname: string): 'en' | 'de' {
|
||||||
|
return pathname.startsWith('/faith/') || pathname.startsWith('/recipes/') ? 'en' : 'de';
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getRandomVerse(
|
||||||
|
fetch: Fetch,
|
||||||
|
pathname: string
|
||||||
|
): Promise<{ text: string; reference: string } | null> {
|
||||||
|
const endpoint =
|
||||||
|
detectLang(pathname) === 'en'
|
||||||
|
? '/api/faith/bibel/zufallszitat'
|
||||||
|
: '/api/glaube/bibel/zufallszitat';
|
||||||
|
try {
|
||||||
|
const res = await fetch(endpoint);
|
||||||
|
if (!res.ok) return null;
|
||||||
|
return await res.json();
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function errorWithVerse(
|
||||||
|
fetch: Fetch,
|
||||||
|
pathname: string,
|
||||||
|
status: number,
|
||||||
|
message = ''
|
||||||
|
): Promise<never> {
|
||||||
|
const bibleQuote = await getRandomVerse(fetch, pathname);
|
||||||
|
error(status, { message, bibleQuote, lang: detectLang(pathname) });
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = ({ fetch, url }) =>
|
||||||
|
errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export const load = () => {
|
|
||||||
error(404, 'Not found');
|
|
||||||
};
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { redirect, error } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ locals, fetch }) => {
|
export const load: PageServerLoad = async ({ locals, fetch, url }) => {
|
||||||
const session = await locals.auth();
|
const session = await locals.auth();
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
throw redirect(302, '/login');
|
throw redirect(302, '/login');
|
||||||
}
|
}
|
||||||
@@ -14,11 +15,11 @@ export const load: PageServerLoad = async ({ locals, fetch }) => {
|
|||||||
fetch('/api/cospend/balance'),
|
fetch('/api/cospend/balance'),
|
||||||
fetch('/api/cospend/debts')
|
fetch('/api/cospend/debts')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!balanceResponse.ok) {
|
if (!balanceResponse.ok) {
|
||||||
throw new Error('Failed to fetch balance');
|
throw new Error('Failed to fetch balance');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debtResponse.ok) {
|
if (!debtResponse.ok) {
|
||||||
throw new Error('Failed to fetch debt data');
|
throw new Error('Failed to fetch debt data');
|
||||||
}
|
}
|
||||||
@@ -33,6 +34,6 @@ export const load: PageServerLoad = async ({ locals, fetch }) => {
|
|||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error loading dashboard data:', e);
|
console.error('Error loading dashboard data:', e);
|
||||||
throw error(500, 'Failed to load dashboard data');
|
await errorWithVerse(fetch, url.pathname, 500, 'Failed to load dashboard data');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { redirect, error } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ locals, fetch, url }) => {
|
export const load: PageServerLoad = async ({ locals, fetch, url }) => {
|
||||||
const session = await locals.auth();
|
const session = await locals.auth();
|
||||||
@@ -29,6 +30,6 @@ export const load: PageServerLoad = async ({ locals, fetch, url }) => {
|
|||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error loading payments data:', e);
|
console.error('Error loading payments data:', e);
|
||||||
throw error(500, 'Failed to load payments data');
|
await errorWithVerse(fetch, url.pathname, 500, 'Failed to load payments data');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { redirect, error } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ locals, params, fetch }) => {
|
export const load: PageServerLoad = async ({ locals, params, fetch, url }) => {
|
||||||
const session = await locals.auth();
|
const session = await locals.auth();
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
@@ -23,6 +24,6 @@ export const load: PageServerLoad = async ({ locals, params, fetch }) => {
|
|||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error loading payment data:', e);
|
console.error('Error loading payment data:', e);
|
||||||
throw error(500, 'Failed to load payment data');
|
await errorWithVerse(fetch, url.pathname, 500, 'Failed to load payment data');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,13 +1,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
|
||||||
import SectionError from '$lib/components/SectionError.svelte';
|
import SectionError from '$lib/components/SectionError.svelte';
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
let faithLang = $derived($page.params.faithLang);
|
let faithLang = $derived($page.params.faithLang);
|
||||||
let isEnglish = $derived(faithLang === 'faith');
|
let isEnglish = $derived(faithLang === 'faith');
|
||||||
|
let sectionLabel = $derived(
|
||||||
|
faithLang === 'fides'
|
||||||
|
? { en: 'Fides', de: 'Fides' }
|
||||||
|
: { en: 'Faith', de: 'Glaube' }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SectionError
|
<SectionError
|
||||||
sectionHref="/{faithLang}"
|
sectionHref="/{faithLang}"
|
||||||
sectionLabel={{ en: 'Faith', de: 'Glaube' }}
|
{sectionLabel}
|
||||||
{isEnglish}
|
{isEnglish}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { LayoutServerLoad } from "./$types"
|
import type { LayoutServerLoad } from "./$types"
|
||||||
import { error } from "@sveltejs/kit";
|
import { errorWithVerse } from "$lib/server/errorQuote"
|
||||||
|
|
||||||
export const load : LayoutServerLoad = async ({locals, params}) => {
|
export const load : LayoutServerLoad = async ({locals, params, fetch, url}) => {
|
||||||
// Validate faithLang parameter
|
// Validate faithLang parameter
|
||||||
if (params.faithLang !== 'glaube' && params.faithLang !== 'faith' && params.faithLang !== 'fides') {
|
if (params.faithLang !== 'glaube' && params.faithLang !== 'faith' && params.faithLang !== 'fides') {
|
||||||
throw error(404, 'Not found');
|
await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const lang = params.faithLang === 'faith' ? 'en' : params.faithLang === 'fides' ? 'la' : 'de';
|
const lang = params.faithLang === 'faith' ? 'en' : params.faithLang === 'fides' ? 'la' : 'de';
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = ({ fetch, url }) =>
|
||||||
|
errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export const load = () => {
|
|
||||||
error(404, 'Not found');
|
|
||||||
};
|
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import { error, redirect } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { expectedSlug } from './calendarI18n';
|
import { expectedSlug } from './calendarI18n';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, url }) => {
|
export const load: PageServerLoad = async ({ params, url, fetch }) => {
|
||||||
const slug = expectedSlug(params.faithLang);
|
const slug = expectedSlug(params.faithLang);
|
||||||
if (slug === null) throw error(404, 'Not found');
|
if (slug === null) await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
if (params.calendar !== slug) {
|
if (params.calendar !== slug) {
|
||||||
throw redirect(307, `/${params.faithLang}/${slug}`);
|
throw redirect(307, `/${params.faithLang}/${slug}`);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -1,5 +1,6 @@
|
|||||||
import { error, redirect } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
import {
|
import {
|
||||||
DEFAULT_DIOCESE_1962,
|
DEFAULT_DIOCESE_1962,
|
||||||
DEFAULT_DIOCESE_1969,
|
DEFAULT_DIOCESE_1969,
|
||||||
@@ -29,9 +30,9 @@ export type {
|
|||||||
YearDay
|
YearDay
|
||||||
} from '$lib/calendarTypes';
|
} from '$lib/calendarTypes';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, url, locals }) => {
|
export const load: PageServerLoad = async ({ params, url, locals, fetch }) => {
|
||||||
const slug = expectedSlug(params.faithLang);
|
const slug = expectedSlug(params.faithLang);
|
||||||
if (slug === null) throw error(404, 'Not found');
|
if (slug === null) await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
if (params.calendar !== slug) {
|
if (params.calendar !== slug) {
|
||||||
throw redirect(307, `/${params.faithLang}/${slug}`);
|
throw redirect(307, `/${params.faithLang}/${slug}`);
|
||||||
}
|
}
|
||||||
@@ -52,7 +53,7 @@ export const load: PageServerLoad = async ({ params, url, locals }) => {
|
|||||||
// Reject mm without yyyy, dd without yyyy+mm. Sveltekit optional routes let
|
// Reject mm without yyyy, dd without yyyy+mm. Sveltekit optional routes let
|
||||||
// gaps through so we normalize here.
|
// gaps through so we normalize here.
|
||||||
if ((params.mm && !params.yyyy) || (params.dd && !params.mm)) {
|
if ((params.mm && !params.yyyy) || (params.dd && !params.mm)) {
|
||||||
throw error(404, 'Not found');
|
await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
@@ -92,7 +93,7 @@ export const load: PageServerLoad = async ({ params, url, locals }) => {
|
|||||||
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
||||||
if (params.dd) {
|
if (params.dd) {
|
||||||
const ddNum = Number(params.dd);
|
const ddNum = Number(params.dd);
|
||||||
if (ddNum < 1 || ddNum > daysInMonth) throw error(404, 'Not found');
|
if (ddNum < 1 || ddNum > daysInMonth) await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
}
|
}
|
||||||
// Tentative selectedIso used only for the LY rollover decision. The real
|
// Tentative selectedIso used only for the LY rollover decision. The real
|
||||||
// selectedIso is recomputed after monthDays below (same logic, now on the
|
// selectedIso is recomputed after monthDays below (same logic, now on the
|
||||||
|
|||||||
+8
-7
@@ -1,5 +1,6 @@
|
|||||||
import { error, redirect } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
import {
|
import {
|
||||||
DEFAULT_DIOCESE_1962,
|
DEFAULT_DIOCESE_1962,
|
||||||
DEFAULT_DIOCESE_1969,
|
DEFAULT_DIOCESE_1969,
|
||||||
@@ -13,9 +14,9 @@ import {
|
|||||||
} from '../../../../../calendarI18n';
|
} from '../../../../../calendarI18n';
|
||||||
import { getYear, getYear1962, isoFor } from '$lib/server/liturgicalCalendar';
|
import { getYear, getYear1962, isoFor } from '$lib/server/liturgicalCalendar';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, url, locals }) => {
|
export const load: PageServerLoad = async ({ params, url, locals, fetch }) => {
|
||||||
const slug = expectedSlug(params.faithLang);
|
const slug = expectedSlug(params.faithLang);
|
||||||
if (slug === null) throw error(404, 'Not found');
|
if (slug === null) await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
if (params.calendar !== slug) {
|
if (params.calendar !== slug) {
|
||||||
throw redirect(307, `/${params.faithLang}/${slug}`);
|
throw redirect(307, `/${params.faithLang}/${slug}`);
|
||||||
}
|
}
|
||||||
@@ -38,10 +39,10 @@ export const load: PageServerLoad = async ({ params, url, locals }) => {
|
|||||||
const month = Number(params.mm) - 1;
|
const month = Number(params.mm) - 1;
|
||||||
const day = Number(params.dd);
|
const day = Number(params.dd);
|
||||||
|
|
||||||
if (!Number.isFinite(year) || year < minYear || year > 2100) throw error(404, 'Not found');
|
if (!Number.isFinite(year) || year < minYear || year > 2100) await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
if (!Number.isFinite(month) || month < 0 || month > 11) throw error(404, 'Not found');
|
if (!Number.isFinite(month) || month < 0 || month > 11) await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
||||||
if (!Number.isFinite(day) || day < 1 || day > daysInMonth) throw error(404, 'Not found');
|
if (!Number.isFinite(day) || day < 1 || day > daysInMonth) await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
|
|
||||||
const iso = isoFor(year, month, day);
|
const iso = isoFor(year, month, day);
|
||||||
const yearMap =
|
const yearMap =
|
||||||
@@ -49,7 +50,7 @@ export const load: PageServerLoad = async ({ params, url, locals }) => {
|
|||||||
? await getYear1962(lang, diocese1962, year)
|
? await getYear1962(lang, diocese1962, year)
|
||||||
: await getYear(lang, diocese1969, year);
|
: await getYear(lang, diocese1969, year);
|
||||||
const entry = yearMap.get(iso);
|
const entry = yearMap.get(iso);
|
||||||
if (!entry) throw error(404, 'Not found');
|
if (!entry) await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
|
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const todayIso = today.toISOString().slice(0, 10);
|
const todayIso = today.toISOString().slice(0, 10);
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import type { PageServerLoad, Actions } from "./$types";
|
import type { PageServerLoad, Actions } from "./$types";
|
||||||
import { error } from "@sveltejs/kit";
|
import { error } from "@sveltejs/kit";
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
import { validPrayerSlugs } from '$lib/data/prayerSlugs';
|
import { validPrayerSlugs } from '$lib/data/prayerSlugs';
|
||||||
|
|
||||||
const angelusSlugs = new Set(['angelus', 'regina-caeli']);
|
const angelusSlugs = new Set(['angelus', 'regina-caeli']);
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, url, locals, fetch }) => {
|
export const load: PageServerLoad = async ({ params, url, locals, fetch }) => {
|
||||||
if (!validPrayerSlugs.has(params.prayer)) {
|
if (!validPrayerSlugs.has(params.prayer)) {
|
||||||
throw error(404, 'Prayer not found');
|
await errorWithVerse(fetch, url.pathname, 404, 'Prayer not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const latinParam = url.searchParams.get('latin');
|
const latinParam = url.searchParams.get('latin');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
|
||||||
import SectionError from '$lib/components/SectionError.svelte';
|
import SectionError from '$lib/components/SectionError.svelte';
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
let recipeLang = $derived($page.params.recipeLang);
|
let recipeLang = $derived($page.params.recipeLang);
|
||||||
let isEnglish = $derived(recipeLang === 'recipes');
|
let isEnglish = $derived(recipeLang === 'recipes');
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { LayoutServerLoad } from "./$types"
|
import type { LayoutServerLoad } from "./$types"
|
||||||
import { error } from "@sveltejs/kit";
|
import { errorWithVerse } from "$lib/server/errorQuote"
|
||||||
|
|
||||||
export const load : LayoutServerLoad = async ({locals, params}) => {
|
export const load : LayoutServerLoad = async ({locals, params, fetch, url}) => {
|
||||||
// Validate recipeLang parameter
|
// Validate recipeLang parameter
|
||||||
if (params.recipeLang !== 'rezepte' && params.recipeLang !== 'recipes') {
|
if (params.recipeLang !== 'rezepte' && params.recipeLang !== 'recipes') {
|
||||||
throw error(404, 'Not found');
|
await errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const lang = params.recipeLang === 'recipes' ? 'en' : 'de';
|
const lang = params.recipeLang === 'recipes' ? 'en' : 'de';
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = ({ fetch, url }) =>
|
||||||
|
errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export const load = () => {
|
|
||||||
error(404, 'Not found');
|
|
||||||
};
|
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
import { redirect, error } from '@sveltejs/kit';
|
import { redirect, error } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad, Actions } from './$types';
|
import type { PageServerLoad, Actions } from './$types';
|
||||||
import { stripHtmlTags } from '$lib/js/stripHtmlTags';
|
import { stripHtmlTags } from '$lib/js/stripHtmlTags';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ fetch, params, locals }) => {
|
export const load: PageServerLoad = async ({ fetch, params, locals, url }) => {
|
||||||
const isEnglish = params.recipeLang === 'recipes';
|
const isEnglish = params.recipeLang === 'recipes';
|
||||||
const apiBase = `/api/${params.recipeLang}`;
|
const apiBase = `/api/${params.recipeLang}`;
|
||||||
|
|
||||||
const res = await fetch(`${apiBase}/items/${params.name}`);
|
const res = await fetch(`${apiBase}/items/${params.name}`);
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw error(res.status, 'Recipe not found');
|
await errorWithVerse(fetch, url.pathname, res.status, 'Recipe not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const item = await res.json();
|
const item = await res.json();
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { redirect, error } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ locals, url }) => {
|
export const load: PageServerLoad = async ({ locals, url, fetch }) => {
|
||||||
const session = await locals.auth();
|
const session = await locals.auth();
|
||||||
|
|
||||||
// Redirect to login if not authenticated
|
// Redirect to login if not authenticated
|
||||||
@@ -12,7 +13,7 @@ export const load: PageServerLoad = async ({ locals, url }) => {
|
|||||||
|
|
||||||
// Check user group permission
|
// Check user group permission
|
||||||
if (!session.user.groups?.includes('rezepte_users')) {
|
if (!session.user.groups?.includes('rezepte_users')) {
|
||||||
throw error(403, 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich.');
|
await errorWithVerse(fetch, url.pathname, 403, 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { redirect, error } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ locals, url }) => {
|
export const load: PageServerLoad = async ({ locals, url, fetch }) => {
|
||||||
const session = await locals.auth();
|
const session = await locals.auth();
|
||||||
|
|
||||||
if (!session?.user?.nickname) {
|
if (!session?.user?.nickname) {
|
||||||
@@ -10,7 +11,7 @@ export const load: PageServerLoad = async ({ locals, url }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!session.user.groups?.includes('rezepte_users')) {
|
if (!session.user.groups?.includes('rezepte_users')) {
|
||||||
throw error(403, 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich.');
|
await errorWithVerse(fetch, url.pathname, 403, 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { PageServerLoad } from "./$types";
|
import type { PageServerLoad } from "./$types";
|
||||||
import { redirect, error } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ fetch, locals, url, params }) => {
|
export const load: PageServerLoad = async ({ fetch, locals, url, params }) => {
|
||||||
const session = await locals.auth();
|
const session = await locals.auth();
|
||||||
@@ -12,7 +13,7 @@ export const load: PageServerLoad = async ({ fetch, locals, url, params }) => {
|
|||||||
|
|
||||||
// Check user group permission
|
// Check user group permission
|
||||||
if (!session.user.groups?.includes('rezepte_users')) {
|
if (!session.user.groups?.includes('rezepte_users')) {
|
||||||
throw error(403, 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich.');
|
await errorWithVerse(fetch, url.pathname, 403, 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich.');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { redirect, error } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ locals, params, url }) => {
|
export const load: PageServerLoad = async ({ locals, params, url, fetch }) => {
|
||||||
const session = await locals.auth();
|
const session = await locals.auth();
|
||||||
|
|
||||||
// Redirect to login if not authenticated
|
// Redirect to login if not authenticated
|
||||||
@@ -12,7 +13,7 @@ export const load: PageServerLoad = async ({ locals, params, url }) => {
|
|||||||
|
|
||||||
// Check user group permission
|
// Check user group permission
|
||||||
if (!session.user.groups?.includes('rezepte_users')) {
|
if (!session.user.groups?.includes('rezepte_users')) {
|
||||||
throw error(403, 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich.');
|
await errorWithVerse(fetch, url.pathname, 403, 'Zugriff verweigert. Du hast keine Berechtigung für diesen Bereich.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = ({ fetch, url }) =>
|
||||||
|
errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export const load = () => {
|
|
||||||
error(404, 'Not found');
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, fetch, url }) => {
|
export const load: PageServerLoad = async ({ params, fetch, url }) => {
|
||||||
const lang = url.pathname.includes('/uebungen') ? 'de' : 'en';
|
const lang = url.pathname.includes('/uebungen') ? 'de' : 'en';
|
||||||
@@ -10,7 +10,7 @@ export const load: PageServerLoad = async ({ params, fetch, url }) => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (!exerciseRes.ok) {
|
if (!exerciseRes.ok) {
|
||||||
error(404, 'Exercise not found');
|
await errorWithVerse(fetch, url.pathname, 404, 'Exercise not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const exerciseData = await exerciseRes.json();
|
const exerciseData = await exerciseRes.json();
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, fetch }) => {
|
export const load: PageServerLoad = async ({ params, fetch, url }) => {
|
||||||
const res = await fetch(`/api/fitness/sessions/${params.id}`);
|
const res = await fetch(`/api/fitness/sessions/${params.id}`);
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
error(404, 'Session not found');
|
await errorWithVerse(fetch, url.pathname, 404, 'Session not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { error } from '@sveltejs/kit';
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
import { NUTRITION_DB } from '$lib/data/nutritionDb';
|
import { NUTRITION_DB } from '$lib/data/nutritionDb';
|
||||||
import { BLS_DB } from '$lib/data/blsDb';
|
import { BLS_DB } from '$lib/data/blsDb';
|
||||||
import { DRI_MALE } from '$lib/data/dailyReferenceIntake';
|
import { DRI_MALE } from '$lib/data/dailyReferenceIntake';
|
||||||
@@ -60,16 +60,16 @@ async function computeRecipePer100g(id: string): Promise<Record<string, number>>
|
|||||||
return per100g;
|
return per100g;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, url }) => {
|
export const load: PageServerLoad = async ({ params, url, fetch }) => {
|
||||||
const { source, id } = params;
|
const { source, id } = params;
|
||||||
|
|
||||||
if (source !== 'bls' && source !== 'usda' && source !== 'recipe' && source !== 'off' && source !== 'custom') {
|
if (source !== 'bls' && source !== 'usda' && source !== 'recipe' && source !== 'off' && source !== 'custom') {
|
||||||
throw error(404, 'Invalid source');
|
await errorWithVerse(fetch, url.pathname, 404, 'Invalid source');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source === 'bls') {
|
if (source === 'bls') {
|
||||||
const entry = BLS_DB.find(e => e.blsCode === id);
|
const entry = BLS_DB.find(e => e.blsCode === id);
|
||||||
if (!entry) throw error(404, 'Food not found');
|
if (!entry) await errorWithVerse(fetch, url.pathname, 404, 'Food not found');
|
||||||
return {
|
return {
|
||||||
food: {
|
food: {
|
||||||
source: 'bls' as const,
|
source: 'bls' as const,
|
||||||
@@ -91,7 +91,7 @@ export const load: PageServerLoad = async ({ params, url }) => {
|
|||||||
const recipe = await Recipe.findOne(recipeQuery)
|
const recipe = await Recipe.findOne(recipeQuery)
|
||||||
.select('short_name name translations images')
|
.select('short_name name translations images')
|
||||||
.lean();
|
.lean();
|
||||||
if (!recipe) throw error(404, 'Recipe not found');
|
if (!recipe) await errorWithVerse(fetch, url.pathname, 404, 'Recipe not found');
|
||||||
|
|
||||||
// Use logged per100g from food diary entry if provided, otherwise compute from current recipe
|
// Use logged per100g from food diary entry if provided, otherwise compute from current recipe
|
||||||
const logEntryId = url.searchParams.get('logEntry');
|
const logEntryId = url.searchParams.get('logEntry');
|
||||||
@@ -131,7 +131,7 @@ export const load: PageServerLoad = async ({ params, url }) => {
|
|||||||
if (source === 'off') {
|
if (source === 'off') {
|
||||||
await dbConnect();
|
await dbConnect();
|
||||||
const entry = await OpenFoodFact.findOne({ barcode: id }).lean();
|
const entry = await OpenFoodFact.findOne({ barcode: id }).lean();
|
||||||
if (!entry) throw error(404, 'Food not found');
|
if (!entry) await errorWithVerse(fetch, url.pathname, 404, 'Food not found');
|
||||||
const portions: { description: string; grams: number }[] = [];
|
const portions: { description: string; grams: number }[] = [];
|
||||||
if (entry.serving?.grams) {
|
if (entry.serving?.grams) {
|
||||||
portions.push(entry.serving as { description: string; grams: number });
|
portions.push(entry.serving as { description: string; grams: number });
|
||||||
@@ -156,7 +156,7 @@ export const load: PageServerLoad = async ({ params, url }) => {
|
|||||||
if (source === 'custom') {
|
if (source === 'custom') {
|
||||||
await dbConnect();
|
await dbConnect();
|
||||||
const meal = await CustomMeal.findById(id).lean();
|
const meal = await CustomMeal.findById(id).lean();
|
||||||
if (!meal) throw error(404, 'Meal not found');
|
if (!meal) await errorWithVerse(fetch, url.pathname, 404, 'Meal not found');
|
||||||
|
|
||||||
// Aggregate per100g from ingredients
|
// Aggregate per100g from ingredients
|
||||||
const totals: Record<string, number> = {};
|
const totals: Record<string, number> = {};
|
||||||
@@ -211,7 +211,7 @@ export const load: PageServerLoad = async ({ params, url }) => {
|
|||||||
// USDA
|
// USDA
|
||||||
const fdcId = Number(id);
|
const fdcId = Number(id);
|
||||||
const entry = NUTRITION_DB.find(e => e.fdcId === fdcId);
|
const entry = NUTRITION_DB.find(e => e.fdcId === fdcId);
|
||||||
if (!entry) throw error(404, 'Food not found');
|
if (!entry) await errorWithVerse(fetch, url.pathname, 404, 'Food not found');
|
||||||
return {
|
return {
|
||||||
food: {
|
food: {
|
||||||
source: 'usda' as const,
|
source: 'usda' as const,
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { errorWithVerse } from '$lib/server/errorQuote';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = ({ fetch, url }) =>
|
||||||
|
errorWithVerse(fetch, url.pathname, 404, 'Not found');
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export const load = () => {
|
|
||||||
error(404, 'Not found');
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user