use chrono::NaiveDate; use rocket::{ form::Form, get, post, request::FlashMessage, response::{Flash, Redirect}, routes, FromForm, Route, State, }; use rocket_dyn_templates::Template; use sqlx::SqlitePool; use tera::Context; use crate::{ model::{ log::Log, trailer::Trailer, trailerreservation::{TrailerReservation, TrailerReservationToAdd}, user::{DonauLinzUser, User, UserWithDetails}, }, tera::log::KioskCookie, }; #[get("/")] async fn index_kiosk( db: &State, flash: Option>, _kiosk: KioskCookie, ) -> Template { let trailerreservations = TrailerReservation::all_future(db).await; let mut context = Context::new(); if let Some(msg) = flash { context.insert("flash", &msg.into_inner()); } context.insert("trailerreservations", &trailerreservations); context.insert("trailers", &Trailer::all(db).await); context.insert("user", &User::all(db).await); context.insert("show_kiosk_header", &true); Template::render("trailerreservations", context.into_json()) } #[get("/", rank = 2)] async fn index( db: &State, flash: Option>, user: DonauLinzUser, ) -> Template { let trailerreservations = TrailerReservation::all_future(db).await; let mut context = Context::new(); if let Some(msg) = flash { context.insert("flash", &msg.into_inner()); } context.insert("trailerreservations", &trailerreservations); context.insert("trailers", &Trailer::all(db).await); context.insert("user", &User::all(db).await); context.insert( "loggedin_user", &UserWithDetails::from_user(user.into(), db).await, ); Template::render("trailerreservations", context.into_json()) } #[derive(Debug, FromForm)] pub struct FormTrailerReservationToAdd<'r> { pub trailer_id: i64, pub start_date: &'r str, pub end_date: &'r str, pub time_desc: &'r str, pub usage: &'r str, pub user_id_applicant: Option, } #[post("/new", data = "", rank = 2)] async fn create<'r>( db: &State, data: Form>, user: DonauLinzUser, ) -> Flash { let user_applicant: User = user.into(); let trailer = Trailer::find_by_id(db, data.trailer_id as i32) .await .unwrap(); let trailerreservation_to_add = TrailerReservationToAdd { trailer: &trailer, start_date: NaiveDate::parse_from_str(data.start_date, "%Y-%m-%d").unwrap(), end_date: NaiveDate::parse_from_str(data.end_date, "%Y-%m-%d").unwrap(), time_desc: data.time_desc, usage: data.usage, user_applicant: &user_applicant, }; match TrailerReservation::create(db, trailerreservation_to_add).await { Ok(_) => Flash::success( Redirect::to("/trailerreservation"), "Reservierung erfolgreich hinzugefügt", ), Err(e) => Flash::error(Redirect::to("/trailerreservation"), format!("Fehler: {e}")), } } #[post("/new", data = "")] async fn create_from_kiosk<'r>( db: &State, data: Form>, _kiosk: KioskCookie, ) -> Flash { let user_applicant: User = User::find_by_id(db, data.user_id_applicant.unwrap() as i32) .await .unwrap(); let trailer = Trailer::find_by_id(db, data.trailer_id as i32) .await .unwrap(); let trailerreservation_to_add = TrailerReservationToAdd { trailer: &trailer, start_date: NaiveDate::parse_from_str(data.start_date, "%Y-%m-%d").unwrap(), end_date: NaiveDate::parse_from_str(data.end_date, "%Y-%m-%d").unwrap(), time_desc: data.time_desc, usage: data.usage, user_applicant: &user_applicant, }; match TrailerReservation::create(db, trailerreservation_to_add).await { Ok(_) => Flash::success( Redirect::to("/trailerreservation"), "Reservierung erfolgreich hinzugefügt", ), Err(e) => Flash::error(Redirect::to("/trailerreservation"), format!("Fehler: {e}")), } } #[derive(FromForm, Debug)] pub struct ReservationEditForm { pub(crate) id: i32, pub(crate) time_desc: String, pub(crate) usage: String, } #[post("/", data = "")] async fn update( db: &State, data: Form, user: User, ) -> Flash { let Some(reservation) = TrailerReservation::find_by_id(db, data.id).await else { return Flash::error( Redirect::to("/trailerreservation"), format!("Reservation with ID {} does not exist!", data.id), ); }; if user.id != reservation.user_id_applicant && !user.has_role(db, "admin").await { return Flash::error( Redirect::to("/trailerreservation"), "Not allowed to update reservation (only admins + creator do so).".to_string(), ); } Log::create( db, format!( "{} updated reservation from {reservation:?} to {data:?}", user.name ), ) .await; reservation.update(db, data.into_inner()).await; Flash::success( Redirect::to("/trailerreservation"), "Reservierung erfolgreich bearbeitet", ) } #[get("//delete")] async fn delete<'r>( db: &State, reservation_id: i32, user: DonauLinzUser, ) -> Flash { let reservation = TrailerReservation::find_by_id(db, reservation_id) .await .unwrap(); if user.id == reservation.user_id_applicant || user.has_role(db, "admin").await { reservation.delete(db).await; Flash::success( Redirect::to("/trailerreservation"), "Reservierung erfolgreich gelöscht", ) } else { Flash::error( Redirect::to("/trailerreservation"), "Nur der Reservierer darf die Reservierung löschen.".to_string(), ) } } pub fn routes() -> Vec { routes![ index, index_kiosk, create, create_from_kiosk, delete, update ] }