Merge pull request 'update-ergo' (#773) from update-ergo into staging
Reviewed-on: #773
This commit is contained in:
commit
3272833b2d
@ -678,18 +678,8 @@ WHERE family_id IS NULL;
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn ergo(db: &SqlitePool) -> Vec<Self> {
|
pub async fn ergo(db: &SqlitePool) -> Vec<Self> {
|
||||||
sqlx::query_as!(
|
let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
||||||
Self,
|
Self::all_with_role(db, &ergo).await
|
||||||
"
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cox(db: &SqlitePool) -> Vec<Self> {
|
pub async fn cox(db: &SqlitePool) -> Vec<Self> {
|
||||||
@ -723,6 +713,19 @@ ORDER BY last_access DESC
|
|||||||
.is_ok()
|
.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> {
|
pub async fn update(&self, db: &SqlitePool, data: UserEditForm<'_>) -> Result<(), String> {
|
||||||
let mut db = db.begin().await.map_err(|e| e.to_string())?;
|
let mut db = db.begin().await.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::{Datelike, Utc};
|
||||||
use rocket::{
|
use rocket::{
|
||||||
form::Form,
|
form::Form,
|
||||||
fs::TempFile,
|
fs::TempFile,
|
||||||
@ -17,8 +17,7 @@ use sqlx::SqlitePool;
|
|||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
log::Log,
|
log::Log, notification::Notification, role::Role, user::{AdminUser, User, UserWithDetails}
|
||||||
user::{AdminUser, User, UserWithDetails},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@ -50,7 +49,7 @@ async fn send(db: &State<SqlitePool>, _user: AdminUser) -> Template {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Template::render(
|
Template::render(
|
||||||
"ergo.final",
|
"ergo/final",
|
||||||
context!(loggedin_user: &UserWithDetails::from_user(_user.user, db).await, thirty, dozen),
|
context!(loggedin_user: &UserWithDetails::from_user(_user.user, db).await, thirty, dozen),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -98,6 +97,19 @@ async fn update(
|
|||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_>>) -> Template {
|
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 users = User::ergo(db).await;
|
||||||
|
|
||||||
let thirty = sqlx::query_as!(
|
let thirty = sqlx::query_as!(
|
||||||
@ -116,16 +128,56 @@ async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.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("users", &users);
|
||||||
context.insert("thirty", &thirty);
|
context.insert("thirty", &thirty);
|
||||||
context.insert("dozen", &dozen);
|
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)]
|
#[derive(FromForm, Debug)]
|
||||||
@ -173,6 +225,9 @@ async fn new_thirty(
|
|||||||
)
|
)
|
||||||
.await;
|
.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")
|
Flash::success(Redirect::to("/ergo"), "Erfolgreich eingetragen")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,11 +269,14 @@ async fn new_dozen(
|
|||||||
)
|
)
|
||||||
.await;
|
.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")
|
Flash::success(Redirect::to("/ergo"), "Erfolgreich eingetragen")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
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)]
|
#[cfg(test)]
|
||||||
|
@ -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 %}
|
|
231
templates/ergo/index.html.tera
Normal file
231
templates/ergo/index.html.tera
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
{% 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">
|
||||||
|
Montag → 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>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<details class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md p-2">
|
||||||
|
<summary class="cursor-pointer">Noch mehr Infos</summary>
|
||||||
|
<strong>Um was geht es bei den Ergochallenges?</strong>
|
||||||
|
<p>
|
||||||
|
Der Linzer Verein Ister veranstaltet seit einigen Jahren zwei Challenges im Winter, ‘Dirty Thirty’ (6x im Winter) und ‘Dirty Dozen’ (12 Wochen lang).
|
||||||
|
<ul>
|
||||||
|
<li>Bei Dirty Thirty geht es darum so viele Kilometer wie möglich in 30 Minuten zu fahren.</li>
|
||||||
|
<li>
|
||||||
|
Bei Dirty Dozen werden jede Woche neue Ziele ausgeschrieben, gestartet wird mit einem Halbmarathon und es geht runter bis auf 100m.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
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>Video Tipps von Marie:</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="https://www.youtube.com/watch?v=TJsQPV6LNPI"
|
||||||
|
target="_blank"
|
||||||
|
style="text-decoration: underline">Intro</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://www.youtube.com/watch?v=KOacKLOpWkI"
|
||||||
|
target="_blank"
|
||||||
|
style="text-decoration: underline">Schlagaufbau</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<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">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 %}
|
33
templates/ergo/missing-data.html.tera
Normal file
33
templates/ergo/missing-data.html.tera
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{% 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="mb-2">
|
||||||
|
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) }}
|
||||||
|
<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>
|
||||||
|
<input type="submit" class="btn btn-primary" value="Abschicken" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -303,6 +303,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% 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 %}
|
{% 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"
|
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||||
role="alert">
|
role="alert">
|
||||||
@ -369,19 +380,6 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% 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"
|
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
|
||||||
role="alert">
|
role="alert">
|
||||||
<h2 class="h2">Allgemein</h2>
|
<h2 class="h2">Allgemein</h2>
|
||||||
|
Loading…
Reference in New Issue
Block a user