fix(filter): ensure tag filtering with empty search or root URL properly displays matching items

This commit is contained in:
2026-08-18 13:34:14 -05:00
parent d28faf59a1
commit 974d99141e
+9 -5
View File
@@ -34,7 +34,6 @@ database.close();
const requested=Astro.url.searchParams.get("type");
if (requested === "inventory") return Astro.redirect("/app/inventory/", 303);
const type=["recipe","ingredient","book","purchase"].includes(requested??"")?requested:undefined;
const query=(Astro.url.searchParams.get("q")??"").trim();
const normalizedQuery=query.toLocaleLowerCase();
const validSearchTypes=["recipe","ingredient","book","purchase"];
@@ -42,6 +41,11 @@ const selectedSearchTypes=Astro.url.searchParams.getAll("item_type").filter((val
const filteringSearchTypes=selectedSearchTypes.length>0;
const selectedTags=Astro.url.searchParams.getAll("tag").map(t=>t.trim().toLowerCase()).filter(Boolean);
// Default to "recipe" when not in a global search
const type = ["recipe","ingredient","book","purchase"].includes(requested ?? "")
? requested
: (query ? undefined : "recipe");
// Recipe attention filters (Meez spec)
const emptyRecipe=Astro.url.searchParams.get("empty_recipe")==="1";
const missingYield=Astro.url.searchParams.get("missing_yield")==="1";
@@ -178,10 +182,10 @@ const tabs:Array<{type:string;label:string;count:number;kind:"recipe"|"ingredien
{type:"inventory",label:"Inventory",count:inventoryCounts?.c ?? 0,kind:"inventory",href:"/app/inventory/"},
];
const allSearchResults=normalizedQuery ? [
...recipes.filter((item)=>`${item.title} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery)).map((item)=>({id:item.id,kind:"recipe" as const,label:"Recipe",name:item.title,detail:`${item.yield_quantity} ${item.yield_unit_id}`,href:`/app/recipes/${item.id}/`})),
...ingredients.filter((item)=>`${item.name} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery)).map((item)=>({id:item.id,kind:"ingredient" as const,label:"Ingredient",name:titleCase(item.name),detail:`Used in ${item.recipe_count} ${item.recipe_count===1?"recipe":"recipes"}`,href:`/app/ingredients/${item.id}/`})),
...books.filter((item)=>`${item.name} ${item.description??""} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery)).map((item)=>({id:item.id,kind:"book" as const,label:"Recipe book",name:item.name,detail:`${item.recipe_count} ${item.recipe_count===1?"recipe":"recipes"}`,href:`/app/recipe-books/${item.id}/`})),
...purchases.filter((item)=>`${item.name} ${item.ingredient_name} ${item.supplier_id??""} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery)).map((item)=>({id:item.id,kind:"purchase" as const,label:"Purchase item",name:item.name,detail:titleCase(item.ingredient_name),href:`/app/ingredients/${item.ingredient_id}/#costs`})),
...recipes.filter((item)=>`${item.title} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery) && (selectedTags.length === 0 || parseItemTags(item.tags_json, item.categories_json).some(t => selectedTags.includes(t)))).map((item)=>({id:item.id,kind:"recipe" as const,label:"Recipe",name:item.title,detail:`${item.yield_quantity} ${item.yield_unit_id}`,href:`/app/recipes/${item.id}/`})),
...ingredients.filter((item)=>`${item.name} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery) && (selectedTags.length === 0 || parseItemTags(item.tags_json, item.categories_json).some(t => selectedTags.includes(t)))).map((item)=>({id:item.id,kind:"ingredient" as const,label:"Ingredient",name:titleCase(item.name),detail:`Used in ${item.recipe_count} ${item.recipe_count===1?"recipe":"recipes"}`,href:`/app/ingredients/${item.id}/`})),
...books.filter((item)=>`${item.name} ${item.description??""} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery) && selectedTags.length === 0).map((item)=>({id:item.id,kind:"book" as const,label:"Recipe book",name:item.name,detail:`${item.recipe_count} ${item.recipe_count===1?"recipe":"recipes"}`,href:`/app/recipe-books/${item.id}/`})),
...purchases.filter((item)=>`${item.name} ${item.ingredient_name} ${item.supplier_id??""} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery) && selectedTags.length === 0).map((item)=>({id:item.id,kind:"purchase" as const,label:"Purchase item",name:item.name,detail:titleCase(item.ingredient_name),href:`/app/ingredients/${item.ingredient_id}/#costs`})),
].sort((a,b)=>a.name.localeCompare(b.name)):[];
const searchResults=filteringSearchTypes?allSearchResults.filter((result)=>selectedSearchTypes.includes(result.kind)):allSearchResults;
const searchRows=searchResults.map(({id,kind,name,href,label,detail})=>({id,name,href,kind,detail:`${label} · ${detail}`}));