Rename new-registration-app to meal-manager

This commit is contained in:
2025-10-12 21:25:23 +02:00
parent 773f8ad2b6
commit 03d823c713
66 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
{% 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>
</form>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,43 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Allmende Essen</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/icons/bootstrap-icons.min.css" rel="stylesheet">
<link href="/static/css/allmende.css" rel="stylesheet">
</head>
<body class="p-3 m-0 border-0 bd-example">
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img src="/static/img/Logo.png" alt="Logo" height="30" class="d-inline-block align-text-top">
Allmende Essen
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link {% if current_page == 'home' %}active{% endif %}" {% if current_page == 'home' %}aria-current="page"{% endif %} href="/">Kommende</a>
</li>
<li class="nav-item">
<a class="nav-link {% if current_page == 'past' %}active{% endif %}" {% if current_page == 'past' %}aria-current="page"{% endif %} href="/past_events">Vergangene</a>
</li>
<!-- <li class="nav-item">-->
<!-- <a class="nav-link {% if current_page == 'preise' %}active{% endif %}" {% if current_page == 'preise' %}aria-current="page"{% endif %} href="/preise">Preise</a>-->
<!-- </li>-->
</ul>
</div>
</div>
</nav>
<div class="container">
{% block content %}{% endblock %}
</div>
<script src="/static/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,257 @@
{% macro teamEntries(event, work_type) -%}
{% for entry in event.team | selectattr("work_type", "equalto", work_type)%}
<div class="d-inline-flex align-items-center bg-light border rounded-pill px-3 py-1 m-1">
<span class="me-2">{{ entry.person_name }}</span>
<button type="button" class="btn btn-sm p-0 border-0 bg-transparent text-muted">
<a href="/event/{{event.id}}/register_team/{{entry.id}}/delete">
<i class="bi bi-trash"></i>
</a>
</button>
</div>
{% endfor %}
{%- endmacro %}
{% extends "base.html" %}
{% block content %}
<p class="h1">{{ event.title }}</p>
<p class="text-muted">{{ event.event_time.strftime('%A, %d.%m.%Y') }}</p>
<p>{{ event.description }}</p>
<hr class="hr"/>
<div class="container">
<p class="h3">Anmeldungen</p>
<div class="row m-2">
<div class="col-md-4 d-flex justify-content-center align-items-center flex-column">
<p class="text-muted w-100 mb-2">Anmeldung schließt {{ event.registration_deadline.strftime('%A, %d.%m.%Y, %H:%M Uhr') }}</p>
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary mb-2 w-100" {% if event.registration_deadline < now %}disabled{% endif%} data-bs-toggle="modal" data-bs-target="#registration">
Anmeldung hinzufügen
</button>
<button type="button" class="btn btn-primary mb-2 w-100" {% if event.all_teams_max() or event.event_time < now %}disabled{% endif %} data-bs-toggle="modal" data-bs-target="#teamRegistration">
Dienst übernehmen
</button>
{% if event.recipe_link %}
<a href="{{ event.recipe_link }}" class="btn btn-outline-primary mb-2 w-100" target="_blank">
<i class="bi bi-book"></i> Original Rezept ansehen
</a>
{% endif %}
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Dienste</h5>
<div class="row">
<div class="col-md-4">
Kochen: {% if event.team_min_reached("cooking") %}✅{% endif %}
</div>
<div class="col-md-8">
{{ teamEntries(event, "cooking") }}
</div>
</div>
<hr/>
<div class="row">
<div class="col-md-4">
Spülen: {% if event.team_min_reached("dishes") %}✅{% endif %}
</div>
<div class="col-md-8">
{{ teamEntries(event, "dishes") }}
</div>
</div>
<hr/>
<div class="row">
<div class="col-md-4">
Tische vorbereiten: {% if event.team_min_reached("tables") %}✅{% endif %}
</div>
<div class="col-md-8">
{{ teamEntries(event, "tables") }}
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Zusammenfassung</h5>
<table class="table table-sm">
<tr>
<td>Erwachsene:</td>
<td>{{ event.registrations | sum(attribute="num_adult_meals") }}</td>
</tr>
<tr>
<td>Kinder:</td>
<td>{{ event.registrations | sum(attribute="num_children_meals") }}</td>
</tr>
<tr>
<td>Kleinkinder:</td>
<td>{{ event.registrations | sum(attribute="num_small_children_meals") }}</td>
</tr>
<tr>
<th>Gesamt:</th>
<th>{{ event.registrations | sum(attribute="num_adult_meals") + event.registrations | sum(attribute="num_children_meals") +event.registrations | sum(attribute="num_small_children_meals")}} </th>
</tr>
</table>
</div>
</div>
</div>
</div>
<!-- Desktop table view -->
<div class="d-none d-md-block">
<table class="table">
<thead>
<tr>
<th scope="col">Haushalt</th>
<th scope="col">Erwachsene</th>
<th scope="col">Kinder</th>
<th scope="col">Kleinkinder</th>
<th scope="col">Kommentar</th>
<th scope="col">Löschen</th>
</tr>
</thead>
<tbody>
{% for reg in event.registrations %}
<tr>
<td>{{ reg.household.name }}</td>
<td>{{ reg.num_adult_meals }}</td>
<td>{{ reg.num_children_meals }}</td>
<td>{{ reg.num_small_children_meals }}</td>
<td>{{ reg.comment }}</td>
<td><a href="/event/{{event.id}}/registration/{{reg.household_id}}/delete"><i class="bi bi-trash"></i></a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Mobile card view -->
<div class="d-md-none">
{% for reg in event.registrations %}
<div class="card mb-3">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-2">
<h5 class="card-title mb-0">{{ reg.household.name }}</h5>
<a href="/event/{{event.id}}/registration/{{reg.household_id}}/delete" class="text-danger">
<i class="bi bi-trash"></i>
</a>
</div>
<div class="row mt-3">
<div class="col-3 text-center">
<div class="text-muted small">Erwachsene</div>
<div class="fw-bold">{{ reg.num_adult_meals }}</div>
</div>
<div class="col-3 text-center">
<div class="text-muted small">Kinder</div>
<div class="fw-bold">{{ reg.num_children_meals }}</div>
</div>
<div class="col-3 text-center">
<div class="text-muted small">Kleinkinder</div>
<div class="fw-bold">{{ reg.num_small_children_meals }}</div>
</div>
<div class="col-3 text-center">
<div class="text-muted small">Kommentar</div>
<div class="small">{{ reg.comment }}</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="registration" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<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>
</div>
<form action="/event/{{event.id}}/register" method="POST">
<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">
<select name="household" class="form-select" aria-label="Multiple select example" required>
<option value="" disabled selected hidden>Wer?</option>
{% for household in households %}
<option value="{{household.id}}">{{household.name}}</option>
{% endfor %}
</select>
</div>
<div class="row">
<div class="col">
<label for="InputAdults" class="form-label">Anzahl Erwachsene</label>
<input name="numAdults" id="InputAdults" type="number" class="form-control"
aria-label="Anzahl Erwachsene" min="0" step="1" inputmode="numeric">
</div>
<div class="col">
<label for="InputKids" class="form-label">Anzahl Kinder >7 </label>
<input name="numKids" id="InputKids" type="number" class="form-control"
aria-label="Anzahl Kinder >7" min="0" step="1" inputmode="numeric">
</div>
<div class="col">
<label for="InputSmallKids" class="form-label">Anzahl Kinder <7 </label>
<input name="numSmallKids" id="InputSmallKids" type="number" class="form-control"
aria-label="Anzahl Kinder <7" min="0" step="1" inputmode="numeric">
</div>
<div class="mb-3 mt-3">
<label for="InputComment" class="form-label">Kommentar</label>
<input name="comment" id="InputComment" class="form-control"
aria-label="Kommentar">
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Anmelden</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
</div>
</form>
</div>
</div>
</div>
<!-- Team Modal -->
<div class="modal fade" id="teamRegistration" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
aria-labelledby="teamRegistrationLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="teamRegistrationLabel">Dienst übernehmen</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="/event/{{event.id}}/register_team" method="POST">
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<label for="personName" class="form-label">Name</label>
<input name="personName" id="personName" type="text" class="form-control"
aria-label="Name" list="people">
</div>
<datalist id="people">
{% for household in households %}
{% for person in household.name.split(",") %}
<option value="{{ person.strip() }}">
{% endfor %}
{% endfor %}
</datalist>
<div class="col-md-6">
<label for="workType" class="form-label">Dienst-Art</label>
<select id="workType" name="workType" class="form-select" aria-label="Multiple select example">
{% if not event.team_max_reached("cooking") %}<option value="cooking">Kochen</option>{% endif %}
{% if not event.team_max_reached("dishes") %}<option value="dishes">Spülen</option>{% endif %}
{% if not event.team_max_reached("tables") %}<option value="tables">Tische vorbereiten</option>{% endif %}
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Anmelden</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,43 @@
{% extends "base.html" %}
{% block content %}
<div class="row mt-4 mb-3">
<div class="col d-flex justify-content-between align-items-center">
<h2>{% if current_page == "home" %}Kommende{% else %}Vergangene{% endif %} Kochabende</h2>
<a href="/event/add" class="btn btn-primary">
<i class="bi bi-plus-circle"></i> Neues Event erstellen
</a>
</div>
</div>
<div class="mb-4">
<div class="card bg-success-subtle text-success-emphasis border-0 shadow-sm text-center">
<div class="card-body py-4">
<i class="bi bi-calendar-heart fs-3 mb-2"></i>
<h5 class="card-title mb-2">Nie wieder die Anmeldung vergessen</h5>
<p class="card-text small mb-3">
Die Dauerhafte Anmeldung gilt für alle kommenden Kochabende.
</p>
<a href="/subscribe" class="btn btn-light btn-sm fw-semibold px-3">
Jetzt dauerhaft Anmelden
</a>
</div>
</div>
</div>
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
{% for event in events %}
<div class="col">
<div class="card h-100 shadow-sm">
<div class="card-body">
<h5 class="card-title mb-1">{{ event.title }}</h5>
<p class="text-muted mb-3"><i class="bi bi-calendar"></i> {{ event.event_time.strftime('%A, %d.%m.%Y')
}}
</p>
<p class="card-text">{{ event.description }}</p>
<a href="event/{{ event.id }}" class="btn btn-sm {% 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>
{% endfor %}
</div>
{% endblock %}

View File

@@ -0,0 +1,140 @@
{% extends "base.html" %}
{% block content %}
<div class="row mt-4">
<!-- Left column: subscription form -->
<div class="col-12 col-lg-6">
<div class="row justify-content-center">
<div class="col">
<div class="card shadow-sm mt-4">
<div class="card-header bg-primary text-white">
<h1 class="fs-5 mb-0">Dauerhafte Anmeldung zu allen Kochabenden</h1>
</div>
<form action="/subscribe" method="POST">
<div class="card-body">
<p>
Mit einer dauerhaften Anmeldung kannst du dich/euch für alle zukünftigen Kochabende
anmelden. Es ist möglich
diese Anmeldung auf bestimmte Wochentage zu beschränken.
</p>
<p>
Dauerhafte Anmeldungen werden eine Woche vor einem Kochabend als Anmeldungen für diesen
Abend eingetragen. Danach
können sie auch noch gelöscht bzw. bearbeitet werden.
</p>
<!-- Info box about 7-day limitation -->
<div class="alert alert-info" role="alert">
<i class="bi bi-info-circle"></i>
<strong>Hinweis:</strong> Neu angelegte dauerhafte Anmeldungen werden erst nach einer Woche aktiv. Für Kochabende, die in weniger als 7 Tagen stattfinden, musst du dich noch separat anmelden.
</div>
<!-- Household selection -->
<div class="mb-3">
<select name="household" class="form-select" required>
<option value="" disabled selected hidden>Wer?</option>
{% for household in households %}
<option value="{{household.id}}">{{household.name}}</option>
{% endfor %}
</select>
</div>
<p class="text-muted">
Wenn dein Haushalt hier nicht auswählbar ist, besteht bereits eine dauerhafte Anmeldung.
Um Änderungen vorzunehmen, lösche die bestehende Anmeldung und lege eine neue an.
</p>
<!-- Person counts -->
<div class="row g-3 mb-3">
<div class="col">
<label for="InputAdults" class="form-label">Anzahl Erwachsene</label>
<input name="numAdults" id="InputAdults" type="number" class="form-control"
aria-label="Anzahl Erwachsene" min="0" step="1" inputmode="numeric">
</div>
<div class="col">
<label for="InputKids" class="form-label">Anzahl Kinder &gt;7</label>
<input name="numKids" id="InputKids" type="number" class="form-control"
aria-label="Anzahl Kinder &gt;7" min="0" step="1" inputmode="numeric">
</div>
<div class="col">
<label for="InputSmallKids" class="form-label">Anzahl Kinder &lt;7</label>
<input name="numSmallKids" id="InputSmallKids" type="number" class="form-control"
aria-label="Anzahl Kinder &lt;7" min="0" step="1" inputmode="numeric">
</div>
</div>
<!-- Days of the week -->
<div class="mb-3">
<label class="form-label">Wochentage auswählen (optional)</label>
<p class="text-muted small mb-2">
Wenn du nur an bestimmten Tagen teilnehmen möchtest, wähle sie hier aus.
</p>
<div class="d-flex flex-wrap gap-3">
{% set days = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag",
"Sonntag"] %}
{% for day in days %}
<div class="form-check">
<input class="form-check-input" type="checkbox" name="days" value="{{loop.index}}"
id="day-{{loop.index}}">
<label class="form-check-label" for="day-{{loop.index}}">
{{day}}
</label>
</div>
{% endfor %}
</div>
</div>
</div>
<!-- Footer -->
<div class="card-footer d-flex justify-content-end gap-2">
<button type="submit" class="btn btn-primary">Dauerhaft anmelden</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Right column: existing registrations -->
<div class="col-12 col-lg-6 mt-4 mt-lg-0">
<p class="h4 m-2">Bestehende dauerhafte Anmeldungen</p>
{% if subscriptions | length == 0 %}
<p class="m-2">Es gibt noch keine dauerhaften Anmeldungen</p>
{% else %}
{% for sub in subscriptions %}
<div class="card mb-2">
<div class="card-body py-2 px-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<h6 class="mb-0">{{ sub.household.name }}</h6>
<a href="/subscribe/{{sub.household.id}}/delete" class="text-danger">
<i class="bi bi-trash"></i>
</a>
</div>
<div class="row g-2">
<div class="col-3 text-center">
<div class="text-muted" style="font-size: 0.7rem;">Erwachsene</div>
<div class="fw-bold small">{{ sub.num_adult_meals }}</div>
</div>
<div class="col-3 text-center">
<div class="text-muted" style="font-size: 0.7rem;">Kinder</div>
<div class="fw-bold small">{{ sub.num_children_meals }}</div>
</div>
<div class="col-3 text-center">
<div class="text-muted" style="font-size: 0.7rem;">Kleinkinder</div>
<div class="fw-bold small">{{ sub.num_small_children_meals }}</div>
</div>
<div class="col-3 text-center">
<div class="text-muted" style="font-size: 0.7rem;">Tage</div>
<div class="fw-bold small">{{ sub.day_string_de() }}</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endif %}
</div>
</div>
{% endblock %}