From 6995599a8182ff1616612c0e3df36673ad4d6dc9 Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Mon, 27 Jan 2025 13:23:19 +0100 Subject: [PATCH] feat: WIP combine adjacent availability --- web/src/endpoints/availability/post_update.rs | 44 ++++++++++++++++--- web/src/models/availabillity.rs | 18 ++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/web/src/endpoints/availability/post_update.rs b/web/src/endpoints/availability/post_update.rs index f0fcc290..28b647a4 100644 --- a/web/src/endpoints/availability/post_update.rs +++ b/web/src/endpoints/availability/post_update.rs @@ -15,18 +15,18 @@ pub async fn post( path: web::Path, form: web::Form, ) -> Result { - let Some(availabillity) = Availability::read_by_id(pool.get_ref(), path.id).await? else { + let Some(availability) = Availability::read_by_id(pool.get_ref(), path.id).await? else { return Ok(HttpResponse::NotFound().finish()); }; - if availabillity.user_id != user.id { + if availability.user_id != user.id { return Err(ApplicationError::Unauthorized); } let existing_availabilities = - Availability::read_by_user_and_date(pool.get_ref(), user.id, &availabillity.date).await?; + Availability::read_by_user_and_date(pool.get_ref(), user.id, &availability.date).await?; let context = AvailabilityContext { - existing_availabilities, + existing_availabilities: existing_availabilities.clone(), }; let time = if form.from.is_some() && form.till.is_some() { @@ -35,7 +35,7 @@ pub async fn post( AvailabilityTime::WholeDay }; - let changeset = AvailabilityChangeset { + let mut changeset = AvailabilityChangeset { time, comment: form.comment.clone(), }; @@ -44,8 +44,38 @@ pub async fn post( return Ok(HttpResponse::BadRequest().body(e.to_string())); }; - // TODO: check if adjacent availabillity is present and combine - Availability::update(pool.get_ref(), availabillity.id, changeset).await?; + let mut adjacent = None; + if let AvailabilityTime::Temporarily(changeset_start, changeset_end) = changeset.time { + for a in existing_availabilities + .iter() + .filter(|a| a.id != availability.id) + { + if let AvailabilityTime::Temporarily(start, end) = a.time { + if start == changeset_end || end == changeset_start { + adjacent = Some(a); + break; + } + } + } + } + + if let Some(a) = adjacent { + let (changeset_start, changeset_end) = changeset.time.time_tuple_opt().unwrap(); + let (adjacent_start, adjacent_end) = changeset.time.time_tuple_opt().unwrap(); + + if adjacent_end == changeset_start { + changeset.time = AvailabilityTime::Temporarily(adjacent_start, changeset_end); + } + + if adjacent_start == changeset_end { + changeset.time = AvailabilityTime::Temporarily(changeset_start, adjacent_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.date); Ok(HttpResponse::Found() diff --git a/web/src/models/availabillity.rs b/web/src/models/availabillity.rs index eac43982..2ceb284b 100644 --- a/web/src/models/availabillity.rs +++ b/web/src/models/availabillity.rs @@ -1,6 +1,8 @@ use chrono::{NaiveDate, NaiveTime}; use sqlx::{query, PgPool}; +use crate::{END_OF_DAY, START_OF_DAY}; + use super::{Area, AvailabilityChangeset, Function, Result, Role, User}; #[derive(Clone, Debug)] @@ -19,6 +21,22 @@ pub enum AvailabilityTime { Temporarily(NaiveTime, NaiveTime), } +impl AvailabilityTime { + pub fn time_tuple(&self) -> (NaiveTime, NaiveTime) { + match self { + AvailabilityTime::WholeDay => (START_OF_DAY, END_OF_DAY), + AvailabilityTime::Temporarily(start, end) => (*start, *end), + } + } + + pub fn time_tuple_opt(&self) -> Option<(NaiveTime, NaiveTime)> { + match self { + AvailabilityTime::WholeDay => None, + AvailabilityTime::Temporarily(start, end) => Some((*start, *end)), + } + } +} + impl Availability { // TODO: fix db name pub async fn create(