Merge pull request 'improvements, styling, additional infos' (#731) from aequatorpreis into staging
All checks were successful
CI/CD Pipeline / test (push) Successful in 11m12s
CI/CD Pipeline / deploy-staging (push) Successful in 8m37s
CI/CD Pipeline / deploy-main (push) Has been skipped

Reviewed-on: #731
This commit is contained in:
philipp 2024-09-04 18:42:09 +02:00
commit a356e7bd08
6 changed files with 192 additions and 107 deletions

View File

@ -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,

View File

@ -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
} }

View File

@ -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,
} }
} }
} }

View File

@ -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)
} }
} }
} }

View File

@ -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 %}

View File

@ -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 %}&#127881;{% 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 %}
&#127881;
{% 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>
&#9989; {% if badge.multi_day_trips_over_required_distance | length >= 1 %}
{% else %} &#9989;
&#10060; {% else %}
{% endif %} &#10060;
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>
&#9989; {% if badge.single_day_trips_over_required_distance | length >= 2 %}
{% else %} &#9989;
&#10060; {% else %}
{% endif %} &#10060;
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>