Compare commits
1 commit
main
...
experiment
Author | SHA1 | Date | |
---|---|---|---|
324df6a007 |
6 changed files with 133 additions and 307 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
.env/
|
||||
venv/
|
||||
**/__pycache__/
|
|
@ -1 +1,8 @@
|
|||
{"reservations": [{"item_id": "77b3c3a0-303b-482f-a1e0-67c29030ec69", "name": "Max"}, {"item_id": "c2d7e720-8541-4b89-b6d6-08d723f2c487", "name": ""}]}
|
||||
{
|
||||
"reservations": [
|
||||
{
|
||||
"item_id": "77b3c3a0-303b-482f-a1e0-67c29030ec69",
|
||||
"name": "Max"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,23 +1,3 @@
|
|||
"id","name","description","shop","image","price"
|
||||
"d3e203ba-9aab-4283-8c46-f4a46a5d1f62","Dune: Part 2 - 4K HDR Blu-Ray","Der zweite Film der Dune Reihe in bester Qualität auf Blu-Ray. Die Qualität ist für den Film wichtig, weshalb auf 4K HDR geachtet werden sollte. Das ist in der Regel gut auf der Verpackung gekennzeichnet.","https://www.mediamarkt.de/de/product/_dune-part-two-blu-ray-2923536.html","https://assets.mmsrg.com/isr/166325/c1/-/ASSET_MMS_138728291?x=536&y=402&format=jpg&quality=80&sp=yes&strip=yes&trim&ex=536&ey=402&align=center&resizesource&unsharp=1.5x1+0.7+0.02&cox=0&coy=0&cdx=536&cdy=402",29.99
|
||||
"77b3c3a0-303b-482f-a1e0-67c29030ec69","Ex-Machina","","","",14.99
|
||||
"b7f313fa-0a7b-4513-b9de-3f5d5e5f1f42","The Beatles - Abbey Road (Vinyl)","Das ikonische Album der Beatles auf Vinyl. Perfekt für Liebhaber klassischer Rockmusik und Vinylsammler.","https://www.jpc.de/jpcng/poprock/detail/-/art/beatles-abbey-road/hnum/1234567","https://images-na.ssl-images-amazon.com/images/I/81P8CSlKvHL._SL1500_.jpg",22.99
|
||||
"c2d7e720-8541-4b89-b6d6-08d723f2c487","Inception - 4K Blu-Ray","Christopher Nolans Meisterwerk in atemberaubender 4K-Qualität auf Blu-Ray. Ein Muss für jeden Sci-Fi-Fan.","https://www.mediamarkt.de/de/product/_inception-4k-blu-ray-1234567.html","https://images-na.ssl-images-amazon.com/images/I/81XxGGnBkBL._SL1500_.jpg",24.99
|
||||
"f8a8a9c0-38da-4975-bc30-78567121f8b6","The Rolling Stones - Let It Bleed (CD)","Ein Klassiker der Rockgeschichte auf CD, inklusive Hits wie 'Gimme Shelter'.","https://www.jpc.de/jpcng/poprock/detail/-/art/rolling-stones-let-it-bleed/hnum/9876543","https://images-na.ssl-images-amazon.com/images/I/713o05Y57mL._SL1400_.jpg",12.99
|
||||
"a0df23f8-00c4-4d85-b78f-9984e74e7f57","Blade Runner 2049 - 4K UHD Blu-Ray","Die visuell beeindruckende Fortsetzung des Sci-Fi-Kultfilms in gestochen scharfer 4K UHD Qualität.","https://www.mediamarkt.de/de/product/_blade-runner-2049-4k-uhd-blu-ray-654321.html","https://s.pacn.ws/1500/um/blade-runner-2049-4k-ultra-hd-bluray-set-limited-edition-551289.1.jpg?p2a9av",27.99
|
||||
"9f234bc1-4568-4f59-bf16-6f034f3f3125","Nirvana - Nevermind (Vinyl)","Das legendäre Grunge-Album von Nirvana auf hochwertigem Vinyl.","https://www.jpc.de/jpcng/poprock/detail/-/art/nirvana-nevermind/hnum/1122334","",19.99
|
||||
"c3b1d3a8-2bf0-4766-90a1-1b33d412c17e","Interstellar - 4K Blu-Ray","Ein episches Weltraum-Abenteuer von Christopher Nolan in gestochen scharfer 4K-Qualität auf Blu-Ray.","https://www.mediamarkt.de/de/product/_interstellar-4k-blu-ray-456789.html","",26.99
|
||||
"b01e679a-06bb-43d5-b79c-e27b0ddc1949","Pink Floyd - The Dark Side of the Moon (CD)","Ein zeitloses Meisterwerk der Rockmusik auf CD, ideal für Fans klassischer Alben.","https://www.jpc.de/jpcng/poprock/detail/-/art/pink-floyd-the-dark-side-of-the-moon/hnum/3344556","",14.99
|
||||
"df8e3b0e-fb9e-4ec8-a916-517bf0801f1b","The Godfather - 4K Blu-Ray","Das epische Gangsterdrama in brillanter 4K-Qualität. Ein unverzichtbarer Klassiker für jede Filmsammlung.","https://www.mediamarkt.de/de/product/_the-godfather-4k-blu-ray-898765.html","",29.99
|
||||
"c9478c92-8327-4e45-b51e-e3c8b7c95d7f","Radiohead - OK Computer (Vinyl)","Das einflussreiche Album von Radiohead auf hochwertigem Vinyl, perfekt für Sammler und Musikliebhaber.","https://www.jpc.de/jpcng/poprock/detail/-/art/radiohead-ok-computer/hnum/9988776","",21.99
|
||||
"1ef8a341-ec8d-4a0f-b8c6-efcde0f2a907","The Matrix - 4K HDR Blu-Ray","Der bahnbrechende Sci-Fi-Film in 4K HDR-Qualität auf Blu-Ray, inklusive neuer Extras und Interviews.","https://www.mediamarkt.de/de/product/_the-matrix-4k-hdr-blu-ray-678543.html","",28.99
|
||||
"e015acb0-cb96-4f7d-8a94-9c04b6df1963","Bob Dylan - Highway 61 Revisited (CD)","Ein Klassiker der Folk- und Rockgeschichte, ideal für Fans von Bob Dylan und authentischer Musik.","https://www.jpc.de/jpcng/poprock/detail/-/art/bob-dylan-highway-61-revisited/hnum/5544332","",12.49
|
||||
"df89c0e3-14f2-45ec-9ba8-47f61e3f688e","The Lord of the Rings: The Fellowship of the Ring - 4K Blu-Ray","Das epische Fantasy-Abenteuer in 4K, inklusive zahlreicher Extras und Hintergrundmaterial.","https://www.mediamarkt.de/de/product/_lord-of-the-rings-fellowship-4k-blu-ray-234567.html","",31.99
|
||||
"bb60b242-3b44-41d4-82cb-6f4724b2527b","Queen - A Night at the Opera (Vinyl)","Das gefeierte Album von Queen auf Vinyl, inklusive 'Bohemian Rhapsody'.","https://www.jpc.de/jpcng/poprock/detail/-/art/queen-a-night-at-the-opera/hnum/7654321","",18.99
|
||||
"b35b30f2-7c5b-47fc-b8ef-46c9289d7a31","Casablanca - 4K Blu-Ray","Der zeitlose Filmklassiker in brillanter 4K-Qualität, ideal für Sammler von alten Filmen.","https://www.mediamarkt.de/de/product/_casablanca-4k-blu-ray-876543.html","",24.49
|
||||
"24d3ebcf-937d-4095-a4db-82cbb7baba7f","Led Zeppelin - IV (CD)","Ein wegweisendes Album der Rockgeschichte, bekannt für 'Stairway to Heaven'.","https://www.jpc.de/jpcng/poprock/detail/-/art/led-zeppelin-iv/hnum/1123445","",13.99
|
||||
"97f8bca7-77da-4ed8-b8bc-0c5f6f7f3b91","The Great Gatsby - 4K Blu-Ray","Die opulente Verfilmung des klassischen Romans in 4K, inklusive audiovisuellen Features.","https://www.mediamarkt.de/de/product/_great-gatsby-4k-blu-ray-556677.html","",23.99
|
||||
"f9e24a8c-47c0-4d82-a7ea-b6a8b9e0d4c5","Miles Davis - Kind of Blue (Vinyl)","Das einflussreichste Jazzalbum aller Zeiten auf Vinyl, ein Muss für Jazzliebhaber.","https://www.jpc.de/jpcng/jazz/detail/-/art/miles-davis-kind-of-blue/hnum/3332211","",19.49
|
||||
"e8f3c5a9-91f6-43b7-95c3-e4e5b7f60d2e","Gladiator - 4K Blu-Ray","Der epische Historienfilm mit Russell Crowe in atemberaubender 4K-Qualität.","https://www.mediamarkt.de/de/product/_gladiator-4k-blu-ray-223344.html","",26.49
|
||||
"fa79d63b-f7cf-46c8-89dc-96b1a9e6f716","David Bowie - Ziggy Stardust (CD)","Das legendäre Konzeptalbum von David Bowie auf CD, ein Muss für Glam-Rock-Fans.","https://www.jpc.de/jpcng/poprock/detail/-/art/david-bowie-ziggy-stardust/hnum/4433221","",15.99
|
||||
"c63e5b17-46d1-44a7-9237-8775f5df4e38","Pulp Fiction - 4K Blu-Ray","Quentin Tarantinos Kultfilm in beeindruckender 4K-Qualität, inklusive exklusiver Extras.","https://www.mediamarkt.de/de/product/_pulp-fiction-4k-blu-ray-778899.html","",25.99
|
||||
"77b3c3a0-303b-482f-a1e0-67c29030ec69","Ex-Machina","","","",14.99
|
|
18
src/main.py
18
src/main.py
|
@ -1,6 +1,7 @@
|
|||
import uuid
|
||||
from fastapi import Depends, FastAPI, Request, Response
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from wishlist import (
|
||||
read_all_wishlists,
|
||||
|
@ -26,15 +27,30 @@ async def update_reservation(
|
|||
),
|
||||
):
|
||||
global wishlist_cache
|
||||
|
||||
if reservation_request.name.strip() == "":
|
||||
return Response(status_code=400)
|
||||
|
||||
wishlist_dir: str = wishlist_cache[reservation_request.wishlist_id].directory
|
||||
reserved = None
|
||||
if reservation_request.reserved:
|
||||
new_reservation = ItemReservation()
|
||||
new_reservation.name = reservation_request.name
|
||||
new_reservation.item_id = str(reservation_request.item_id)
|
||||
add_reservation(wishlist_dir, new_reservation)
|
||||
reserved = True
|
||||
else:
|
||||
reserved = False
|
||||
remove_reservation(wishlist_dir, reservation_request.item_id)
|
||||
|
||||
return JSONResponse(
|
||||
content={
|
||||
"item_id": str(reservation_request.item_id),
|
||||
"wishlist_id": str(reservation_request.wishlist_id),
|
||||
"reserved": reserved,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@app.get("/{wishlist_id}/view", response_class=HTMLResponse)
|
||||
async def show_wishlist(request: Request, wishlist_id: uuid.UUID):
|
||||
|
|
29
src/templates/components/wishlist_item.html
Normal file
29
src/templates/components/wishlist_item.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
<!-- item.html -->
|
||||
<div class="item-card {{ 'reserved' if item.reserved else '' }}">
|
||||
<div class="item-header" onclick="toggleDescription(this)">
|
||||
<h2>{{ item.name }}{% if item.reserved %} (Reserved){% endif %}</h2>
|
||||
<img src="{{ item.image }}" alt="{{ item.name }}">
|
||||
<p class="price">€{{ "%.2f"|format(item.price) }}</p>
|
||||
</div>
|
||||
|
||||
<div class="item-footer">
|
||||
<!-- Reserve or Unreserve Form -->
|
||||
<form method="POST" action="/reserve-item">
|
||||
<input type="hidden" name="wishlist_id" value="{{ wishlist.config.id }}">
|
||||
<input type="hidden" name="item_id" value="{{ item.id }}">
|
||||
<input type="hidden" name="reserved" value="{{ 'false' if item.reserved else 'true' }}">
|
||||
{% if item.reserved %}
|
||||
<input type="text" name="reserver_name" value="{{ item.reserver_name }}" readonly>
|
||||
<button type="submit" class="reserve-button">Unreserve</button>
|
||||
{% else %}
|
||||
<input type="text" name="reserver_name" placeholder="Your name" required>
|
||||
<button type="submit" class="reserve-button">Reserve</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="item-description hide">
|
||||
<p>{{ item.description }}</p>
|
||||
<a href="{{ item.shop }}" target="_blank">Shop Link</a>
|
||||
</div>
|
||||
</div>
|
|
@ -1,301 +1,96 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{{ wishlist.config.title }}</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: #1a1a1a;
|
||||
color: #aaa;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "Fira Code", "Fira Mono", "Roboto Mono",
|
||||
"Lucida Console", "Courier New", monospace;
|
||||
}
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ wishlist.config.title }}</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: #1a1a1a;
|
||||
color: #aaa;
|
||||
font-family: "Fira Code", "Fira Mono", "Roboto Mono", "Lucida Console", "Courier New", monospace;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
main {
|
||||
max-width: 40rem;
|
||||
margin: auto;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1,
|
||||
h3 {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
.item-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
ul {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
list-style: none;
|
||||
align-content: flex-start;
|
||||
padding: 0 1em;
|
||||
margin: 1em auto;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
.item-card {
|
||||
background: #222;
|
||||
border-radius: 8px;
|
||||
margin: 10px;
|
||||
padding: 15px;
|
||||
width: 250px;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
li {
|
||||
width: auto;
|
||||
margin: 0.2em;
|
||||
padding: 1em;
|
||||
.item-card:hover {
|
||||
background-color: #333;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
order: 0;
|
||||
border-color: #aaa;
|
||||
border-radius: 4px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-self: flex-start;
|
||||
}
|
||||
.item-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
li.reserved-item {
|
||||
order: 1 !important;
|
||||
border-style: dashed;
|
||||
}
|
||||
.item-description {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
li.reserved-item .item-name {
|
||||
color: rgb(178, 172, 162) !important;
|
||||
}
|
||||
.item-description.show {
|
||||
max-height: 200px; /* Adjust based on expected content */
|
||||
}
|
||||
|
||||
li.reserved-item .price {
|
||||
display: none;
|
||||
}
|
||||
.item-footer {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
li.reserved-item img {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.reserve-button {
|
||||
padding: 5px 10px;
|
||||
border: none;
|
||||
background-color: #444;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
}
|
||||
.reserve-button:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
.item-name {
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
<body>
|
||||
<h1>{{ wishlist.config.title }}</h1>
|
||||
|
||||
p {
|
||||
color: #888;
|
||||
font-size: 14px;
|
||||
}
|
||||
<div class="item-grid">
|
||||
{% for item_id, item in wishlist.items.items() %}
|
||||
{% include 'components/wishlist_item.html' %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
a {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
<script>
|
||||
function toggleDescription(header) {
|
||||
const description = header.nextElementSibling;
|
||||
description.classList.toggle('show');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
a:hover {
|
||||
background-color: #444;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
1 .price {
|
||||
color: rgb(178, 172, 162);
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 10em;
|
||||
max-height: 8em;
|
||||
border-radius: 2px;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
|
||||
.reserve-button {
|
||||
color: white;
|
||||
background: transparent;
|
||||
border: #2c2c2c solid 1px;
|
||||
padding: 0.8em 1em 1em 1em;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.5s;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.reserve-button:hover {
|
||||
background-color: #202324;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 1px solid #333;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
padding: 8px;
|
||||
background-color: #333;
|
||||
border: 1px solid #555;
|
||||
color: #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.details {
|
||||
height: 0;
|
||||
transition: height 1s !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.details.show {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.details-button:hover {
|
||||
text-decoration-line: underline;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.button {
|
||||
color: #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 6pt;
|
||||
box-shadow: 4px 4px 15px #555, 2px 2px 13px #333 inset;
|
||||
transition: box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
box-shadow: 4px 4px 13px #888, 2px 2px 13px #333 inset;
|
||||
}
|
||||
|
||||
.button:active {
|
||||
box-shadow: 1px 1px 3px #888, 2px 2px 3px #333 inset;
|
||||
transition: box-shadow 0.1s !important;
|
||||
}
|
||||
|
||||
.unselectable {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<h1>{{ wishlist.config.title }}</h1>
|
||||
|
||||
<div id="welcome">
|
||||
Bitte Name eingeben um Wunschliste zu sehen. Dieser wird zu deinen Reservierungen hinterlegt.
|
||||
<br />
|
||||
<input id="name" name="name" type="text" placeholder="Dein Name" /> <span id="register-btn"
|
||||
class="button unselectable">Wunschliste
|
||||
anzeigen</span>
|
||||
</div>
|
||||
{% if wishlist.items.items()|selectattr("reservation")|list %}
|
||||
<h3>Deine Reservierungen</h3>
|
||||
<ul>
|
||||
{% for item_id, item in wishlist.items.items() if item.reservation %}
|
||||
<li class="{{ 'reserved-item' if item.reservation else '' }}">
|
||||
{% if item.image %}<img src="{{ item.image }}" alt="{{ item.name }}" />{% endif %}
|
||||
<div class="item-name">{{ item.name }}</div>
|
||||
<form method="POST" action="/reservation/update">
|
||||
<input type="hidden" name="wishlist_id" value="{{ wishlist.config.id }}" />
|
||||
<input type="hidden" name="item_id" value="{{ item.id }}" />
|
||||
<input type="hidden" name="reserved" value="{{ 'false' if item.reservation else 'true' }}" />
|
||||
<input type="hidden" name="name" value="" />
|
||||
{% if item.reservation %}
|
||||
<button type="submit" class="reserve-button">
|
||||
Reservierung aufheben
|
||||
</button>
|
||||
{% else %}
|
||||
<button type="submit" class="reserve-button">
|
||||
Reservieren
|
||||
</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
<div>
|
||||
<p class="price">Ca. {{ "%.2f"|format(item.price) }}€</p>
|
||||
<div class="details-button" onclick="toggleDetails('details-{{ item_id }}')">
|
||||
Mehr Details
|
||||
</div>
|
||||
</div>
|
||||
<div id="details-{{ item_id }}" class="details">
|
||||
<p>{{ item.description }}</p>
|
||||
<a href="{{ item.shop }}" target="_blank">Shop Link</a>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<h3>Verfügbare Geschenke</h3>
|
||||
<ul>
|
||||
{% for item_id, item in wishlist.items.items() if not item.reservation %}
|
||||
<li class="{{ 'reserved-item' if item.reservation else '' }}">
|
||||
{% if item.image %}<img
|
||||
src="{{ item.image }}"
|
||||
alt="{{ item.name }}"
|
||||
/>{% endif %}
|
||||
<div class="item-name">{{ item.name }}</div>
|
||||
<form method="POST" action="/reservation/update">
|
||||
<input
|
||||
type="hidden"
|
||||
name="wishlist_id"
|
||||
value="{{ wishlist.config.id }}"
|
||||
/>
|
||||
<input type="hidden" name="item_id" value="{{ item.id }}" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="reserved"
|
||||
value="{{ 'false' if item.reservation else 'true' }}"
|
||||
/>
|
||||
<input type="hidden" name="name" value="" />
|
||||
{% if item.reservation %}
|
||||
<button type="submit" class="reserve-button">
|
||||
Reservierung aufheben
|
||||
</button>
|
||||
{% else %}
|
||||
<button type="submit" class="reserve-button">
|
||||
Reservieren
|
||||
</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
<div>
|
||||
<p class="price">Ca. {{ "%.2f"|format(item.price) }}€</p>
|
||||
<div
|
||||
class="details-button"
|
||||
onclick="toggleDetails('details-{{ item_id }}')"
|
||||
>
|
||||
Mehr Details
|
||||
</div>
|
||||
</div>
|
||||
<div id="details-{{ item_id }}" class="details">
|
||||
<p>{{ item.description }}</p>
|
||||
<a href="{{ item.shop }}" target="_blank">Shop Link</a>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
function toggleDetails(id) {
|
||||
const detailsBox = document.getElementById(id);
|
||||
if (detailsBox) {
|
||||
detailsBox.classList.toggle("show");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue