fix: make recipe ingredinets interactive
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { asset } from "$fresh/runtime.ts";
|
import { asset } from "$fresh/runtime.ts";
|
||||||
import * as CSS from "https://esm.sh/csstype@3.1.2";
|
import * as CSS from "csstype";
|
||||||
|
|
||||||
interface ResponsiveAttributes {
|
interface ResponsiveAttributes {
|
||||||
srcset: string;
|
srcset: string;
|
||||||
|
|||||||
@@ -26,11 +26,14 @@
|
|||||||
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.1",
|
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.1",
|
||||||
"@std/http": "jsr:@std/http@^1.0.12",
|
"@std/http": "jsr:@std/http@^1.0.12",
|
||||||
"@std/yaml": "jsr:@std/yaml@^1.0.5",
|
"@std/yaml": "jsr:@std/yaml@^1.0.5",
|
||||||
|
"csstype": "npm:csstype@^3.1.3",
|
||||||
"defuddle": "npm:defuddle@^0.6.6",
|
"defuddle": "npm:defuddle@^0.6.6",
|
||||||
"drizzle-kit": "npm:drizzle-kit@^0.30.1",
|
"drizzle-kit": "npm:drizzle-kit@^0.30.1",
|
||||||
"drizzle-orm": "npm:drizzle-orm@^0.38.3",
|
"drizzle-orm": "npm:drizzle-orm@^0.38.3",
|
||||||
"fuzzysort": "npm:fuzzysort@^3.1.0",
|
"fuzzysort": "npm:fuzzysort@^3.1.0",
|
||||||
"jsdom": "npm:jsdom@^24.1.3",
|
"jsdom": "npm:jsdom@^24.1.3",
|
||||||
|
"moviedb-promise": "npm:moviedb-promise@^4.0.7",
|
||||||
|
"parse-ingredient": "npm:parse-ingredient@^1.3.1",
|
||||||
"playwright": "npm:playwright@^1.49.1",
|
"playwright": "npm:playwright@^1.49.1",
|
||||||
"playwright-extra": "npm:playwright-extra@^4.3.6",
|
"playwright-extra": "npm:playwright-extra@^4.3.6",
|
||||||
"preact": "https://esm.sh/preact@10.22.0",
|
"preact": "https://esm.sh/preact@10.22.0",
|
||||||
@@ -42,6 +45,7 @@
|
|||||||
"tailwindcss/": "npm:/tailwindcss@^3.4.17/",
|
"tailwindcss/": "npm:/tailwindcss@^3.4.17/",
|
||||||
"tailwindcss/plugin": "npm:/tailwindcss@^3.4.17/plugin.js",
|
"tailwindcss/plugin": "npm:/tailwindcss@^3.4.17/plugin.js",
|
||||||
"camelcase-css": "npm:camelcase-css",
|
"camelcase-css": "npm:camelcase-css",
|
||||||
|
"thumbhash": "npm:thumbhash@^0.1.1",
|
||||||
"tsx": "npm:tsx@^4.19.2",
|
"tsx": "npm:tsx@^4.19.2",
|
||||||
"yaml": "https://deno.land/std@0.197.0/yaml/mod.ts",
|
"yaml": "https://deno.land/std@0.197.0/yaml/mod.ts",
|
||||||
"zod": "npm:zod@^3.24.1",
|
"zod": "npm:zod@^3.24.1",
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ const Ingredient = (
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={key}>
|
<tr key={key}>
|
||||||
<td class="pr-4 py-2">
|
<td class="pr-4 py-1">
|
||||||
{formatAmount(finalAmount || 0)}
|
{formatAmount(finalAmount || 0)}
|
||||||
<span class="ml-0.5 opacity-50">
|
<span class="ml-0.5 opacity-50">
|
||||||
{formatUnit(unit, finalAmount || 0)}
|
{formatUnit(unit, finalAmount || 0)}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-2">{name}</td>
|
<td class="px-4 py-1">{name}</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -66,14 +66,10 @@ export const IngredientsList: FunctionalComponent<
|
|||||||
return (
|
return (
|
||||||
<table class="w-full border-collapse table-auto">
|
<table class="w-full border-collapse table-auto">
|
||||||
<tbody>
|
<tbody>
|
||||||
{ingredients.filter((s) => !!s?.length).map((item) => {
|
{ingredients.map((item) => {
|
||||||
return (
|
return (
|
||||||
<div dangerouslySetInnerHTML={{ __html: renderMarkdown(item) }}>
|
<Ingredient ingredient={item} amount={amount} portion={portion} />
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
// return (
|
|
||||||
// <Ingredient ingredient={item} amount={amount} portion={portion} />
|
|
||||||
// );
|
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ export const SearchResultItem = (
|
|||||||
) => {
|
) => {
|
||||||
const resourceType = resources[item?.content._type];
|
const resourceType = resources[item?.content._type];
|
||||||
const href = item?.path.replace("/resources", "").replace(/\.md$/, "");
|
const href = item?.path.replace("/resources", "").replace(/\.md$/, "");
|
||||||
console.log({ item, href });
|
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href={href}
|
href={href}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
parseIngredient,
|
parseIngredient,
|
||||||
unitsOfMeasure as _unitsOfMeasure,
|
unitsOfMeasure as _unitsOfMeasure,
|
||||||
} from "https://esm.sh/parse-ingredient@1.2.1";
|
} from "npm:parse-ingredient";
|
||||||
import { Ingredient, IngredientGroup } from "@lib/recipeSchema.ts";
|
import { Ingredient, IngredientGroup } from "@lib/recipeSchema.ts";
|
||||||
import { removeMarkdownFormatting } from "@lib/string.ts";
|
import { removeMarkdownFormatting } from "@lib/string.ts";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as thumbhash from "https://esm.sh/thumbhash@0.1.1";
|
import * as thumbhash from "thumbhash";
|
||||||
|
|
||||||
export function generateThumbhash(buffer: Uint8Array, w: number, h: number) {
|
export function generateThumbhash(buffer: Uint8Array, w: number, h: number) {
|
||||||
const hash = thumbhash.rgbaToThumbHash(w, h, buffer);
|
const hash = thumbhash.rgbaToThumbHash(w, h, buffer);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
MovieResultsResponse,
|
MovieResultsResponse,
|
||||||
ShowResponse,
|
ShowResponse,
|
||||||
TvResultsResponse,
|
TvResultsResponse,
|
||||||
} from "https://esm.sh/moviedb-promise@3.4.1";
|
} from "moviedb-promise";
|
||||||
import { createCache } from "@lib/cache.ts";
|
import { createCache } from "@lib/cache.ts";
|
||||||
const moviedb = new MovieDb(Deno.env.get("TMDB_API_KEY") || "");
|
const moviedb = new MovieDb(Deno.env.get("TMDB_API_KEY") || "");
|
||||||
|
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ export default async function Greet(
|
|||||||
return ctx.renderNotFound();
|
return ctx.renderNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
const { author = "", datePublished = "" } = movie.content;
|
const { author = "", datePublished = "",reviewBody } = movie.content;
|
||||||
|
|
||||||
const content = renderMarkdown(
|
const content = renderMarkdown(
|
||||||
removeImage(movie.content.reviewBody || "", movie.content.image),
|
removeImage(reviewBody || "", movie.content.image),
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -57,7 +57,7 @@ export default async function Greet(
|
|||||||
title: author?.name,
|
title: author?.name,
|
||||||
href: `/?q=${encodeURIComponent(author?.name)}`,
|
href: `/?q=${encodeURIComponent(author?.name)}`,
|
||||||
},
|
},
|
||||||
datePublished.toString(),
|
date.toString(),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{movie.content.reviewRating && (
|
{movie.content.reviewRating && (
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { IngredientsList } from "@islands/IngredientsList.tsx";
|
|||||||
import { MainLayout } from "@components/layouts/main.tsx";
|
import { MainLayout } from "@components/layouts/main.tsx";
|
||||||
import Counter from "@islands/Counter.tsx";
|
import Counter from "@islands/Counter.tsx";
|
||||||
import { Signal, useSignal } from "@preact/signals";
|
import { Signal, useSignal } from "@preact/signals";
|
||||||
import { Recipe } from "@lib/recipeSchema.ts";
|
|
||||||
import { RedirectSearchHandler } from "@islands/Search.tsx";
|
import { RedirectSearchHandler } from "@islands/Search.tsx";
|
||||||
import { KMenu } from "@islands/KMenu.tsx";
|
import { KMenu } from "@islands/KMenu.tsx";
|
||||||
import PageHero from "@components/PageHero.tsx";
|
import PageHero from "@components/PageHero.tsx";
|
||||||
@@ -12,8 +11,12 @@ import { renderMarkdown } from "@lib/markdown.ts";
|
|||||||
import { isValidRecipe } from "@lib/recipeSchema.ts";
|
import { isValidRecipe } from "@lib/recipeSchema.ts";
|
||||||
import { MetaTags } from "@components/MetaTags.tsx";
|
import { MetaTags } from "@components/MetaTags.tsx";
|
||||||
import { fetchResource } from "@lib/marka/index.ts";
|
import { fetchResource } from "@lib/marka/index.ts";
|
||||||
|
import { RecipeResource } from "@lib/marka/schema.ts";
|
||||||
|
import { parseIngredients } from "@lib/parseIngredient.ts";
|
||||||
|
|
||||||
export const handler: Handlers<{ recipe: Recipe; session: unknown } | null> = {
|
export const handler: Handlers<
|
||||||
|
{ recipe: RecipeResource; session: unknown } | null
|
||||||
|
> = {
|
||||||
async GET(_, ctx) {
|
async GET(_, ctx) {
|
||||||
try {
|
try {
|
||||||
const recipe = await fetchResource(`recipes/${ctx.params.name}.md`);
|
const recipe = await fetchResource(`recipes/${ctx.params.name}.md`);
|
||||||
@@ -31,7 +34,11 @@ function ValidRecipe({
|
|||||||
recipe,
|
recipe,
|
||||||
amount,
|
amount,
|
||||||
portion,
|
portion,
|
||||||
}: { recipe: Recipe; amount: Signal<number>; portion: number }) {
|
}: { recipe: RecipeResource; amount: Signal<number>; portion: number }) {
|
||||||
|
const ingredients = parseIngredients(
|
||||||
|
recipe.content.recipeIngredient?.join("\n"),
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div class="flex items-center gap-8">
|
<div class="flex items-center gap-8">
|
||||||
@@ -39,7 +46,7 @@ function ValidRecipe({
|
|||||||
{portion && <Counter count={amount} />}
|
{portion && <Counter count={amount} />}
|
||||||
</div>
|
</div>
|
||||||
<IngredientsList
|
<IngredientsList
|
||||||
ingredients={recipe.content.recipeIngredient}
|
ingredients={ingredients}
|
||||||
amount={amount}
|
amount={amount}
|
||||||
portion={portion}
|
portion={portion}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ export const handler: Handlers<{ serie: ReviewResource; session: unknown }> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Greet(
|
export default function Greet(
|
||||||
props: PageProps<{ serie: Series; session: Record<string, string> }>,
|
props: PageProps<{ serie: ReviewResource; session: Record<string, string> }>,
|
||||||
) {
|
) {
|
||||||
const { serie, session } = props.data;
|
const { serie, session } = props.data;
|
||||||
|
|
||||||
const { author = "", date = "" } = serie?.content || {};
|
const { author = "", date = "", reviewBody } = serie?.content || {};
|
||||||
|
|
||||||
const content = renderMarkdown(
|
const content = renderMarkdown(
|
||||||
removeImage(serie.description || "", serie.content?.image),
|
removeImage(reviewBody, serie.image?.url),
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user