allow-reservation-edits #424

Merged
philipp merged 21 commits from allow-reservation-edits into main 2024-04-23 23:23:13 +02:00
4 changed files with 96 additions and 13 deletions
Showing only changes of commit 61261c9816 - Show all commits

View File

@ -1,4 +1,5 @@
use crate::model::{boat::Boat, user::User}; use crate::model::{boat::Boat, user::User};
use crate::tera::boatreservation::ReservationEditForm;
use chrono::NaiveDate; use chrono::NaiveDate;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use rocket::serde::{Deserialize, Serialize}; use rocket::serde::{Deserialize, Serialize};
@ -177,6 +178,20 @@ AND start_date <= ? AND end_date >= ?;",
> 0 > 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) { pub async fn delete(&self, db: &SqlitePool) {
sqlx::query!("DELETE FROM boat_reservation WHERE id=?", self.id) sqlx::query!("DELETE FROM boat_reservation WHERE id=?", self.id)
.execute(db) .execute(db)

View File

@ -14,6 +14,7 @@ use crate::{
model::{ model::{
boat::Boat, boat::Boat,
boatreservation::{BoatReservation, BoatReservationToAdd}, boatreservation::{BoatReservation, BoatReservationToAdd},
log::Log,
user::{DonauLinzUser, User, UserWithRoles}, user::{DonauLinzUser, User, UserWithRoles},
}, },
tera::log::KioskCookie, tera::log::KioskCookie,
@ -90,7 +91,7 @@ pub struct FormBoatReservationToAdd<'r> {
pub user_id_applicant: Option<i64>, pub user_id_applicant: Option<i64>,
} }
#[post("/", data = "<data>", rank = 2)] #[post("/new", data = "<data>", rank = 2)]
async fn create<'r>( async fn create<'r>(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<FormBoatReservationToAdd<'r>>, 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>( async fn create_from_kiosk<'r>(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<FormBoatReservationToAdd<'r>>, 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")] #[get("/<reservation_id>/delete")]
async fn delete<'r>( async fn delete<'r>(
db: &State<SqlitePool>, db: &State<SqlitePool>,
@ -167,5 +212,12 @@ async fn delete<'r>(
} }
pub fn routes() -> Vec<Route> { pub fn routes() -> Vec<Route> {
routes![index, index_kiosk, create, create_from_kiosk, delete] routes![
index,
index_kiosk,
create,
create_from_kiosk,
delete,
update
]
} }

View File

@ -30,7 +30,7 @@ pub(crate) mod admin;
mod auth; mod auth;
pub(crate) mod board; pub(crate) mod board;
mod boatdamage; mod boatdamage;
mod boatreservation; pub(crate) mod boatreservation;
mod cox; mod cox;
mod ergo; mod ergo;
mod log; mod log;

View File

@ -18,7 +18,7 @@
</h2> </h2>
<div class="hidden"> <div class="hidden">
<div id="new-reservation"> <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') }} {{ log::boat_select(only_ones=false, id='boat') }}
{% if not loggedin_user %}{{ macros::select(label='Reserviert von', data=user, name='user_id_applicant') }}{% endif %} {% 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') }} {{ macros::input(label='Beginn', name='start_date', type='date', required=true, wrapper_class='col-span-4') }}
@ -41,6 +41,12 @@
</div> </div>
<div id="filter-result-js" class="search-result"></div> <div id="filter-result-js" class="search-result"></div>
{% for reservation in boatreservations %} {% 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" <div data-filterable="true"
data-filter="{{ reservation.user_applicant.name }} {{ reservation.boat.name }}" 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"> 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 }} {{ reservation.end_date }}
{% endif %} {% endif %}
<br /> <br />
{% if not allowed_to_edit %}
<strong>Uhrzeit:</strong> <strong>Uhrzeit:</strong>
{{ reservation.time_desc }} {{ reservation.time_desc }}
<br /> <br />
<strong>Zweck:</strong> <strong>Zweck:</strong>
{{ reservation.usage }} {{ reservation.usage }}
{% if loggedin_user %} {% endif %}
{% if loggedin_user.id == reservation.user_applicant.id or "admin" in loggedin_user.roles %} {% if allowed_to_edit %}
<form action="/boatreservation"
method="post"
class="bg-white dark:bg-primary-900 p-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"> <div class="mt-3 text-right">
<a href="/boatreservation/{{ reservation.id }}/delete" <a href="/boatreservation/{{ reservation.id }}/delete"
class="w-28 btn btn-alert" class="w-28 btn btn-alert"
@ -72,8 +87,9 @@
{% include "includes/delete-icon" %} {% include "includes/delete-icon" %}
Löschen Löschen
</a> </a>
<input value="Ändern" type="submit" class="w-28 btn btn-primary ml-1" />
</div> </div>
{% endif %} </form>
{% endif %} {% endif %}
</div> </div>
</div> </div>