allow-reservation-edits #423
@ -1,6 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
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};
|
||||||
@ -204,6 +205,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)
|
||||||
|
@ -14,7 +14,8 @@ use crate::{
|
|||||||
model::{
|
model::{
|
||||||
boat::Boat,
|
boat::Boat,
|
||||||
boatreservation::{BoatReservation, BoatReservationToAdd},
|
boatreservation::{BoatReservation, BoatReservationToAdd},
|
||||||
user::{DonauLinzUser, User, UserWithRolesAndNotificationCount},
|
log::Log,
|
||||||
|
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
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 />
|
||||||
<strong>Uhrzeit:</strong>
|
{% if not allowed_to_edit %}
|
||||||
{{ reservation.time_desc }}
|
<strong>Uhrzeit:</strong>
|
||||||
<br />
|
{{ reservation.time_desc }}
|
||||||
<strong>Zweck:</strong>
|
<br />
|
||||||
{{ reservation.usage }}
|
<strong>Zweck:</strong>
|
||||||
{% if loggedin_user %}
|
{{ reservation.usage }}
|
||||||
{% if loggedin_user.id == reservation.user_applicant.id or "admin" in loggedin_user.roles %}
|
{% 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">
|
<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>
|
||||||
|
Loading…
Reference in New Issue
Block a user