Replace season: number[] (months 1-12) on Recipe with seasonRanges, a list of date ranges where each endpoint is either a fixed MM-DD or a movable liturgical anchor (Easter, Ash Wednesday, Palm Sunday, Pentecost, Advent I) plus a day offset. The old month list couldn't express liturgical seasons whose boundaries shift each year (Advent, Lent, Easter Octave, Christmas Octave) nor sub-month windows. The shared evaluator resolves anchors against [Y-1, Y, Y+1] so spans that wrap the calendar year boundary (e.g. christmas + 0 to christmas + 7) match correctly on both sides. SeasonSelect was rewritten as a controlled bind:ranges editor with a fixed/liturgical kind toggle, anchor + offset inputs, per-row resolved-this-year preview, and preset chips. Run the one-time migration before deploying: pnpm exec vite-node scripts/migrate-season-to-ranges.ts It coalesces contiguous month runs into single fixed ranges and merges Dec/Jan wrap into one wrapping range; the new code does not read the legacy season field, so order matters.
This commit is contained in:
+13
-13
@@ -1,7 +1,8 @@
|
||||
import type { BriefRecipeType, RecipeModelType } from '$types/types';
|
||||
import { isRecipeInSeason, recipeOverlapsMonth } from '$lib/js/seasonRange';
|
||||
|
||||
const DB_NAME = 'bocken-recipes';
|
||||
const DB_VERSION = 2; // Bumped to force recreation of stores
|
||||
const DB_VERSION = 3; // v3: dropped multi-entry season index after migration to seasonRanges
|
||||
|
||||
const STORE_BRIEF = 'recipes_brief';
|
||||
const STORE_FULL = 'recipes_full';
|
||||
@@ -51,10 +52,12 @@ function openDB(): Promise<IDBDatabase> {
|
||||
db.deleteObjectStore(STORE_META);
|
||||
}
|
||||
|
||||
// Brief recipes store - keyed by short_name for quick lookups
|
||||
// Brief recipes store - keyed by short_name for quick lookups.
|
||||
// Season membership is now driven by date ranges with movable
|
||||
// liturgical anchors that can't be expressed as a static index, so
|
||||
// season filtering loads all rows and runs the shared evaluator.
|
||||
const briefStore = db.createObjectStore(STORE_BRIEF, { keyPath: 'short_name' });
|
||||
briefStore.createIndex('category', 'category', { unique: false });
|
||||
briefStore.createIndex('season', 'season', { unique: false, multiEntry: true });
|
||||
|
||||
// Full recipes store - keyed by short_name
|
||||
db.createObjectStore(STORE_FULL, { keyPath: 'short_name' });
|
||||
@@ -104,17 +107,14 @@ export async function getBriefRecipesByCategory(category: string): Promise<Brief
|
||||
});
|
||||
}
|
||||
|
||||
export async function getBriefRecipesBySeason(month: number): Promise<BriefRecipeType[]> {
|
||||
const db = await openDB();
|
||||
return new Promise((resolve, reject) => {
|
||||
const tx = db.transaction(STORE_BRIEF, 'readonly');
|
||||
const store = tx.objectStore(STORE_BRIEF);
|
||||
const index = store.index('season');
|
||||
const request = index.getAll(month);
|
||||
export async function getBriefRecipesInSeasonOn(date: Date = new Date()): Promise<BriefRecipeType[]> {
|
||||
const all = await getAllBriefRecipes();
|
||||
return all.filter(r => isRecipeInSeason(r as any, date));
|
||||
}
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
});
|
||||
export async function getBriefRecipesOverlappingMonth(month: number, year: number = new Date().getFullYear()): Promise<BriefRecipeType[]> {
|
||||
const all = await getAllBriefRecipes();
|
||||
return all.filter(r => recipeOverlapsMonth(r as any, month, year));
|
||||
}
|
||||
|
||||
export async function getBriefRecipesByTag(tag: string): Promise<BriefRecipeType[]> {
|
||||
|
||||
@@ -241,11 +241,13 @@ async function precacheRecipeData(recipes: BriefRecipeType[]): Promise<void> {
|
||||
dataUrls.push(`/recipes/icon/${encodeURIComponent(icon)}/__data.json`);
|
||||
}
|
||||
|
||||
// Add season subroute data (all 12 months)
|
||||
// Add season subroute data (all 12 months + today's liturgical-aware view)
|
||||
for (let month = 1; month <= 12; month++) {
|
||||
dataUrls.push(`/rezepte/season/${month}/__data.json`);
|
||||
dataUrls.push(`/recipes/season/${month}/__data.json`);
|
||||
}
|
||||
dataUrls.push(`/rezepte/season/__data.json`);
|
||||
dataUrls.push(`/recipes/season/__data.json`);
|
||||
|
||||
// Send message to service worker to cache these URLs
|
||||
if (dataUrls.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user