diff --git a/src/lib/components/ActionButton.svelte b/src/lib/components/ActionButton.svelte index f83247a..a3549b6 100644 --- a/src/lib/components/ActionButton.svelte +++ b/src/lib/components/ActionButton.svelte @@ -19,7 +19,11 @@ background-color: var(--red); display: grid; justify-content: center; align-content: center; - +} +@media screen and (max-width: 500px) { + .container{ + margin: 1rem; + } } :global(.icon_svg){ width: 2rem; diff --git a/src/lib/components/CardAdd.svelte b/src/lib/components/CardAdd.svelte index 67d870e..6566d50 100644 --- a/src/lib/components/CardAdd.svelte +++ b/src/lib/components/CardAdd.svelte @@ -215,12 +215,19 @@ input::placeholder{ color:var(--nord0); } .card .description{ + box-sizing:border-box; + border: 2px solid var(--nord5); + border-radius: 30px; padding-inline: 1em; + padding-block: 0.5em; + margin-inline: 1em; + margin-top: 0; color: var(--nord4); width: calc(300px - 2em); /*??*/ } .card .description:hover{ color: var(--nord0); + border: 2px solid var(--nord0); } .card .tags{ display: flex; @@ -354,7 +361,7 @@ input::placeholder{
- +

{#each card_data.tags as tag} diff --git a/src/lib/components/CreateIngredientList.svelte b/src/lib/components/CreateIngredientList.svelte index 7b6a3e8..7fe86a4 100644 --- a/src/lib/components/CreateIngredientList.svelte +++ b/src/lib/components/CreateIngredientList.svelte @@ -10,6 +10,7 @@ import "$lib/css/action_button.css" import { do_on_key } from '$lib/components/do_on_key.js' export let ingredients +export let portions let new_ingredient = { amount: "", @@ -107,7 +108,6 @@ export function show_keys(event){ +
+

Portionen:

+

+

Zutaten

{#each ingredients as list, list_index}

@@ -326,26 +355,23 @@ h3{ {/if}
- +

- +
{/each} +
do_on_key(event, 'Enter', false, add_new_ingredient)}> @@ -358,7 +384,6 @@ h3{
-

Zutat verändern

diff --git a/src/lib/components/CreateStepList.svelte b/src/lib/components/CreateStepList.svelte index 54a18c8..dad87ed 100644 --- a/src/lib/components/CreateStepList.svelte +++ b/src/lib/components/CreateStepList.svelte @@ -12,6 +12,7 @@ import { do_on_key } from '$lib/components/do_on_key.js' const step_placeholder = "Kartoffeln schälen..." export let instructions +export let add_info let new_step = { name: "", @@ -32,6 +33,12 @@ function get_sublist_index(sublist_name, list){ return -1 } export function remove_list(list_index){ + if(instructions[list_index].steps.length > 1){ + const response = confirm("Bist du dir sicher, dass du diese Liste löschen möchtest? Alle Zubereitungsschritte der Liste werden hiermit auch gelöscht."); + if(!response){ + return + } + } instructions.splice(list_index, 1); instructions = instructions //tells svelte to update dom } @@ -117,9 +124,23 @@ input::placeholder{ all:unset; } - +li > div{ + display:flex; + flex-direction: row; + justify-items: space-between; + align-items:center; +} +li > div > div:first-child{ + flex-grow: 1; + cursor: pointer; +} +li > div > div:last-child{ + display: flex; + flex-direction: row; +} input.heading{ all: unset; + box-sizing: border-box; background-color: var(--nord0); padding: 1rem; padding-inline: 2rem; @@ -139,7 +160,7 @@ input.heading:focus-visible .heading_wrapper{ position: relative; - width: 300px; + width: min(300px, 95dvw); margin-inline: auto; transition: 200ms; } @@ -152,15 +173,20 @@ input.heading:focus-visible .heading_wrapper button{ position: absolute; bottom: -1.5rem; - right: -5rem; + right: -1.5rem; } .adder{ margin-inline: auto; position: relative; margin-block: 3rem; - width: 50ch; + width: 90%; border-radius: 20px; transition: 200ms; + background-color: var(--blue); + padding: 1.5rem 2rem; +} +dialog .adder{ + width: 400px; } .shadow{ box-shadow: 0 0 1em 0.2em rgba(0,0,0,0.3); @@ -202,17 +228,18 @@ input.heading:focus-visible font-family: sans-serif; width: 100%; font-size: 1.2rem; - padding: 2rem; - padding-top: 2.5rem; border-radius: 20px; - background-color: var(--blue); - color: #bbb; - transition: 200ms; + border: 2px solid var(--nord4); + border-radius: 30px; + padding: 0.5em 1em; + color: var(--nord4); + transition: 100ms; } .add_step p:hover, .add_step p:focus-visible { color: white; + scale: 1.02 1.02; } dialog{ @@ -239,6 +266,21 @@ dialog h2{ drop-shadow(0 0 1em black) ; } +@media screen and (max-width: 500px){ + dialog h2{ + margin-top: 2rem; + } + dialog .adder{ + width: 85%; + padding-inline: 0.5em; + } + dialog .adder .category{ + width: 70%; + } + dialog .adder input::placeholder{ + font-size: 1.2rem; + } +} dialog[open]{ animation: show 200ms ease forwards; } @@ -250,10 +292,122 @@ dialog[open]{ backdrop-filter: blur(10px); } } +ol li::marker{ + font-weight: bold; + color: var(--blue); + font-size: 1.2rem; +} +.instructions{ + flex-basis: 0; + flex-grow: 2; + background-color: var(--nord5); + padding-block: 1rem; + padding-inline: 2rem; +} +.instructions ol{ + padding-left: 1em; +} +.instructions li{ + margin-block: 0.5em; + font-size: 1.1rem; +} + +.additional_info{ + display: flex; + flex-wrap: wrap; + gap: 1em; +} +.additional_info > *{ + flex-grow: 0; + overflow: hidden; + padding: 1em; + background-color: #FAFAFE; + box-shadow: 0.3em 0.3em 1em 0.2em rgba(0,0,0,0.3); + /*max-width: 30%*/ +} +.additional_info > div > *:not(h4){ + line-height: 2em; +} +h4{ + line-height: 1em; + margin-block: 0; +} +.button_subtle{ + padding: 0em; + animation: unset; + margin: 0.2em 0.1em; + background-color: transparent; + box-shadow: unset; + display:inline; +} +.button_subtle:hover{ + scale: 1.2 1.2; +} +h3{ + display:flex; + gap: 1rem; +} +.additional_info input{ + all:unset; + display: inline; + width: 10ch; + border-radius: 1000px; + border: 2px solid grey; + padding: 0em 0.5em; +} +.additional_info input::placeholder{ + color: grey; +} +.additional_info p[contenteditable]{ + display: inline; + padding: 0.25em 1em; + border: 2px solid grey; + border-radius: 1000px; +} +.additional_info div:has(p[contenteditable]){ + transition: 200ms; + display: inline; +} +.additional_info div:has(p[contenteditable]):hover, +.additional_info div:has(p[contenteditable]):focus-within +{ + transform: scale(1.1, 1.1); +} +@media screen and (max-width: 500px){ + dialog h2{ + margin-top: 2rem; + } + dialog .heading_wrapper{ + width: 80%; + } +} +
+
+ +

Vorbereitung:

+

+
+

Stockgare:

+

+
+ +

Stückgare:

+

+
+ +

Backen:

+

bei

°C

+ +

Auf dem Teller:

+

+
+
+ +

Zubereitung

{#each instructions as list, list_index}

{#if list.name} @@ -261,31 +415,34 @@ dialog[open]{ {:else} Leer {/if} - - + +

    {#each list.steps as step, step_index} -
  1. {step} - - - +
{/each} {/each} +
do_on_key(event, 'Enter', false , add_new_step)} >
-

do_on_key(event, 'Enter', true , add_new_step)}>

+

do_on_key(event, 'Enter', true , add_new_step)}>

diff --git a/src/lib/components/IngredientsPage.svelte b/src/lib/components/IngredientsPage.svelte new file mode 100644 index 0000000..f006bc2 --- /dev/null +++ b/src/lib/components/IngredientsPage.svelte @@ -0,0 +1,45 @@ + + +{#if data.ingredients} +
+{#if data.portions} +

Portionen:

+ {data.portions} +{/if} +

Zutaten

+{#each data.ingredients as list} +{#if list.name} +

{list.name}

+{/if} +
+ {#each list.list as item} +
{item.amount} {item.unit}
{@html item.name}
+ {/each} +
+{/each} +
+{/if} diff --git a/src/lib/components/InstructionsPage.svelte b/src/lib/components/InstructionsPage.svelte new file mode 100644 index 0000000..0ddf886 --- /dev/null +++ b/src/lib/components/InstructionsPage.svelte @@ -0,0 +1,90 @@ + + +
+
+{#if data.preparation} +

Vorbereitung:

{data.preparation}
+{/if} + + +{#if data.fermentation} + {#if data.fermentation.bulk} +

Stockgare:

{data.fermentation.bulk}
+ {/if} + + {#if data.fermentation.final} +

Stückgare:

{data.fermentation.final}
+ {/if} +{/if} + +{#if data.baking.temperature} +

Backen:

{data.baking.length} bei {data.baking.temperature} °C {data.baking.mode}
+{/if} + +{#if data.total_time} +

Auf dem Teller:

{data.total_time}
+{/if} +
+ +{#if data.instructions} +

Zubereitung

+{#each data.instructions as list} +{#if list.name} +

{list.name}

+{/if} +
    + {#each list.steps as step} +
  1. {@html step}
  2. + {/each} +
+{/each} +{/if} +
diff --git a/src/lib/components/Search.svelte b/src/lib/components/Search.svelte index 17ed7d0..fbe0626 100644 --- a/src/lib/components/Search.svelte +++ b/src/lib/components/Search.svelte @@ -5,7 +5,6 @@ onMount(() => { const recipes = document.querySelectorAll(".search_me"); - console.log("######", recipes) const search = document.getElementById("search"); const clearSearch = document.getElementById("clear-search"); diff --git a/src/lib/components/SeasonSelect.svelte b/src/lib/components/SeasonSelect.svelte index ee4a790..dfe5411 100644 --- a/src/lib/components/SeasonSelect.svelte +++ b/src/lib/components/SeasonSelect.svelte @@ -1,9 +1,16 @@ @@ -75,6 +82,3 @@ input[type=checkbox]::after
{/each}
- - - diff --git a/src/lib/js/season_store.js b/src/lib/js/season_store.js new file mode 100644 index 0000000..e8ab5b8 --- /dev/null +++ b/src/lib/js/season_store.js @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const season = writable([]); diff --git a/src/models/Recipe.ts b/src/models/Recipe.ts index 660f632..06f52fc 100644 --- a/src/models/Recipe.ts +++ b/src/models/Recipe.ts @@ -16,16 +16,17 @@ const RecipeSchema = new mongoose.Schema( description: {type: String, required: true}, tags : [String], season : [Number], - baking: { temperature: String, - length: String, - mode: String, + baking: { temperature: {type:String, default: ""}, + length: {type:String, default: ""}, + mode: {type:String, default: ""}, }, - preparation : String, - fermentation: {bulk: String, - final: String, + preparation : {type:String, default: ""}, + fermentation: { bulk: {type:String, default: ""}, + final: {type:String, default: ""}, + }, - portions : String, - total_time : String, + portions :{type:String, default: ""}, + total_time : {type:String, default: ""}, ingredients : [ { name: {type: String, default: ""}, list: [{name: {type: String, default: ""}, unit: String, @@ -34,6 +35,7 @@ const RecipeSchema = new mongoose.Schema( }], instructions : [{name: {type: String, default: ""}, steps: [String]}], + preamble : String, addendum : String, }, ); diff --git a/src/routes/rezepte/+layout.svelte b/src/routes/+layout.svelte similarity index 83% rename from src/routes/rezepte/+layout.svelte rename to src/routes/+layout.svelte index c6883ab..f3d6ccd 100644 --- a/src/routes/rezepte/+layout.svelte +++ b/src/routes/+layout.svelte @@ -4,10 +4,12 @@ import "$lib/components/nordtheme.css"
diff --git a/src/routes/.jukit/.jukit_info.json b/src/routes/.jukit/.jukit_info.json new file mode 100644 index 0000000..92c7342 --- /dev/null +++ b/src/routes/.jukit/.jukit_info.json @@ -0,0 +1 @@ +{"terminal": "nvimterm"} \ No newline at end of file diff --git a/src/routes/api/add/+server.ts b/src/routes/api/add/+server.ts index 8f0389b..9eec68e 100644 --- a/src/routes/api/add/+server.ts +++ b/src/routes/api/add/+server.ts @@ -16,7 +16,7 @@ export const POST: RequestHandler = async ({request}) => { await dbConnect(); await Recipe.create(recipe_json); await dbDisconnect(); - return {status: 400} //TODO: cleanup error throwing + return {status: 200} //TODO: cleanup error throwing } else{ console.log("PASSWORD INCORRECT") diff --git a/src/routes/api/delete/+server.ts b/src/routes/api/delete/+server.ts new file mode 100644 index 0000000..fb4c407 --- /dev/null +++ b/src/routes/api/delete/+server.ts @@ -0,0 +1,23 @@ +import type { RequestHandler } from '@sveltejs/kit'; +import { Recipe } from '../../../models/Recipe'; +import { dbConnect, dbDisconnect } from '../../../utils/db'; +import type {RecipeModelType} from '../../../types/types'; +import { BEARER_TOKEN } from '$env/static/private' +// header: use for bearer token for now +// recipe json in body +export const POST: RequestHandler = async ({request}) => { + let message = await request.json() + const short_name = message.old_short_name + const bearer_token = message.headers.bearer + if(bearer_token === BEARER_TOKEN){ + console.log("PASSWORD CORRECT") + await dbConnect(); + await Recipe.findOneAndDelete({short_name: short_name}); + await dbDisconnect(); + return {status: 400} //TODO: cleanup error throwing + } + else{ + console.log("PASSWORD INCORRECT") + return {status: 403} + } +}; diff --git a/src/routes/api/edit/+server.ts b/src/routes/api/edit/+server.ts index c06b814..75de2d4 100644 --- a/src/routes/api/edit/+server.ts +++ b/src/routes/api/edit/+server.ts @@ -3,6 +3,7 @@ import { Recipe } from '../../../models/Recipe'; import { dbConnect, dbDisconnect } from '../../../utils/db'; import type {RecipeModelType} from '../../../types/types'; import { BEARER_TOKEN } from '$env/static/private' +import { error } from '@sveltejs/kit'; // header: use for bearer token for now // recipe json in body export const POST: RequestHandler = async ({request}) => { @@ -10,16 +11,15 @@ export const POST: RequestHandler = async ({request}) => { let message = await request.json() const recipe_json = message.recipe const bearer_token = message.headers.bearer - console.log("RECIPE:", recipe_json) - console.log("BEARER:", bearer_token) if(bearer_token === BEARER_TOKEN){ await dbConnect(); await Recipe.findOneAndUpdate({short_name: message.old_short_name }, recipe_json); await dbDisconnect(); - return {status: 400} //TODO: cleanup error throwing + const res = new Response(JSON.stringify({ message: "Updated Recipe successfully"}), { status: 200 }) + return res } else{ - console.log("PASSWORD INCORRECT") - return {status: 403} + console.log("INCORRECT PASSWORD") + throw error(403, "Password incorrect") } }; diff --git a/src/routes/api/items/icon/+server.ts b/src/routes/api/items/icon/+server.ts new file mode 100644 index 0000000..8a8ecbc --- /dev/null +++ b/src/routes/api/items/icon/+server.ts @@ -0,0 +1,13 @@ +import { json, type RequestHandler } from '@sveltejs/kit'; +import { Recipe } from '../../../../models/Recipe'; +import { dbConnect, dbDisconnect } from '../../../../utils/db'; +import type {BriefRecipeType} from '../../../../types/types'; + +export const GET: RequestHandler = async ({params}) => { + await dbConnect(); + let icons = (await Recipe.distinct('icon').lean()); + await dbDisconnect(); + + icons = JSON.parse(JSON.stringify(icons)); + return json(icons); +}; diff --git a/src/routes/api/items/icon/[icon]/+server.ts b/src/routes/api/items/icon/[icon]/+server.ts new file mode 100644 index 0000000..60be55d --- /dev/null +++ b/src/routes/api/items/icon/[icon]/+server.ts @@ -0,0 +1,13 @@ +import { json, type RequestHandler } from '@sveltejs/kit'; +import { Recipe } from '../../../../../models/Recipe'; +import { dbConnect, dbDisconnect } from '../../../../../utils/db'; +import type {BriefRecipeType} from '../../../../../types/types'; + +export const GET: RequestHandler = async ({params}) => { + await dbConnect(); + let recipes = (await Recipe.find({tags: params.icon}, 'name short_name images tags category icon description season').lean()) as BriefRecipeType[]; + await dbDisconnect(); + + recipes = JSON.parse(JSON.stringify(recipes)); + return json(recipes); +}; diff --git a/src/routes/api/seed/+server.ts b/src/routes/api/seed/+server.ts index dda6d3e..720f139 100644 --- a/src/routes/api/seed/+server.ts +++ b/src/routes/api/seed/+server.ts @@ -16,10 +16,12 @@ const test_json = [ caption: "", }], description: "Alles was das Bauernherz erfreuen lässt in einer Mahlzeit.", - tags: ["Schweiz", "Käse", "Speck", "Nudeln", "Apfelmuß", "Kartoffeln"], - season: [6,7,8,9,10,11,12,1], + preamble: "Dieser Schweizer Klassiker ist wohl das beste Essen nach einem langen Tag von Skifahren. Die Beilage aus Apfelmus ist ein Muss.", + tags: ["Schweiz", "Käse", "Speck", "Nudeln", "Apfelmuß", "Kartoffeln", "Fleisch"], + season: [10,11,12,1], portions: "4 Hauptspeisen", - total_time: "30 Minuten", + preparation: "10 min", + total_time: "30 min", ingredients: [ { name: "", list: [ diff --git a/src/routes/api/seed/json/aelplermagronen.js b/src/routes/api/seed/json/aelplermagronen.js new file mode 100644 index 0000000..39bdac8 --- /dev/null +++ b/src/routes/api/seed/json/aelplermagronen.js @@ -0,0 +1,77 @@ +const obj = +{ + short_name: "aelplermagronen", + name : "Älplermagronen", + category: "Hauptspeise", + icon: "🍂", + datecreated: 20230619, + datemodified: 20230619, + images: [{ + mediapath: "aelplermagronen.webp", + alt: "Älplermagronen serviert mit Apfelmuß", + caption: "", + }], + description: "Alles was das Bauernherz erfreuen lässt in einer Mahlzeit.", + tags: ["Schweiz", "Käse", "Speck", "Nudeln", "Apfelmuß", "Kartoffeln"], + season: [6,7,8,9,10,11,12,1], + portions: "4 Hauptspeisen", + total_time: "30 Minuten", + ingredients: [ { + name: "", + list: [ + { name: "Speckwürfel", + unit: "g", + amount: "150" + }, + { + name: "mittelgroße Zwiebeln", + unit: "", + amount: "3", + }, + { + name: "Kartoffeln, festkochend", + unit: "g", + amount: "400", + }, + { + name: "Milch", + unit: "L", + amount: "1-2", + }, + { + name: "Maccaroni", + unit: "g", + amount: "400", + }, + { + name: "Appenzeller", + unit: "g", + amount: "150", + }, + { + name: "Apfelmuß", + unit: "", + amount: "", + }, + + ]}, + ], + instructions: [ + {name: "", + steps: [ + "In einem großen Topf oder tiefer Pfanne Speckwürfel anbraten.", + "Zwiebel in Halbringe schneiden und im gleichen Topf schwitzen lassen.", + "Kartoffeln schälen und in ~1 cm3 schneiden.", + "Wenn Ziwebeln genügend gekocht sind die Kartoffeln hinzufügen und Milch hinzufügen, sodass alles bedeckt ist. Ca. 10 Minuten kochen lassen.", + "Ca. 1 L Milch hinzugeben. Für den nächsten Schritt wollen wir die Maccaroni hinzufügen. Damit diese nicht zu breiig werden geben wir erst die Milch zu und lassen sie aufkochen.", + "Wenn die der Topf wieder kocht jetzt die Maccaroni hinzugeben.", + "Den Käse zerreiben oder in kleine Würfel schneiden.", + "Ein bis zwei Minuten bevor die Nudeln durchgekocht sind den Käse hinzugeben und schmelzen lassen.", + "Mit Salz und Muskat würzen.", + "Den Topf ein bisschen zu früh vom Herd nehmen und ein bisschen auskühlen lassen.", + "Mit Apfelmuß oder Apfelkompott servieren." + ] + } + ], + addendum: "

Man kann das Gericht noch dekanter machen indem man zu Teilen Rahm an Stelle von Milch verwendet. Zudem kann man das ganze auch noch in eine Auflaufform geben und im Ofen eine Kruste anbacken

", +} diff --git a/src/routes/api/seed/json/template.js b/src/routes/api/seed/json/template.js new file mode 100644 index 0000000..0eb137d --- /dev/null +++ b/src/routes/api/seed/json/template.js @@ -0,0 +1,50 @@ +const obj = +{ + short_name: "<++>", + name : "<++>", + category: "<++>", + icon: "<++>", + datecreated: 20230619, + datemodified: 20230619, + images: [{ + mediapath: "<++>.webp", + alt: "<++>", + caption: "<++>", + }], + description: "<++>", + tags: [<++>], + season: [<++>], + baking: { + temperature: "<++>", + length: "<++>", + mode: "<++>", + }, + preparation: "<++>", + fermentation: { + bulk: "<++>", + final: "<++>" + }, + portions: "<++>", + total_time: "<++>", + ingredients: [ { + name: "<++>", + list: [ + { name: "<++>", + unit: "<++>", + amount: <++>, + }, + { + name: "<++>", + unit: "<++>", + amount: <++>, + }, + ]}, + ], + instructions: [ + {name: "<++>", + steps: [ + "<++>", + "<++>" + ] + } + ]} diff --git a/src/routes/rezepte/+page.svelte b/src/routes/rezepte/+page.svelte index 5226dd8..5aaf776 100644 --- a/src/routes/rezepte/+page.svelte +++ b/src/routes/rezepte/+page.svelte @@ -8,7 +8,6 @@ export let data: PageData; export let current_month = new Date().getMonth() + 1 -

Rezepte

In Saison

diff --git a/src/routes/rezepte/[name]/+page.svelte b/src/routes/rezepte/[name]/+page.svelte index 2f9a1df..e899af8 100644 --- a/src/routes/rezepte/[name]/+page.svelte +++ b/src/routes/rezepte/[name]/+page.svelte @@ -6,19 +6,42 @@ import "$lib/components/nordtheme.css" import MultiImgWrapper from './MultiImgWrapper.svelte' import EditButton from '$lib/components/EditButton.svelte'; + import InstructionsPage from '$lib/components/InstructionsPage.svelte'; + import IngredientsPage from '$lib/components/IngredientsPage.svelte'; export let data: PageData; + let hero_img_src = "/images/" + data.images[0].mediapath export let months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"] function season_intervals() { let interval_arr = [] - let start = 0 - for(var i = 0; i < data.season.length - 1; i++) - { - if(Math.abs(data.season[i] - data.season[i + 1])%11 > 1){ - interval_arr.push([data.season[start], data.season[i]]) - start=i+1 + + + let start_i = 0 + for(var i = 12; i > 0; i--){ + if(data.season.includes(i)){ + start_i = data.season.indexOf(i); + } + else{ + break } } - interval_arr.push([data.season[start], data.season[data.season.length -1]]) + + var start = data.season[start_i] + var end_i + const len = data.season.length + for(var i = 0; i < len -1; i++){ + if(data.season.includes((start + i) %12 + 1)){ + end_i = (start_i + i + 1) % len + } + else{ + interval_arr.push([start, data.season[end_i]]) + start = data.season[(start + i + 1) % len] + } + + } + if(interval_arr.length == 0){ + interval_arr.push([start, data.season[end_i]]) + } + return interval_arr } export let season_iv = season_intervals(); @@ -29,20 +52,16 @@ font-family: sans-serif; } h1{ text-align: center; - padding: 0.5em 2em; + padding-block: 0.5em; border-radius: 10000px; margin:0; font-size: 3rem; } -.wrapper{ - margin-inline: auto; - max-width: 700px; - padding-inline: 2rem; -} .tags{ margin-block: 1rem; display: flex; flex-direction: row; + align-items: center; flex-wrap: wrap; gap: 1em; } @@ -64,12 +83,109 @@ h1{ background-color: var(--orange); box-shadow: 0.1em 0.1em 0.2em 0.2em rgba(0,0,0,0.3); } + +.wrapper{ + display: flex; + flex-direction: row; + max-width: 1000px; + justify-content: center; + margin-inline: auto; +} + +@media screen and (max-width: 700px){ + .wrapper{ + flex-direction:column; + } +} + +.title_container{ + max-width: 1000px; + display: flex; + flex-direction: column; + margin-inline: auto; +} +.title{ + position: relative; + width: min(800px, 80vw); + margin-inline: auto; + transform: translateY(-4rem); + background-color: var(--nord6); + padding: 1rem 2rem; +} +.title_container .img{ + width: 100%; + height: 700px; + background-size: cover; + background-repeat: no-repeat; + background-position: center; +} +.icon{ + position: absolute; + top: -1em; + right: -0.75em; + text-decoration: unset; + background-color: #FAFAFE; + padding: 0.5em; + font-size: 1.5rem; + border-radius: 100000px; + transition: 100ms; + box-shadow: 0em 0em 1em 0.5em rgba(0,0,0,0.5); +} +.icon:hover, +.icon:focus-visible{ + scale: 1.2 1.2; + animation: shake 0.5s ease forwards; +} + +h4{ + margin-block: 0; +} +.addendum{ + max-width: 800px; + margin-inline: auto; + padding-inline: 2rem; +} +@media screen and (max-width: 800px){ + .title{ + width: 100%; + } + .icon{ + right: 1rem; + } +} +@keyframes shake{ + 0%{ + transform: rotate(0) + scale(1,1); + } + 25%{ + box-shadow: 0em 0em 1em 0.2em rgba(0, 0, 0, 0.6); + transform: rotate(var(--angle)) + scale(1.2,1.2) + ; + } + 50%{ + + box-shadow: 0em 0em 1em 0.2em rgba(0, 0, 0, 0.6); + transform: rotate(calc(-1* var(--angle))) + scale(1.2,1.2); + } + 74%{ + + box-shadow: 0em 0em 1em 0.2em rgba(0, 0, 0, 0.6); + transform: rotate(var(--angle)) + scale(1.2, 1.2); + } + 100%{ + transform: rotate(0) + scale(1.2,1.2); + } + } + -
-

{data.name}

-1} class=double> + + +
+
+
+{data.icon} +

{data.name}

+{#if data.preamble} +

{data.preamble}

+{/if}
-Saison: +

Saison:

{#each season_iv as season} {months[season[0] - 1]}-{months[season[1] - 1]} {/each}
+

Stichwörter:

-Stichwörter: {#each data.tags as tag} {tag} {/each}
+
+
-{#if data.preparation} -
Vorbereitung: {data.preparation}
-{/if} - - -{#if data.fermentation} - {#if data.fermentation.bulk} -
Stockgare: {data.fermentation.bulk}
- {/if} - - {#if data.fermentation.final} -
Stückgare: {data.fermentation.final}
- {/if} -{/if} - -{#if data.baking} -
Backen: {data.baking.length} bei {data.baking.temperature} °C {data.baking.mode}
-{/if} - -{#if data.total_time} -
Gesamtzeit: {data.total_time}
-{/if} - - -{#if data.ingredients} -

Zutaten

-{#each data.ingredients as list} -{#if list.name} -

{list.name}

-{/if} -
    - {#each list.list as item} -
  • {item.amount} {item.unit} {@html item.name}
  • - {/each} -
-{/each} -{/if} - - -{#if data.instructions} -

Zubereitung

-{#each data.instructions as list} -{#if list.name} -

{list.name}

-{/if} -
    - {#each list.steps as step} -
  1. {@html step}
  2. - {/each} -
-{/each} -{/if} +
+ + +
+
{#if data.addendum} {@html data.addendum} {/if} diff --git a/src/routes/rezepte/add/+page.svelte b/src/routes/rezepte/add/+page.svelte index 73d66fe..67b5b3a 100644 --- a/src/routes/rezepte/add/+page.svelte +++ b/src/routes/rezepte/add/+page.svelte @@ -1,39 +1,92 @@ -

Rezept hinzufügen

+

Rezept erstellen

- +

Kurzname (für URL):

+ - +
+
+

Eine etwas längere Beschreibung:

+

+
+

Saison:

+ +
+
+
-

Zutaten

- -

Zubereitung

- - - +
+
+ +
+
+ +
+
+ +
+

Nachtrag:

+
+
+ +
+

Neues Rezept hinzufügen:

+ + +
diff --git a/src/routes/rezepte/edit/[name]/+page.svelte b/src/routes/rezepte/edit/[name]/+page.svelte index 26af762..c1dba06 100644 --- a/src/routes/rezepte/edit/[name]/+page.svelte +++ b/src/routes/rezepte/edit/[name]/+page.svelte @@ -1,5 +1,21 @@ -

Rezept hinzufügen

+

Rezept editieren

- - - + +

Kurzname (für URL):

-

Zutaten

- -

Zubereitung

- + +
+
+

Eine etwas längere Beschreibung:

+

+
+

Saison:

+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+

Nachtrag:

+
+
+ +
+

Editiertes Rezept abspeichern:

- + +
+ +
+

Rezept löschen:

+ + +
diff --git a/src/types/types.ts b/src/types/types.ts index 6e10107..17110ac 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -38,6 +38,7 @@ export type RecipeModelType = { name?: string; steps: [string] }] + preamble?: String addendum?: string };