diff --git a/src/params/fitnessDate.ts b/src/params/fitnessDate.ts new file mode 100644 index 00000000..c36756b9 --- /dev/null +++ b/src/params/fitnessDate.ts @@ -0,0 +1,5 @@ +import type { ParamMatcher } from '@sveltejs/kit'; + +export const match: ParamMatcher = (param) => { + return /^\d{4}-\d{2}-\d{2}$/.test(param); +}; diff --git a/src/routes/fitness/+layout.svelte b/src/routes/fitness/+layout.svelte index b6e84208..3fe58de7 100644 --- a/src/routes/fitness/+layout.svelte +++ b/src/routes/fitness/+layout.svelte @@ -64,7 +64,9 @@ const activePath = $derived(`/fitness/${s.workout}/${s.active}`); const isOnActivePage = $derived($page.url.pathname === activePath); const isNutritionPage = $derived( - $page.url.pathname === `/fitness/${s.nutrition}` || $page.url.pathname === `/fitness/${s.nutrition}/` + $page.url.pathname.startsWith(`/fitness/${s.nutrition}`) && + !$page.url.pathname.startsWith(`/fitness/${s.nutrition}/food`) && + !$page.url.pathname.startsWith(`/fitness/${s.nutrition}/meals`) ); /** @param {number} secs */ diff --git a/src/routes/fitness/[nutrition=fitnessNutrition]/+page.server.ts b/src/routes/fitness/[nutrition=fitnessNutrition]/[[date=fitnessDate]]/+page.server.ts similarity index 96% rename from src/routes/fitness/[nutrition=fitnessNutrition]/+page.server.ts rename to src/routes/fitness/[nutrition=fitnessNutrition]/[[date=fitnessDate]]/+page.server.ts index 059d9130..19d1a6cb 100644 --- a/src/routes/fitness/[nutrition=fitnessNutrition]/+page.server.ts +++ b/src/routes/fitness/[nutrition=fitnessNutrition]/[[date=fitnessDate]]/+page.server.ts @@ -6,8 +6,8 @@ import { Recipe } from '$models/Recipe'; import { RoundOffCache } from '$models/RoundOffCache'; import mongoose from 'mongoose'; -export const load: PageServerLoad = async ({ fetch, url, locals }) => { - const dateParam = url.searchParams.get('date') || new Date().toISOString().slice(0, 10); +export const load: PageServerLoad = async ({ fetch, params, locals }) => { + const dateParam = params.date || new Date().toISOString().slice(0, 10); // Run all independent work in parallel: 3 API calls + workout kcal DB query const dayStart = new Date(dateParam + 'T00:00:00.000Z'); diff --git a/src/routes/fitness/[nutrition=fitnessNutrition]/+page.svelte b/src/routes/fitness/[nutrition=fitnessNutrition]/[[date=fitnessDate]]/+page.svelte similarity index 98% rename from src/routes/fitness/[nutrition=fitnessNutrition]/+page.svelte rename to src/routes/fitness/[nutrition=fitnessNutrition]/[[date=fitnessDate]]/+page.svelte index 3ed1dc57..6d1dbc36 100644 --- a/src/routes/fitness/[nutrition=fitnessNutrition]/+page.svelte +++ b/src/routes/fitness/[nutrition=fitnessNutrition]/[[date=fitnessDate]]/+page.svelte @@ -29,17 +29,17 @@ return d.toLocaleDateString(isEn ? 'en-US' : 'de-DE', { weekday: 'short', day: 'numeric', month: 'short' }); }); - async function navigateDate(offset) { + function dateOffset(offset) { const d = new Date(currentDate + 'T12:00:00'); d.setDate(d.getDate() + offset); - currentDate = d.toISOString().slice(0, 10); - await loadEntries(); + return d.toISOString().slice(0, 10); } - async function goToday() { - currentDate = todayStr; - await loadEntries(); - } + const prevDate = $derived(dateOffset(-1)); + const nextDate = $derived(dateOffset(1)); + const prevHref = $derived(prevDate === todayStr ? `/fitness/${s.nutrition}` : `/fitness/${s.nutrition}/${prevDate}`); + const nextHref = $derived(nextDate === todayStr ? `/fitness/${s.nutrition}` : `/fitness/${s.nutrition}/${nextDate}`); + const todayHref = $derived(`/fitness/${s.nutrition}`); // --- Entries --- // svelte-ignore state_referenced_locally @@ -47,10 +47,6 @@ // svelte-ignore state_referenced_locally let recipeImages = $state(data.recipeImages ?? {}); - async function loadEntries() { - await goto(`/fitness/${s.nutrition}?date=${currentDate}`, { replaceState: true, noScroll: true }); - } - // Keep reactive with server data when navigating $effect(() => { entries = data.foodLog?.entries ?? []; @@ -748,7 +744,7 @@ }) }); - await goto(`/fitness/${s.nutrition}?date=${currentDate}`, { replaceState: true, noScroll: true }); + await goto(`/fitness/${s.nutrition}/${currentDate}`, { replaceState: true, noScroll: true }); selectedCmMeal = null; closeFabModal(); toast.success(isEn ? `Logged "${meal.name}"` : `"${meal.name}" eingetragen`); @@ -793,7 +789,7 @@ }) }); - await goto(`/fitness/${s.nutrition}?date=${currentDate}`, { replaceState: true, noScroll: true }); + await goto(`/fitness/${s.nutrition}/${currentDate}`, { replaceState: true, noScroll: true }); selectedCmMeal = null; cancelAdd(); toast.success(isEn ? `Logged "${meal.name}"` : `"${meal.name}" eingetragen`); @@ -1160,18 +1156,18 @@