improvements, styling, additional infos #731
@ -299,6 +299,50 @@ ORDER BY departure DESC
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn year_first_logbook_entry(db: &SqlitePool, user: &User) -> Option<i32> {
|
||||||
|
let log: Option<Self> = sqlx::query_as(
|
||||||
|
&format!("
|
||||||
|
SELECT id, boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype
|
||||||
|
FROM logbook
|
||||||
|
JOIN rower ON logbook.id = rower.logbook_id
|
||||||
|
WHERE arrival is not null AND rower_id = {}
|
||||||
|
ORDER BY arrival
|
||||||
|
LIMIT 1
|
||||||
|
", user.id)
|
||||||
|
)
|
||||||
|
.fetch_optional(db)
|
||||||
|
.await
|
||||||
|
.unwrap(); //TODO: fixme
|
||||||
|
|
||||||
|
if let Some(log) = log {
|
||||||
|
Some(log.arrival.unwrap().year())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn year_last_logbook_entry(db: &SqlitePool, user: &User) -> Option<i32> {
|
||||||
|
let log: Option<Self> = sqlx::query_as(
|
||||||
|
&format!("
|
||||||
|
SELECT id, boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype
|
||||||
|
FROM logbook
|
||||||
|
JOIN rower ON logbook.id = rower.logbook_id
|
||||||
|
WHERE arrival is not null AND rower_id = {}
|
||||||
|
ORDER BY arrival DESC
|
||||||
|
LIMIT 1
|
||||||
|
", user.id)
|
||||||
|
)
|
||||||
|
.fetch_optional(db)
|
||||||
|
.await
|
||||||
|
.unwrap(); //TODO: fixme
|
||||||
|
|
||||||
|
if let Some(log) = log {
|
||||||
|
Some(log.arrival.unwrap().year())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn completed_wanderfahrten_with_user_over_km_in_year(
|
pub(crate) async fn completed_wanderfahrten_with_user_over_km_in_year(
|
||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
user: &User,
|
user: &User,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::SqlitePool;
|
|
||||||
|
|
||||||
#[derive(Serialize, PartialEq, Debug)]
|
#[derive(Serialize, PartialEq, Debug)]
|
||||||
pub(crate) enum Level {
|
pub(crate) enum Level {
|
||||||
@ -31,7 +30,7 @@ impl Level {
|
|||||||
} else if km < Level::GOLD.required_km() {
|
} else if km < Level::GOLD.required_km() {
|
||||||
Level::GOLD
|
Level::GOLD
|
||||||
} else if km < Level::DIAMOND.required_km() {
|
} else if km < Level::DIAMOND.required_km() {
|
||||||
Level::BRONZE
|
Level::DIAMOND
|
||||||
} else {
|
} else {
|
||||||
Level::DONE
|
Level::DONE
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use equatorprice::Level;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use super::{stat::Stat, user::User};
|
use super::{logbook::Logbook, stat::Stat, user::User};
|
||||||
|
|
||||||
pub(crate) mod equatorprice;
|
pub(crate) mod equatorprice;
|
||||||
pub(crate) mod rowingbadge;
|
pub(crate) mod rowingbadge;
|
||||||
@ -14,6 +14,9 @@ pub(crate) struct Achievements {
|
|||||||
pub(crate) curr_equatorprice_name: String,
|
pub(crate) curr_equatorprice_name: String,
|
||||||
pub(crate) new_equatorprice_this_season: bool,
|
pub(crate) new_equatorprice_this_season: bool,
|
||||||
pub(crate) rowingbadge: Option<rowingbadge::Status>,
|
pub(crate) rowingbadge: Option<rowingbadge::Status>,
|
||||||
|
pub(crate) all_time_km: i32,
|
||||||
|
pub(crate) year_first_mentioned: Option<i32>,
|
||||||
|
pub(crate) year_last_mentioned: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Achievements {
|
impl Achievements {
|
||||||
@ -31,25 +34,18 @@ impl Achievements {
|
|||||||
.await
|
.await
|
||||||
.rowed_km
|
.rowed_km
|
||||||
};
|
};
|
||||||
println!(
|
|
||||||
"old: {}; new: {}",
|
|
||||||
rowed_km,
|
|
||||||
rowed_km - rowed_km_this_season
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
"old: {:?}; new: {:?}",
|
|
||||||
Level::curr_level(rowed_km),
|
|
||||||
Level::curr_level(rowed_km - rowed_km_this_season)
|
|
||||||
);
|
|
||||||
let new_equatorprice_this_season =
|
let new_equatorprice_this_season =
|
||||||
Level::curr_level(rowed_km) != Level::curr_level(rowed_km - rowed_km_this_season);
|
Level::curr_level(rowed_km) != Level::curr_level(rowed_km - rowed_km_this_season);
|
||||||
println!("{new_equatorprice_this_season:?}");
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
equatorprice: equatorprice::Next::new(rowed_km),
|
equatorprice: equatorprice::Next::new(rowed_km),
|
||||||
curr_equatorprice_name: equatorprice::Level::curr_level(rowed_km).desc().to_string(),
|
curr_equatorprice_name: equatorprice::Level::curr_level(rowed_km).desc().to_string(),
|
||||||
new_equatorprice_this_season,
|
new_equatorprice_this_season,
|
||||||
rowingbadge: rowingbadge::Status::for_user(db, user).await,
|
rowingbadge: rowingbadge::Status::for_user(db, user).await,
|
||||||
|
all_time_km: rowed_km,
|
||||||
|
year_first_mentioned: Logbook::year_first_logbook_entry(db, user).await,
|
||||||
|
year_last_mentioned: Logbook::year_last_logbook_entry(db, user).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,26 +69,29 @@ impl TryFrom<&User> for AgeBracket {
|
|||||||
type Error = String;
|
type Error = String;
|
||||||
|
|
||||||
fn try_from(value: &User) -> Result<Self, Self::Error> {
|
fn try_from(value: &User) -> Result<Self, Self::Error> {
|
||||||
if let Some(birthdate) = value.birthdate.clone() {
|
let Some(birthdate) = value.birthdate.clone() else {
|
||||||
let today = Local::now().date_naive();
|
return Err("User has no birthdate".to_string());
|
||||||
let birthdate = NaiveDate::parse_from_str(&birthdate, "%Y-%m-%d").unwrap();
|
};
|
||||||
|
|
||||||
let age = today.year() - birthdate.year();
|
let Ok(birthdate) = NaiveDate::parse_from_str(&birthdate, "%Y-%m-%d") else {
|
||||||
if age <= 14 {
|
return Err("Birthdate in wrong format...".to_string());
|
||||||
Ok(AgeBracket::Till14)
|
};
|
||||||
} else if age <= 18 {
|
|
||||||
Ok(AgeBracket::From14Till18)
|
let today = Local::now().date_naive();
|
||||||
} else if age <= 30 {
|
|
||||||
Ok(AgeBracket::From19Till30)
|
let age = today.year() - birthdate.year();
|
||||||
} else if age <= 60 {
|
if age <= 14 {
|
||||||
Ok(AgeBracket::From31Till60)
|
Ok(AgeBracket::Till14)
|
||||||
} else if age <= 75 {
|
} else if age <= 18 {
|
||||||
Ok(AgeBracket::From61Till75)
|
Ok(AgeBracket::From14Till18)
|
||||||
} else {
|
} else if age <= 30 {
|
||||||
Ok(AgeBracket::From76)
|
Ok(AgeBracket::From19Till30)
|
||||||
}
|
} else if age <= 60 {
|
||||||
|
Ok(AgeBracket::From31Till60)
|
||||||
|
} else if age <= 75 {
|
||||||
|
Ok(AgeBracket::From61Till75)
|
||||||
} else {
|
} else {
|
||||||
Err("User has no birthdate".to_string())
|
Ok(AgeBracket::From76)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,19 @@
|
|||||||
{% extends "base" %}
|
{% extends "base" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<link rel="stylesheet" href="/public/table.css" />
|
<link rel="stylesheet" href="/public/table.css" />
|
||||||
<div class="max-w-screen-lg w-full">
|
<div class="w-full">
|
||||||
<h1 class="h1">Abzeichen für {{ rowingbadge_year }}</h1>
|
<h1 class="h1">Abzeichen für {{ rowingbadge_year }}</h1>
|
||||||
<div class="text-black dark:text-white">
|
<div class="text-black dark:text-white">
|
||||||
<table id="basic">
|
<table id="basic">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Äquatorpreis</th>
|
<th>Erster Log</th>
|
||||||
<th>Fahrtenabzeichen (FA) geschafft</th>
|
<th>Letzter Log</th>
|
||||||
|
<th>Gesamt-KM</th>
|
||||||
|
<th>Äquatorpreis (ÄP)</th>
|
||||||
|
<th>ÄP diese<br>Saison bekommen</th>
|
||||||
|
<th>Fahrtenabzeichen (FA)<br>geschafft</th>
|
||||||
<th>FA - KM</th>
|
<th>FA - KM</th>
|
||||||
<th>FA - fehlende KM</th>
|
<th>FA - fehlende KM</th>
|
||||||
<th>Eintagesausfahrten</th>
|
<th>Eintagesausfahrten</th>
|
||||||
@ -24,7 +28,15 @@
|
|||||||
{% set achievement = person.1 %}
|
{% set achievement = person.1 %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ user.name }}</td>
|
<td>{{ user.name }}</td>
|
||||||
<td>{% if achievement.new_equatorprice_this_season %}(NEU!) {% endif %}{{ achievement.curr_equatorprice_name }} </td>
|
<td>{% if achievement.year_first_mentioned %}{{ achievement.year_first_mentioned }}{% endif %}</td>
|
||||||
|
<td>{% if achievement.year_last_mentioned %}{{ achievement.year_last_mentioned }}{% endif %}</td>
|
||||||
|
<td>{{ achievement.all_time_km }}</td>
|
||||||
|
<td>
|
||||||
|
{{ achievement.curr_equatorprice_name }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if achievement.new_equatorprice_this_season %}🎉{% else %}-{% endif %}
|
||||||
|
</td>
|
||||||
{% if achievement.rowingbadge %}
|
{% if achievement.rowingbadge %}
|
||||||
{% set badge = achievement.rowingbadge %}
|
{% set badge = achievement.rowingbadge %}
|
||||||
<td>
|
<td>
|
||||||
@ -57,11 +69,11 @@
|
|||||||
</details>
|
</details>
|
||||||
</td>
|
</td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td>no birthdate of this person</td>
|
<td>Geb.datum fehlt 👻</td>
|
||||||
<td>no birthdate of this person</td>
|
<td>Geb.datum fehlt 👻</td>
|
||||||
<td>no birthdate of this person</td>
|
<td>Geb.datum fehlt 👻</td>
|
||||||
<td>no birthdate of this person</td>
|
<td>Geb.datum fehlt 👻</td>
|
||||||
<td>no birthdate of this person</td>
|
<td>Geb.datum fehlt 👻</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -79,78 +79,109 @@
|
|||||||
<h2 class="h2">Persönliches</h2>
|
<h2 class="h2">Persönliches</h2>
|
||||||
<div class="mx-2 divide-y divide-gray-200 dark:divide-primary-600">
|
<div class="mx-2 divide-y divide-gray-200 dark:divide-primary-600">
|
||||||
<div class="py-3">
|
<div class="py-3">
|
||||||
<h3 class="font-bold text-xl">
|
<details>
|
||||||
{% if achievements.rowingbadge and achievements.rowingbadge.achieved %}🎉{% endif %}
|
<summary>
|
||||||
Fahrtenabzeichen
|
<h3 class="inline">
|
||||||
{% if achievements.rowingbadge %}{{ achievements.rowingbadge.year }}{% endif %}
|
<span class="text-xl">
|
||||||
<span><a href="http://www.rudern.at/OFFICE/Downloads/Ausschreibungen/2022/Wanderfahrten//Fahrtenabzeichen%20%C3%84quatorpreis%20und%20Danubius%202022.pdf"
|
{% if achievements.rowingbadge and achievements.rowingbadge.achieved %}
|
||||||
|
🎉
|
||||||
|
{% else %}
|
||||||
|
📋
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
Fahrtenabzeichen
|
||||||
|
{% if achievements.rowingbadge %}{{ achievements.rowingbadge.year }}{% endif %}
|
||||||
|
<span><a href="http://www.rudern.at/OFFICE/Downloads/Ausschreibungen/2022/Wanderfahrten//Fahrtenabzeichen%20%C3%84quatorpreis%20und%20Danubius%202022.pdf"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="w-7 h-7 inline-flex align-center justify-center rounded-full bg-primary-500 ml-2">?</a></span>
|
class="w-6 h-6 inline-flex align-center justify-center rounded-full bg-primary-500 ml-2">?</a></span>
|
||||||
</h3>
|
</h3>
|
||||||
{% if achievements.rowingbadge %}
|
</summary>
|
||||||
{% set badge = achievements.rowingbadge %}
|
{% if achievements.rowingbadge %}
|
||||||
<div class="mb-3">{{ badge.category }}</div>
|
{% set badge = achievements.rowingbadge %}
|
||||||
<label for="rowingbadge" class="label">Kilometer ({{ badge.rowed_km }} / {{ badge.required_km }} km)</label>
|
<div class="mb-3">{{ badge.category }}</div>
|
||||||
<progress id="rowingbadge"
|
<label for="rowingbadge" class="label">Kilometer ({{ badge.rowed_km }} / {{ badge.required_km }} km)</label>
|
||||||
class="w-full block my-3"
|
<progress id="rowingbadge"
|
||||||
value="{{ badge.rowed_km }}"
|
class="w-full block my-3"
|
||||||
max="{{ badge.required_km }}"></progress>
|
value="{{ badge.rowed_km }}"
|
||||||
<h4 class="font-bold mt-4">Wanderfahrten</h4>
|
max="{{ badge.required_km }}"></progress>
|
||||||
<div>Nur 1 muss erreicht werden</div>
|
<h4 class="font-bold mt-4">Wanderfahrten</h4>
|
||||||
<ol class="list-decimal ml-4 my-3">
|
<div>Nur 1 muss erreicht werden</div>
|
||||||
<li>
|
<ol class="list-decimal ml-4 my-3">
|
||||||
{% if badge.multi_day_trips_over_required_distance | length >= 1 %}
|
<li>
|
||||||
✅
|
{% if badge.multi_day_trips_over_required_distance | length >= 1 %}
|
||||||
{% else %}
|
✅
|
||||||
❌
|
{% else %}
|
||||||
{% endif %}
|
❌
|
||||||
1 mehrtägige Wanderfahrt > {{ badge.multi_day_trips_required_distance }} km
|
{% endif %}
|
||||||
</li>
|
1 mehrtägige Wanderfahrt > {{ badge.multi_day_trips_required_distance }} km
|
||||||
<li>
|
</li>
|
||||||
{% if badge.single_day_trips_over_required_distance | length >= 2 %}
|
<li>
|
||||||
✅
|
{% if badge.single_day_trips_over_required_distance | length >= 2 %}
|
||||||
{% else %}
|
✅
|
||||||
❌
|
{% else %}
|
||||||
{% endif %}
|
❌
|
||||||
2 eintägige Wanderfahrten > {{ badge.single_day_trips_required_distance }} km
|
{% endif %}
|
||||||
</li>
|
2 eintägige Wanderfahrten > {{ badge.single_day_trips_required_distance }} km
|
||||||
</ol>
|
</li>
|
||||||
<details>
|
</ol>
|
||||||
<summary>Details zu den Wanderfahrten</summary>
|
<details>
|
||||||
|
<summary>Details zu den Wanderfahrten</summary>
|
||||||
|
<div class="mt-3">
|
||||||
|
{% for log in badge.single_day_trips_over_required_distance %}
|
||||||
|
{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% for log in badge.multi_day_trips_over_required_distance %}
|
||||||
|
{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index) }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{% else %}
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
{% for log in badge.single_day_trips_over_required_distance %}
|
Wir haben leider kein Geburtsdatum von dir und können dir leider deinen heurigen Status für das Fahrtenabzeichen nicht anzeigen. Wenn du dein Geburtsdatum an <a href="mailto:it@rudernlinz.at" class="underline">it@rudernlinz.at</a> schreibst, lässt sich das ändern :-)
|
||||||
{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index) }}
|
|
||||||
{% endfor %}
|
|
||||||
{% for log in badge.multi_day_trips_over_required_distance %}
|
|
||||||
{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index) }}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
</details>
|
{% endif %}
|
||||||
{% else %}
|
</details>
|
||||||
Wir haben leider kein Geburtsdatum von dir und können dir leider deinen heurigen Status für das Fahrtenabzeichen nicht anzeigen. Wenn du dein Geburtsdatum an <a href="mailto:it@rudernlinz.at" class="underline">it@rudernlinz.at</a> schreibst, lässt sich das ändern :-)
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="py-3">
|
<div class="py-3">
|
||||||
<h3 class="font-bold text-xl mb-3">
|
<details>
|
||||||
Äquatorpreis
|
<summary>
|
||||||
<span><a href="http://www.rudern.at/OFFICE/Downloads/Ausschreibungen/2022/Wanderfahrten//Fahrtenabzeichen%20%C3%84quatorpreis%20und%20Danubius%202022.pdf"
|
<h3 class="mb-3 inline">
|
||||||
|
{% set price = achievements.equatorprice %}
|
||||||
|
<span class="text-xl">
|
||||||
|
{% if achievements.curr_equatorprice_name == "-" %}
|
||||||
|
📋
|
||||||
|
{% elif achievements.curr_equatorprice_name == "Bronze" %}
|
||||||
|
🥉
|
||||||
|
{% elif achievements.curr_equatorprice_name == "Silber" %}
|
||||||
|
🥈
|
||||||
|
{% elif achievements.curr_equatorprice_name == "Gold" %}
|
||||||
|
🥇
|
||||||
|
{% elif achievements.curr_equatorprice_name == "Diamant" %}
|
||||||
|
💍
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
Äquatorpreis
|
||||||
|
<span><a href="http://www.rudern.at/OFFICE/Downloads/Ausschreibungen/2022/Wanderfahrten//Fahrtenabzeichen%20%C3%84quatorpreis%20und%20Danubius%202022.pdf"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="w-7 h-7 inline-flex align-center justify-center rounded-full bg-primary-500 ml-2">?</a></span>
|
class="w-6 h-6 inline-flex align-center justify-center rounded-full bg-primary-500 ml-2">?</a></span>
|
||||||
</h3>
|
</h3>
|
||||||
{% set price = achievements.equatorprice %}
|
</summary>
|
||||||
{% if price.level == "DONE" %}
|
<div class="mt-3">
|
||||||
Gratuliere, du hast alles in deinem Rudererleben erreicht, was es (beim Äquatorpreis) zu erreichen gibt.
|
{% if price.level == "DONE" %}
|
||||||
{% else %}
|
Gratuliere, du hast alles in deinem Rudererleben erreicht, was es (beim Äquatorpreis) zu erreichen gibt.
|
||||||
<label for="equatorprice" class="label">{{ price.desc }} ({{ price.rowed_km }} / {{ price.required_km }} km)</label>
|
{% else %}
|
||||||
<progress id="equatorprice"
|
<label for="equatorprice" class="label">{{ price.desc }} ({{ price.rowed_km }} / {{ price.required_km }} km)</label>
|
||||||
class="w-full block my-3"
|
<progress id="equatorprice"
|
||||||
value="{{ price.rowed_km }}"
|
class="w-full block my-3"
|
||||||
max="{{ price.required_km }}"></progress>
|
value="{{ price.rowed_km }}"
|
||||||
<details>
|
max="{{ price.required_km }}"></progress>
|
||||||
<summary>Details</summary>
|
<details>
|
||||||
Du bist insgesamt {{ price.rowed_km }} km gerudert. Um den Äquatorpreis in {{ price.level }} zu erhalten, benötigst du noch {{ price.missing_km }} km um die notwendigen {{ price.required_km }} km zu erreichen.
|
<summary>Details</summary>
|
||||||
</details>
|
Du bist insgesamt {{ price.rowed_km }} km gerudert. Um den Äquatorpreis in {{ price.desc }} zu erhalten, benötigst du noch {{ price.missing_km }} km um die notwendigen {{ price.required_km }} km zu erreichen.
|
||||||
{% endif %}
|
</details>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user