Merge pull request 'inform people of participation; require updating personal data before joining' (#774) from update-ergo into main
Reviewed-on: #774
This commit is contained in:
commit
d0b0888a9b
@ -690,18 +690,8 @@ WHERE family_id IS NULL;
|
||||
}
|
||||
|
||||
pub async fn ergo(db: &SqlitePool) -> Vec<Self> {
|
||||
sqlx::query_as!(
|
||||
Self,
|
||||
"
|
||||
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, user_token
|
||||
FROM user
|
||||
WHERE deleted = 0 AND dob != '' and weight != '' and sex != ''
|
||||
ORDER BY name
|
||||
"
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.unwrap()
|
||||
let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
||||
Self::all_with_role(db, &ergo).await
|
||||
}
|
||||
|
||||
pub async fn cox(db: &SqlitePool) -> Vec<Self> {
|
||||
@ -735,6 +725,19 @@ ORDER BY last_access DESC
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
pub async fn update_ergo(&self, db: &SqlitePool, dob: i32, weight: i64, sex: &str) {
|
||||
sqlx::query!(
|
||||
"UPDATE user SET dob = ?, weight = ?, sex = ? where id = ?",
|
||||
dob,
|
||||
weight,
|
||||
sex,
|
||||
self.id
|
||||
)
|
||||
.execute(db)
|
||||
.await
|
||||
.unwrap(); //Okay, because we can only create a User of a valid id
|
||||
}
|
||||
|
||||
pub async fn update(&self, db: &SqlitePool, data: UserEditForm<'_>) -> Result<(), String> {
|
||||
let mut db = db.begin().await.map_err(|e| e.to_string())?;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::env;
|
||||
|
||||
use chrono::Utc;
|
||||
use chrono::{Datelike, Utc};
|
||||
use rocket::{
|
||||
form::Form,
|
||||
fs::TempFile,
|
||||
@ -17,8 +17,7 @@ use sqlx::SqlitePool;
|
||||
use tera::Context;
|
||||
|
||||
use crate::model::{
|
||||
log::Log,
|
||||
user::{AdminUser, User, UserWithDetails},
|
||||
log::Log, notification::Notification, role::Role, user::{AdminUser, User, UserWithDetails}
|
||||
};
|
||||
|
||||
#[derive(Serialize)]
|
||||
@ -50,7 +49,7 @@ async fn send(db: &State<SqlitePool>, _user: AdminUser) -> Template {
|
||||
.unwrap();
|
||||
|
||||
Template::render(
|
||||
"ergo.final",
|
||||
"ergo/final",
|
||||
context!(loggedin_user: &UserWithDetails::from_user(_user.user, db).await, thirty, dozen),
|
||||
)
|
||||
}
|
||||
@ -98,6 +97,19 @@ async fn update(
|
||||
|
||||
#[get("/")]
|
||||
async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_>>) -> Template {
|
||||
let mut context = Context::new();
|
||||
if let Some(msg) = flash {
|
||||
context.insert("flash", &msg.into_inner());
|
||||
}
|
||||
context.insert("loggedin_user", &UserWithDetails::from_user(user.clone(), db).await);
|
||||
|
||||
if !user.has_role(db, "ergo").await {
|
||||
return Template::render(
|
||||
"ergo/missing-data",
|
||||
context.into_json()
|
||||
);
|
||||
}
|
||||
|
||||
let users = User::ergo(db).await;
|
||||
|
||||
let thirty = sqlx::query_as!(
|
||||
@ -116,16 +128,56 @@ async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mut context = Context::new();
|
||||
if let Some(msg) = flash {
|
||||
context.insert("flash", &msg.into_inner());
|
||||
}
|
||||
context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await);
|
||||
context.insert("users", &users);
|
||||
context.insert("thirty", &thirty);
|
||||
context.insert("dozen", &dozen);
|
||||
|
||||
Template::render("ergo", context.into_json())
|
||||
Template::render("ergo/index", context.into_json())
|
||||
}
|
||||
|
||||
#[derive(FromForm, Debug)]
|
||||
pub struct UserAdd {
|
||||
birthyear: i32,
|
||||
weight: i64,
|
||||
sex: String,
|
||||
}
|
||||
|
||||
#[post("/set-data", data = "<data>")]
|
||||
async fn new_user(
|
||||
db: &State<SqlitePool>,
|
||||
data: Form<UserAdd>,
|
||||
user: User,
|
||||
) -> Flash<Redirect> {
|
||||
if user.has_role(db, "ergo").await {
|
||||
return
|
||||
Flash::error(Redirect::to("/ergo"), "Du hast deine Daten schon eingegeben. Wenn du sie updaten willst, melde dich bitte bei it@rudernlinz.at");
|
||||
}
|
||||
|
||||
// check data
|
||||
if data.birthyear <1900 || data.birthyear > chrono::Utc::now().year() - 5 {
|
||||
return
|
||||
Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geburtsjahr...");
|
||||
}
|
||||
if data.weight < 20 || data.weight > 200 {
|
||||
return
|
||||
Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Gewicht...");
|
||||
}
|
||||
if &data.sex != "f" && &data.sex != "m"{
|
||||
return
|
||||
Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geschlecht...");
|
||||
}
|
||||
|
||||
// set data
|
||||
user.update_ergo(db, data.birthyear, data.weight, &data.sex).await;
|
||||
|
||||
// inform all other `ergo` users
|
||||
let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
||||
Notification::create_for_role(db, &ergo, &format!("{} nimmt heuer an der Ergochallenge teil 💪", user.name), "Ergo Challenge", None, None).await;
|
||||
|
||||
// add to `ergo` group
|
||||
user.add_role(db,&ergo).await.unwrap();
|
||||
|
||||
Flash::success(Redirect::to("/ergo"), "Du hast deine Daten erfolgreich eingegeben. Viel Spaß beim Schwitzen :-)")
|
||||
}
|
||||
|
||||
#[derive(FromForm, Debug)]
|
||||
@ -173,6 +225,9 @@ async fn new_thirty(
|
||||
)
|
||||
.await;
|
||||
|
||||
let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
||||
Notification::create_for_role(db, &ergo, &format!("{} ist gerade die Dirty Thirty Challenge gefahren 🥵", user.name), "Ergo Challenge", Some("/ergo"), None).await;
|
||||
|
||||
Flash::success(Redirect::to("/ergo"), "Erfolgreich eingetragen")
|
||||
}
|
||||
|
||||
@ -214,11 +269,14 @@ async fn new_dozen(
|
||||
)
|
||||
.await;
|
||||
|
||||
let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
||||
Notification::create_for_role(db, &ergo, &format!("{} ist gerade die Dirty Dozen Challenge gefahren 🥵", user.name), "Ergo Challenge", Some("/ergo"), None).await;
|
||||
|
||||
Flash::success(Redirect::to("/ergo"), "Erfolgreich eingetragen")
|
||||
}
|
||||
|
||||
pub fn routes() -> Vec<Route> {
|
||||
routes![index, new_thirty, new_dozen, send, reset, update]
|
||||
routes![index, new_thirty, new_dozen, send, reset, update, new_user]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::{fs::OpenOptions, io::Write};
|
||||
|
||||
use chrono::Local;
|
||||
use chrono::{Datelike, Local};
|
||||
use rocket::{
|
||||
catch, catchers,
|
||||
fairing::{AdHoc, Fairing, Info, Kind},
|
||||
@ -63,6 +63,11 @@ async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_
|
||||
context.insert("last_trips", &last_trips);
|
||||
}
|
||||
|
||||
let date = chrono::Utc::now();
|
||||
if date.month() <= 3 || date.month() >= 10 {
|
||||
context.insert("show_quick_ergo_button", "yes");
|
||||
}
|
||||
|
||||
context.insert("achievements", &Achievements::for_user(db, &user).await);
|
||||
context.insert("notifications", &Notification::for_user(db, &user).await);
|
||||
context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await);
|
||||
|
@ -1,205 +0,0 @@
|
||||
{% import "includes/macros" as macros %}
|
||||
{% extends "base" %}
|
||||
{% block content %}
|
||||
<div class="max-w-screen-lg w-full">
|
||||
<h1 class="h1">Ergo Challenges</h1>
|
||||
<div class="grid gap-3">
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||
role="alert">
|
||||
<h2 class="h2">Ergo-Challenge?!</h2>
|
||||
<div class="text-sm p-3">
|
||||
<ul class="list-disc ms-2">
|
||||
<li class="py-1">
|
||||
<a href="https://rudernlinz.at/termin"
|
||||
target="_blank"
|
||||
class="link-primary">Überblick der Challenges</a>
|
||||
</li>
|
||||
<li class="py-1">
|
||||
Eintragung ist jederzeit möglich, alle Daten die bis Sonntag 23:59 hier hochgeladen wurden, werden gesammelt an die Ister Ergo Challenge geschickt
|
||||
<li class="py-1">
|
||||
Dienstag + Donnerstag → gemeinsames Training; bitte um <a href="/" class="link-primary">Anmeldung</a>, damit jeder einen Ergo hat
|
||||
</li>
|
||||
<li class="py-1">
|
||||
Offizielle Ergebnisse: <a href="https://rudernlinz.at/dt"
|
||||
target="_blank"
|
||||
style="text-decoration: underline">Dirty Thirty (rudernlinz.at/dt)</a> / <a href="https://rudernlinz.at/dd"
|
||||
target="_blank"
|
||||
style="text-decoration: underline">Dirty Dozen (rudernlinz.at/dd)</a>, bei Fehlern direkt mit <a href="mailto:office@ergochallenge.at"
|
||||
style="text-decoration: underline">Christian (Ister)</a> Kontakt aufnehmen
|
||||
</li>
|
||||
<li class="py-1">
|
||||
<a href="https://cloud.rudernlinz.at/s/m7mPQdwSWscpaXT"
|
||||
target="_blank"
|
||||
class="link-primary">Noch mehr Infos zur Ergo-Challenge findest du hier</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<details class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md p-2">
|
||||
<summary class="cursor-pointer">Deine Daten</summary>
|
||||
<div class="pt-3">
|
||||
<p>
|
||||
Folgende Daten hat der Ruderassistent von dir. Wenn diese nicht mehr aktuell sind, bitte gewünschte Änderungen an Philipp melden (Tel. nr siehe Signal, oder an <a href="mailto:it@rudernlinz.at"
|
||||
class="text-primary-600 dark:text-primary-200 hover:text-primary-950 hover:dark:text-primary-300 underline"
|
||||
target="_blank">it@rudernlinz.at</a>).
|
||||
<br />
|
||||
<br />
|
||||
<ul>
|
||||
<li>Geburtsdatum: {{ loggedin_user.dob }}</li>
|
||||
<li>Gewicht: {{ loggedin_user.weight }} kg</li>
|
||||
<li>Geschlecht: {{ loggedin_user.sex }}</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
||||
<h2 class="h2">
|
||||
Neuer Eintrag
|
||||
</h1>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">Dirty Thirty</summary>
|
||||
<div class="mt-3">
|
||||
<form action="/ergo/thirty"
|
||||
class="grid gap-3"
|
||||
method="post"
|
||||
enctype="multipart/form-data">
|
||||
<div>
|
||||
<label for="user-thirty" class="text-sm text-gray-600 dark:text-gray-100">Ergo-Fahrer</label>
|
||||
<select name="user" id="user-thirty" class="input rounded-md">
|
||||
<option disabled="disabled">User auswählen</option>
|
||||
{% for user in users %}
|
||||
{% if user.id == loggedin_user.id %}
|
||||
<option value="{{ user.id }}" selected="selected">{{ user.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ user.id }}">{{ user.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{{ macros::input(label="Distanz [m]", name="result", required=true, type="number", class="input rounded-md") }}
|
||||
<div>
|
||||
<label for="file-thirty" class="text-sm text-gray-600 dark:text-gray-100">Ergebnis-Foto vom Ergo-Display</label>
|
||||
<input type="file"
|
||||
id="file-thirty"
|
||||
name="proof"
|
||||
class="input rounded-md"
|
||||
accept="image/*">
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<input type="submit" value="Speichern" class="btn btn-primary btn-fw m-auto" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">Dirty Dozen</summary>
|
||||
<div class="mt-3">
|
||||
<form action="/ergo/dozen"
|
||||
class="grid gap-3"
|
||||
method="post"
|
||||
enctype="multipart/form-data">
|
||||
<div>
|
||||
<label for="user-dozen" class="text-sm text-gray-600 dark:text-gray-100">Ergo-Fahrer</label>
|
||||
<select name="user" id="user-dozen" class="input rounded-md">
|
||||
<option disabled="disabled">User auswählen</option>
|
||||
{% for user in users %}
|
||||
{% if user.id == loggedin_user.id %}
|
||||
<option value="{{ user.id }}" selected="selected">{{ user.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ user.id }}">{{ user.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{{ macros::input(label="Zeit [hh:mm:ss.s] oder Distanz [m]", name="result", required=true, type="text", class="input rounded-md", pattern="(?:\d+:\d{2}:\d{2}\.\d+|\d{1,2}:\d{2}\.\d+|\d+(\.\d+)?)") }}
|
||||
<div>
|
||||
<label for="file-dozen" class="text-sm text-gray-600 dark:text-gray-100">Ergebnis-Foto vom Ergo-Display</label>
|
||||
<input type="file"
|
||||
id="file-dozen"
|
||||
name="proof"
|
||||
class="input rounded-md"
|
||||
accept="image/*">
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<input type="submit" value="Speichern" class="btn btn-primary btn-fw m-auto" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
||||
<h2 class="h2">Aktuelle Woche</h2>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">
|
||||
Dirty Thirty <small class="text-gray-600 dark:text-white">({{ thirty | length }})</small>
|
||||
</summary>
|
||||
<div class="mt-3">
|
||||
<ol>
|
||||
{% for stat in thirty %}
|
||||
<li>
|
||||
<strong>{{ stat.name }}:</strong> {{ stat.result }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">
|
||||
Dirty Dozen <small class="text-gray-600 dark:text-white">({{ dozen | length }})</small>
|
||||
</summary>
|
||||
<div class="mt-3">
|
||||
<ol>
|
||||
{% for stat in dozen %}
|
||||
<li>
|
||||
<strong>{{ stat.name }}:</strong> {{ stat.result }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
{% if "admin" in loggedin_user.roles %}
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
||||
<h2 class="h2">Update</h2>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">
|
||||
Dirty Thirty <small class="text-gray-600 dark:text-white">({{ thirty | length }})</small>
|
||||
</summary>
|
||||
<div class="mt-3">
|
||||
<ol>
|
||||
{% for stat in thirty %}
|
||||
<li>
|
||||
<form action="/ergo/thirty/user/{{ stat.id }}/new" method="get">
|
||||
{{ stat.name }}:
|
||||
<input type="text" value="{{ stat.result }}" name="new" style="color: black" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">
|
||||
Dirty Dozen <small class="text-gray-600 dark:text-white">({{ dozen | length }})</small>
|
||||
</summary>
|
||||
<div class="mt-3">
|
||||
<ol>
|
||||
{% for stat in dozen %}
|
||||
<li>
|
||||
<form action="/ergo/dozen/user/{{ stat.id }}/new" method="get">
|
||||
{{ stat.name }}:
|
||||
<input type="text" value="{{ stat.result }}" name="new" style="color: black" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
230
templates/ergo/index.html.tera
Normal file
230
templates/ergo/index.html.tera
Normal file
@ -0,0 +1,230 @@
|
||||
{% import "includes/macros" as macros %}
|
||||
{% extends "base" %}
|
||||
{% block content %}
|
||||
<div class="max-w-screen-lg w-full">
|
||||
<h1 class="h1">Ergo Challenges</h1>
|
||||
<div class="grid gap-3">
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||
role="alert">
|
||||
<h2 class="h2">Ergo Challenge?!</h2>
|
||||
<div class="p-3">
|
||||
<ul class="list-disc ms-2">
|
||||
<li class="py-1">
|
||||
<a href="https://rudernlinz.at/termin"
|
||||
target="_blank"
|
||||
class="link-primary">Überblick der Challenges</a>
|
||||
</li>
|
||||
<li class="py-1">
|
||||
Eintragung ist jederzeit möglich, alle Daten die bis Sonntag 23:59 hier hochgeladen wurden, werden gesammelt an die Ister Ergo Challenge geschickt
|
||||
<li class="py-1">
|
||||
Montag → gemeinsames Training; bitte um <a href="/planned" class="link-primary">Anmeldung</a>, damit jeder einen Ergo hat
|
||||
</li>
|
||||
<li class="py-1">
|
||||
Offizielle Ergebnisse: <a href="https://rudernlinz.at/dt"
|
||||
target="_blank"
|
||||
style="text-decoration: underline">Dirty Thirty (rudernlinz.at/dt)</a> / <a href="https://rudernlinz.at/dd"
|
||||
target="_blank"
|
||||
style="text-decoration: underline">Dirty Dozen (rudernlinz.at/dd)</a>, bei Fehlern direkt mit <a href="mailto:office@ergochallenge.at"
|
||||
style="text-decoration: underline">Christian (Ister)</a> Kontakt aufnehmen
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<details class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md p-2">
|
||||
<summary class="cursor-pointer"><strong>Um was geht es bei den Ergochallenges?</strong></summary>
|
||||
<p class="py-2 ">
|
||||
Der Linzer Verein Ister veranstaltet seit einigen Jahren zwei Challenges im Winter, ‘Dirty Thirty’ (6x im Winter) und ‘Dirty Dozen’ (12 Wochen lang).
|
||||
<ul class="list-decimal ms-4">
|
||||
<li class="py-1">Bei <strong>Dirty Thirty</strong> geht es darum so viele Kilometer wie möglich in 30 Minuten zu fahren.</li>
|
||||
<li class="py-1">
|
||||
Bei <strong>Dirty Dozen</strong> werden jede Woche neue Ziele ausgeschrieben, gestartet wird mit einem Halbmarathon und es geht runter bis auf 100m.
|
||||
</li>
|
||||
</ul>
|
||||
<p class="py-2">Ihr könnt gerne bei allen Challenges mitmachen und es ist möglich jederzeit ein- bzw. auszusteigen. Für alle komplett neuen Teilnehmer würde ich allerdings empfehlen die ersten beiden Dirty Dozen Challenges (Halbmarathon und 16 Kilometer) auszulassen und es am Anfang etwas ruhiger anzugehen. Es steht der Spaß und die Festigung der Technik im Vordergrund, nicht Rekorde.</p>
|
||||
<strong>Video Tipps 🐞</strong>
|
||||
<ul class="list-disc ms-3">
|
||||
<li class="py-1">
|
||||
<a href="https://www.youtube.com/watch?v=TJsQPV6LNPI"
|
||||
target="_blank"
|
||||
style="text-decoration: underline">Intro</a>
|
||||
</li>
|
||||
<li class="py-1">
|
||||
<a href="https://www.youtube.com/watch?v=KOacKLOpWkI"
|
||||
target="_blank"
|
||||
style="text-decoration: underline">Schlagaufbau</a>
|
||||
</li>
|
||||
<li class="py-1">
|
||||
<a href="https://www.youtube.com/watch?v=m6VP11EDjcM"
|
||||
target="_blank"
|
||||
style="text-decoration: underline">PM5 Monitor</a>
|
||||
</li>
|
||||
</ul>
|
||||
</details>
|
||||
<details class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md p-2">
|
||||
<summary class="cursor-pointer"><strong>Deine Daten</strong></summary>
|
||||
<div class="pt-3">
|
||||
<p>
|
||||
Folgende Daten hat der Ruderassistent von dir. Wenn diese nicht mehr aktuell sind, bitte gewünschte Änderungen an Philipp melden (Tel. nr siehe Signal, oder an <a href="mailto:it@rudernlinz.at"
|
||||
class="text-primary-600 dark:text-primary-200 hover:text-primary-950 hover:dark:text-primary-300 underline"
|
||||
target="_blank">it@rudernlinz.at</a>).
|
||||
<br />
|
||||
<br />
|
||||
<ul>
|
||||
<li>Geburtsdatum: {{ loggedin_user.dob }}</li>
|
||||
<li>Gewicht: {{ loggedin_user.weight }} kg</li>
|
||||
<li>Geschlecht: {{ loggedin_user.sex }}</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
||||
<h2 class="h2">
|
||||
Neuer Eintrag
|
||||
</h1>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">Dirty Thirty</summary>
|
||||
<div class="mt-3">
|
||||
<form action="/ergo/thirty"
|
||||
class="grid gap-3"
|
||||
method="post"
|
||||
enctype="multipart/form-data">
|
||||
<div>
|
||||
<label for="user-thirty" class="text-sm text-gray-600 dark:text-gray-100">Ergo-Fahrer</label>
|
||||
<select name="user" id="user-thirty" class="input rounded-md">
|
||||
<option disabled="disabled">User auswählen</option>
|
||||
{% for user in users %}
|
||||
{% if user.id == loggedin_user.id %}
|
||||
<option value="{{ user.id }}" selected="selected">{{ user.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ user.id }}">{{ user.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{{ macros::input(label="Distanz [m]", name="result", required=true, type="number", class="input rounded-md") }}
|
||||
<div>
|
||||
<label for="file-thirty" class="text-sm text-gray-600 dark:text-gray-100">Ergebnis-Foto vom Ergo-Display</label>
|
||||
<input type="file"
|
||||
id="file-thirty"
|
||||
name="proof"
|
||||
class="input rounded-md"
|
||||
accept="image/*">
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<input type="submit" value="Speichern" class="btn btn-primary btn-fw m-auto" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">Dirty Dozen</summary>
|
||||
<div class="mt-3">
|
||||
<form action="/ergo/dozen"
|
||||
class="grid gap-3"
|
||||
method="post"
|
||||
enctype="multipart/form-data">
|
||||
<div>
|
||||
<label for="user-dozen" class="text-sm text-gray-600 dark:text-gray-100">Ergo-Fahrer</label>
|
||||
<select name="user" id="user-dozen" class="input rounded-md">
|
||||
<option disabled="disabled">User auswählen</option>
|
||||
{% for user in users %}
|
||||
{% if user.id == loggedin_user.id %}
|
||||
<option value="{{ user.id }}" selected="selected">{{ user.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ user.id }}">{{ user.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{{ macros::input(label="Zeit [hh:mm:ss.s] oder Distanz [m]", name="result", required=true, type="text", class="input rounded-md", pattern="(?:\d+:\d{2}:\d{2}\.\d+|\d{1,2}:\d{2}\.\d+|\d+(\.\d+)?)") }}
|
||||
<div>
|
||||
<label for="file-dozen" class="text-sm text-gray-600 dark:text-gray-100">Ergebnis-Foto vom Ergo-Display</label>
|
||||
<input type="file"
|
||||
id="file-dozen"
|
||||
name="proof"
|
||||
class="input rounded-md"
|
||||
accept="image/*">
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<input type="submit" value="Speichern" class="btn btn-primary btn-fw m-auto" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
||||
<h2 class="h2">Aktuelle Woche</h2>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">
|
||||
Dirty Thirty <small class="text-gray-600 dark:text-white">({{ thirty | length }})</small>
|
||||
</summary>
|
||||
<div class="mt-3">
|
||||
<ol>
|
||||
{% for stat in thirty %}
|
||||
<li>
|
||||
<strong>{{ stat.name }}:</strong> {{ stat.result }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">
|
||||
Dirty Dozen <small class="text-gray-600 dark:text-white">({{ dozen | length }})</small>
|
||||
</summary>
|
||||
<div class="mt-3">
|
||||
<ol>
|
||||
{% for stat in dozen %}
|
||||
<li>
|
||||
<strong>{{ stat.name }}:</strong> {{ stat.result }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
{% if "admin" in loggedin_user.roles %}
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
||||
<h2 class="h2">Update</h2>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">
|
||||
Dirty Thirty <small class="text-gray-600 dark:text-white">({{ thirty | length }})</small>
|
||||
</summary>
|
||||
<div class="mt-3">
|
||||
<ol>
|
||||
{% for stat in thirty %}
|
||||
<li>
|
||||
<form action="/ergo/thirty/user/{{ stat.id }}/new" method="get">
|
||||
{{ stat.name }}:
|
||||
<input type="text" value="{{ stat.result }}" name="new" style="color: black" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
<details class="p-2">
|
||||
<summary class="cursor-pointer">
|
||||
Dirty Dozen <small class="text-gray-600 dark:text-white">({{ dozen | length }})</small>
|
||||
</summary>
|
||||
<div class="mt-3">
|
||||
<ol>
|
||||
{% for stat in dozen %}
|
||||
<li>
|
||||
<form action="/ergo/dozen/user/{{ stat.id }}/new" method="get">
|
||||
{{ stat.name }}:
|
||||
<input type="text" value="{{ stat.result }}" name="new" style="color: black" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
37
templates/ergo/missing-data.html.tera
Normal file
37
templates/ergo/missing-data.html.tera
Normal file
@ -0,0 +1,37 @@
|
||||
{% import "includes/macros" as macros %}
|
||||
{% import "includes/forms/boat" as boat %}
|
||||
{% extends "base" %}
|
||||
{% block content %}
|
||||
<div class="max-w-screen-lg w-full dark:text-white">
|
||||
<h1 class="h1">Ergo Challenge</h1>
|
||||
<div class="grid ">
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||
role="alert">
|
||||
<p class="px-3 pt-3">
|
||||
Schön, dass du heuer bei der Ergo Challenge mitmachen willst!
|
||||
Dafür benötigen wir 3 Daten: Geburtsjahr, Gewicht und Geschlecht.
|
||||
{% if loggedin_user.weight %}Wir haben von dir schon Daten, bitte überprüfe (und aktualisiere) diese kurz:{% endif %}
|
||||
</p>
|
||||
<form action="/ergo/set-data" method="post" class="grid gap-3 p-3">
|
||||
{{ macros::input(label="Geburtsjahr [YYYY]", name="birthyear", required=true, type="number", class="input rounded-md", value=loggedin_user.dob) }}
|
||||
{{ macros::input(label="Gewicht [kg]", name="weight", required=true, type="number", class="input rounded-md", value=loggedin_user.weight) }}
|
||||
<div>
|
||||
<label for="sex" class="text-sm text-gray-600 dark:text-gray-100">Geschlecht</label>
|
||||
<select name="sex" id="sex" class="input rounded-md" required>
|
||||
<option disabled="disabled"
|
||||
{% if loggedin_user.sex != 'f' and loggedin_user.sex != 'm' %}selected="selected"{% endif %}>
|
||||
Geschlecht auswählen
|
||||
</option>
|
||||
<option value="f"
|
||||
{% if loggedin_user.sex == 'f' %}selected="selected"{% endif %}>weiblich</option>
|
||||
<option value="m"
|
||||
{% if loggedin_user.sex == 'm' %}selected="selected"{% endif %}>männlich</option>
|
||||
</select>
|
||||
<small class="block py-1">Du fühlst dich beim Geschlecht nicht angesprochen? Dann melde dich bitte direkt beim Ergo-Christian, Kontaktmöglichkeit auf der nächsten Seite.</small>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-primary" value="Abschicken" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
@ -6,12 +6,23 @@
|
||||
<h1 class="h1">Ruder­assistent</h1>
|
||||
<div class="grid gap-3 my-5">
|
||||
<div class="m-auto">
|
||||
<a href="/planned"
|
||||
class="btn btn-primary flex items-center justify-center">
|
||||
{% include "includes/rowing-icon" %}
|
||||
<a href="/planned" style="display:inline-flex;"
|
||||
class="btn btn-primary flex items-center justify-between w-80 max-w-full">
|
||||
<span class="text-2xl">🚣♀️</span>
|
||||
<span class="text-xl px-3">Geplante Ausfahrten</span>
|
||||
<span class="text-2xl">🚣♂️</span>
|
||||
</a>
|
||||
</div>
|
||||
{% if show_quick_ergo_button %}
|
||||
<div class="m-auto">
|
||||
<a href="/ergo" style="display:inline-flex;"
|
||||
class="btn btn-primary flex items-center justify-between w-80 max-w-full">
|
||||
<span class="text-2xl">💪</span>
|
||||
<span class="text-xl px-3">Ergo Challenge</span>
|
||||
<span class="text-2xl">💪🏿</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if notifications %}
|
||||
<div id="notification"
|
||||
class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||
@ -303,6 +314,17 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||
role="alert">
|
||||
<h2 class="h2">Ergo</h2>
|
||||
<div class="p-3">
|
||||
<ul class="list-none ms-2">
|
||||
<li class="py-1">
|
||||
<a href="/ergo" class="block w-100 py-2 hover:text-primary-600">Ergo</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% if "schnupper-betreuer" in loggedin_user.roles %}
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||
role="alert">
|
||||
@ -369,19 +391,6 @@
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if loggedin_user.weight and loggedin_user.sex and loggedin_user.dob %}
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||
role="alert">
|
||||
<h2 class="h2">Ergo</h2>
|
||||
<div class="p-3">
|
||||
<ul class="list-none ms-2">
|
||||
<li class="py-1">
|
||||
<a href="/ergo" class="block w-100 py-2 hover:text-primary-600">Ergo</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||
role="alert">
|
||||
<h2 class="h2">Allgemein</h2>
|
||||
|
Loading…
Reference in New Issue
Block a user