handoperatable-feature #432
| @@ -1,6 +1,7 @@ | ||||
| use std::collections::HashMap; | ||||
|  | ||||
| use crate::model::{boat::Boat, user::User}; | ||||
| use crate::tera::boatreservation::ReservationEditForm; | ||||
| use chrono::NaiveDate; | ||||
| use chrono::NaiveDateTime; | ||||
| use rocket::serde::{Deserialize, Serialize}; | ||||
| @@ -204,6 +205,20 @@ AND start_date <= ? AND end_date >= ?;", | ||||
|             > 0 | ||||
|     } | ||||
|  | ||||
|     pub async fn update(&self, db: &SqlitePool, data: ReservationEditForm) { | ||||
|         let time_desc = data.time_desc.trim(); | ||||
|         let usage = data.usage.trim(); | ||||
|         sqlx::query!( | ||||
|             "UPDATE boat_reservation SET time_desc = ?, usage = ? where id = ?", | ||||
|             time_desc, | ||||
|             usage, | ||||
|             self.id | ||||
|         ) | ||||
|         .execute(db) | ||||
|         .await | ||||
|         .unwrap(); //Okay, because we can only create a User of a valid id | ||||
|     } | ||||
|  | ||||
|     pub async fn delete(&self, db: &SqlitePool) { | ||||
|         sqlx::query!("DELETE FROM boat_reservation WHERE id=?", self.id) | ||||
|             .execute(db) | ||||
|   | ||||
| @@ -14,7 +14,8 @@ use crate::{ | ||||
|     model::{ | ||||
|         boat::Boat, | ||||
|         boatreservation::{BoatReservation, BoatReservationToAdd}, | ||||
|         user::{DonauLinzUser, User, UserWithRolesAndNotificationCount}, | ||||
|         log::Log, | ||||
|         user::{DonauLinzUser, User, UserWithRoles}, | ||||
|     }, | ||||
|     tera::log::KioskCookie, | ||||
| }; | ||||
| @@ -90,7 +91,7 @@ pub struct FormBoatReservationToAdd<'r> { | ||||
|     pub user_id_applicant: Option<i64>, | ||||
| } | ||||
|  | ||||
| #[post("/", data = "<data>", rank = 2)] | ||||
| #[post("/new", data = "<data>", rank = 2)] | ||||
| async fn create<'r>( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<FormBoatReservationToAdd<'r>>, | ||||
| @@ -115,7 +116,7 @@ async fn create<'r>( | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[post("/", data = "<data>")] | ||||
| #[post("/new", data = "<data>")] | ||||
| async fn create_from_kiosk<'r>( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<FormBoatReservationToAdd<'r>>, | ||||
| @@ -142,6 +143,50 @@ async fn create_from_kiosk<'r>( | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(FromForm, Debug)] | ||||
| pub struct ReservationEditForm { | ||||
|     pub(crate) id: i32, | ||||
|     pub(crate) time_desc: String, | ||||
|     pub(crate) usage: String, | ||||
| } | ||||
|  | ||||
| #[post("/", data = "<data>")] | ||||
| async fn update( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<ReservationEditForm>, | ||||
|     user: User, | ||||
| ) -> Flash<Redirect> { | ||||
|     let Some(reservation) = BoatReservation::find_by_id(db, data.id).await else { | ||||
|         return Flash::error( | ||||
|             Redirect::to("/boatreservation"), | ||||
|             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("/boatreservation"), | ||||
|             format!("Not allowed to update reservation (only admins + creator do so)."), | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     Log::create( | ||||
|         db, | ||||
|         format!( | ||||
|             "{} updated reservation from {reservation:?} to {data:?}", | ||||
|             user.name | ||||
|         ), | ||||
|     ) | ||||
|     .await; | ||||
|  | ||||
|     reservation.update(db, data.into_inner()).await; | ||||
|  | ||||
|     Flash::success( | ||||
|         Redirect::to("/boatreservation"), | ||||
|         "Reservierung erfolgreich bearbeitet", | ||||
|     ) | ||||
| } | ||||
|  | ||||
| #[get("/<reservation_id>/delete")] | ||||
| async fn delete<'r>( | ||||
|     db: &State<SqlitePool>, | ||||
| @@ -167,5 +212,12 @@ async fn delete<'r>( | ||||
| } | ||||
|  | ||||
| pub fn routes() -> Vec<Route> { | ||||
|     routes![index, index_kiosk, create, create_from_kiosk, delete] | ||||
|     routes![ | ||||
|         index, | ||||
|         index_kiosk, | ||||
|         create, | ||||
|         create_from_kiosk, | ||||
|         delete, | ||||
|         update | ||||
|     ] | ||||
| } | ||||
|   | ||||
| @@ -30,7 +30,7 @@ pub(crate) mod admin; | ||||
| mod auth; | ||||
| pub(crate) mod board; | ||||
| mod boatdamage; | ||||
| mod boatreservation; | ||||
| pub(crate) mod boatreservation; | ||||
| mod cox; | ||||
| mod ergo; | ||||
| mod log; | ||||
|   | ||||
| @@ -18,7 +18,7 @@ | ||||
|         </h2> | ||||
|         <div class="hidden"> | ||||
|             <div id="new-reservation"> | ||||
|                 <form action="/boatreservation" method="post" class="grid gap-3"> | ||||
|                 <form action="/boatreservation/new" method="post" class="grid gap-3"> | ||||
|                     {{ log::boat_select(only_ones=false, id='boat') }} | ||||
|                     {% if not loggedin_user %}{{ macros::select(label='Reserviert von', data=user, name='user_id_applicant') }}{% endif %} | ||||
|                     {{ macros::input(label='Beginn', name='start_date', type='date', required=true, wrapper_class='col-span-4') }} | ||||
| @@ -41,6 +41,12 @@ | ||||
|         </div> | ||||
|         <div id="filter-result-js" class="search-result"></div> | ||||
|         {% for reservation in boatreservations %} | ||||
|             {% set allowed_to_edit = false %} | ||||
|             {% if loggedin_user %} | ||||
|                 {% if loggedin_user.id == reservation.user_applicant.id or "admin" in loggedin_user.roles %} | ||||
|                     {% set allowed_to_edit = true %} | ||||
|                 {% endif %} | ||||
|             {% endif %} | ||||
|             <div data-filterable="true" | ||||
|                  data-filter="{{ reservation.user_applicant.name }} {{ reservation.boat.name }}" | ||||
|                  class="w-full border-t bg-white dark:bg-primary-900 text-black dark:text-white p-3"> | ||||
| @@ -58,13 +64,22 @@ | ||||
|                         {{ reservation.end_date }} | ||||
|                     {% endif %} | ||||
|                     <br /> | ||||
|                     <strong>Uhrzeit:</strong> | ||||
|                     {{ reservation.time_desc }} | ||||
|                     <br /> | ||||
|                     <strong>Zweck:</strong> | ||||
|                     {{ reservation.usage }} | ||||
|                     {% if loggedin_user %} | ||||
|                         {% if loggedin_user.id == reservation.user_applicant.id or "admin" in loggedin_user.roles %} | ||||
|                     {% if not allowed_to_edit %} | ||||
|                         <strong>Uhrzeit:</strong> | ||||
|                         {{ reservation.time_desc }} | ||||
|                         <br /> | ||||
|                         <strong>Zweck:</strong> | ||||
|                         {{ reservation.usage }} | ||||
|                     {% endif %} | ||||
|                     {% if allowed_to_edit %} | ||||
|                         <form action="/boatreservation" | ||||
|                               method="post" | ||||
|                               class="bg-white dark:bg-primary-900 pt-3 rounded-md w-full"> | ||||
|                             <div class="w-full grid gap-3"> | ||||
|                                 <input type="hidden" name="id" value="{{ reservation.id }}" /> | ||||
|                                 {{ macros::input(label='Uhrzeit', name='time_desc', id=loop.index, type="text", value=reservation.time_desc, readonly=false) }} | ||||
|                                 {{ macros::input(label='Zweck', name='usage', id=loop.index, type="text", value=reservation.usage, readonly=false) }} | ||||
|                             </div> | ||||
|                             <div class="mt-3 text-right"> | ||||
|                                 <a href="/boatreservation/{{ reservation.id }}/delete" | ||||
|                                    class="w-28 btn btn-alert" | ||||
| @@ -72,8 +87,9 @@ | ||||
|                                     {% include "includes/delete-icon" %} | ||||
|                                     Löschen | ||||
|                                 </a> | ||||
|                                 <input value="Ändern" type="submit" class="w-28 btn btn-primary ml-1" /> | ||||
|                             </div> | ||||
|                         {% endif %} | ||||
|                         </form> | ||||
|                     {% endif %} | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user