diff --git a/src/model/boat.rs b/src/model/boat.rs index 19e2b89..585ceef 100644 --- a/src/model/boat.rs +++ b/src/model/boat.rs @@ -1,3 +1,4 @@ +use rocket::FromForm; use serde::{Deserialize, Serialize}; use sqlx::{FromRow, SqlitePool}; @@ -18,36 +19,46 @@ pub struct Boat { external: bool, } +#[derive(FromForm)] +pub struct BoatToAdd<'r> { + pub name: &'r str, + pub amount_seats: i64, + pub year_built: Option, + pub boatbuilder: Option<&'r str>, + pub default_shipmaster_only_steering: bool, + pub skull: bool, + pub external: bool, + pub location_id: Option, + pub owner: Option, +} + +#[derive(FromForm)] +pub struct BoatToUpdate<'r> { + pub id: i32, + pub name: &'r str, + pub amount_seats: i64, + pub year_built: Option, + pub boatbuilder: Option<&'r str>, + pub default_shipmaster_only_steering: bool, + pub skull: bool, + pub external: bool, + pub location_id: Option, + pub owner: Option, +} + impl Boat { pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option { sqlx::query_as!( Self, - " - SELECT id, name, amount_seats, location_id, owner, year_built, boatbuilder, default_shipmaster_only_steering, skull, external - FROM boat - WHERE id like ? - ", + "SELECT id, name, amount_seats, location_id, owner, year_built, boatbuilder, default_shipmaster_only_steering, skull, external + FROM boat + WHERE id like ?", id ) .fetch_one(db) .await .ok() } - // - // pub async fn find_by_name(db: &SqlitePool, name: &str) -> Option { - // sqlx::query_as!( - // User, - // " - //SELECT id, name, pw, is_cox, is_admin, is_guest, deleted, last_access - //FROM user - //WHERE name like ? - // ", - // name - // ) - // .fetch_one(db) - // .await - // .ok() - // } pub async fn is_locked(&self, db: &SqlitePool) -> bool { sqlx::query!("SELECT * FROM boat_damage WHERE boat_id=? AND lock_boat=true AND user_id_verified is null", self.id).fetch_optional(db).await.unwrap().is_some() @@ -78,58 +89,35 @@ ORDER BY amount_seats DESC .unwrap() //TODO: fixme } - pub async fn create( - db: &SqlitePool, - name: &str, - amount_seats: i64, - year_built: Option, - boatbuilder: Option<&str>, - default_shipmaster_only_steering: bool, - skull: bool, - external: bool, - location_id: Option, - owner: Option, - ) -> bool { + pub async fn create(db: &SqlitePool, boat: BoatToAdd<'_>) -> bool { sqlx::query!( "INSERT INTO boat(name, amount_seats, year_built, boatbuilder, default_shipmaster_only_steering, skull, external, location_id, owner) VALUES (?,?,?,?,?,?,?,?,?)", - name, - amount_seats, - year_built, - boatbuilder, - default_shipmaster_only_steering, - skull, - external, - location_id, - owner + boat.name, + boat.amount_seats, + boat.year_built, + boat.boatbuilder, + boat.default_shipmaster_only_steering, + boat.skull, + boat.external, + boat.location_id, + boat.owner ) .execute(db) .await.is_ok() } - pub async fn update( - &self, - db: &SqlitePool, - name: &str, - amount_seats: i64, - year_built: Option, - boatbuilder: Option<&str>, - default_shipmaster_only_steering: bool, - skull: bool, - external: bool, - location_id: Option, - owner: Option, - ) -> bool { + pub async fn update(&self, db: &SqlitePool, boat: BoatToUpdate<'_>) -> bool { sqlx::query!( "UPDATE boat SET name=?, amount_seats=?, year_built=?, boatbuilder=?, default_shipmaster_only_steering=?, skull=?, external=?, location_id=?, owner=? WHERE id=?", - name, - amount_seats, - year_built, - boatbuilder, - default_shipmaster_only_steering, - skull, - external, - location_id, - owner, + boat.name, + boat.amount_seats, + boat.year_built, + boat.boatbuilder, + boat.default_shipmaster_only_steering, + boat.skull, + boat.external, + boat.location_id, + boat.owner, self.id ) .execute(db) @@ -141,13 +129,16 @@ ORDER BY amount_seats DESC sqlx::query!("DELETE FROM boat WHERE id=?", self.id) .execute(db) .await - .unwrap(); //Okay, because we can only create a User of a valid id + .unwrap(); //Okay, because we can only create a Boat of a valid id } } #[cfg(test)] mod test { - use crate::{model::boat::Boat, testdb}; + use crate::{ + model::boat::{Boat, BoatToAdd}, + testdb, + }; use sqlx::SqlitePool; @@ -179,15 +170,17 @@ mod test { assert_eq!( Boat::create( &pool, - "new-boat-name".into(), - 42, - None, - "Best Boatbuilder".into(), - true, - true, - false, - Some(1), - None + BoatToAdd { + name: "new-boat-name".into(), + amount_seats: 42, + year_built: None, + boatbuilder: "Best Boatbuilder".into(), + default_shipmaster_only_steering: true, + skull: true, + external: false, + location_id: Some(1), + owner: None + } ) .await, true @@ -201,15 +194,17 @@ mod test { assert_eq!( Boat::create( &pool, - "Haichenbach".into(), - 42, - None, - "Best Boatbuilder".into(), - true, - true, - false, - Some(1), - None + BoatToAdd { + name: "Haichenbach".into(), + amount_seats: 42, + year_built: None, + boatbuilder: "Best Boatbuilder".into(), + default_shipmaster_only_steering: true, + skull: true, + external: false, + location_id: Some(1), + owner: None + } ) .await, false diff --git a/src/model/location.rs b/src/model/location.rs index b0e69c3..a66d810 100644 --- a/src/model/location.rs +++ b/src/model/location.rs @@ -24,20 +24,14 @@ impl Location { } pub async fn all(db: &SqlitePool) -> Vec { - sqlx::query_as!( - Self, - " -SELECT id, name -FROM location - " - ) - .fetch_all(db) - .await - .unwrap() //TODO: fixme + sqlx::query_as!(Self, "SELECT id, name FROM location") + .fetch_all(db) + .await + .unwrap() //TODO: fixme } pub async fn create(db: &SqlitePool, name: &str) -> bool { - sqlx::query!("INSERT INTO location(name) VALUES (?)", name,) + sqlx::query!("INSERT INTO location(name) VALUES (?)", name) .execute(db) .await .is_ok() diff --git a/src/model/logbook.rs b/src/model/logbook.rs index 1aa60ef..9406ae0 100644 --- a/src/model/logbook.rs +++ b/src/model/logbook.rs @@ -1,6 +1,7 @@ use chrono::NaiveDateTime; +use rocket::FromForm; use serde::Serialize; -use sqlx::{FromRow, SqlitePool}; +use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use super::{boat::Boat, rower::Rower, user::User}; @@ -19,6 +20,29 @@ pub struct Logbook { pub logtype: Option, } +#[derive(FromForm)] +pub struct LogToAdd { + pub boat_id: i32, + pub shipmaster: i64, + pub shipmaster_only_steering: bool, + pub departure: String, + pub arrival: Option, + pub destination: Option, + pub distance_in_km: Option, + pub comments: Option, + pub logtype: Option, + pub rower: Vec, +} + +#[derive(FromForm)] +pub struct LogToFinalize { + pub destination: String, + pub distance_in_km: i64, + pub comments: Option, + pub logtype: Option, + pub rower: Vec, +} + #[derive(Serialize)] pub struct LogbookWithBoatAndRowers { #[serde(flatten)] @@ -56,21 +80,6 @@ impl Logbook { .ok() } - // pub async fn find_by_name(db: &SqlitePool, name: &str) -> Option { - // sqlx::query_as!( - // User, - // " - //SELECT id, name, pw, is_cox, is_admin, is_guest, deleted, last_access - //FROM user - //WHERE name like ? - // ", - // name - // ) - // .fetch_one(db) - // .await - // .ok() - // } - // pub async fn on_water(db: &SqlitePool) -> Vec { let logs = sqlx::query_as!( Logbook, @@ -123,20 +132,8 @@ impl Logbook { ret } - pub async fn create( - db: &SqlitePool, - boat_id: i32, - shipmaster: i64, - shipmaster_only_steering: bool, - departure: NaiveDateTime, - arrival: Option, - destination: Option, - distance_in_km: Option, - comments: Option, - logtype: Option, - rower: Vec, - ) -> Result<(), LogbookCreateError> { - let boat = match Boat::find_by_id(db, boat_id).await { + pub async fn create(db: &SqlitePool, log: LogToAdd) -> Result<(), LogbookCreateError> { + let boat = match Boat::find_by_id(db, log.boat_id).await { Some(b) => b, None => { return Err(LogbookCreateError::BoatNotFound); @@ -151,27 +148,44 @@ impl Logbook { return Err(LogbookCreateError::BoatAlreadyOnWater); } - if rower.len() > boat.amount_seats as usize - 1 { + if log.rower.len() > boat.amount_seats as usize - 1 { return Err(LogbookCreateError::TooManyRowers( boat.amount_seats as usize, - rower.len() + 1, + log.rower.len() + 1, )); } + let mut tx = db.begin().await.unwrap(); + + let departure = NaiveDateTime::parse_from_str(&log.departure, "%Y-%m-%dT%H:%M").unwrap(); + let arrival = log + .arrival + .map(|a| NaiveDateTime::parse_from_str(&a, "%Y-%m-%dT%H:%M").unwrap()); let inserted_row = sqlx::query!( "INSERT INTO logbook(boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype) VALUES (?,?,?,?,?,?,?,?,?) RETURNING id", - boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype + log.boat_id, + log.shipmaster, + log.shipmaster_only_steering, + departure, + arrival, + log.destination, + log.distance_in_km, + log.comments, + log.logtype ) - .fetch_one(db) + .fetch_one(&mut tx) .await.unwrap(); - for rower in &rower { - Rower::create(db, inserted_row.id, *rower).await; + for rower in &log.rower { + Rower::create(&mut tx, inserted_row.id, *rower).await; } + + tx.commit().await.unwrap(); + Ok(()) } - async fn remove_rowers(&self, db: &SqlitePool) { + async fn remove_rowers(&self, db: &mut Transaction<'_, Sqlite>) { sqlx::query!("DELETE FROM rower WHERE logbook_id=?", self.id) .execute(db) .await @@ -182,11 +196,7 @@ impl Logbook { &self, db: &SqlitePool, user: &User, - destination: String, - distance_in_km: i64, - comments: Option, - logtype: Option, - rower: Vec, + log: LogToFinalize, ) -> Result<(), LogbookUpdateError> { if user.id != self.shipmaster { return Err(LogbookUpdateError::NotYourEntry); @@ -194,35 +204,37 @@ impl Logbook { let boat = Boat::find_by_id(db, self.boat_id as i32).await.unwrap(); //ok - if rower.len() > boat.amount_seats as usize - 1 { + if log.rower.len() > boat.amount_seats as usize - 1 { return Err(LogbookUpdateError::TooManyRowers( boat.amount_seats as usize, - rower.len() + 1, + log.rower.len() + 1, )); } - //TODO: check current date - let arrival = format!("{}", chrono::offset::Local::now().format("%Y-%m-%d %H:%M")); + let mut tx = db.begin().await.unwrap(); + sqlx::query!( "UPDATE logbook SET destination=?, distance_in_km=?, comments=?, logtype=?, arrival=? WHERE id=?", - destination, - distance_in_km, - comments, - logtype, + log.destination, + log.distance_in_km, + log.comments, + log.logtype, arrival, self.id ) - .execute(db) + .execute(&mut tx) .await.unwrap(); //TODO: fixme - self.remove_rowers(db).await; + self.remove_rowers(&mut tx).await; - for rower in &rower { - Rower::create(db, self.id, *rower).await; + for rower in &log.rower { + Rower::create(&mut tx, self.id, *rower).await; } + tx.commit().await.unwrap(); + Ok(()) } diff --git a/src/model/rower.rs b/src/model/rower.rs index 4bcdc69..f2b4f78 100644 --- a/src/model/rower.rs +++ b/src/model/rower.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use sqlx::{FromRow, SqlitePool}; +use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use super::{logbook::Logbook, user::User}; @@ -10,21 +10,6 @@ pub struct Rower { } impl Rower { - //pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option { - // sqlx::query_as!( - // Self, - // " - //SELECT id,boat_id,shipmaster,shipmaster_only_steering,departure,arrival,destination,distance_in_km,comments,logtype - //FROM logbook - //WHERE id like ? - // ", - // id - // ) - // .fetch_one(db) - // .await - // .ok() - //} - pub async fn for_log(db: &SqlitePool, log: &Logbook) -> Vec { sqlx::query_as!( User, @@ -40,9 +25,7 @@ impl Rower { .unwrap() } - pub async fn create(db: &SqlitePool, logbook_id: i64, rower_id: i64) { - //Check if boat is not locked - //Check if boat is already on water + pub async fn create(db: &mut Transaction<'_, Sqlite>, logbook_id: i64, rower_id: i64) { let _ = sqlx::query!( "INSERT INTO rower(logbook_id, rower_id) VALUES (?,?)", logbook_id, @@ -52,83 +35,4 @@ impl Rower { .await .unwrap(); } - - // pub async fn delete(&self, db: &SqlitePool) { - // sqlx::query!("DELETE FROM boat WHERE id=?", self.id) - // .execute(db) - // .await - // .unwrap(); //Okay, because we can only create a User of a valid id - // } } -// -//#[cfg(test)] -//mod test { -// use crate::{model::boat::Boat, testdb}; -// -// use sqlx::SqlitePool; -// -// #[sqlx::test] -// fn test_find_correct_id() { -// let pool = testdb!(); -// let boat = Boat::find_by_id(&pool, 1).await.unwrap(); -// assert_eq!(boat.id, 1); -// } -// -// #[sqlx::test] -// fn test_find_wrong_id() { -// let pool = testdb!(); -// let boat = Boat::find_by_id(&pool, 1337).await; -// assert!(boat.is_none()); -// } -// -// #[sqlx::test] -// fn test_all() { -// let pool = testdb!(); -// let res = Boat::all(&pool).await; -// assert!(res.len() > 3); -// } -// -// #[sqlx::test] -// fn test_succ_create() { -// let pool = testdb!(); -// -// assert_eq!( -// Boat::create( -// &pool, -// "new-boat-name".into(), -// 42, -// None, -// "Best Boatbuilder".into(), -// true, -// true, -// false, -// Some(1), -// None -// ) -// .await, -// true -// ); -// } -// -// #[sqlx::test] -// fn test_duplicate_name_create() { -// let pool = testdb!(); -// -// assert_eq!( -// Boat::create( -// &pool, -// "Haichenbach".into(), -// 42, -// None, -// "Best Boatbuilder".into(), -// true, -// true, -// false, -// Some(1), -// None -// ) -// .await, -// false -// ); -// } -//} diff --git a/src/model/tripdetails.rs b/src/model/tripdetails.rs index 986b80a..c4f2fff 100644 --- a/src/model/tripdetails.rs +++ b/src/model/tripdetails.rs @@ -1,17 +1,31 @@ use chrono::NaiveDate; +use rocket::FromForm; use serde::{Deserialize, Serialize}; use sqlx::{FromRow, SqlitePool}; #[derive(FromRow, Debug, Serialize, Deserialize)] pub struct TripDetails { pub id: i64, - planned_starting_time: String, - max_people: i64, - day: String, - notes: Option, + pub planned_starting_time: String, + pub max_people: i64, + pub day: String, + pub notes: Option, pub allow_guests: bool, - trip_type_id: Option, - always_show: bool, + pub trip_type_id: Option, + pub always_show: bool, +} + +#[derive(FromForm, Serialize)] +pub struct TripDetailsToAdd<'r> { + //TODO: properly parse `planned_starting_time` + pub planned_starting_time: &'r str, + pub max_people: i32, + pub day: String, + //#[field(validate = range(1..))] TODO: fixme + pub notes: Option<&'r str>, + pub trip_type: Option, + pub allow_guests: bool, + pub always_show: bool, } impl TripDetails { @@ -31,25 +45,16 @@ WHERE id like ? } /// Creates a new entry in `trip_details` and returns its id. - pub async fn create( - db: &SqlitePool, - planned_starting_time: &str, - max_people: i32, - day: &str, - notes: Option<&str>, - allow_guests: bool, - trip_type_id: Option, - always_show: bool, - ) -> i64 { + pub async fn create(db: &SqlitePool, tripdetails: TripDetailsToAdd<'_>) -> i64 { let query = sqlx::query!( "INSERT INTO trip_details(planned_starting_time, max_people, day, notes, allow_guests, trip_type_id, always_show) VALUES(?, ?, ?, ?, ?, ?, ?)" , - planned_starting_time, - max_people, - day, - notes, - allow_guests, - trip_type_id, - always_show + tripdetails.planned_starting_time, + tripdetails.max_people, + tripdetails.day, + tripdetails.notes, + tripdetails.allow_guests, + tripdetails.trip_type, + tripdetails.always_show ) .execute(db) .await @@ -87,7 +92,7 @@ ORDER BY day;", #[cfg(test)] mod test { - use crate::testdb; + use crate::{model::tripdetails::TripDetailsToAdd, testdb}; use super::TripDetails; use sqlx::SqlitePool; @@ -113,13 +118,15 @@ mod test { assert_eq!( TripDetails::create( &pool, - "10:00".into(), - 2, - "1970-01-01".into(), - None, - false, - None, - false + TripDetailsToAdd { + planned_starting_time: "10:00".into(), + max_people: 2, + day: "1970-01-01".into(), + notes: None, + allow_guests: false, + trip_type: None, + always_show: false + } ) .await, 3, @@ -127,13 +134,15 @@ mod test { assert_eq!( TripDetails::create( &pool, - "10:00".into(), - 2, - "1970-01-01".into(), - None, - false, - None, - false + TripDetailsToAdd { + planned_starting_time: "10:00".into(), + max_people: 2, + day: "1970-01-01".into(), + notes: None, + allow_guests: false, + trip_type: None, + always_show: false + } ) .await, 4, diff --git a/src/model/user.rs b/src/model/user.rs index ddd6208..b045871 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -148,15 +148,15 @@ ORDER BY last_access DESC } pub async fn login(db: &SqlitePool, name: &str, pw: &str) -> Result { - Log::create(db, format!("User '{name}' is trying to login...").into()).await; + Log::create(db, format!("User '{name}' is trying to login...")).await; let name = name.trim(); // just to make sure... let Some(user) = User::find_by_name(db, name).await else { - Log::create(db, format!("Username ({name}) not found").into()).await; + Log::create(db, format!("Username ({name}) not found")).await; return Err(LoginError::InvalidAuthenticationCombo); // Username not found }; if user.deleted { - Log::create(db, format!("User ({name}) already deleted.").into()).await; + Log::create(db, format!("User ({name}) already deleted.")).await; return Err(LoginError::InvalidAuthenticationCombo); //User existed sometime ago; has //been deleted } @@ -165,10 +165,10 @@ ORDER BY last_access DESC Some(user_pw) => { let password_hash = &Self::get_hashed_pw(pw); if password_hash == user_pw { - Log::create(db, format!("User {name} successfully logged in").into()).await; + Log::create(db, format!("User {name} successfully logged in")).await; return Ok(user); } - Log::create(db, format!("User {name} supplied the wrong PW").into()).await; + Log::create(db, format!("User {name} supplied the wrong PW")).await; Err(LoginError::InvalidAuthenticationCombo) } None => { diff --git a/src/tera/admin/boat.rs b/src/tera/admin/boat.rs index d69d9df..b8007c9 100644 --- a/src/tera/admin/boat.rs +++ b/src/tera/admin/boat.rs @@ -1,5 +1,5 @@ use crate::model::{ - boat::Boat, + boat::{Boat, BoatToAdd, BoatToUpdate}, location::Location, user::{AdminUser, User}, }; @@ -8,7 +8,7 @@ use rocket::{ get, post, request::FlashMessage, response::{Flash, Redirect}, - routes, FromForm, Route, State, + routes, Route, State, }; use rocket_dyn_templates::{tera::Context, Template}; use sqlx::SqlitePool; @@ -50,96 +50,39 @@ async fn delete(db: &State, _admin: AdminUser, boat: i32) -> Flash { - id: i32, - name: &'r str, - amount_seats: i64, - year_built: Option, - boatbuilder: Option<&'r str>, - default_shipmaster_only_steering: bool, - skull: bool, - external: bool, - location_id: Option, - owner: Option, -} - #[post("/boat", data = "")] async fn update( db: &State, - data: Form>, + data: Form>, _admin: AdminUser, ) -> Flash { let boat = Boat::find_by_id(db, data.id).await; let Some(boat) = boat else { return Flash::error( Redirect::to("/admin/boat"), - format!("Boat with ID {} does not exist!", data.id), + "Boat does not exist!", ) }; - if !boat - .update( - db, - data.name, - data.amount_seats, - data.year_built, - data.boatbuilder, - data.default_shipmaster_only_steering, - data.skull, - data.external, - data.location_id, - data.owner, - ) - .await - { - return Flash::error( - Redirect::to("/admin/boat"), - format!("Boat with ID {} could not be updated!", data.id), - ); + if !boat.update(db, data.into_inner()).await { + return Flash::error(Redirect::to("/admin/boat"), "Boat could not be updated!"); } Flash::success(Redirect::to("/admin/boat"), "Successfully updated boat") } -#[derive(FromForm)] -struct BoatAddForm<'r> { - name: &'r str, - amount_seats: i64, - year_built: Option, - boatbuilder: Option<&'r str>, - default_shipmaster_only_steering: bool, - skull: bool, - external: bool, - location_id: Option, - owner: Option, -} - #[post("/boat/new", data = "")] async fn create( db: &State, - data: Form>, + data: Form>, _admin: AdminUser, ) -> Flash { - if Boat::create( - db, - data.name, - data.amount_seats, - data.year_built, - data.boatbuilder, - data.default_shipmaster_only_steering, - data.skull, - data.external, - data.location_id, - data.owner, - ) - .await - { + if Boat::create(db, data.into_inner()).await { Flash::success(Redirect::to("/admin/boat"), "Successfully created boat") } else { Flash::error( Redirect::to("/admin/boat"), - format!("Error while creating boat {} in DB", data.name), + "Error while creating the boat in DB", ) } } diff --git a/src/tera/admin/planned_event.rs b/src/tera/admin/planned_event.rs index 6e1a609..6d10216 100644 --- a/src/tera/admin/planned_event.rs +++ b/src/tera/admin/planned_event.rs @@ -4,22 +4,22 @@ use rocket::{ response::{Flash, Redirect}, routes, FromForm, Route, State, }; +use serde::Serialize; use sqlx::SqlitePool; -use crate::model::{planned_event::PlannedEvent, tripdetails::TripDetails, user::AdminUser}; +use crate::model::{ + planned_event::PlannedEvent, + tripdetails::{TripDetails, TripDetailsToAdd}, + user::AdminUser, +}; //TODO: add constraints (e.g. planned_amount_cox > 0) -#[derive(FromForm)] +#[derive(FromForm, Serialize)] struct AddPlannedEventForm<'r> { - day: &'r str, name: &'r str, planned_amount_cox: i32, - allow_guests: bool, - planned_starting_time: &'r str, - max_people: i32, - always_show: bool, - notes: Option<&'r str>, - trip_type: Option, + #[serde(flatten)] + tripdetails: TripDetailsToAdd<'r>, } #[post("/planned-event", data = "")] @@ -28,17 +28,9 @@ async fn create( data: Form>, _admin: AdminUser, ) -> Flash { - let trip_details_id = TripDetails::create( - db, - data.planned_starting_time, - data.max_people, - data.day, - data.notes, - data.allow_guests, - data.trip_type, - data.always_show, - ) - .await; + let data = data.into_inner(); + + let trip_details_id = TripDetails::create(db, data.tripdetails).await; let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap(); //Okay, bc. we //just created diff --git a/src/tera/cox.rs b/src/tera/cox.rs index 8d2a54f..2aecced 100644 --- a/src/tera/cox.rs +++ b/src/tera/cox.rs @@ -10,52 +10,29 @@ use crate::model::{ log::Log, planned_event::PlannedEvent, trip::{CoxHelpError, Trip, TripDeleteError, TripUpdateError}, - tripdetails::TripDetails, + tripdetails::{TripDetails, TripDetailsToAdd}, user::CoxUser, }; -#[derive(FromForm)] -struct AddTripForm<'r> { - day: String, - //TODO: properly parse `planned_starting_time` - planned_starting_time: &'r str, - #[field(validate = range(1..))] - max_people: i32, - notes: Option<&'r str>, - trip_type: Option, - allow_guests: bool, - always_show: bool, -} - #[post("/trip", data = "")] async fn create( db: &State, - data: Form>, + data: Form>, cox: CoxUser, ) -> Flash { - let trip_details_id = TripDetails::create( - db, - data.planned_starting_time, - data.max_people, - &data.day, - data.notes, - data.allow_guests, - data.trip_type, - data.always_show, - ) - .await; + let trip_details_id = TripDetails::create(db, data.into_inner()).await; let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap(); //Okay, bc just //created - Trip::new_own(db, &cox, trip_details).await; + Trip::new_own(db, &cox, trip_details).await; //TODO: fix - Log::create( - db, - format!( - "Cox {} created trip on {} @ {} for {} rower", - cox.name, data.day, data.planned_starting_time, data.max_people, - ), - ) - .await; + //Log::create( + // db, + // format!( + // "Cox {} created trip on {} @ {} for {} rower", + // cox.name, trip_details.day, trip_details.planned_starting_time, trip_details.max_people, + // ), + //) + //.await; Flash::success(Redirect::to("/"), "Ausfahrt erfolgreich erstellt.") } @@ -402,7 +379,7 @@ mod test { login.dispatch().await; let req = client.get("/join/1"); - let response = req.dispatch().await; + let _ = req.dispatch().await; let req = client.get("/cox/join/1"); let response = req.dispatch().await; diff --git a/src/tera/log.rs b/src/tera/log.rs index f7d6669..f268053 100644 --- a/src/tera/log.rs +++ b/src/tera/log.rs @@ -1,10 +1,9 @@ -use chrono::NaiveDateTime; use rocket::{ form::Form, get, post, request::FlashMessage, response::{Flash, Redirect}, - routes, FromForm, Route, State, + routes, Route, State, }; use rocket_dyn_templates::Template; use sqlx::SqlitePool; @@ -12,7 +11,7 @@ use tera::Context; use crate::model::{ boat::Boat, - logbook::{Logbook, LogbookCreateError}, + logbook::{LogToAdd, LogToFinalize, Logbook, LogbookCreateError}, logtype::LogType, user::{AdminUser, User}, }; @@ -47,40 +46,15 @@ async fn index( Template::render("log", context.into_json()) } -#[derive(FromForm)] -struct LogAddForm { - boat_id: i32, - shipmaster: i64, - shipmaster_only_steering: bool, - departure: String, - arrival: Option, - destination: Option, - distance_in_km: Option, - comments: Option, - logtype: Option, - rower: Vec, -} - #[post("/", data = "")] async fn create( db: &State, - data: Form, + data: Form, _adminuser: AdminUser, ) -> Flash { match Logbook::create( db, - data.boat_id, - data.shipmaster, - data.shipmaster_only_steering, - NaiveDateTime::parse_from_str(&data.departure, "%Y-%m-%dT%H:%M").unwrap(), //TODO: fix - data.arrival - .clone() - .map(|a| NaiveDateTime::parse_from_str(&a, "%Y-%m-%dT%H:%M").unwrap()), //TODO: fix - data.destination.clone(), //TODO: fix - data.distance_in_km, - data.comments.clone(), //TODO: fix - data.logtype, - data.rower.clone(), //TODO: fix + data.into_inner() ) .await { @@ -92,19 +66,10 @@ async fn create( } } -#[derive(FromForm)] -struct LogHomeForm { - destination: String, - distance_in_km: i64, - comments: Option, - logtype: Option, - rower: Vec, -} - #[post("/", data = "")] async fn home( db: &State, - data: Form, + data: Form, logbook_id: i32, _adminuser: AdminUser, ) -> Flash { @@ -116,18 +81,7 @@ async fn home( ) }; - match logbook - .home( - db, - &_adminuser.user, - data.destination.clone(), //TODO: fixme - data.distance_in_km, - data.comments.clone(), //TODO: fixme - data.logtype, - data.rower.clone(), //TODO: fixme - ) - .await - { + match logbook.home(db, &_adminuser.user, data.into_inner()).await { Ok(_) => Flash::success(Redirect::to("/log"), "Successfully updated log"), Err(_) => Flash::error( Redirect::to("/log"),