2023-07-23 12:17:57 +02:00
use rocket ::{
form ::Form ,
2023-07-27 14:40:05 +02:00
get ,
http ::{ Cookie , CookieJar } ,
post ,
request ::{ self , FlashMessage , FromRequest } ,
2023-07-23 12:17:57 +02:00
response ::{ Flash , Redirect } ,
2023-07-27 14:40:05 +02:00
routes ,
time ::{ Duration , OffsetDateTime } ,
Request , Route , State ,
2023-07-23 12:17:57 +02:00
} ;
use rocket_dyn_templates ::Template ;
use sqlx ::SqlitePool ;
use tera ::Context ;
use crate ::model ::{
boat ::Boat ,
2023-07-27 15:24:29 +02:00
logbook ::{ LogToAdd , LogToFinalize , Logbook , LogbookCreateError , LogbookUpdateError } ,
2023-07-23 12:17:57 +02:00
logtype ::LogType ,
user ::{ AdminUser , User } ,
} ;
2023-07-27 14:38:46 +02:00
pub struct KioskCookie ( String ) ;
#[ rocket::async_trait ]
impl < ' r > FromRequest < ' r > for KioskCookie {
type Error = std ::convert ::Infallible ;
async fn from_request ( request : & ' r Request < '_ > ) -> request ::Outcome < KioskCookie , Self ::Error > {
match request . cookies ( ) . get_private ( " kiosk " ) {
Some ( cookie ) = > request ::Outcome ::Success ( KioskCookie ( cookie . value ( ) . to_string ( ) ) ) ,
None = > request ::Outcome ::Forward ( ( ) ) ,
}
}
}
2023-07-27 22:20:40 +02:00
#[ get( " / " , rank = 2) ]
2023-07-23 12:17:57 +02:00
async fn index (
db : & State < SqlitePool > ,
flash : Option < FlashMessage < '_ > > ,
adminuser : AdminUser ,
) -> Template {
let boats = Boat ::all ( db ) . await ;
2023-07-24 13:01:39 +02:00
let coxes = User ::cox ( db ) . await ;
let users = User ::all ( db ) . await ;
2023-07-23 12:17:57 +02:00
let logtypes = LogType ::all ( db ) . await ;
2023-07-26 12:56:19 +02:00
let distances = Logbook ::distances ( db ) . await ;
2023-07-23 12:17:57 +02:00
let on_water = Logbook ::on_water ( db ) . await ;
let mut context = Context ::new ( ) ;
if let Some ( msg ) = flash {
context . insert ( " flash " , & msg . into_inner ( ) ) ;
}
context . insert ( " boats " , & boats ) ;
2023-07-24 13:01:39 +02:00
context . insert ( " coxes " , & coxes ) ;
2023-07-23 12:17:57 +02:00
context . insert ( " users " , & users ) ;
context . insert ( " logtypes " , & logtypes ) ;
context . insert ( " loggedin_user " , & adminuser . user ) ;
context . insert ( " on_water " , & on_water ) ;
2023-07-26 12:56:19 +02:00
context . insert ( " distances " , & distances ) ;
2023-07-23 12:17:57 +02:00
Template ::render ( " log " , context . into_json ( ) )
}
2023-07-27 14:38:46 +02:00
#[ get( " /kiosk/ekrv2019 " ) ]
2023-07-27 14:40:05 +02:00
fn new_kiosk ( cookies : & CookieJar < '_ > ) -> Redirect {
2023-07-27 22:20:40 +02:00
let mut cookie = Cookie ::new ( " kiosk " , " yes " . to_string ( ) ) ;
2023-07-27 14:38:46 +02:00
cookie . set_expires ( OffsetDateTime ::now_utc ( ) + Duration ::weeks ( 12 ) ) ;
cookies . add_private ( cookie ) ;
2023-07-27 15:24:29 +02:00
Redirect ::to ( " /log " )
2023-07-27 14:38:46 +02:00
}
2023-07-27 15:24:29 +02:00
#[ get( " / " ) ]
2023-07-27 14:40:05 +02:00
async fn kiosk (
db : & State < SqlitePool > ,
flash : Option < FlashMessage < '_ > > ,
_kiosk : KioskCookie ,
) -> Template {
2023-07-27 14:38:46 +02:00
let boats = Boat ::all ( db ) . await ;
let coxes = User ::cox ( db ) . await ;
let users = User ::all ( db ) . await ;
let logtypes = LogType ::all ( db ) . await ;
let distances = Logbook ::distances ( db ) . await ;
let on_water = Logbook ::on_water ( db ) . await ;
let mut context = Context ::new ( ) ;
if let Some ( msg ) = flash {
context . insert ( " flash " , & msg . into_inner ( ) ) ;
}
context . insert ( " boats " , & boats ) ;
context . insert ( " coxes " , & coxes ) ;
context . insert ( " users " , & users ) ;
context . insert ( " logtypes " , & logtypes ) ;
context . insert ( " on_water " , & on_water ) ;
context . insert ( " distances " , & distances ) ;
Template ::render ( " kiosk " , context . into_json ( ) )
}
2023-07-27 22:20:40 +02:00
async fn create_logbook ( db : & SqlitePool , data : Form < LogToAdd > ) -> Flash < Redirect > {
2023-07-23 16:49:14 +02:00
match Logbook ::create (
2023-07-23 12:17:57 +02:00
db ,
2023-07-25 13:22:11 +02:00
data . into_inner ( )
2023-07-23 12:17:57 +02:00
)
. await
{
2023-07-23 16:49:14 +02:00
Ok ( _ ) = > Flash ::success ( Redirect ::to ( " /log " ) , " Ausfahrt erfolgreich hinzugefügt " ) ,
2023-07-24 13:01:39 +02:00
Err ( LogbookCreateError ::BoatAlreadyOnWater ) = > Flash ::error ( Redirect ::to ( " /log " ) , format! ( " Boot schon am Wasser " ) ) ,
2023-07-27 15:00:52 +02:00
Err ( LogbookCreateError ::ShipmasterAlreadyOnWater ) = > Flash ::error ( Redirect ::to ( " /log " ) , format! ( " Schiffsführer schon am Wasser " ) ) ,
2023-07-27 15:24:29 +02:00
Err ( LogbookCreateError ::RowerAlreadyOnWater ( rower ) ) = > Flash ::error ( Redirect ::to ( " /log " ) , format! ( " Ruderer {} schon am Wasser " , rower . name ) ) ,
2023-07-24 13:01:39 +02:00
Err ( LogbookCreateError ::BoatLocked ) = > Flash ::error ( Redirect ::to ( " /log " ) , format! ( " Boot gesperrt " ) ) ,
Err ( LogbookCreateError ::BoatNotFound ) = > Flash ::error ( Redirect ::to ( " /log " ) , format! ( " Boot gibt's ned " ) ) ,
Err ( LogbookCreateError ::TooManyRowers ( expected , actual ) ) = > Flash ::error ( Redirect ::to ( " /log " ) , format! ( " Zu viele Ruderer (Boot fasst maximal {expected} , es wurden jedoch {actual} Ruderer ausgewählt) " ) ) ,
2023-07-27 15:00:52 +02:00
2023-07-24 13:01:39 +02:00
}
2023-07-27 14:38:46 +02:00
}
2023-07-27 15:24:29 +02:00
#[ post( " / " , data = " <data> " , rank = 2) ]
async fn create (
2023-07-27 14:38:46 +02:00
db : & State < SqlitePool > ,
2023-07-27 15:24:29 +02:00
data : Form < LogToAdd > ,
_adminuser : AdminUser ,
2023-07-27 14:38:46 +02:00
) -> Flash < Redirect > {
2023-07-27 15:24:29 +02:00
create_logbook ( db , data ) . await
}
#[ post( " / " , data = " <data> " ) ]
2023-07-27 22:20:40 +02:00
async fn create_kiosk (
db : & State < SqlitePool > ,
data : Form < LogToAdd > ,
_kiosk : KioskCookie ,
) -> Flash < Redirect > {
2023-07-27 15:24:29 +02:00
create_logbook ( db , data ) . await
}
2023-07-27 22:20:40 +02:00
async fn home_logbook (
db : & SqlitePool ,
data : Form < LogToFinalize > ,
logbook_id : i32 ,
user : & User ,
) -> Flash < Redirect > {
2023-07-27 15:24:29 +02:00
let logbook : Option < Logbook > = Logbook ::find_by_id ( db , logbook_id ) . await ;
2023-07-27 14:38:46 +02:00
let Some ( logbook ) = logbook else {
return Flash ::error (
2023-07-27 15:24:29 +02:00
Redirect ::to ( " /admin/log " ) ,
2023-07-27 14:38:46 +02:00
format! ( " Log with ID {} does not exist! " , logbook_id ) ,
)
} ;
2023-07-27 15:24:29 +02:00
match logbook . home ( db , user , data . into_inner ( ) ) . await {
Ok ( _ ) = > Flash ::success ( Redirect ::to ( " /log " ) , " Successfully updated log " ) ,
Err ( LogbookUpdateError ::TooManyRowers ( expected , actual ) ) = > Flash ::error ( Redirect ::to ( " /log " ) , format! ( " Zu viele Ruderer (Boot fasst maximal {expected} , es wurden jedoch {actual} Ruderer ausgewählt) " ) ) ,
2023-07-27 14:38:46 +02:00
Err ( _ ) = > Flash ::error (
2023-07-27 15:24:29 +02:00
Redirect ::to ( " /log " ) ,
2023-07-27 14:38:46 +02:00
format! ( " Logbook with ID {} could not be updated! " , logbook_id ) ,
) ,
}
2023-07-27 15:24:29 +02:00
}
#[ post( " /<logbook_id> " , data = " <data> " ) ]
async fn home_kiosk (
db : & State < SqlitePool > ,
data : Form < LogToFinalize > ,
logbook_id : i32 ,
2023-07-27 22:20:40 +02:00
_kiosk : KioskCookie ,
2023-07-27 15:24:29 +02:00
) -> Flash < Redirect > {
let logbook = Logbook ::find_by_id ( db , logbook_id ) . await . unwrap ( ) ; //TODO: fixme
2023-07-27 22:20:40 +02:00
home_logbook (
db ,
data ,
logbook_id ,
& User ::find_by_id ( db , logbook . shipmaster as i32 )
. await
. unwrap ( ) ,
)
. await
2023-07-27 14:38:46 +02:00
}
2023-07-27 14:40:05 +02:00
#[ post( " /<logbook_id> " , data = " <data> " , rank = 2) ]
2023-07-23 16:49:14 +02:00
async fn home (
db : & State < SqlitePool > ,
2023-07-25 13:22:11 +02:00
data : Form < LogToFinalize > ,
2023-07-23 16:49:14 +02:00
logbook_id : i32 ,
2023-07-25 13:32:20 +02:00
adminuser : AdminUser ,
2023-07-23 16:49:14 +02:00
) -> Flash < Redirect > {
2023-07-27 15:24:29 +02:00
home_logbook ( db , data , logbook_id , & adminuser . user ) . await
2023-07-23 12:17:57 +02:00
}
pub fn routes ( ) -> Vec < Route > {
2023-07-27 14:40:05 +02:00
routes! [
index ,
create ,
create_kiosk ,
home ,
kiosk ,
home_kiosk ,
new_kiosk
]
2023-07-23 12:17:57 +02:00
}
#[ cfg(test) ]
mod test { }