Skip to content

Commit

Permalink
feature: add additional info to recipe
Browse files Browse the repository at this point in the history
- number of servings
- estimated time to cook
- difficulty level
- calories (optional)
  • Loading branch information
martinhauke committed Aug 16, 2024
1 parent cc0e4c8 commit f6c020c
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 9,643 deletions.
9,632 changes: 1 addition & 9,631 deletions .gitignore

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.10.2",
"@astrojs/check": "^0.7.0",
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"astro": "^4.10.2",
"typescript": "^5.4.5"
}
}
}
5 changes: 4 additions & 1 deletion src/components/ContentBox.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface Props {
const {class: additionalClass, title: title, ...rest} = Astro.props;
---
<div class:list={["content-box", additionalClass]} {...rest}>
<div class:list={["content-box", additionalClass, title ? "with-title" : "no-title"]} {...rest}>
{title && <h1 class="heading">{title}</h1>}
<section>
<slot/>
Expand All @@ -25,6 +25,9 @@ const {class: additionalClass, title: title, ...rest} = Astro.props;
padding: 10px;
}
}
.no-title section {
width: 100%;
}

.heading {
margin: 0;
Expand Down
1 change: 1 addition & 0 deletions src/components/RecipeList.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const recipes = await getCollection('recipes')
title={recipe.data.name}
body={recipe.data.description ?? ''}
img={recipe.data.image}
metaInformation={recipe.data.metaInformation}
/>
))}
</ul>
Expand Down
15 changes: 9 additions & 6 deletions src/components/RecipeListItem.astro
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
---
import Link from "./Link.astro";
import {type Image} from "../content/config";
import {type Image, type MetaInformation} from "../content/config";
import RecipeMetaData from "./RecipeMetaData.astro";
interface Props {
title: string;
body: string;
img: Image;
href: string;
title: string
body: string
img: Image
href: string
metaInformation: MetaInformation
}
const {href, title, body, img} = Astro.props;
const {href, title, body, img, metaInformation} = Astro.props;
---

<Link href={href} title={title} class="list-item">
<img class="image" src={import.meta.env.BASE_URL + "/" + img.src} alt={img.alt}/>
<RecipeMetaData metaInformation={metaInformation} isCompactView={true} />
<h2>
{title}
</h2>
Expand Down
64 changes: 64 additions & 0 deletions src/components/RecipeMetaData.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
import ContentBox from "./ContentBox.astro";
import {type MetaInformation} from "../content/config";
// Font Awesome
import { library, icon } from "@fortawesome/fontawesome-svg-core";
import { faUsers, faClock } from "@fortawesome/free-solid-svg-icons";
// Declare all the icons you plan on using
library.add(faUsers, faClock);
// Instantiate the icon with the icon function
const numberOfServingsIcon = icon({ prefix: "fas", iconName: faUsers.iconName });
const timeNeededIcon = icon({ prefix: "fas", iconName: faClock.iconName });
interface Props {
metaInformation: MetaInformation;
isCompactView?: boolean;
}
const {metaInformation, isCompactView} = Astro.props;
---

<ContentBox class={isCompactView ? "meta-information--compact-view" : "meta-information"}>
<ul class={isCompactView ? "compact-view" : ""}>
<li><Fragment set:html={numberOfServingsIcon.html}/><span class="label">Portionen:</span><span class="value">{metaInformation.numberOfServings}</span></li>
<li><Fragment set:html={timeNeededIcon.html}/><span class="label">Zubereitungszeit:</span><span class="value">{metaInformation.timeNeeded}</span></li>
<li><span class="label">Schwierigkeit:</span><span class="value">{metaInformation.difficulty}</span></li>
{metaInformation.kcalPerServing && <li><span class="label">Energiegehalt pro Portion:</span><span class="value">{metaInformation.kcalPerServing} kcal</span></li>}
</ul>
</ContentBox>

<style>
.meta-information {
background-color: var(--flatgreen);
color: var(--darkgreen);
margin: 0;
}
ul {
display: flex;
margin: 0;
padding: 10px 20px;
justify-content: space-between;
}
li {
display: flex;
flex-direction: row;
list-style: none;
gap: 10px;
align-items: center;
}
.value {
font-weight: bold;
}
.meta-information--compact-view {
margin: 0;
section {
padding: 0;
background-color: var(--darkgreen);
color: var(--flatgreen);
}
.label {
display: none;
}
}
</style>
15 changes: 12 additions & 3 deletions src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,16 @@ const ingredientGroup = z.object({
})

