use actix_web::{http::header::LOCATION, web, HttpResponse, Responder}; use garde::Validate; use sqlx::PgPool; use crate::{ endpoints::{ availability::{find_adjacend_availability, AvailabilityForm}, IdPath, }, models::{Availability, AvailabilityChangeset, AvailabilityContext, User}, utils::{self, ApplicationError}, }; #[actix_web::post("/availability/edit/{id}")] pub async fn post( user: web::ReqData, pool: web::Data, path: web::Path, form: web::Form, ) -> Result { let Some(availability) = Availability::read_by_id(pool.get_ref(), path.id).await? else { return Ok(HttpResponse::NotFound().finish()); }; if availability.user_id != user.id { return Err(ApplicationError::Unauthorized); } let existing_availabilities: Vec = Availability::read_by_user_and_date(pool.get_ref(), user.id, &availability.start.date()) .await? .into_iter() .filter(|a| a.id != availability.id) .collect(); let context = AvailabilityContext { existing_availabilities: existing_availabilities.clone(), }; let start = form.startdate.and_time(form.starttime); let end = form.enddate.and_time(form.endtime); let mut changeset = AvailabilityChangeset { time: (start, end), comment: form.comment.clone(), }; if let Err(e) = changeset.validate_with(&context) { return Ok(HttpResponse::BadRequest().body(e.to_string())); }; if let Some(a) = find_adjacend_availability(&changeset, Some(availability.id), &existing_availabilities) { let (changeset_start, changeset_end) = changeset.time; if a.end == changeset_start { changeset.time.0 = a.start; } if a.start == changeset_end { changeset.time.1 = a.end; } Availability::update(pool.get_ref(), a.id, changeset).await?; Availability::delete(pool.get_ref(), availability.id).await?; } else { Availability::update(pool.get_ref(), availability.id, changeset).await?; } let url = utils::get_return_url_for_date(&form.startdate); Ok(HttpResponse::Found() .insert_header((LOCATION, url.clone())) .insert_header(("HX-LOCATION", url)) .finish()) }