Initial commit
This commit is contained in:
2
src/routes/+page.svelte
Normal file
2
src/routes/+page.svelte
Normal file
@ -0,0 +1,2 @@
|
||||
<h1>Welcome to SvelteKit</h1>
|
||||
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
|
13
src/routes/api/items/[name]/+server.ts
Normal file
13
src/routes/api/items/[name]/+server.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { json, type RequestHandler } from '@sveltejs/kit';
|
||||
import { Recipe } from '../../../../models/Recipe';
|
||||
import { dbConnect, dbDisconnect } from '../../../../utils/db';
|
||||
import type {RecipeModelType} from '../../../../types/types';
|
||||
|
||||
export const GET: RequestHandler = async ({params}) => {
|
||||
await dbConnect();
|
||||
let recipe = (await Recipe.findOne({ short_name: params.name}).lean()) as RecipeModelType[];
|
||||
await dbDisconnect();
|
||||
|
||||
recipe = JSON.parse(JSON.stringify(recipe));
|
||||
return json(recipe);
|
||||
};
|
13
src/routes/api/items/all_brief/+server.ts
Normal file
13
src/routes/api/items/all_brief/+server.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { json, type RequestHandler } from '@sveltejs/kit';
|
||||
import { Recipe } from '../../../../models/Recipe'
|
||||
import { dbConnect, dbDisconnect } from '../../../../utils/db';
|
||||
|
||||
export const GET: RequestHandler = async ({params}) => {
|
||||
let current_month = 6;
|
||||
await dbConnect();
|
||||
let found_brief = (await Recipe.find({}, 'name short_name images tags category icon description season').lean());
|
||||
await dbDisconnect();
|
||||
console.log(found_brief)
|
||||
let recipes = JSON.parse(JSON.stringify(found_brief));
|
||||
return json(recipes);
|
||||
};
|
12
src/routes/api/items/in_season/+server.ts
Normal file
12
src/routes/api/items/in_season/+server.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { json, type RequestHandler } from '@sveltejs/kit';
|
||||
import { Recipe } from '../../../../models/Recipe'
|
||||
import { dbConnect, dbDisconnect } from '../../../../utils/db';
|
||||
|
||||
export const GET: RequestHandler = async ({params}) => {
|
||||
let current_month = 6;
|
||||
await dbConnect();
|
||||
let found_in_season = (await Recipe.find({season: current_month}, 'name short_name images tags category icon description season').lean());
|
||||
await dbDisconnect();
|
||||
found_in_season = JSON.parse(JSON.stringify(found_in_season));
|
||||
return json(found_in_season);
|
||||
};
|
13
src/routes/api/items/tag/[tag]/+server.ts
Normal file
13
src/routes/api/items/tag/[tag]/+server.ts
Normal file
@ -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.tag}, 'name short_name images tags category icon description season').lean()) as BriefRecipeType[];
|
||||
await dbDisconnect();
|
||||
|
||||
recipes = JSON.parse(JSON.stringify(recipes));
|
||||
return json(recipes);
|
||||
};
|
147
src/routes/api/seed/+server.ts
Normal file
147
src/routes/api/seed/+server.ts
Normal file
@ -0,0 +1,147 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { Recipe } from '../../../models/Recipe';
|
||||
import { dbConnect, dbDisconnect } from '../../../utils/db';
|
||||
|
||||
const test_json = [
|
||||
{ short_name: "rhabarberkonfi",
|
||||
name: "Rharbarberkonfi",
|
||||
category: "Aufstrich",
|
||||
icon: "☀️",
|
||||
datecreated: 20230610,
|
||||
datemodified: 20230611,
|
||||
images:
|
||||
[ {
|
||||
mediapath: "rharbarberkonfi.webp",
|
||||
alt: "Ein Brot mit Marmelade darauf.",
|
||||
caption: ""
|
||||
}
|
||||
],
|
||||
description: "Saure Marmelade",
|
||||
tags:["marmelade", "schweiz", "sauer", "rhabarber", "zucker", "aufstrich", "marmelade" , "ein weteres langes tag", "und noch eins", "und ein weiteres", "und nochmal"],
|
||||
season: [4,5,6],
|
||||
baking: {
|
||||
temperature: "160",
|
||||
length: "4 Stunden",
|
||||
mode: "Ober-/Unterhitze"
|
||||
},
|
||||
preparation: "20 Minuten",
|
||||
fermentation: {
|
||||
bulk: "2.5 Stunden",
|
||||
final: "2 Stunden"
|
||||
},
|
||||
portions: "4 Pizzen",
|
||||
total_time: "1 Tag",
|
||||
ingredients: [ {
|
||||
name: "Teig",
|
||||
list: [
|
||||
{name: "Mehl",
|
||||
unit: "g",
|
||||
amount: 500
|
||||
} ,
|
||||
{
|
||||
name: "Salz",
|
||||
unit: "g",
|
||||
amount: 6
|
||||
}
|
||||
]},
|
||||
{
|
||||
name: "Füllung",
|
||||
list: [
|
||||
{
|
||||
name: "Aprikose",
|
||||
unit: "Stück",
|
||||
amount: 10
|
||||
},
|
||||
{
|
||||
name: "Zuckerwürfel",
|
||||
unit: "Stück",
|
||||
amount: 10
|
||||
}
|
||||
] }
|
||||
],
|
||||
instructions: [
|
||||
{name: "",
|
||||
steps: [
|
||||
"Den Rhabarber schälen und in ca. 1 cm große Stücke schneiden",
|
||||
"Have fun"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{ short_name: "osterfladen",
|
||||
name: "Osterfladen",
|
||||
category: "Aufstrich",
|
||||
icon: "🐇",
|
||||
datecreated: 20230610,
|
||||
datemodified: 20230611,
|
||||
images:
|
||||
[ {
|
||||
mediapath: "osterfladen.webp",
|
||||
alt: "Ein Brot mit Marmelade darauf.",
|
||||
caption: ""
|
||||
}
|
||||
],
|
||||
description: "Saure Marmelade",
|
||||
tags:["marmelade", "schweiz", "sauer", "rhabarber", "zucker", "aufstrich", "marmelade"],
|
||||
season: [2,3,4],
|
||||
baking: {
|
||||
temperature: "160",
|
||||
length: "4 Stunden",
|
||||
mode: "Ober-/Unterhitze"
|
||||
},
|
||||
preparation: "20 Minuten",
|
||||
fermentation: {
|
||||
bulk: "2.5 Stunden",
|
||||
final: "2 Stunden"
|
||||
},
|
||||
portions: "4 Pizzen",
|
||||
total_time: "1 Tag",
|
||||
ingredients: [ {
|
||||
name: "Teig",
|
||||
list: [
|
||||
{name: "Mehl",
|
||||
unit: "g",
|
||||
amount: 500
|
||||
} ,
|
||||
{
|
||||
name: "Salz",
|
||||
unit: "g",
|
||||
amount: 6
|
||||
}
|
||||
]},
|
||||
{
|
||||
name: "Füllung",
|
||||
list: [
|
||||
{
|
||||
name: "Aprikose",
|
||||
unit: "Stück",
|
||||
amount: 10
|
||||
},
|
||||
{
|
||||
name: "Zuckerwürfel",
|
||||
unit: "Stück",
|
||||
amount: 10
|
||||
}
|
||||
] }
|
||||
],
|
||||
instructions: [
|
||||
{name: "",
|
||||
steps: [
|
||||
"Den Rhabarber schälen und in ca. 1 cm große Stücke schneiden",
|
||||
"Have fun"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
// seed data
|
||||
export const GET = async () => {
|
||||
await dbConnect();
|
||||
await Recipe.deleteMany();
|
||||
await Recipe.insertMany(test_json);
|
||||
await dbDisconnect();
|
||||
return json({
|
||||
message: 'seeded',
|
||||
});
|
||||
}
|
12
src/routes/rezepte/+page.server.ts
Normal file
12
src/routes/rezepte/+page.server.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import type { PageLoad } from "./$types";
|
||||
|
||||
export async function load({ fetch }) {
|
||||
const res_season = await fetch(`/api/items/in_season`);
|
||||
const res_all_brief = await fetch(`/api/items/all_brief`);
|
||||
const item_season = await res_season.json();
|
||||
const item_all_brief = await res_all_brief.json();
|
||||
return {
|
||||
season: item_season,
|
||||
all_brief: item_all_brief,
|
||||
};
|
||||
};
|
36
src/routes/rezepte/+page.svelte
Normal file
36
src/routes/rezepte/+page.svelte
Normal file
@ -0,0 +1,36 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import './card.css';
|
||||
export let data: PageData;
|
||||
import Card from './Card.svelte'
|
||||
export let current_month = new Date().getMonth() + 1
|
||||
</script>
|
||||
<style>
|
||||
.accordion{
|
||||
display:flex;
|
||||
background-color: #111111;
|
||||
flex-direction: row;
|
||||
margin-inline: auto;
|
||||
padding-inline: 1rem;
|
||||
padding-block: 3rem;
|
||||
margin-block: 3rem;
|
||||
align-items:center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
<h1>Rezepte</h1>
|
||||
<h2>In Saison</h2>
|
||||
<section>
|
||||
<div class=accordion>
|
||||
{#each data.season as recipe}
|
||||
<Card {recipe} {current_month}></Card>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
||||
<h2>Alle Rezepte</h2>
|
||||
<div class=accordion>
|
||||
{#each data.all_brief as recipe}
|
||||
<Card {recipe} {current_month}></Card>
|
||||
{/each}
|
||||
</div>
|
1
src/routes/rezepte/.jukit/.jukit_info.json
Normal file
1
src/routes/rezepte/.jukit/.jukit_info.json
Normal file
@ -0,0 +1 @@
|
||||
{"terminal": "nvimterm"}
|
29
src/routes/rezepte/Card.svelte
Normal file
29
src/routes/rezepte/Card.svelte
Normal file
@ -0,0 +1,29 @@
|
||||
<script>
|
||||
export let recipe
|
||||
export let current_month
|
||||
|
||||
import alragu from '$lib/assets/al_ragu.webp'
|
||||
export let src
|
||||
import './card.css'
|
||||
// Winter: ❄️
|
||||
// Weihnachten: 🎄
|
||||
// Ostern: 🐇
|
||||
// Fastenzeit: ✝️
|
||||
// Herbst: 🍂
|
||||
// Sommer: ☀️
|
||||
</script>
|
||||
|
||||
<a class=card href="/rezepte/{recipe.short_name}">
|
||||
<img {src} alt="">
|
||||
<div class=title>
|
||||
{#if recipe.season.includes(current_month)}
|
||||
<div class=icon>{recipe.icon}</div>
|
||||
{/if}
|
||||
<div class=name>{recipe.name}</div>
|
||||
<div class=tags>
|
||||
{#each recipe.tags as tag}
|
||||
<a class=tag href="/rezepte/tag/{tag}">{tag}</a>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
11
src/routes/rezepte/[name]/+page.server.ts
Normal file
11
src/routes/rezepte/[name]/+page.server.ts
Normal file
@ -0,0 +1,11 @@
|
||||
// import { error } from '@sveltejs/kit';
|
||||
import type { PageLoad } from "./$types";
|
||||
//import { Recipe } from '../../../models/Recipe';
|
||||
//import { dbConnect, dbDisconnect } from '../../../utils/db';
|
||||
|
||||
export async function load({ fetch, params }) {
|
||||
const res = await fetch(`/api/items/${params.name}`);
|
||||
const item = await res.json();
|
||||
|
||||
return item;
|
||||
};
|
46
src/routes/rezepte/[name]/+page.svelte
Normal file
46
src/routes/rezepte/[name]/+page.svelte
Normal file
@ -0,0 +1,46 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import MultiImgWrapper from './MultiImgWrapper.svelte'
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<h1>{data.name}</h1>
|
||||
|
||||
<MultiImgWrapper wrap={data.images.length>1} class=double>
|
||||
{#each data.images as img}
|
||||
<figure>
|
||||
{#if img.caption}
|
||||
<caption>{img.caption}</caption>
|
||||
{/if}
|
||||
</figure>
|
||||
{/each}
|
||||
</MultiImgWrapper>
|
||||
|
||||
{#if data.ingredients}
|
||||
<h2>Zutaten</h2>
|
||||
{#each data.ingredients as list}
|
||||
{#if list.name}
|
||||
<h3>{list.name}</h3>
|
||||
{/if}
|
||||
<ul>
|
||||
{#each list.list as item}
|
||||
<li>{item.amount} {item.unit} {item.name}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
|
||||
{#if data.instructions}
|
||||
<h2>Zubereitung</h2>
|
||||
{#each data.instructions as list}
|
||||
{#if list.name}
|
||||
<h3>{list.name}</h3>
|
||||
{/if}
|
||||
<ol>
|
||||
{#each list.steps as step}
|
||||
<li>{step}</li>
|
||||
{/each}
|
||||
</ol>
|
||||
{/each}
|
||||
{/if}
|
1
src/routes/rezepte/[name]/.jukit/.jukit_info.json
Normal file
1
src/routes/rezepte/[name]/.jukit/.jukit_info.json
Normal file
@ -0,0 +1 @@
|
||||
{"terminal": "nvimterm"}
|
10
src/routes/rezepte/[name]/MultiImgWrapper.svelte
Normal file
10
src/routes/rezepte/[name]/MultiImgWrapper.svelte
Normal file
@ -0,0 +1,10 @@
|
||||
<script>
|
||||
export let wrap = false
|
||||
</script>
|
||||
{#if wrap}
|
||||
<div {...$$restProps}>
|
||||
<slot />
|
||||
</div>
|
||||
{:else}
|
||||
<slot />
|
||||
{/if}
|
110
src/routes/rezepte/card.css
Normal file
110
src/routes/rezepte/card.css
Normal file
@ -0,0 +1,110 @@
|
||||
.card{
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif;
|
||||
cursor: pointer;
|
||||
width: 300px;
|
||||
aspect-ratio: 4/7;
|
||||
border-radius: 20px;
|
||||
background-size: contain;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: end;
|
||||
transition: 200ms;
|
||||
}
|
||||
.card:hover,
|
||||
.card:focus-visible{
|
||||
transform: scale(1.02,1.02)
|
||||
}
|
||||
|
||||
.card img{
|
||||
height: 50%;
|
||||
object-fit: cover;
|
||||
border-top-left-radius: inherit;
|
||||
border-top-right-radius: inherit;
|
||||
background-color: #5E81AC;
|
||||
}
|
||||
.card .title {
|
||||
box-sizing: border-box;
|
||||
padding-top: 0.5em;
|
||||
height: 50%;
|
||||
width: 100% ;
|
||||
padding-inline: 1em;
|
||||
border-bottom-left-radius: inherit;
|
||||
border-bottom-right-radius: inherit;
|
||||
background-color: #5E81AC;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
transition: 100ms;
|
||||
}
|
||||
.card:hover .title{
|
||||
background-color:#BF616A;
|
||||
}
|
||||
.card .name{
|
||||
font-size: 2em;
|
||||
color: white;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.card .tags{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
column-gap: 0.25em;
|
||||
margin-bottom:0.5em;
|
||||
flex-grow: 0;
|
||||
}
|
||||
.card .tag{
|
||||
cursor: pointer;
|
||||
text-decoration: unset;
|
||||
background-color: #D8DEE9;
|
||||
color: #2E3440;
|
||||
border-radius: 100px;
|
||||
padding-inline: 1em;
|
||||
line-height: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
transition: 100ms;
|
||||
}
|
||||
.card .tag:hover{
|
||||
transform: scale(1.04, 1.04);
|
||||
background-color: #D08770;
|
||||
}
|
||||
|
||||
.card .title .icon{
|
||||
position: absolute;
|
||||
font-size: 1.5rem;
|
||||
top:-0.5em;
|
||||
right:-0.5em;
|
||||
padding: 0.25em;
|
||||
background-color: white;
|
||||
border-radius:1000px;
|
||||
}
|
||||
.card:hover .title .icon{
|
||||
animation: shake 0.6s
|
||||
}
|
||||
|
||||
@keyframes shake{
|
||||
0%{
|
||||
transform: rotate(0)
|
||||
scale(1,1);
|
||||
}
|
||||
25%{
|
||||
transform: rotate(30deg)
|
||||
scale(1.2,1.2)
|
||||
;
|
||||
}
|
||||
50%{
|
||||
transform: rotate(-30deg)
|
||||
scale(1.2,1.2);
|
||||
}
|
||||
74%{
|
||||
transform: rotate(30deg)
|
||||
scale(1.2, 1.2);
|
||||
}
|
||||
100%{
|
||||
transform: rotate(0)
|
||||
scale(1,1);
|
||||
}
|
||||
}
|
9
src/routes/rezepte/tag/+page.server.ts
Normal file
9
src/routes/rezepte/tag/+page.server.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import type { PageLoad } from "./$types";
|
||||
|
||||
export async function load({ fetch }) {
|
||||
const res_tag = await fetch(`/api/tags`);
|
||||
const items_tag = await res_tag.json();
|
||||
return {
|
||||
tags: item.tags
|
||||
}
|
||||
};
|
30
src/routes/rezepte/tag/+page.svelte
Normal file
30
src/routes/rezepte/tag/+page.svelte
Normal file
@ -0,0 +1,30 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import '../../card.css';
|
||||
import Card from '../../Card.svelte';
|
||||
export let data: PageData;
|
||||
export let current_month = new Date().getMonth() + 1;
|
||||
</script>
|
||||
<style>
|
||||
.accordion{
|
||||
display:flex;
|
||||
background-color: #111111;
|
||||
flex-direction: row;
|
||||
margin-inline: auto;
|
||||
padding-inline: 1rem;
|
||||
padding-block: 3rem;
|
||||
margin-block: 3rem;
|
||||
align-items:center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
<h1>Rezepte</h1>
|
||||
<h2>In Tag {data.tag}</h2>
|
||||
<section>
|
||||
<div class=accordion>
|
||||
{#each data.recipes as recipe}
|
||||
<Card {recipe} {current_month}></Card>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
1
src/routes/rezepte/tag/.jukit/.jukit_info.json
Normal file
1
src/routes/rezepte/tag/.jukit/.jukit_info.json
Normal file
@ -0,0 +1 @@
|
||||
{"terminal": "nvimterm"}
|
10
src/routes/rezepte/tag/[tag]/+page.server.ts
Normal file
10
src/routes/rezepte/tag/[tag]/+page.server.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import type { PageLoad } from "./$types";
|
||||
|
||||
export async function load({ fetch, params }) {
|
||||
const res_tag = await fetch(`/api/items/tag/${params.tag}`);
|
||||
const items_tag = await res_tag.json();
|
||||
return {
|
||||
tag: params.tag,
|
||||
recipes: items_tag
|
||||
}
|
||||
};
|
30
src/routes/rezepte/tag/[tag]/+page.svelte
Normal file
30
src/routes/rezepte/tag/[tag]/+page.svelte
Normal file
@ -0,0 +1,30 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import '../../card.css';
|
||||
export let data: PageData;
|
||||
export let current_month = new Date().getMonth() + 1;
|
||||
import Card from '../../Card.svelte'
|
||||
</script>
|
||||
<style>
|
||||
.accordion{
|
||||
display:flex;
|
||||
background-color: #111111;
|
||||
flex-direction: row;
|
||||
margin-inline: auto;
|
||||
padding-inline: 1rem;
|
||||
padding-block: 3rem;
|
||||
margin-block: 3rem;
|
||||
align-items:center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
<h1>Rezepte</h1>
|
||||
<h2>In Tag {data.tag}</h2>
|
||||
<section>
|
||||
<div class=accordion>
|
||||
{#each data.recipes as recipe}
|
||||
<Card {recipe} {current_month}></Card>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
1
src/routes/rezepte/tag/[tag]/.jukit/.jukit_info.json
Normal file
1
src/routes/rezepte/tag/[tag]/.jukit/.jukit_info.json
Normal file
@ -0,0 +1 @@
|
||||
{"terminal": "nvimterm"}
|
Reference in New Issue
Block a user