Add edit, fix svg colors
This commit is contained in:
parent
e573555e29
commit
19b47b7988
@ -2317,10 +2317,6 @@ details.collapse summary::-webkit-details-marker{
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.mr-4{
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.mr-auto{
|
||||
margin-right: auto;
|
||||
}
|
||||
@ -2357,6 +2353,10 @@ details.collapse summary::-webkit-details-marker{
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
.h-8{
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.w-1\/2{
|
||||
width: 50%;
|
||||
}
|
||||
@ -2385,6 +2385,10 @@ details.collapse summary::-webkit-details-marker{
|
||||
width: 1.5rem;
|
||||
}
|
||||
|
||||
.w-8{
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.w-full{
|
||||
width: 100%;
|
||||
}
|
||||
@ -3121,6 +3125,10 @@ code{
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.md\:justify-between{
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.md\:text-left{
|
||||
text-align: left;
|
||||
}
|
||||
@ -3159,19 +3167,17 @@ code{
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark){
|
||||
.dark\:bg-gray-700{
|
||||
.dark\:bg-gray-700:where(.dark, .dark *){
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
||||
}
|
||||
}
|
||||
|
||||
.dark\:text-white{
|
||||
.dark\:text-white:where(.dark, .dark *){
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
}
|
||||
|
||||
.dark\:hover\:bg-gray-600:hover{
|
||||
.dark\:hover\:bg-gray-600:hover:where(.dark, .dark *){
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::collections::hash_map::Values;
|
||||
|
||||
use crate::types::Page;
|
||||
|
||||
pub fn duration(sec: &&i32) -> ::askama::Result<String> {
|
||||
|
@ -123,7 +123,7 @@ async fn main() {
|
||||
let redis = Data::new(redis);
|
||||
|
||||
let qs_config = QsQueryConfig::default()
|
||||
.error_handler(|err, req| {
|
||||
.error_handler(|err, _req| {
|
||||
// <- create custom error response
|
||||
error::InternalError::from_response(err, HttpResponse::Conflict().finish()).into()
|
||||
})
|
||||
|
@ -12,7 +12,7 @@ use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use sea_orm::{prelude::*, DatabaseTransaction, QueryOrder, QuerySelect, TransactionTrait};
|
||||
use serde::Deserialize;
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use serde_qs::actix::QsForm;
|
||||
|
||||
#[derive(Debug, Template, derive_more::Deref)]
|
||||
|
@ -1,5 +1,6 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
darkMode: 'selector',
|
||||
content: [
|
||||
"./templates/**/*.html",
|
||||
"./templates/**/*.jinja",
|
||||
|
@ -7,42 +7,57 @@
|
||||
<a href="/" class="hover:text-gray-600">Cooked</a>
|
||||
</h1>
|
||||
<div class="px-4 cursor-pointer md:hidden" id="burger">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 stroke-current fill-current" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="text-sm hidden md:flex flex-col gap-8" id="menu">
|
||||
<li>
|
||||
<a href="/" class="px-4 flex justify-end hover:shadow-md {{(page, Page::Index)|page_class}}">
|
||||
<a href="/" class="px-4 flex gap-2 justify-end hover:shadow-md {{(page, Page::Index)|page_class}}">
|
||||
<span>Home</span>
|
||||
<svg class="w-5 ml-2" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 fill-current" viewBox="0 0 20 20">
|
||||
<path
|
||||
d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/search" class="px-4 flex justify-end hover:shadow-md {{(page, Page::Search)|page_class}}">
|
||||
<a href="/search" class="px-4 flex gap-2 justify-end hover:shadow-md {{(page, Page::Search)|page_class}}">
|
||||
<span>Search</span>
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-5 ml-2">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.25007 2.38782C8.54878 2.0992 10.1243 2 12 2C13.8757 2 15.4512 2.0992 16.7499 2.38782C18.06 2.67897 19.1488 3.176 19.9864 4.01358C20.824 4.85116 21.321 5.94002 21.6122 7.25007C21.9008 8.54878 22 10.1243 22 12C22 13.8757 21.9008 15.4512 21.6122 16.7499C21.321 18.06 20.824 19.1488 19.9864 19.9864C19.1488 20.824 18.06 21.321 16.7499 21.6122C15.4512 21.9008 13.8757 22 12 22C10.1243 22 8.54878 21.9008 7.25007 21.6122C5.94002 21.321 4.85116 20.824 4.01358 19.9864C3.176 19.1488 2.67897 18.06 2.38782 16.7499C2.0992 15.4512 2 13.8757 2 12C2 10.1243 2.0992 8.54878 2.38782 7.25007C2.67897 5.94002 3.176 4.85116 4.01358 4.01358C4.85116 3.176 5.94002 2.67897 7.25007 2.38782ZM9 11.5C9 10.1193 10.1193 9 11.5 9C12.8807 9 14 10.1193 14 11.5C14 12.8807 12.8807 14 11.5 14C10.1193 14 9 12.8807 9 11.5ZM11.5 7C9.01472 7 7 9.01472 7 11.5C7 13.9853 9.01472 16 11.5 16C12.3805 16 13.202 15.7471 13.8957 15.31L15.2929 16.7071C15.6834 17.0976 16.3166 17.0976 16.7071 16.7071C17.0976 16.3166 17.0976 15.6834 16.7071 15.2929L15.31 13.8957C15.7471 13.202 16 12.3805 16 11.5C16 9.01472 13.9853 7 11.5 7Z" fill="#323232"/>
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-5 fill-current">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.25007 2.38782C8.54878 2.0992 10.1243 2 12 2C13.8757 2 15.4512 2.0992 16.7499 2.38782C18.06 2.67897 19.1488 3.176 19.9864 4.01358C20.824 4.85116 21.321 5.94002 21.6122 7.25007C21.9008 8.54878 22 10.1243 22 12C22 13.8757 21.9008 15.4512 21.6122 16.7499C21.321 18.06 20.824 19.1488 19.9864 19.9864C19.1488 20.824 18.06 21.321 16.7499 21.6122C15.4512 21.9008 13.8757 22 12 22C10.1243 22 8.54878 21.9008 7.25007 21.6122C5.94002 21.321 4.85116 20.824 4.01358 19.9864C3.176 19.1488 2.67897 18.06 2.38782 16.7499C2.0992 15.4512 2 13.8757 2 12C2 10.1243 2.0992 8.54878 2.38782 7.25007C2.67897 5.94002 3.176 4.85116 4.01358 4.01358C4.85116 3.176 5.94002 2.67897 7.25007 2.38782ZM9 11.5C9 10.1193 10.1193 9 11.5 9C12.8807 9 14 10.1193 14 11.5C14 12.8807 12.8807 14 11.5 14C10.1193 14 9 12.8807 9 11.5ZM11.5 7C9.01472 7 7 9.01472 7 11.5C7 13.9853 9.01472 16 11.5 16C12.3805 16 13.202 15.7471 13.8957 15.31L15.2929 16.7071C15.6834 17.0976 16.3166 17.0976 16.7071 16.7071C17.0976 16.3166 17.0976 15.6834 16.7071 15.2929L15.31 13.8957C15.7471 13.202 16 12.3805 16 11.5C16 9.01472 13.9853 7 11.5 7Z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/tags" class="px-4 flex justify-end hover:shadow-md {{(page, Page::Search)|page_class}}">
|
||||
<a href="/tags" class="px-4 flex justify-end hover:shadow-md {{(page, Page::Search)|page_class}} gap-2">
|
||||
<span>Tags</span>
|
||||
<svg fill="#000000" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" class="w-5 ml-2">
|
||||
<svg
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 100 100"
|
||||
enable-background="new 0 0 100 100"
|
||||
xml:space="preserve"
|
||||
class="w-5 fill-current"
|
||||
>
|
||||
<path d="M88.286,67.965c-0.022-0.038-0.052-0.069-0.076-0.105l0.002-0.001L61.307,21.26l-0.015,0.008 c-0.23-0.368-0.558-0.637-0.929-0.801l0.038-0.022l-7.986-4.612l8.871,15.365l20.178,34.949l-0.002,0.001 c0.024,0.036,0.054,0.067,0.076,0.105c0.577,0.999,0.234,2.277-0.765,2.855l0.014,0.025l-29.861,17.24l1.293,2.239 c0.026,0.055,0.044,0.112,0.075,0.166c0.562,0.971,1.785,1.316,2.772,0.801l0.005,0.008l32.465-18.743l-0.014-0.025 C88.52,70.243,88.862,68.964,88.286,67.965z"></path> <path d="M73.88,67.143c0.999-0.577,1.341-1.855,0.765-2.855c-0.022-0.038-0.052-0.069-0.076-0.105l0.002-0.001L47.666,17.583 l-0.015,0.008c-0.23-0.368-0.558-0.637-0.929-0.801l0.038-0.022l-11.01-6.357l0,0.044c-0.554-0.315-1.232-0.367-1.846-0.107 l-0.012-0.021l-0.206,0.119c-0.004,0.003-0.009,0.003-0.013,0.006c-0.004,0.003-0.007,0.006-0.012,0.008l-21.183,12.23 c-0.656,0.378-1.021,1.058-1.037,1.764l-0.007-0.004v12.714l0.021-0.012c-0.047,0.427,0.03,0.872,0.261,1.273 c0.014,0.024,0.032,0.042,0.047,0.065l0,0l26.815,46.446c0.026,0.055,0.044,0.112,0.075,0.166c0.562,0.971,1.785,1.316,2.772,0.801 l0.005,0.008l32.465-18.743L73.88,67.143z M29.545,27.522c-1.849,1.068-4.214,0.435-5.281-1.414 c-1.068-1.849-0.434-4.213,1.415-5.281c1.849-1.068,4.213-0.434,5.281,1.416C32.028,24.091,31.395,26.456,29.545,27.522z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/ingeredients" class="px-4 flex justify-end hover:shadow-md {{(page, Page::Search)|page_class}}">
|
||||
<a href="/ingeredients" class="px-4 flex justify-end hover:shadow-md {{(page, Page::Search)|page_class}} gap-2">
|
||||
<span>Ingeredients</span>
|
||||
<svg fill="#000000" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.999 511.999" xml:space="preserve">
|
||||
<svg
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 511.999 511.999"
|
||||
xml:space="preserve"
|
||||
class="w-5 fill-current"
|
||||
>
|
||||
<path d="M203.271,92.915c-0.493,0-0.985,0.01-1.477,0.016l-5.121,13.178l44.17,34.042c7.051,5.434,8.359,15.553,2.926,22.604 c-3.174,4.12-7.95,6.281-12.777,6.281c-3.435,0-6.896-1.095-9.827-3.354l-27.767-21.4v29.012c0,8.901-7.216,16.117-16.117,16.117 s-16.117-7.216-16.117-16.117v-29.013l-27.766,21.4c-2.932,2.26-6.392,3.354-9.827,3.354c-4.827,0-9.601-2.161-12.777-6.281 c-5.432-7.051-4.125-17.169,2.926-22.604l50.168-38.664l3.015-7.762c-5.207-0.534-10.422-0.808-15.608-0.808 c-44.894,0-80.666,11.223-106.325,33.358C15.13,152.017,0,191.558,0,243.79c0,71.125,42.108,132.589,102.697,160.805 l136.181-232.307c14.711-25.094,36.334-43.59,61.373-53.109C275.694,101.899,243.149,92.915,203.271,92.915z"></path> </g> </g> <g> <g> <path d="M204.61,41.202c-8.294-3.222-17.636,0.887-20.859,9.184l-16.845,43.337l34.89-0.793l0.869-2.238l11.127-28.63 C217.018,53.766,212.907,44.427,204.61,41.202z"></path> </g> </g> <g> <g> <path d="M511.878,187.62c-1.107-9.953-9.533-17.312-19.316-17.312c-0.717,0-1.441,0.04-2.171,0.122l-43.375,4.819l37.389-37.39 c7.599-7.599,7.599-19.916,0-27.516c-3.799-3.799-8.779-5.7-13.757-5.7c-4.98,0-9.959,1.9-13.759,5.7l-37.39,37.39l4.821-43.374 c1.187-10.679-6.509-20.3-17.19-21.486c-0.73-0.082-1.455-0.121-2.173-0.121c-9.783,0-18.209,7.36-19.314,17.31l-6.876,61.886 c-12.27-7.242-25.753-11.089-39.284-11.089c-2.802,0-5.606,0.183-8.404,0.515c-0.202,0.026-0.406,0.032-0.608,0.058 c-23.544,3.021-44.693,17.795-58.023,40.534l-29.023,49.51l42.511,42.511c7.597,7.597,7.597,19.918-0.001,27.516 c-7.597,7.597-19.917,7.597-27.516,0c-0.001,0,0,0-0.001,0l-35.33-35.331l-82.676,141.034l-14.885,25.39 c-4.479,7.638-3.235,17.336,3.026,23.596c3.749,3.75,8.732,5.701,13.765,5.701c3.373,0,6.767-0.877,9.832-2.672l235.427-138.006 l-39.587-39.589l-24.758-24.76c-7.599-7.597-7.6-19.919-0.001-27.516c7.597-7.597,19.919-7.597,27.517,0l3.806,3.806 l65.787,65.788c12.695-12.376,20.827-27.905,22.976-44.667c2.117-16.494-1.664-33.3-10.516-48.297l61.888-6.876 C505.369,207.917,513.064,198.298,511.878,187.62z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
@ -58,7 +73,9 @@
|
||||
<svg
|
||||
class="swap-off fill-current w-5 h-5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24">
|
||||
viewBox="0 0 24 24"
|
||||
class="w-5 h-5"
|
||||
>
|
||||
<path
|
||||
d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
|
||||
</svg>
|
||||
|
@ -1,83 +0,0 @@
|
||||
{% extends "base.jinja" %}
|
||||
|
||||
{% block content %}
|
||||
<main class="m-4 flex flex-col gap-4 w-full">
|
||||
{% include "../top_bar.jinja" %}
|
||||
|
||||
<div class="sm:rounded-3xl w-full flex flex-col gap-4">
|
||||
<div class="text-center w-full">
|
||||
<img src={{ recipe.image_url.clone() }} alt="{{recipe.title}}" class="rounded-xl w-40 md:w-3/4 ml-auto mr-auto">
|
||||
</div>
|
||||
<div class="flex flex-col gap-7">
|
||||
<h1 class="font-young-serif text-desktop-heading-l text-stone-700 sm:text-stone-800 text-center md:text-left">
|
||||
{{ recipe.title }}
|
||||
</h1>
|
||||
<p class="font-outfit-regular text-stone-500 sm:text-base">
|
||||
{{ recipe.summary.clone().unwrap_or_default() }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
<div class="flex flex-col gap-7">
|
||||
<p class="text-desktop-heading-m">
|
||||
Ingredients
|
||||
</p>
|
||||
<ul class="list-disc marker:text-rose-900 list-inside flex flex-col gap-3">
|
||||
{% for ingeredient in ingeredients %}
|
||||
<li class="paragraph">
|
||||
<span class="mr-1">
|
||||
{{ ingeredient.qty }}
|
||||
</span>
|
||||
<span class="mr-4">
|
||||
{{ ingeredient.unit }}
|
||||
</span>
|
||||
<span>
|
||||
{{ ingeredient.name }}
|
||||
</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
<div class="marker:text-rose-900 marker:font-outfit-semibold flex flex-col gap-7">
|
||||
<p class="text-desktop-heading-m">
|
||||
Instructions
|
||||
</p>
|
||||
<ol class="list-decimal list-inside flex flex-col gap-3">
|
||||
{% for step in steps %}
|
||||
<li class="font-outfit-regular text-stone-500 text-base">
|
||||
{{ step.body }}
|
||||
<div>{{ step.hint.clone().unwrap_or_default() }}</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
<div class="marker:text-rose-900 marker:font-outfit-semibold flex flex-col gap-7">
|
||||
<p class="text-desktop-heading-m">
|
||||
Tags
|
||||
</p>
|
||||
<div class="flex gap-4">
|
||||
{% for tag in tags %}
|
||||
<a class="bg-gray-300 dark:bg-gray-700 text-base text-gray-700 dark:text-white py-2 px-4 rounded-full font-bold hover:bg-gray-400 dark:hover:bg-gray-600 flex justify-center items-center">
|
||||
{{ tag.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
<div class="marker:text-rose-900 marker:font-outfit-semibold flex flex-col gap-7">
|
||||
<p class="text-desktop-heading-m">
|
||||
Ingredients
|
||||
</p>
|
||||
<div class="flex gap-4">
|
||||
{% for ingeredient in ingeredients %}
|
||||
<a class="bg-gray-300 dark:bg-gray-700 text-base text-gray-700 dark:text-white py-2 px-4 rounded-full font-bold hover:bg-gray-400 dark:hover:bg-gray-600 flex justify-center items-center">
|
||||
{{ ingeredient.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{% endblock %}
|
@ -9,9 +9,16 @@
|
||||
<img src={{ recipe.image_url.clone() }} alt="{{recipe.title}}" class="rounded-xl w-40 md:w-3/4 ml-auto mr-auto">
|
||||
</div>
|
||||
<div class="flex flex-col gap-7">
|
||||
<div class="flex md:justify-between items-center">
|
||||
<h1 class="font-young-serif text-desktop-heading-l text-stone-700 sm:text-stone-800 text-center md:text-left">
|
||||
{{ recipe.title }}
|
||||
</h1>
|
||||
<a href="/recipe/{{recipe.id}}/edit">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-8 h-8 fill-current" viewBox="0 -0.5 21 21">
|
||||
<path d="M18.9 18.01H2.1V2.097h8.4V.106H0V20h21v-9.947h-2.1zM6.3 9.95 16.63 0 21 4.115l-10.666 9.917H6.3z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
{% match recipe.summary %}
|
||||
{% when Some with (summary) %}
|
||||
<p class="font-outfit-regular text-stone-500 sm:text-base">
|
||||
|
@ -0,0 +1,155 @@
|
||||
{% extends "base.jinja" %}
|
||||
|
||||
{% block head %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/14.1.3/marked.min.js" integrity="sha512-kZ9BCD8vqCw2vJ1XG3EVZN5M5aRNxxMK3+uYuZPWc+TtW2Z1zSgmFlTIVHYHaWH0bH2lp2dUlB/1+M1h+lvfeg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="md:col-span-3 flex flex-col gap-4 m-4 w-full">
|
||||
{{ TopBar::new(session)|safe }}
|
||||
|
||||
<header class="flex flex-col gap-2">
|
||||
<h2 class="text-gray-600 text-6xl font-semibold text-center">Create recipe</h2>
|
||||
</header>
|
||||
<div class="flex flex-col gap-8">
|
||||
<div class="flex flex-wrap gap-8 justify-center">
|
||||
<form action="/recipe/{{id}}/update" method="post" class="flex flex-col gap-4 md:w-1/2 md:mb-10">
|
||||
<label for="image" class="flex gap-4">
|
||||
<input type="file" class="file-input w-full max-w-xs" name="image" id="image" />
|
||||
<input name="image_url" id='image_url' class="hidden" required />
|
||||
</label>
|
||||
|
||||
<label for="title" class="flex gap-4">
|
||||
<span class="w-24 shrink-0">Title:</span>
|
||||
<input id="title" name="title" class="input border border-solid border-gray-200 rounded-lg" type="text" value="{{title}}" required />
|
||||
</label>
|
||||
|
||||
<label for="summary" class="flex gap-4">
|
||||
<span class="w-24 shrink-0">Summary:</span>
|
||||
<div class="flex gap-2 w-full">
|
||||
<textarea id="summary" name="summary" class="textarea-with-view" required>{{summary}}</textarea>
|
||||
<div class="content w-1/2"></div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<blockquote class="w-full">
|
||||
<p class="text-base font-semibold">Summary supports Markdown</p>
|
||||
</blockquote>
|
||||
|
||||
<label for="ingeredients" class="flex gap-4">
|
||||
<span class="w-24 shrink-0">Ingeredients:</span>
|
||||
<div class="flex gap-2 w-full">
|
||||
<textarea id="ingeredients" name="ingeredients" class="textarea-without-view" required>{{ingeredients}}</textarea>
|
||||
</div>
|
||||
</label>
|
||||
<div class="w-full flex gap-4 flex-wrap">
|
||||
{% for ingredient in known_ingredients %}
|
||||
<label class="border rounded-lg p-2 styled-checkbox cursor-pointer">
|
||||
<span>{{ ingredient.name }}</span>
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<details class="w-full collapse collapse-arrow">
|
||||
<summary class="text-base font-semibold collapse-title">Ingeredients should be listed as list of AMOUNT UNIT INGEREDIENT. Example:</summary>
|
||||
|
||||
<div class="flex flex-col gap-1 font-normal collapse-content">
|
||||
<div>1 KG Potato</div>
|
||||
<div>200 G Sugar</div>
|
||||
<div>3 Bananas</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<label for="steps" class="flex gap-4">
|
||||
<span class="w-24 shrink-0">Steps:</span>
|
||||
<div class="flex gap-2 w-full">
|
||||
<textarea id="steps" name="steps" class="textarea-with-view" required>{{steps}}</textarea>
|
||||
<div class="content w-1/2"></div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<details class="w-full">
|
||||
<summary class="text-base font-semibold">Syntax for steps:</summary>
|
||||
<div>
|
||||
<p class="text-base"><code>*</code> is step</p>
|
||||
<p class="text-base"><code>></code> is hint for step</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<label for="tags" class="flex gap-4">
|
||||
<span class="w-24 shrink-0">Tags:</span>
|
||||
<input id="tags" name="tags" class="textarea-with-view" value="{{tags}}" />
|
||||
</label>
|
||||
<div class="w-full flex gap-4 flex-wrap">
|
||||
{% for tag in known_tags %}
|
||||
<label class="border rounded-lg p-2 styled-checkbox cursor-pointer">
|
||||
<span>{{ tag.name }}</span>
|
||||
{% match (tag.id, selected_tags.as_slice())|is_checked %}
|
||||
{% when true %}
|
||||
<input type="checkbox" name="selected_tags[]" value="{{tag.id}}" class="hidden" checked data-type="number[]" />
|
||||
{% when false %}
|
||||
<input type="checkbox" name="selected_tags[]" value="{{tag.id}}" class="hidden" data-type="number[]" />
|
||||
{% endmatch %}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" class="btn w-full" value="Save" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script type="module">
|
||||
document.addEventListener("DOMContentLoaded", (event) => {
|
||||
const body = document.body;
|
||||
Array.from(body.querySelectorAll('textarea')).forEach(el => {
|
||||
if (!el.parentElement.querySelector('.content')) return;
|
||||
el.parentElement.querySelector('div').innerHTML = marked.parse(el.value);
|
||||
el.addEventListener('keyup', () => {
|
||||
el.parentElement.querySelector('div').innerHTML = marked.parse(el.value);
|
||||
});
|
||||
});
|
||||
|
||||
const image = body.querySelector('input#image');
|
||||
const image_url = body.querySelector('#image_url');
|
||||
image.addEventListener('change', () => {
|
||||
const f = new FormData();
|
||||
f.append('image', image.files[0]);
|
||||
fetch('/recipe-image', { body: f, method: 'post' })
|
||||
.then(res => res.json())
|
||||
.then(({ url }) => image_url.value = url);
|
||||
});
|
||||
const form = body.querySelector('form');
|
||||
return;
|
||||
form.addEventListener('submit', ev => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
const p = Array.from(form.elements).reduce((memo, el) => {
|
||||
const { name, value } = el;
|
||||
console.log(name);
|
||||
if (name.endsWith('[]')) {
|
||||
const n = name.replace('[]', '');
|
||||
const v = memo[n] || [];
|
||||
v.push(value);
|
||||
memo[n] = v;
|
||||
} else {
|
||||
memo[name] = value;
|
||||
}
|
||||
return memo;
|
||||
}, {});
|
||||
async function f() {
|
||||
const res = fetch(form.action, { method: form.method, body: JSON.stringify(p), headers: { 'Content-Type': 'application/json' } });
|
||||
console.log(res);
|
||||
if (res.ok) {
|
||||
res => document.location = res.headers.get('location');
|
||||
} else {
|
||||
const html = await res.text();
|
||||
body.innerHTML = html;
|
||||
}
|
||||
}
|
||||
f();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user