first working prototype

This commit is contained in:
2023-06-19 20:38:45 +02:00
parent be19e63970
commit 4e6291fa5d
287 changed files with 863 additions and 268 deletions

View File

@ -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 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.create(recipe_json);
await dbDisconnect();
return {status: 400}
}
else{
return {status: 403}
}
};

View File

@ -1,13 +1,11 @@
import { json, type RequestHandler } from '@sveltejs/kit';
import type { BriefRecipeType } from '../../../../types/types';
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());
let found_brief = (await Recipe.find({}, 'name short_name images tags category icon description season').lean()) as BriefRecipeType[];
await dbDisconnect();
console.log(found_brief)
let recipes = JSON.parse(JSON.stringify(found_brief));
return json(recipes);
return json(JSON.parse(JSON.stringify(found_brief)));
};

View 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 categories = (await Recipe.distinct('category').lean());
await dbDisconnect();
categories= JSON.parse(JSON.stringify(categories));
return json(categories);
};

View 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({category: params.category}, 'name short_name images tags category icon description season').lean()) as BriefRecipeType[];
await dbDisconnect();
recipes = JSON.parse(JSON.stringify(recipes));
return json(recipes);
};

View File

@ -1,12 +0,0 @@
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);
};

View File

@ -0,0 +1,11 @@
import { json, type RequestHandler } from '@sveltejs/kit';
import { Recipe } from '../../../../../models/Recipe'
import { dbConnect, dbDisconnect } from '../../../../../utils/db';
export const GET: RequestHandler = async ({params}) => {
await dbConnect();
let found_in_season = (await Recipe.find({season: params.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);
};

View 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 categories = (await Recipe.distinct('tags').lean());
await dbDisconnect();
categories= JSON.parse(JSON.stringify(categories));
return json(categories);
};

View File

@ -2,22 +2,177 @@ import { json } from '@sveltejs/kit';
import { Recipe } from '../../../models/Recipe';
import { dbConnect, dbDisconnect } from '../../../utils/db';
const test_json = [
const test_json = [{
short_name: "anisbroetli",
name : "Anisbrötli",
category: "Guetzli",
icon: "🎄",
datecreated: 20230619,
datemodified: 20230619,
images: [{
mediapath: "anisbrot.webp",
alt: "Ein ganzes Brot",
caption: "",
}],
description: "Einfach und sehr lecker",
tags: ["backen", "advent", "schweiz", "deutschland", "anis", "weihnachtenn", "kekse"],
season: [ 12,1],
baking: {
temperature: "220",
length: "40 Minuten",
mode: "Ober-/Unterhitze",
},
preparation: "20 Minuten",
fermentation: {
bulk: "2.5 Stunden",
final: "2 Stunden"
},
portions: "4 Pizzen",
total_time: "1 Tag",
ingredients: [],
instructions: []
},
{
short_name: "alragu",
name : "Pasta al Ragù",
category: "Pasta",
icon: "☀️",
datecreated: 20230619,
datemodified: 20230619,
images: [{
mediapath: "al_ragu.webp",
alt: "Ein ganzes Brot",
caption: "",
}],
description: "Einfach und sehr lecker",
tags: ["pasta", "fleisch", "rind", "italienisch", "bolognese"],
season: [ 6,7,8,9],
baking: {
temperature: "220",
length: "40 Minuten",
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: "sauerteigbrot",
name : "Simples Sauerteigbrot",
category: "Brot",
icon: "🍂",
datecreated: 20230619,
datemodified: 20230619,
images: [{
mediapath: "sauerteigbrot.webp",
alt: "Ein ganzes Brot",
caption: "",
}],
description: "Einfach und sehr lecker",
tags: ["brot", "backen", "sauerteig", "hefe"],
season: [],
baking: {
temperature: "220",
length: "40 Minuten",
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: "rhabarberkonfi",
name: "Rharbarberkonfi",
name: "Rhabarberkonfi",
category: "Aufstrich",
icon: "☀️",
datecreated: 20230610,
datemodified: 20230611,
images:
[ {
mediapath: "rharbarberkonfi.webp",
mediapath: "rhabarberkonfi.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"],
tags:["marmelade", "sauer", "sommer", "süß"],
season: [4,5,6],
baking: {
temperature: "160",
@ -68,22 +223,22 @@ const test_json = [
}
]
},
{ short_name: "osterfladen",
name: "Osterfladen",
category: "Aufstrich",
{ short_name: "osterkuchen",
name: "Osterkuchen",
category: "Kuchen",
icon: "🐇",
datecreated: 20230610,
datemodified: 20230611,
images:
[ {
mediapath: "osterfladen.webp",
mediapath: "osterkuchen.webp",
alt: "Ein Brot mit Marmelade darauf.",
caption: ""
}
],
description: "Saure Marmelade",
tags:["marmelade", "schweiz", "sauer", "rhabarber", "zucker", "aufstrich", "marmelade"],
season: [2,3,4],
tags:["schweiz", "ostern", "milchreis", "aprikosen", 'backen', 'süß', "marmelade"],
season: [3,4],
baking: {
temperature: "160",
length: "4 Stunden",

View File

@ -0,0 +1,66 @@
<script>
import "$lib/components/nordtheme.css"
</script>
<style>
*{
box-sizing: border-box;
}
li{
list-style-type:none;
transition: 100ms;
color: white;
}
li>a{
text-decoration: none;
font-family: sans-serif;
font-size: 1.5rem;
color: inherit
}
li:hover{
cursor: pointer;
color: var(--red);
transform: scale(1.1,1.1);
}
ul {
padding-block: 2rem;
display: flex;
flex-direction: row;
gap: 1rem;
justify-content: space-evenly;
max-width: 1000px;
margin-inline: auto;
}
nav{
background-color: var(--nord0);
}
.wrapper{
display:flex;
flex-direction: column;
min-height: 95vh;
justify-content: space-between;
}
footer{
padding-block: 1rem;
justify-self: end;
text-align: center;
}
</style>
<div class=wrapper>
<div>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/rezepte">Alle Rezepte</a></li>
<li><a href="/rezepte/season">In Saison</a></li>
<li><a href="/rezepte/category">Nach Kategorie</a></li>
<li><a href="/rezepte/tag">Stichwörter</a></li>
</ul>
</nav>
<slot></slot>
</div>
<footer>
Ad maiorem Dei gloriam
</footer>
</div>

View File

@ -1,8 +1,11 @@
<script lang="ts">
import type { PageData } from './$types';
import './card.css';
import '$lib/components/card.css';
import MediaScroller from '$lib/components/MediaScroller.svelte';
import Recipes from '$lib/components/Recipes.svelte';
import Card from '$lib/components/Card.svelte';
import Search from '$lib/components/Search.svelte';
export let data: PageData;
import Card from './Card.svelte'
export let current_month = new Date().getMonth() + 1
</script>
<style>
@ -22,15 +25,16 @@
<h1>Rezepte</h1>
<h2>In Saison</h2>
<section>
<div class=accordion>
<MediaScroller>
{#each data.season as recipe}
<Card {recipe} {current_month}></Card>
{/each}
</div>
</MediaScroller>
</section>
<!--<Search></Search>-->
<h2>Alle Rezepte</h2>
<div class=accordion>
{#each data.all_brief as recipe}
<Card {recipe} {current_month}></Card>
{/each}
</div>
<Recipes>
{#each data.all_brief as recipe}
<Card {recipe} {current_month}></Card>
{/each}
</Recipes>

View File

@ -1,7 +1,8 @@
import type { PageLoad } from "./$types";
export async function load({ fetch }) {
const res_season = await fetch(`/api/items/in_season`);
let current_month = new Date().getMonth() + 1
const res_season = await fetch(`/api/items/in_season/` + current_month);
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();

View File

@ -1,29 +0,0 @@
<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>

View File

@ -0,0 +1,76 @@
<script lang="ts">
let name = 'name'
let short_name = 'short_name'
let category = 'category'
let icon = 'icon'
let description = 'description'
let datecreated = new Date()
let datemodified = datecreated
let tags : string[] = []
import type { PageData } from './$types';
import '$lib/components/card.css';
import MediaScroller from '$lib/components/MediaScroller.svelte';
import Card from '$lib/components/Card.svelte';
import Search from '$lib/components/Search.svelte';
export let data: PageData;
export let current_month = new Date().getMonth() + 1
async function doPost () {
const res = await fetch('/api/add', {
method: 'POST',
body: JSON.stringify({
bearer: "password1234",
recipe: {
short_name,
name,
category,
datecreated,
datemodified,
tags,
description,
icon
},
headers: {
'content-type': 'application/json',
bearer: "password1234",
}
})
})
const json = await res.json()
result = JSON.stringify(json)
console.log(result)
}
</script>
<style>
input{
display: block;
margin: 1rem;
}
</style>
<h1>Rezept hinzufügen</h1>
<input bind:value={short_name} />
<input bind:value={name} />
<input bind:value={icon} />
<input bind:value={category} />
<input bind:value={description} />
<input type="text" name="" id="" bind:value={tags}>
<button on:click={doPost}>HIT IT</button>
<h3>Zutaten</h3>
<!-- already added ingredients
<input type="number"><select name="" id=""></select><input type="text">
<br>
<br>
<input type="text" name="" id=""><button>Neue Unterkategorie hinzufügen</button>
<h3> Schritte </h3>
<input type="text">
<button>Neue Unterkategorie hinzufügen</button>
<br>
<input type="text"><button>Schritt hinzufügen</button>-->

View File

@ -0,0 +1,13 @@
import type { PageLoad } from "./$types";
export async function load({ fetch }) {
let current_month = new Date().getMonth() + 1
const res_season = await fetch(`/api/items/category`);
const res_all_brief = await fetch(`/api/items/tag`);
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,
};
};

View File

@ -0,0 +1 @@
{"terminal": "nvimterm"}

View File

@ -1,110 +0,0 @@
.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);
}
}

View File

@ -0,0 +1,16 @@
<script lang="ts">
import type { PageData } from './$types';
export let data: PageData;
import TagCloud from '$lib/components/TagCloud.svelte';
import TagBall from '$lib/components/TagBall.svelte';
</script>
<h1>Rezepte</h1>
<h2>Kategorien</h2>
<section>
<TagCloud>
{#each data.categories as tag}
<TagBall {tag} ref="/rezepte/category">
</TagBall>
{/each}
</TagCloud>
</section>

View File

@ -0,0 +1,7 @@
import type { PageLoad } from "./$types";
export async function load({ fetch}) {
const res = await fetch(`/api/items/category`);
const categories= await res.json();
return {categories}
};

View File

@ -0,0 +1,17 @@
<script lang="ts">
import type { PageData } from './$types';
import '$lib/components/card.css';
import Recipes from '$lib/components/Recipes.svelte';
export let data: PageData;
export let current_month = new Date().getMonth() + 1;
import Card from '$lib/components/Card.svelte'
</script>
<h1>Rezepte</h1>
<h2>In Kategorie {data.category}</h2>
<section>
<Recipes>
{#each data.recipes as recipe}
<Card {recipe} {current_month}></Card>
{/each}
</Recipes>
</section>

View File

@ -0,0 +1,10 @@
import type { PageLoad } from "./$types";
export async function load({ fetch, params }) {
const res = await fetch(`/api/items/category/${params.category}`);
const items = await res.json();
return {
category: params.category,
recipes: items
}
};

View File

@ -0,0 +1,23 @@
<script lang="ts">
import type { PageData } from './$types';
import '$lib/components/card.css';
import '$lib/components/nordtheme.css';
import Recipes from '$lib/components/Recipes.svelte';
import MediaScroller from '$lib/components/MediaScroller.svelte';
import SeasonLayout from '$lib/components/SeasonLayout.svelte'
import Card from '$lib/components/Card.svelte';
import Search from '$lib/components/Search.svelte';
export let data: PageData;
export let current_month = new Date().getMonth() + 1
</script>
<SeasonLayout>
<h2 slot=test>Rezepte des Monats </h2>
<Recipes slot=recipes>
{#each data.season as recipe}
<Card {recipe} {current_month}></Card>
{/each}
</Recipes>
</SeasonLayout>

View File

@ -0,0 +1,10 @@
import type { PageLoad } from "./$types";
export async function load({ fetch }) {
let current_month = new Date().getMonth() + 1
const res_season = await fetch(`/api/items/in_season/` + current_month);
const item_season = await res_season.json();
return {
season: item_season,
};
};

View File

@ -0,0 +1 @@
{"terminal": "nvimterm"}

View File

@ -0,0 +1,19 @@
<script lang="ts">
import type { PageData } from './$types';
import Recipes from '$lib/components/Recipes.svelte';
import SeasonLayout from '$lib/components/SeasonLayout.svelte';
import '$lib/components/card.css';
import MediaScroller from '$lib/components/MediaScroller.svelte';
import Card from '$lib/components/Card.svelte';
import Search from '$lib/components/Search.svelte';
export let data: PageData;
let months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]
</script>
<SeasonLayout>
<h2 slot=test>Rezepte die im {months[data.month-1]} in Saison sind</h2>
<Recipes slot=recipes>
{#each data.season as recipe}
<Card {recipe} icon_override=true></Card>
{/each}
</Recipes>
</SeasonLayout>

View File

@ -0,0 +1,12 @@
import type { PageLoad } from "./$types";
export async function load({ fetch, params }) {
const res_season = await fetch(`/api/items/in_season/` + params.month);
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 {
month: params.month,
season: item_season,
};
};

View File

@ -1,9 +0,0 @@
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
}
};

View File

@ -1,30 +1,16 @@
<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;
import TagCloud from '$lib/components/TagCloud.svelte';
import TagBall from '$lib/components/TagBall.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>
<h2>Kategorien</h2>
<section>
<div class=accordion>
{#each data.recipes as recipe}
<Card {recipe} {current_month}></Card>
<TagCloud>
{#each data.tags as tag}
<TagBall {tag} ref="/rezepte/tag">
</TagBall>
{/each}
</div>
</TagCloud>
</section>

View File

@ -0,0 +1,7 @@
import type { PageLoad } from "./$types";
export async function load({ fetch}) {
const res = await fetch(`/api/items/tag`);
const tags = await res.json();
return {tags}
};

View File

@ -1,30 +1,17 @@
<script lang="ts">
import type { PageData } from './$types';
import '../../card.css';
import '$lib/components/card.css';
import Recipes from '$lib/components/Recipes.svelte';
export let data: PageData;
export let current_month = new Date().getMonth() + 1;
import Card from '../../Card.svelte'
import Card from '$lib/components/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>
<Recipes>
{#each data.recipes as recipe}
<Card {recipe} {current_month}></Card>
{/each}
</Recipes>
</section>