Add support to add events

This commit is contained in:
2025-10-06 17:08:50 +02:00
parent 74e2039854
commit 98c4a93d56
5 changed files with 118 additions and 11 deletions

View File

@@ -1,4 +1,6 @@
import locale
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from datetime import datetime
from typing import Annotated, Union from typing import Annotated, Union
import starlette.status as status import starlette.status as status
@@ -16,6 +18,8 @@ sqlite_url = f"sqlite:///{sqlite_file_name}"
connect_args = {"check_same_thread": False} connect_args = {"check_same_thread": False}
engine = create_engine(sqlite_url, connect_args=connect_args) engine = create_engine(sqlite_url, connect_args=connect_args)
locale.setlocale(locale.LC_ALL, "de_DE.UTF-8")
def get_session(): def get_session():
with Session(engine) as session: with Session(engine) as session:
@@ -45,10 +49,46 @@ async def read_root(request: Request, session: SessionDep):
statement = select(Event).order_by(Event.event_time) statement = select(Event).order_by(Event.event_time)
events = session.exec(statement).all() events = session.exec(statement).all()
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, name="index.html", context={"events": events} request=request,
name="index.html",
context={"events": events, "current_page": "home", "now": datetime.now()},
) )
@app.get("/event/add")
async def add_event_form(request: Request, session: SessionDep):
return templates.TemplateResponse(request=request, name="add_event.html")
@app.post("/event/add")
async def add_event(request: Request, session: SessionDep):
form_data = await request.form()
event_time = datetime.fromisoformat(form_data["eventTime"])
registration_deadline = form_data.get("registrationDeadline")
if not registration_deadline:
# Find the last Sunday before event_time
deadline = event_time
while deadline.weekday() != 6: # 6 represents Sunday
deadline = deadline.replace(day=deadline.day - 1)
registration_deadline = deadline.replace(
hour=19, minute=30, second=0, microsecond=0
)
else:
registration_deadline = datetime.fromisoformat(registration_deadline)
event = Event(
title=form_data["eventName"],
event_time=event_time,
registration_deadline=registration_deadline,
description=form_data.get("eventDescription"),
recipe_link=form_data.get("recipeLink"),
)
session.add(event)
session.commit()
return RedirectResponse(url="/", status_code=status.HTTP_302_FOUND)
@app.get("/event/{event_id}") @app.get("/event/{event_id}")
async def read_event(request: Request, event_id: int, session: SessionDep): async def read_event(request: Request, event_id: int, session: SessionDep):
statement = select(Event).where(Event.id == event_id) statement = select(Event).where(Event.id == event_id)
@@ -56,6 +96,14 @@ async def read_event(request: Request, event_id: int, session: SessionDep):
statement = select(Household) statement = select(Household)
households = session.exec(statement).all() households = session.exec(statement).all()
# filter out households with existing registrations
households = [
h
for h in households
if h.id not in [reg.household_id for reg in event.registrations]
]
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, request=request,
name="event.html", name="event.html",

View File

