diff --git a/README.md b/README.md index 40ee492..094cf79 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,6 @@ - [ ] Allow sign-outs only >2h before event # Notes / Bugfixes -- [ ] Allow cox to edit own trip - - [x] Nobody has registered yet -> deletable - - [ ] Change max_people (to be settable to 0) - - [ ] Change note # Frontend Process ´cd frontend´ diff --git a/src/model/trip.rs b/src/model/trip.rs index 4b26e75..efcad68 100644 --- a/src/model/trip.rs +++ b/src/model/trip.rs @@ -112,6 +112,45 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i } } + /// Cox decides to update own trip. + pub async fn update_own( + db: &SqlitePool, + cox_id: i64, + trip_id: i64, + max_people: i32, + notes: Option<String>, + ) -> Result<(), TripUpdateError> { + if !Self::is_trip_from_user(db, cox_id, trip_id).await { + return Err(TripUpdateError::NotYourTrip); + } + + let trip_details = sqlx::query!( + "SELECT trip_details_id as id FROM trip WHERE id = ?", + trip_id + ) + .fetch_one(db) + .await + .unwrap(); //TODO: fixme + let trip_details_id = match trip_details.id { + Some(id) => id, + None => { + return Err(TripUpdateError::TripDoesNotExist); + } + }; + + sqlx::query!( + "UPDATE trip_details SET max_people = ?, notes = ? WHERE id = ?", + max_people, + notes, + trip_details_id + ) + .execute(db) + .await + .unwrap(); //TODO: fixme + + Ok(()) + } + pub async fn delete_by_planned_event_id(db: &SqlitePool, user_id: i64, planned_event_id: i64) { let _ = sqlx::query!( "DELETE FROM trip WHERE cox_id = ? AND planned_event_id = ?", @@ -133,11 +172,7 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i return Err(TripDeleteError::SomebodyAlreadyRegistered); } - let trip_cox = sqlx::query!("SELECT cox_id FROM trip WHERE id = ?", trip_id) - .fetch_one(db) - .await - .unwrap(); //TODO: fixme - if trip_cox.cox_id != user_id { + if !Self::is_trip_from_user(db, user_id, trip_id).await { return Err(TripDeleteError::NotYourTrip); } @@ -152,6 +187,14 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM trip WHERE i Ok(()) } + + async fn is_trip_from_user(db: &SqlitePool, user_id: i64, trip_id: i64) -> bool { + let trip_cox = sqlx::query!("SELECT cox_id FROM trip WHERE id = ?", trip_id) + .fetch_one(db) + .await + .unwrap(); //TODO: fixme + trip_cox.cox_id == user_id + } } pub enum CoxHelpError { @@ -163,3 +206,8 @@ pub enum TripDeleteError { SomebodyAlreadyRegistered, NotYourTrip, } + +pub enum TripUpdateError { + NotYourTrip, + TripDoesNotExist, +} diff --git a/src/rest/cox.rs b/src/rest/cox.rs index 68b986b..8085480 100644 --- a/src/rest/cox.rs +++ b/src/rest/cox.rs @@ -7,7 +7,7 @@ use rocket::{ use sqlx::SqlitePool; use crate::model::{ - trip::{CoxHelpError, Trip, TripDeleteError}, + trip::{CoxHelpError, Trip, TripDeleteError, TripUpdateError}, tripdetails::TripDetails, user::CoxUser, }; @@ -36,7 +36,31 @@ async fn create(db: &State<SqlitePool>, data: Form<AddTripForm>, cox: CoxUser) - //TODO: fix clone() Trip::new_own(db, cox.id, trip_details_id).await; - Flash::success(Redirect::to("/"), "Successfully planned the event") + Flash::success(Redirect::to("/"), "Ausfahrt erfolgreich erstellt.") +} + +#[derive(FromForm)] +struct EditTripForm { + max_people: i32, + notes: Option<String>, +} + +#[post("/trip/<trip_id>", data = "<data>")] +async fn update( + db: &State<SqlitePool>, + data: Form<EditTripForm>, + trip_id: i64, + cox: CoxUser, +) -> Flash<Redirect> { + match Trip::update_own(db, cox.id, trip_id, data.max_people, data.notes.clone()).await { + Ok(_) => Flash::success(Redirect::to("/"), "Ausfahrt erfolgreich aktualisiert."), + Err(TripUpdateError::NotYourTrip) => { + Flash::error(Redirect::to("/"), "Nicht deine Ausfahrt!") + } + Err(TripUpdateError::TripDoesNotExist) => { + Flash::error(Redirect::to("/"), "Ausfahrt gibt's nicht") + } + } } #[get("/join/<planned_event_id>")] @@ -75,5 +99,5 @@ async fn remove(db: &State<SqlitePool>, planned_event_id: i64, cox: CoxUser) -> } pub fn routes() -> Vec<Route> { - routes![create, join, remove, remove_trip] + routes![create, join, remove, remove_trip, update] } diff --git a/src/rest/mod.rs b/src/rest/mod.rs index 85777ae..16ca6a8 100644 --- a/src/rest/mod.rs +++ b/src/rest/mod.rs @@ -29,10 +29,11 @@ async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_ let end_of_year = NaiveDate::from_ymd_opt(Local::now().year(), 12, 31).unwrap(); show_next_n_days = end_of_year .signed_duration_since(Local::now().date_naive()) - .num_days(); + .num_days() + + 1; } - for i in 0..show_next_n_days + 1 { + for i in 0..show_next_n_days { let date = (Local::now() + Duration::days(i)).date_naive(); days.push(Day::new(db, date).await); } diff --git a/templates/index.html.tera b/templates/index.html.tera index fc02ebf..dd7b0e3 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -180,23 +180,35 @@ </div> <div class="px-2 pt-2" style="margin-top: 63px; margin-bottom: 157px"> {% if trip.max_people > 0 %} - <div class="text-primay-900 bg-primary-100 text-center p-1 mt-1 rounded-t-md">{{ trip.max_people }} - {{ - trip.rower | length }} Ruderer können teilnehmen ({{ trip.max_people }})</div> - <div class="p-2 border border-t-0 border-primary-100 mb-4 rounded-b-md"> - {% if trip.rower | length > 0 %} - {% for rower in trip.rower %} - {{ rower.name }} <span class="hidden">(angemeldet seit {{ rower.registered_at }})</span><br /> - {% endfor %} - {% else %} - Keine Ruderer angemeldet - <div class="text-right mt-2"> - <a href="/cox/remove/trip/{{ trip.id }}" class="inline-block btn btn-alert"> - {% include "includes/delete-icon" %} - Termin löschen - </a> - </div> - {% endif %} - </div> + <div class="text-primay-900 bg-primary-100 text-center p-1 mt-1 rounded-t-md">{{ trip.max_people }} - {{ + trip.rower | length }} Ruderer können teilnehmen ({{ trip.max_people }})</div> + <div class="p-2 border border-t-0 border-primary-100 mb-4 rounded-b-md"> + {% if trip.rower | length > 0 %} + {% for rower in trip.rower %} + {{ rower.name }} <span class="hidden">(angemeldet seit {{ rower.registered_at }})</span><br /> + {% endfor %} + {% else %} + Keine Ruderer angemeldet + {% endif %} + </div> + {% if trip.cox_id == loggedin_user.id %} + {% if trip.rower | length == 0 %} + <div class="text-right mt-2"> + <a href="/cox/remove/trip/{{ trip.id }}" class="inline-block btn btn-alert"> + {% include "includes/delete-icon" %} + Termin löschen + </a> + </div> + {% endif %} + <div> + <h3>Edit trip</h3> + <form action="/cox/trip/{{ trip.id }}" method="post"> + Ruderer: <input type="number" name="max_people" required value="{{ trip.max_people }}" /><br /> + Notes: <input type="text" name="notes" required value="{{ trip.notes }}" /><br /> + <input type="submit" /> + </form> + </div> + {% endif %} {% endif %} </div> </div>