Merge pull request 'restructure' (#1050) from restructure into staging
Reviewed-on: #1050
This commit was merged in pull request #1050.
	This commit is contained in:
		| @@ -1,10 +1,7 @@ | ||||
| use std::io::Write; | ||||
|  | ||||
| use chrono::{Duration, NaiveDate, NaiveTime}; | ||||
| use ics::{ | ||||
|     ICalendar, | ||||
|     properties::{DtEnd, DtStart, Summary}, | ||||
| }; | ||||
| use chrono::NaiveDate; | ||||
| use ics::ICalendar; | ||||
| use serde::Serialize; | ||||
| use sqlx::{FromRow, Row, SqlitePool}; | ||||
|  | ||||
| @@ -142,7 +139,7 @@ WHERE planned_event.id like ? | ||||
|         .ok() | ||||
|     } | ||||
|  | ||||
|     async fn trip_type(&self, db: &SqlitePool) -> Option<TripType> { | ||||
|     pub(crate) async fn trip_type(&self, db: &SqlitePool) -> Option<TripType> { | ||||
|         if let Some(trip_type_id) = self.trip_type_id { | ||||
|             TripType::find_by_id(db, trip_type_id).await | ||||
|         } else { | ||||
| @@ -474,66 +471,6 @@ WHERE trip_details.id=? | ||||
|         String::from_utf8(buf).unwrap() | ||||
|     } | ||||
|  | ||||
|     pub(crate) async fn get_vevent(self, db: &SqlitePool) -> ics::Event { | ||||
|         let mut vevent = ics::Event::new( | ||||
|             format!("event-{}@rudernlinz.at", self.id), | ||||
|             "19900101T180000", | ||||
|         ); | ||||
|         let time_str = self.planned_starting_time.replace(':', ""); | ||||
|         let formatted_time = if time_str.len() == 3 { | ||||
|             format!("0{}", time_str) | ||||
|         } else { | ||||
|             time_str.clone() // TODO: remove again | ||||
|         }; | ||||
|         vevent.push(DtStart::new(format!( | ||||
|             "{}T{}00", | ||||
|             self.day.replace('-', ""), | ||||
|             formatted_time | ||||
|         ))); | ||||
|  | ||||
|         let original_time = NaiveTime::parse_from_str(&self.planned_starting_time, "%H:%M") | ||||
|             .expect("Failed to parse time"); | ||||
|  | ||||
|         let long_trip = match self.trip_type(db).await { | ||||
|             Some(a) if a.name == "Lange Ausfahrt" => true, | ||||
|             _ => false, | ||||
|         }; | ||||
|         let later_time = if long_trip { | ||||
|             original_time + Duration::hours(6) | ||||
|         } else { | ||||
|             original_time + Duration::hours(3) | ||||
|         }; | ||||
|         if later_time > original_time { | ||||
|             // Check if no day-overflow | ||||
|             let time_three_hours_later = later_time.format("%H%M").to_string(); | ||||
|             vevent.push(DtEnd::new(format!( | ||||
|                 "{}T{}00", | ||||
|                 self.day.replace('-', ""), | ||||
|                 time_three_hours_later | ||||
|             ))); | ||||
|         } | ||||
|  | ||||
|         let tripdetails = self.trip_details(db).await; | ||||
|         let mut name = String::new(); | ||||
|         if self.is_cancelled() { | ||||
|             name.push_str("ABGESAGT"); | ||||
|             if let Some(notes) = &tripdetails.notes { | ||||
|                 if !notes.is_empty() { | ||||
|                     name.push_str(&format!(" (Grund: {notes})")) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             name.push_str("! :-( "); | ||||
|         } | ||||
|         name.push_str(&format!("{} ", self.name)); | ||||
|  | ||||
|         if let Some(triptype) = tripdetails.triptype(db).await { | ||||
|             name.push_str(&format!("• {} ", triptype.name)) | ||||
|         } | ||||
|         vevent.push(Summary::new(name)); | ||||
|         vevent | ||||
|     } | ||||
|  | ||||
|     pub async fn trip_details(&self, db: &SqlitePool) -> TripDetails { | ||||
|         TripDetails::find_by_id(db, self.trip_details_id) | ||||
|             .await | ||||
|   | ||||
| @@ -1,9 +1,14 @@ | ||||
| use std::io::Write; | ||||
|  | ||||
| use ics::{ICalendar, components::Property}; | ||||
| use ics::{ | ||||
|     components::Property, | ||||
|     properties::{DtEnd, DtStart, Summary}, | ||||
|     ICalendar, | ||||
| }; | ||||
| use sqlx::SqlitePool; | ||||
|  | ||||
| use crate::model::{event::Event, trip::Trip, user::User}; | ||||
| use chrono::{Duration, NaiveTime}; | ||||
|  | ||||
| pub(crate) async fn get_personal_cal(db: &SqlitePool, user: &User) -> String { | ||||
|     let mut calendar = ICalendar::new("2.0", "ics-rs"); | ||||
| @@ -25,3 +30,125 @@ pub(crate) async fn get_personal_cal(db: &SqlitePool, user: &User) -> String { | ||||
|     write!(&mut buf, "{}", calendar).unwrap(); | ||||
|     String::from_utf8(buf).unwrap() | ||||
| } | ||||
|  | ||||
| impl Trip { | ||||
|     pub(crate) async fn get_vevent<'a>(self, db: &'a SqlitePool, user: &'a User) -> ics::Event<'a> { | ||||
|         let mut vevent = | ||||
|             ics::Event::new(format!("trip-{}@rudernlinz.at", self.id), "19900101T180000"); | ||||
|         let time_str = self.planned_starting_time.replace(':', ""); | ||||
|         let formatted_time = if time_str.len() == 3 { | ||||
|             format!("0{}", time_str) | ||||
|         } else { | ||||
|             time_str | ||||
|         }; | ||||
|  | ||||
|         vevent.push(DtStart::new(format!( | ||||
|             "{}T{}00", | ||||
|             self.day.replace('-', ""), | ||||
|             formatted_time | ||||
|         ))); | ||||
|  | ||||
|         let original_time = NaiveTime::parse_from_str(&self.planned_starting_time, "%H:%M") | ||||
|             .expect("Failed to parse time"); | ||||
|         let long_trip = match self.trip_type(db).await { | ||||
|             Some(a) if a.name == "Lange Ausfahrt" => true, | ||||
|             _ => false, | ||||
|         }; | ||||
|         let later_time = if long_trip { | ||||
|             original_time + Duration::hours(6) | ||||
|         } else { | ||||
|             original_time + Duration::hours(3) | ||||
|         }; | ||||
|         if later_time > original_time { | ||||
|             // Check if no day-overflow | ||||
|             let time_three_hours_later = later_time.format("%H%M").to_string(); | ||||
|             vevent.push(DtEnd::new(format!( | ||||
|                 "{}T{}00", | ||||
|                 self.day.replace('-', ""), | ||||
|                 time_three_hours_later | ||||
|             ))); | ||||
|         } | ||||
|  | ||||
|         let mut name = String::new(); | ||||
|         if self.is_cancelled() { | ||||
|             name.push_str("ABGESAGT"); | ||||
|             if let Some(notes) = &self.notes { | ||||
|                 if !notes.is_empty() { | ||||
|                     name.push_str(&format!(" (Grund: {notes})")) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             name.push_str("! :-( "); | ||||
|         } | ||||
|         if self.cox_id == user.id { | ||||
|             name.push_str("Ruderausfahrt (selber ausgeschrieben)"); | ||||
|         } else { | ||||
|             name.push_str(&format!("Ruderausfahrt mit {} ", self.cox_name)); | ||||
|         } | ||||
|  | ||||
|         vevent.push(Summary::new(name)); | ||||
|         vevent | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Event { | ||||
|     pub(crate) async fn get_vevent(self, db: &SqlitePool) -> ics::Event { | ||||
|         let mut vevent = ics::Event::new( | ||||
|             format!("event-{}@rudernlinz.at", self.id), | ||||
|             "19900101T180000", | ||||
|         ); | ||||
|         let time_str = self.planned_starting_time.replace(':', ""); | ||||
|         let formatted_time = if time_str.len() == 3 { | ||||
|             format!("0{}", time_str) | ||||
|         } else { | ||||
|             time_str.clone() // TODO: remove again | ||||
|         }; | ||||
|         vevent.push(DtStart::new(format!( | ||||
|             "{}T{}00", | ||||
|             self.day.replace('-', ""), | ||||
|             formatted_time | ||||
|         ))); | ||||
|  | ||||
|         let original_time = NaiveTime::parse_from_str(&self.planned_starting_time, "%H:%M") | ||||
|             .expect("Failed to parse time"); | ||||
|  | ||||
|         let long_trip = match self.trip_type(db).await { | ||||
|             Some(a) if a.name == "Lange Ausfahrt" => true, | ||||
|             _ => false, | ||||
|         }; | ||||
|         let later_time = if long_trip { | ||||
|             original_time + Duration::hours(6) | ||||
|         } else { | ||||
|             original_time + Duration::hours(3) | ||||
|         }; | ||||
|         if later_time > original_time { | ||||
|             // Check if no day-overflow | ||||
|             let time_three_hours_later = later_time.format("%H%M").to_string(); | ||||
|             vevent.push(DtEnd::new(format!( | ||||
|                 "{}T{}00", | ||||
|                 self.day.replace('-', ""), | ||||
|                 time_three_hours_later | ||||
|             ))); | ||||
|         } | ||||
|  | ||||
|         let tripdetails = self.trip_details(db).await; | ||||
|         let mut name = String::new(); | ||||
|         if self.is_cancelled() { | ||||
|             name.push_str("ABGESAGT"); | ||||
|             if let Some(notes) = &tripdetails.notes { | ||||
|                 if !notes.is_empty() { | ||||
|                     name.push_str(&format!(" (Grund: {notes})")) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             name.push_str("! :-( "); | ||||
|         } | ||||
|         name.push_str(&format!("{} ", self.name)); | ||||
|  | ||||
|         if let Some(triptype) = tripdetails.triptype(db).await { | ||||
|             name.push_str(&format!("• {} ", triptype.name)) | ||||
|         } | ||||
|         vevent.push(Summary::new(name)); | ||||
|         vevent | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										77
									
								
								src/model/trip/create.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/model/trip/create.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| use super::Trip; | ||||
| use crate::model::{ | ||||
|     notification::Notification, | ||||
|     tripdetails::TripDetails, | ||||
|     triptype::TripType, | ||||
|     user::{ErgoUser, SteeringUser, User}, | ||||
| }; | ||||
| use sqlx::SqlitePool; | ||||
|  | ||||
| impl Trip { | ||||
|     /// Cox decides to create own trip. | ||||
|     pub async fn new_own(db: &SqlitePool, cox: &SteeringUser, trip_details: TripDetails) { | ||||
|         Self::perform_new(db, &cox.user, trip_details).await | ||||
|     } | ||||
|  | ||||
|     /// ErgoUser decides to create ergo 'trip'. Returns false, if trip is not a ergo-session (and | ||||
|     /// thus User is not allowed to create such a trip) | ||||
|     pub async fn new_own_ergo(db: &SqlitePool, ergo: &ErgoUser, trip_details: TripDetails) -> bool { | ||||
|         if let Some(typ) = trip_details.triptype(db).await { | ||||
|             let allowed_type = TripType::find_by_id(db, 4).await.unwrap(); | ||||
|             if typ == allowed_type { | ||||
|                 Self::perform_new(db, &ergo.user, trip_details).await; | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         false | ||||
|     } | ||||
|  | ||||
|     async fn perform_new(db: &SqlitePool, user: &User, trip_details: TripDetails) { | ||||
|         let _ = sqlx::query!( | ||||
|             "INSERT INTO trip (cox_id, trip_details_id) VALUES(?, ?)", | ||||
|             user.id, | ||||
|             trip_details.id | ||||
|         ) | ||||
|         .execute(db) | ||||
|         .await; | ||||
|  | ||||
|         Self::notify_trips_same_datetime(db, trip_details, user).await; | ||||
|     } | ||||
|  | ||||
|     async fn notify_trips_same_datetime(db: &SqlitePool, trip_details: TripDetails, user: &User) { | ||||
|         let same_starting_datetime = TripDetails::find_by_startingdatetime( | ||||
|             db, | ||||
|             trip_details.day, | ||||
|             trip_details.planned_starting_time, | ||||
|         ) | ||||
|         .await; | ||||
|  | ||||
|         for notify in same_starting_datetime { | ||||
|             // don't notify oneself | ||||
|             if notify.id == trip_details.id { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // don't notify people who have cancelled their trip | ||||
|             if notify.cancelled() { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if let Some(trip) = Trip::find_by_trip_details(db, notify.id).await { | ||||
|                 let user_earlier_trip = User::find_by_id(db, trip.cox_id as i32).await.unwrap(); | ||||
|                 Notification::create( | ||||
|                     db, | ||||
|                     &user_earlier_trip, | ||||
|                     &format!( | ||||
|                         "{user} hat eine Ausfahrt zur selben Zeit ({} um {}) wie du erstellt", | ||||
|                         trip.day, trip.planned_starting_time | ||||
|                     ), | ||||
|                     "Neue Ausfahrt zur selben Zeit", | ||||
|                     None, | ||||
|                     None, | ||||
|                 ) | ||||
|                 .await; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,25 +1,26 @@ | ||||
| use chrono::{Duration, Local, NaiveDate, NaiveTime}; | ||||
| use ics::properties::{DtEnd, DtStart, Summary}; | ||||
| use chrono::{Local, NaiveDate}; | ||||
| use serde::Serialize; | ||||
| use sqlx::SqlitePool; | ||||
| 
 | ||||
| mod create; | ||||
| 
 | ||||
| use super::{ | ||||
|     event::{Event, Registration}, | ||||
|     log::Log, | ||||
|     notification::Notification, | ||||
|     tripdetails::TripDetails, | ||||
|     triptype::TripType, | ||||
|     user::{ErgoUser, SteeringUser, User}, | ||||
|     user::{SteeringUser, User}, | ||||
|     usertrip::UserTrip, | ||||
| }; | ||||
| 
 | ||||
| #[derive(Serialize, Clone, Debug)] | ||||
| pub struct Trip { | ||||
|     id: i64, | ||||
|     pub id: i64, | ||||
|     pub cox_id: i64, | ||||
|     cox_name: String, | ||||
|     pub cox_name: String, | ||||
|     trip_details_id: Option<i64>, | ||||
|     planned_starting_time: String, | ||||
|     pub planned_starting_time: String, | ||||
|     pub max_people: i64, | ||||
|     pub day: String, | ||||
|     pub notes: Option<String>, | ||||
| @@ -69,65 +70,6 @@ impl TripWithDetails { | ||||
| } | ||||
| 
 | ||||
| impl Trip { | ||||
|     /// Cox decides to create own trip.
 | ||||
|     pub async fn new_own(db: &SqlitePool, cox: &SteeringUser, trip_details: TripDetails) { | ||||
|         Self::perform_new(db, &cox.user, trip_details).await | ||||
|     } | ||||
| 
 | ||||
|     pub async fn new_own_ergo(db: &SqlitePool, ergo: &ErgoUser, trip_details: TripDetails) { | ||||
|         let typ = trip_details.triptype(db).await; | ||||
|         if let Some(typ) = typ { | ||||
|             let allowed_type = TripType::find_by_id(db, 4).await.unwrap(); | ||||
|             if typ == allowed_type { | ||||
|                 Self::perform_new(db, &ergo.user, trip_details).await; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn perform_new(db: &SqlitePool, user: &User, trip_details: TripDetails) { | ||||
|         let _ = sqlx::query!( | ||||
|             "INSERT INTO trip (cox_id, trip_details_id) VALUES(?, ?)", | ||||
|             user.id, | ||||
|             trip_details.id | ||||
|         ) | ||||
|         .execute(db) | ||||
|         .await; | ||||
| 
 | ||||
|         let same_starting_datetime = TripDetails::find_by_startingdatetime( | ||||
|             db, | ||||
|             trip_details.day, | ||||
|             trip_details.planned_starting_time, | ||||
|         ) | ||||
|         .await; | ||||
|         for notify in same_starting_datetime { | ||||
|             // don't notify oneself
 | ||||
|             if notify.id == trip_details.id { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             // don't notify people who have cancelled their trip
 | ||||
|             if notify.cancelled() { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             if let Some(trip) = Trip::find_by_trip_details(db, notify.id).await { | ||||
|                 let user_earlier_trip = User::find_by_id(db, trip.cox_id as i32).await.unwrap(); | ||||
|                 Notification::create( | ||||
|                     db, | ||||
|                     &user_earlier_trip, | ||||
|                     &format!( | ||||
|                         "{} hat eine Ausfahrt zur selben Zeit ({} um {}) wie du erstellt", | ||||
|                         user.name, trip.day, trip.planned_starting_time | ||||
|                     ), | ||||
|                     "Neue Ausfahrt zur selben Zeit", | ||||
|                     None, | ||||
|                     None, | ||||
|                 ) | ||||
|                 .await; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub async fn find_by_trip_details(db: &SqlitePool, tripdetails_id: i64) -> Option<Self> { | ||||
|         sqlx::query_as!( | ||||
|             Self, | ||||
| @@ -145,7 +87,7 @@ WHERE trip_details.id=? | ||||
|         .ok() | ||||
|     } | ||||
| 
 | ||||
|     async fn trip_type(&self, db: &SqlitePool) -> Option<TripType> { | ||||
|     pub(crate) async fn trip_type(&self, db: &SqlitePool) -> Option<TripType> { | ||||
|         if let Some(trip_type_id) = self.trip_type_id { | ||||
|             TripType::find_by_id(db, trip_type_id).await | ||||
|         } else { | ||||
| @@ -153,64 +95,6 @@ WHERE trip_details.id=? | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) async fn get_vevent<'a>(self, db: &'a SqlitePool, user: &'a User) -> ics::Event<'a> { | ||||
|         let mut vevent = | ||||
|             ics::Event::new(format!("trip-{}@rudernlinz.at", self.id), "19900101T180000"); | ||||
|         let time_str = self.planned_starting_time.replace(':', ""); | ||||
|         let formatted_time = if time_str.len() == 3 { | ||||
|             format!("0{}", time_str) | ||||
|         } else { | ||||
|             time_str | ||||
|         }; | ||||
| 
 | ||||
|         vevent.push(DtStart::new(format!( | ||||
|             "{}T{}00", | ||||
|             self.day.replace('-', ""), | ||||
|             formatted_time | ||||
|         ))); | ||||
| 
 | ||||
|         let original_time = NaiveTime::parse_from_str(&self.planned_starting_time, "%H:%M") | ||||
|             .expect("Failed to parse time"); | ||||
|         let long_trip = match self.trip_type(db).await { | ||||
|             Some(a) if a.name == "Lange Ausfahrt" => true, | ||||
|             _ => false, | ||||
|         }; | ||||
|         let later_time = if long_trip { | ||||
|             original_time + Duration::hours(6) | ||||
|         } else { | ||||
|             original_time + Duration::hours(3) | ||||
|         }; | ||||
|         if later_time > original_time { | ||||
|             // Check if no day-overflow
 | ||||
|             let time_three_hours_later = later_time.format("%H%M").to_string(); | ||||
|             vevent.push(DtEnd::new(format!( | ||||
|                 "{}T{}00", | ||||
|                 self.day.replace('-', ""), | ||||
|                 time_three_hours_later | ||||
|             ))); | ||||
|         } | ||||
| 
 | ||||
|         let mut name = String::new(); | ||||
|         if self.is_cancelled() { | ||||
|             name.push_str("ABGESAGT"); | ||||
|             if let Some(notes) = &self.notes { | ||||
|                 if !notes.is_empty() { | ||||
|                     name.push_str(&format!(" (Grund: {notes})")) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             name.push_str("! :-( "); | ||||
|         } | ||||
|         if self.cox_id == user.id { | ||||
|             name.push_str("Ruderausfahrt (selber ausgeschrieben)"); | ||||
|         } else { | ||||
|             name.push_str(&format!("Ruderausfahrt mit {} ", self.cox_name)); | ||||
|         } | ||||
| 
 | ||||
|         vevent.push(Summary::new(name)); | ||||
|         vevent | ||||
|     } | ||||
| 
 | ||||
|     pub async fn all(db: &SqlitePool) -> Vec<Self> { | ||||
|         sqlx::query_as!( | ||||
|             Self, | ||||
| @@ -491,7 +375,7 @@ WHERE day=? | ||||
|         trips | ||||
|     } | ||||
| 
 | ||||
|     fn is_cancelled(&self) -> bool { | ||||
|     pub(crate) fn is_cancelled(&self) -> bool { | ||||
|         self.max_people == -1 | ||||
|     } | ||||
| } | ||||
| @@ -583,11 +467,9 @@ mod test { | ||||
| 
 | ||||
|         let last_notification = &Notification::for_user(&pool, &cox).await[0]; | ||||
| 
 | ||||
|         assert!( | ||||
|             last_notification | ||||
|                 .message | ||||
|                 .starts_with("cox2 hat eine Ausfahrt zur selben Zeit") | ||||
|         ); | ||||
|         assert!(last_notification | ||||
|             .message | ||||
|             .starts_with("cox2 hat eine Ausfahrt zur selben Zeit")); | ||||
|     } | ||||
| 
 | ||||
|     #[sqlx::test] | ||||
| @@ -1,9 +1,8 @@ | ||||
| use rocket::{ | ||||
|     FromForm, Route, State, | ||||
|     form::Form, | ||||
|     get, post, | ||||
|     response::{Flash, Redirect}, | ||||
|     routes, | ||||
|     routes, FromForm, Route, State, | ||||
| }; | ||||
| use sqlx::SqlitePool; | ||||
|  | ||||
| @@ -23,21 +22,13 @@ async fn create_ergo( | ||||
| ) -> Flash<Redirect> { | ||||
|     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 | ||||
|                                                                                     //created | ||||
|     Trip::new_own_ergo(db, &cox, trip_details).await; //TODO: fix | ||||
|  | ||||
|     //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("/planned"), "Ausfahrt erfolgreich erstellt.") | ||||
| } | ||||
|  | ||||
| /// SteeringUser created new trip | ||||
| #[post("/trip", data = "<data>")] | ||||
| async fn create( | ||||
|     db: &State<SqlitePool>, | ||||
| @@ -46,18 +37,9 @@ async fn create( | ||||
| ) -> Flash<Redirect> { | ||||
|     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 | ||||
|                                                                                     //created | ||||
|     Trip::new_own(db, &cox, trip_details).await; //TODO: fix | ||||
|  | ||||
|     //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("/planned"), "Ausfahrt erfolgreich erstellt.") | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user