@@ -0,0 +1,39 @@
{% extends "base.html" %}
{% block content %}
<div class="row justify-content-center mt-4">
<div class="col-md-8">
<h2>Neues Event erstellen</h2>
<form method="post" action="/event/add">
<div class="mb-3">
<label for="eventName" class="form-label">Event Name</label>
<input type="text" class="form-control" id="eventName" name="eventName" required>
</div>
<div class="mb-3">
<label for="eventTime" class="form-label">Datum und Uhrzeit</label>
<input type="datetime-local" class="form-control" id="eventTime" name="eventTime" required>
</div>
<div class="mb-3">
<label for="registrationDeadline" class="form-label">Anmeldungs-Deadline</label>
<input type="datetime-local" class="form-control" id="registrationDeadline" name="registrationDeadline">
<small class="form-text text-muted">Leer lassen für Sonntag Abend vor dem Event</small>
</div>
<div class="mb-3">
<label for="recipeLink" class="form-label">Rezept-Link</label>
<input type="text" class="form-control" id="recipeLink" name="recipeLink">
</div>
<div class="mb-3">
<label for="eventDescription" class="form-label">Beschreibung</label>
<textarea class="form-control" id="eventDescription" name="eventDescription" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Event erstellen</button>
<a href="/new-registration-app/static" class="btn btn-secondary">Abbrechen</a>
</form>
</div>
</div>
{% endblock %}

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Bootstrap demo</title> <title>Allmende Essen</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet" <link href="/static/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"> integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB">
<link href="/static/icons/bootstrap-icons.min.css" rel="stylesheet"> <link href="/static/icons/bootstrap-icons.min.css" rel="stylesheet">
@@ -11,7 +11,7 @@
<body class="p-3 m-0 border-0 bd-example m-0 border-0"> <body class="p-3 m-0 border-0 bd-example m-0 border-0">
<nav class="navbar navbar-expand-lg bg-body-tertiary"> <nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="#"> <a class="navbar-brand" href="/">
<img src="/static/img/Logo.png" alt="Logo" height="30" class="d-inline-block align-text-top"> <img src="/static/img/Logo.png" alt="Logo" height="30" class="d-inline-block align-text-top">
Allmende Essen Allmende Essen
</a> </a>
@@ -22,13 +22,13 @@
<div class="collapse navbar-collapse" id="navbarNav"> <div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a> <a class="nav-link {% if current_page == 'home' %}active{% endif %}" {% if current_page == 'home' %}aria-current="page"{% endif %} href="/">Home</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#">Vergangene</a> <a class="nav-link {% if current_page == 'vergangene' %}active{% endif %}" {% if current_page == 'vergangene' %}aria-current="page"{% endif %} href="/vergangene">Vergangene</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#">Preise</a> <a class="nav-link {% if current_page == 'preise' %}active{% endif %}" {% if current_page == 'preise' %}aria-current="page"{% endif %} href="/preise">Preise</a>
</li> </li>
</ul> </ul>
</div> </div>

View File

@@ -6,11 +6,18 @@
<p class="h3">Anmeldungen</p> <p class="h3">Anmeldungen</p>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-4 d-flex align-items-center"> <div class="col-md-4 d-flex justify-content-center align-items-center flex-column">
<!-- Button trigger modal --> <!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#staticBackdrop"> <button type="button" class="btn btn-primary mb-2" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
Anmeldung hinzufügen Anmeldung hinzufügen
</button> </button>
{% if event.recipe_link %}
<div class="mb-3">
<a href="{{ event.recipe_link }}" class="btn btn-outline-primary" target="_blank">
<i class="bi bi-book"></i> Original Rezept ansehen
</a>
</div>
{% endif %}
</div> </div>
<div class="col-md-8"> <div class="col-md-8">
<div class="card"> <div class="card">
@@ -71,9 +78,9 @@
<h1 class="modal-title fs-5" id="staticBackdropLabel">Anmeldung hinzufügen</h1> <h1 class="modal-title fs-5" id="staticBackdropLabel">Anmeldung hinzufügen</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<form action="/event/{{event.id}}/register" method="POST"> <form action="/event/{{event.id}}/register" method="POST">
<div class="modal-body"> <div class="modal-body">
<p>Wenn dein Haushalt nicht auswählbar ist, existiert schon eine Anmeldung. Wenn du die Anmeldung ändern willst, lösche die bestehende Anmeldung und lege eine neue an.</p>
<div class="mb-3"> <div class="mb-3">
<select name="household" class="form-select" aria-label="Multiple select example"> <select name="household" class="form-select" aria-label="Multiple select example">
<option selected>Wer?</option> <option selected>Wer?</option>

View File

@@ -1,13 +1,26 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<div class="row mt-4 mb-3">
<div class="col d-flex justify-content-between align-items-center">
<h2>Kommende Events</h2>
<a href="/event/add" class="btn btn-primary">
<i class="bi bi-plus-circle"></i> Neues Event erstellen
</a>
</div>
</div>
{% for event in events %} {% for event in events %}
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div class="card p-3 m-3"> <div class="card p-3 m-3">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">{{ event.title }}</h5> <div class="d-flex justify-content-between align-items-center">
<h5 class="card-title">{{ event.title }}</h5>
<h5 class="text-muted"><i class="bi bi-calendar"></i> {{ event.event_time.strftime('%A, %d.%m.%Y')
}}
</h5>
</div>
<p class="card-text">{{ event.description }}</p> <p class="card-text">{{ event.description }}</p>
<a href="event/{{ event.id }}" class="btn btn-primary">Zur Anmeldung</a> <a href="event/{{ event.id }}" class="btn {% if event.registration_deadline > now %}btn-primary{% else %}btn-secondary{% endif %}">{% if event.registration_deadline > now %}Zur Anmeldung{% else %}Details ansehen{% endif %}</a>
</div> </div>
</div> </div>
</div> </div>