const image = z.object({
src: z.string(),
alt: z.string(),
title: z.string().optional(),
src: z.string(),
alt: z.string(),
title: z.string().optional(),
})

const metaInformation = z.object({
numberOfServings: z.number(),
timeNeeded: z.string().regex(/(\d+\s)(min|h)/),
kcalPerServing: z.number().optional(),
difficulty: z.enum(["einfach", "mittel", "schwer"])
})

const recipe = z.object({
Expand All @@ -27,6 +34,7 @@ const recipe = z.object({
image: image,
steps: z.array(z.string()),
isPublic: z.boolean().default(false),
metaInformation: metaInformation,
})

// 2. Define a `type` and `schema` for each collection
Expand All @@ -43,4 +51,5 @@ export const collections = {
export type Ingredient = z.infer<typeof ingredient>
export type IngredientGroup = z.infer<typeof ingredientGroup>
export type Image = z.infer<typeof image>
export type MetaInformation = z.infer<typeof metaInformation>

4 changes: 4 additions & 0 deletions src/content/recipes/Kichererbsencurry.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
id: kichererbsencurry
name: Kichererbsencurry
description: Cremiges Curry mit Kichererbsen, Kokosmilch und Ofentofu.
metaInformation:
timeNeeded: 1 h
difficulty: "mittel"
numberOfServings: 4
ingredientGroups:
- name: default
ingredients:
Expand Down
4 changes: 4 additions & 0 deletions src/content/recipes/Kindergartennudeln.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
id: kindergartennudeln
name: Kindergartennudeln
description: Einfaches Pastarezept mit nostalgischem Flair.
metaInformation:
timeNeeded: 20 min
difficulty: "einfach"
numberOfServings: 4
ingredientGroups:
- name: default
ingredients:
Expand Down
4 changes: 4 additions & 0 deletions src/content/recipes/Nudelsalat.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
id: cremiger-nudelsalat
name: Cremiger Nudelsalat
description: Fruchtiger Nudelsalat mit Balsamico, Tomaten und Basilikum
metaInformation:
timeNeeded: 40 min
difficulty: "einfach"
numberOfServings: 4
ingredientGroups:
- name: default
ingredients:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ id: schmortofu
name: Schmortofu mit frischem Kirchererbsen-Bohnen-Dipp
description: Schnelles Sommergericht mit vielen Proteinen
isPublic: true
metaInformation:
numberOfServings: 4
difficulty: "einfach"
timeNeeded: "30 min"
ingredientGroups:
- name: Tomatenreis
ingredients:
Expand Down
7 changes: 7 additions & 0 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,11 @@ const { title, description } = Astro.props;
main.content {
padding: 0 5px 50px;
}
.svg-inline--fa {
overflow: visible;
box-sizing: content-box;
display: inline-block;
height: 1em;
vertical-align: -0.125em;
}
</style>
3 changes: 3 additions & 0 deletions src/pages/recipe/[name].astro
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ const {recipe} = Astro.props
import Layout from "../../layouts/Layout.astro";
import Steps from "../../components/Steps.astro";
import ContentBox from "../../components/ContentBox.astro";
import RecipeMetaData from "../../components/RecipeMetaData.astro";
---
<Layout title={recipe.data.name} description={recipe.data.description}>
<ContentBox class="title"><h1>{recipe.data.name}</h1></ContentBox>
<img class="header-image image" src={import.meta.env.BASE_URL + "/" + recipe.data.image.src}
alt={recipe.data.image.alt}>
<RecipeMetaData metaInformation={recipe.data.metaInformation} />
<p>{recipe.data.description}</p>
<IngredientList ingredientGroups={recipe.data.ingredientGroups}/>
<Steps steps={recipe.data.steps}/>
Expand All @@ -49,6 +51,7 @@ import ContentBox from "../../components/ContentBox.astro";
}

.header-image {
display: block;
width: 100%;
padding: 0;
aspect-ratio: 16 / 9;
Expand Down

0 comments on commit f6c020c

Please sign in to comment.