Compare commits

...

2 Commits

Author SHA1 Message Date
44bc217452 Merge pull request 'show guest km, Fixes #41' (#99) from guest-km into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 11m14s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 14m24s
Reviewed-on: #99
2023-12-23 22:30:27 +01:00
aca5340370 show guest km, Fixes #41
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m56s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2023-12-23 15:26:49 +01:00
3 changed files with 92 additions and 31 deletions

View File

@ -36,6 +36,36 @@ ORDER BY rowed_km DESC;
.collect() .collect()
} }
pub async fn guest(db: &SqlitePool, year: Option<i32>) -> Stat {
let year = match year {
Some(year) => year,
None => chrono::Utc::now().year(),
};
//TODO: switch to query! macro again (once upgraded to sqlite 3.42 on server)
let rowed_km = sqlx::query(&format!(
"
SELECT SUM((b.amount_seats - COALESCE(m.member_count, 0)) * l.distance_in_km) as total_guest_km
FROM logbook l
JOIN boat b ON l.boat_id = b.id
LEFT JOIN (
SELECT logbook_id, COUNT(*) as member_count
FROM rower
GROUP BY logbook_id
) m ON l.id = m.logbook_id
WHERE l.distance_in_km IS NOT NULL AND l.arrival LIKE '{year}-%' AND b.name != 'Externes Boot';
"
))
.fetch_one(db)
.await
.unwrap()
.get::<i64, usize>(0);
Stat {
name: "Gäste".into(),
rowed_km: rowed_km as i32,
}
}
pub async fn people(db: &SqlitePool, year: Option<i32>) -> Vec<Stat> { pub async fn people(db: &SqlitePool, year: Option<i32>) -> Vec<Stat> {
let year = match year { let year = match year {
Some(year) => year, Some(year) => year,

View File

@ -35,23 +35,25 @@ async fn index_boat_kiosk(
#[get("/?<year>", rank = 2)] #[get("/?<year>", rank = 2)]
async fn index(db: &State<SqlitePool>, user: NonGuestUser, year: Option<i32>) -> Template { async fn index(db: &State<SqlitePool>, user: NonGuestUser, year: Option<i32>) -> Template {
let stat = Stat::people(db, year).await; let stat = Stat::people(db, year).await;
let guest_km = Stat::guest(db, year).await;
let personal = stat::get_personal(db, &user.user).await; let personal = stat::get_personal(db, &user.user).await;
let kiosk = false; let kiosk = false;
Template::render( Template::render(
"stat.people", "stat.people",
context!(loggedin_user: &user.user, stat, personal, kiosk), context!(loggedin_user: &user.user, stat, personal, kiosk, guest_km),
) )
} }
#[get("/?<year>")] #[get("/?<year>")]
async fn index_kiosk(db: &State<SqlitePool>, _kiosk: KioskCookie, year: Option<i32>) -> Template { async fn index_kiosk(db: &State<SqlitePool>, _kiosk: KioskCookie, year: Option<i32>) -> Template {
let stat = Stat::people(db, year).await; let stat = Stat::people(db, year).await;
let guest_km = Stat::guest(db, year).await;
let kiosk = true; let kiosk = true;
Template::render( Template::render(
"stat.people", "stat.people",
context!(stat, kiosk, show_kiosk_header: true), context!(stat, kiosk, show_kiosk_header: true, guest_km),
) )
} }

View File

@ -5,37 +5,66 @@
{% block content %} {% block content %}
<div class="max-w-screen-lg w-full"> <div class="max-w-screen-lg w-full">
<h1 class="h1">Statistik <select id="yearSelect" onchange="changeYear()" style="background: transparent; background-image: none; text-decoration: underline;"></select></h1> <h1 class="h1">
Statistik
<select
id="yearSelect"
onchange="changeYear()"
style="
background: transparent;
background-image: none;
text-decoration: underline;
"
></select>
</h1>
<div class="search-wrapper"> <div class="search-wrapper">
<label for="name" class="sr-only">Suche</label> <label for="name" class="sr-only">Suche</label>
<input type="search" name="name" id="filter-js" class="search-bar" placeholder="Suchen nach Namen..."> <input
type="search"
name="name"
id="filter-js"
class="search-bar"
placeholder="Suchen nach Namen..."
/>
</div> </div>
<div id="filter-result-js" class="search-result"></div> <div id="filter-result-js" class="search-result"></div>
<div class="border-r border-l border-gray-200 dark:border-primary-600"> <div class="border-r border-l border-gray-200 dark:border-primary-600">
{% set_global km = 0 %} {% set_global km = 0 %} {% set_global index = 1 %} {% for s in stat %}
{% set_global index = 1 %} <div
{% for s in stat %} class="border-t border-gray-200 dark:border-primary-600 {% if loop.last %} border-b {% endif %} bg-white dark:bg-primary-900 text-black dark:text-white flex justify-between items-center px-3 py-1"
<div class="border-t border-gray-200 dark:border-primary-600 {% if loop.last %} border-b {% endif %} bg-white dark:bg-primary-900 text-black dark:text-white flex justify-between items-center px-3 py-1" data-filterable="true" data-filter="{{ s.name }}"> data-filterable="true"
data-filter="{{ s.name }}"
>
<span class="text-sm text-gray-600 dark:text-gray-100 w-10"> <span class="text-sm text-gray-600 dark:text-gray-100 w-10">
{% if km != s.rowed_km %} {% if km != s.rowed_km %}
{{loop.index}} {{ loop.index }}
{% set_global index = loop.index %} {% set_global index = loop.index %} {% else %}
{% else %}
{{ index }} {{ index }}
{% endif %} {% endif %}
</span> </span>
<span class="grow">{{s.name}}</span> <span class="grow">{{ s.name }}</span>
<span>{{s.rowed_km}} km</span> <span>{{ s.rowed_km }} km</span>
{% set_global km = s.rowed_km %} {% set_global km = s.rowed_km %}
</div> </div>
{% endfor %} {% endfor %}
<div
class="border-t border-gray-200 dark:border-primary-600 {% if loop.last %} border-b {% endif %} bg-white dark:bg-primary-900 text-black dark:text-white flex justify-between items-center px-3 py-1"
data-filterable="true"
data-filter="{{ guest_km.name }}"
>
<span class="text-sm text-gray-600 dark:text-gray-100 w-10">
</span>
<span class="grow">{{ guest_km.name }}</span>
<span>{{ guest_km.rowed_km }} km</span>
</div>
</div> </div>
<div id="container" class="w-full"></div> <div id="container" class="w-full"></div>
</div> </div>
<script> <script>
{% if personal %} {% if personal %}