add boat stats Fixes #50
This commit is contained in:
		| @@ -9,7 +9,28 @@ pub struct Stat { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl 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) |         //TODO: switch to query! macro again (once upgraded to sqlite 3.42 on server) | ||||||
|         sqlx::query( |         sqlx::query( | ||||||
|             " |             " | ||||||
|   | |||||||
| @@ -9,28 +9,50 @@ use crate::model::{ | |||||||
|  |  | ||||||
| use super::log::KioskCookie; | 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)] | #[get("/", rank = 2)] | ||||||
| async fn index(db: &State<SqlitePool>, user: NonGuestUser) -> Template { | 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 personal = stat::get_personal(db, &user.user).await; | ||||||
|     let kiosk = false; |     let kiosk = false; | ||||||
|  |  | ||||||
|     Template::render( |     Template::render( | ||||||
|         "stat", |         "stat.people", | ||||||
|         context!(loggedin_user: &user.user, stat, personal, kiosk), |         context!(loggedin_user: &user.user, stat, personal, kiosk), | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  |  | ||||||
| #[get("/")] | #[get("/")] | ||||||
| async fn index_kiosk(db: &State<SqlitePool>, _kiosk: KioskCookie) -> Template { | 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; |     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> { | pub fn routes() -> Vec<Route> { | ||||||
|     routes![index, index_kiosk] |     routes![index, index_kiosk, index_boat, index_boat_kiosk] | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
|   | |||||||
| @@ -28,7 +28,10 @@ | |||||||
|                 Logbuch |                 Logbuch | ||||||
|               </a> |               </a> | ||||||
|               <a href="/stat" class="block w-100 py-2 hover:text-primary-600 border-t"> |               <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> |               </a> | ||||||
| 	      {% if loggedin_user.is_admin %} | 	      {% if loggedin_user.is_admin %} | ||||||
|               	<a href="/admin/boat" class="block w-100 py-2 hover:text-primary-600 border-t"> |               	<a href="/admin/boat" class="block w-100 py-2 hover:text-primary-600 border-t"> | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								templates/stat.boats.html.tera
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								templates/stat.boats.html.tera
									
									
									
									
									
										Normal 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%} | ||||||
		Reference in New Issue
	
	Block a user