Merge branch 'boat-stats' into 'staging'

add boat stats Fixes #50

Closes #50

See merge request PhilippHofer/rot!58
This commit is contained in:
PhilippHofer 2023-10-31 15:20:36 +00:00
commit a6519d7b7b
5 changed files with 93 additions and 7 deletions

View File

@ -9,7 +9,28 @@ pub struct Stat {
}
impl Stat {
pub async fn get_rowed_km(db: &SqlitePool) -> Vec<Stat> {
pub async fn boats(db: &SqlitePool) -> Vec<Stat> {
//TODO: switch to query! macro again (once upgraded to sqlite 3.42 on server)
sqlx::query(
"
SELECT (SELECT name FROM boat WHERE id=logbook.boat_id) as name, CAST(SUM(distance_in_km) AS INTEGER) AS rowed_km
FROM logbook
GROUP BY boat_id
ORDER BY rowed_km DESC;
",
)
.fetch_all(db)
.await
.unwrap()
.into_iter()
.map(|row| Stat {
name: row.get("name"),
rowed_km: row.get("rowed_km"),
})
.collect()
}
pub async fn people(db: &SqlitePool) -> Vec<Stat> {
//TODO: switch to query! macro again (once upgraded to sqlite 3.42 on server)
sqlx::query(
"

View File

@ -9,28 +9,50 @@ use crate::model::{
use super::log::KioskCookie;
#[get("/boats", rank = 2)]
async fn index_boat(db: &State<SqlitePool>, user: NonGuestUser) -> Template {
let stat = Stat::boats(db).await;
let kiosk = false;
Template::render(
"stat.boats",
context!(loggedin_user: &user.user, stat, kiosk),
)
}
#[get("/boats")]
async fn index_boat_kiosk(db: &State<SqlitePool>, _kiosk: KioskCookie) -> Template {
let stat = Stat::boats(db).await;
let kiosk = true;
Template::render("stat.boats", context!(stat, kiosk, show_kiosk_header: true))
}
#[get("/", rank = 2)]
async fn index(db: &State<SqlitePool>, user: NonGuestUser) -> Template {
let stat = Stat::get_rowed_km(db).await;
let stat = Stat::people(db).await;
let personal = stat::get_personal(db, &user.user).await;
let kiosk = false;
Template::render(
"stat",
"stat.people",
context!(loggedin_user: &user.user, stat, personal, kiosk),
)
}
#[get("/")]
async fn index_kiosk(db: &State<SqlitePool>, _kiosk: KioskCookie) -> Template {
let stat = Stat::get_rowed_km(db).await;
let stat = Stat::people(db).await;
let kiosk = true;
Template::render("stat", context!(stat, kiosk, show_kiosk_header: true))
Template::render(
"stat.people",
context!(stat, kiosk, show_kiosk_header: true),
)
}
pub fn routes() -> Vec<Route> {
routes![index, index_kiosk]
routes![index, index_kiosk, index_boat, index_boat_kiosk]
}
#[cfg(test)]

View File

@ -28,7 +28,10 @@
Logbuch
</a>
<a href="/stat" class="block w-100 py-2 hover:text-primary-600 border-t">
Statistik
Personen-Statistik
</a>
<a href="/stat/boats" class="block w-100 py-2 hover:text-primary-600 border-t">
Boots-Statistik
</a>
{% if loggedin_user.is_admin %}
<a href="/admin/boat" class="block w-100 py-2 hover:text-primary-600 border-t">

View File

@ -0,0 +1,40 @@
{% import "includes/macros" as macros %}
{% extends "base" %}
{% block content %}
<div class="max-w-screen-lg w-full">
<h1 class="h1">Boots-Statistik</h1>
<div class="bg-gray-200 p-3 mt-4 rounded-t-md">
<label for="name" class="sr-only">Suche</label>
<input type="search" name="name" id="filter-js" class="w-full relative block rounded-md border-0 py-1.5 px-2 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary-600 sm:text-sm sm:leading-6 mb-2 md:mb-0" placeholder="Suchen nach Bootsnamen...">
</div>
<div id="filter-result-js" class="bg-gray-200 text-primary-950 pb-3 px-3 text-right"></div>
<div class="border-r border-l">
{% set_global km = 0 %}
{% set_global index = 1 %}
{% for s in stat %}
<div class="border-t {% if loop.last %} border-b {% endif %} bg-white flex justify-between items-center px-3 py-1" data-filterable="true" data-filter="{{ s.name }}">
<span class="text-sm text-gray-600 w-10">
{% if km != s.rowed_km %}
{{loop.index}}
{% set_global index = loop.index %}
{% else %}
{{ index }}
{% endif %}
</span>
<span class="grow">{{s.name}}</span>
<span>{{s.rowed_km}}
km</span>
{% set_global km = s.rowed_km %}
</div>
{% endfor %}
</div>
<div id="container" class="w-full"></div>
</div>
<script src="/public/logbook.js"></script>
{% endblock content%}