diff --git a/src/backend/data.rs b/src/backend/data.rs index b23ae2c..08c42d8 100644 --- a/src/backend/data.rs +++ b/src/backend/data.rs @@ -349,7 +349,7 @@ pub struct PublicFormData { pub property: ResProperty, pub hours: Vec, pub reservations: Vec, - pub closing_days: Option + pub closing_days: Vec } fn empty_slots() -> Vec { diff --git a/src/backend/opening_hours.rs b/src/backend/opening_hours.rs index 0a499b7..cdb4134 100644 --- a/src/backend/opening_hours.rs +++ b/src/backend/opening_hours.rs @@ -8,6 +8,7 @@ use crate::components::data_form::ForValidation; cfg_if! { if #[cfg(feature = "ssr")] { use crate::error::AppError; + use chrono::Local; pub async fn hours_for_day(day: Weekday) -> Result, AppError> { use crate::backend::get_pool; @@ -21,6 +22,18 @@ cfg_if! { if #[cfg(feature = "ssr")] { Ok(hours.into_iter().map(|h| { DayHour::new(h.from, h.to, h.discount)}).collect()) } + + async fn purge_closing_days() -> Result<(), AppError> { + use crate::backend::get_pool; + + let pool = get_pool().await?; + sqlx::query("DELETE FROM closing_time WHERE to_date < $1") + .bind(Local::now()) + .execute(&pool) + .await?; + + Ok(()) + } }} #[server] @@ -97,7 +110,7 @@ pub async fn get_closing_time() -> Result, ServerFnError> { use sqlx::{Error, query_as}; let pool = get_pool().await?; - let ct = query_as::<_, ClosingTime>("SELECT * FROM closing_time") + let ct = query_as::<_, ClosingTime>("SELECT * FROM closing_time ORDER BY from_date") .fetch_one(&pool) .await; @@ -113,44 +126,49 @@ pub async fn get_closing_time() -> Result, ServerFnError> { } #[server] -pub async fn update_closing_time(time: ClosingTime) -> Result, ServerFnError> { +pub async fn get_closing_times() -> Result, ServerFnError> { + use crate::backend::get_pool; + use sqlx::query_as; + + let pool = get_pool().await?; + purge_closing_days().await?; + Ok(query_as::<_, ClosingTime>("SELECT * FROM closing_time ORDER BY from_date").fetch_all(&pool).await?) +} + +#[server] +pub async fn insert_closing_time(time: ClosingTime) -> Result, ServerFnError> { use crate::perm_check; use crate::backend::get_pool; perm_check!(is_admin); let pool = get_pool().await?; - let mut tx = pool.begin().await?; - sqlx::query("DELETE FROM closing_time") - .execute(&mut *tx) - .await?; sqlx::query("INSERT INTO closing_time(from_date, to_date) VALUES($1, $2)") .bind(time.from_date) .bind(time.to_date) - .execute(&mut *tx) + .execute(&pool) .await?; - tx.commit().await?; - Ok(ApiResponse::Data(())) } -impl ForValidation for UpdateClosingTime { +impl ForValidation for InsertClosingTime { fn entity(&self) -> &dyn Validate { &self.time } } #[server] -pub async fn delete_closing_time() -> Result, ServerFnError> { +pub async fn delete_closing_time(id: i32) -> Result, ServerFnError> { use crate::perm_check; use crate::backend::get_pool; perm_check!(is_admin); let pool = get_pool().await?; - sqlx::query("DELETE FROM closing_time") + sqlx::query("DELETE FROM closing_time WHERE id = $1") + .bind(id) .execute(&pool) .await?; diff --git a/src/backend/reservation.rs b/src/backend/reservation.rs index 035c9e7..1cf575b 100644 --- a/src/backend/reservation.rs +++ b/src/backend/reservation.rs @@ -26,7 +26,6 @@ cfg_if! { if #[cfg(feature = "ssr")] { use crate::backend::user::emails_for_notify; use crate::locales::trl; use rust_decimal::prelude::ToPrimitive; - use crate::backend::opening_hours::get_closing_time; async fn find_sum_by_uuid(uuid: &Uuid, tx: &mut Transaction<'_, Postgres>) -> Result { let reservation = query_as::<_, ReservationSum>("SELECT * FROM reservation_sum WHERE uuid = $1") @@ -236,12 +235,13 @@ cfg_if! { if #[cfg(feature = "ssr")] { pub async fn get_public_form_data(day: NaiveDate) -> Result>, ServerFnError> { use crate::backend::opening_hours::hours_for_day; use crate::backend::property::get_props; + use crate::backend::opening_hours::get_closing_times; use chrono::Datelike; let hours = hours_for_day(day.weekday()).await?; let props = get_props(Some("active = true")).await?; let reservations = reservations_for_day(&day).await?; - let closing_days = get_closing_time().await?; + let closing_days = get_closing_times().await?; info!("Loading public form data"); diff --git a/src/components/admin_portal.rs b/src/components/admin_portal.rs index 167c354..84893b8 100644 --- a/src/components/admin_portal.rs +++ b/src/components/admin_portal.rs @@ -54,7 +54,7 @@ fn settings_menu(opener: MenuOpener) -> impl IntoView {
  • - + {trl("Appearance")}
  • diff --git a/src/locales/catalogues.rs b/src/locales/catalogues.rs index 13ff553..5eb1aea 100644 --- a/src/locales/catalogues.rs +++ b/src/locales/catalogues.rs @@ -167,7 +167,9 @@ lazy_static! { ("Bad username or password", "Špatné uživatelské jméno nebo heslo"), ("You can't escalate your privileges", "Nemůžete povýšit práva sami sobě"), ("Username already exists", "Uživatel již existuje"), - ("You can't delete yourself", "Nemůžete smazat sami sebe") + ("You can't delete yourself", "Nemůžete smazat sami sebe"), + ("Are you sure you want to delete closing days from ", "Opravdu chcete smazat zavírací dny od "), + (" to ", " do ") ])), ("sk", HashMap::from( [ ("Dashboard", "Prehlad"), diff --git a/src/pages/closing_days.rs b/src/pages/closing_days.rs new file mode 100644 index 0000000..ff98472 --- /dev/null +++ b/src/pages/closing_days.rs @@ -0,0 +1,116 @@ +use chrono::Local; +use leptos::*; +use crate::backend::data::ClosingTime; +use crate::backend::opening_hours::{get_closing_times, DeleteClosingTime, InsertClosingTime}; +use crate::components::data_form::{DataForm, QuestionDialog}; +use crate::components::modal_box::DialogOpener; +use crate::locales::{loc_date, trl}; + +#[component] +pub fn del_closing_day(closing_time: ReadSignal, opener: DialogOpener) -> impl IntoView { + let delete = create_server_action::(); + + view! { + + +
    {trl("Are you sure you want to delete closing days from ")}{move || loc_date(closing_time.get().from_date)}{trl(" to ")}{move || loc_date(closing_time.get().to_date)}"?"
    +
    + } +} + +#[component] +pub fn insert_closing_days(opener: DialogOpener) -> impl IntoView { + let insert_day = create_server_action::(); + + view! { + + +
    +
    + + + + +
    +
    +
    + } +} +#[component] +pub fn closing_days() -> impl IntoView { + let delete_dialog = DialogOpener::new(); + let editor = DialogOpener::new(); + let times = create_blocking_resource(move || editor.visible() || delete_dialog.visible(), move |_| {get_closing_times()}); + let time_to_del = create_rw_signal(ClosingTime::default()); + view! { + + +
    +
    +
    " "{trl("Closing days")}
    + {trl("Loading...")}

    }> + + + + + + + + + {move || { + times.get().map(|c| match c { + Err(e) => { + let err = if e.to_string().contains("403") { + "Only admin can edit closing times".to_string() + } else { + e.to_string() + }; + view! { + }} + Ok(c) => { + view! { + + + + + + } + }/> + } + } + }) + }} +
    {trl("From")}{trl("To")}{trl("Actions")}
    {trl(&err)}
    {loc_date(ct.from_date)}{loc_date(ct.to_date)} + + {trl("Delete")} + +
    +
    + + + + +
    +
    + } +} \ No newline at end of file diff --git a/src/pages/hours_edit.rs b/src/pages/hours_edit.rs index e05e6d7..ad36d4a 100644 --- a/src/pages/hours_edit.rs +++ b/src/pages/hours_edit.rs @@ -1,7 +1,6 @@ -use chrono::Local; use leptos::*; use crate::backend::data::WeekHours; -use crate::backend::opening_hours::{DeleteClosingTime, UpdateClosingTime, UpdateHours}; +use crate::backend::opening_hours::{DeleteClosingTime, UpdateHours}; use crate::components::data_form::{DataForm, QuestionDialog}; use crate::components::modal_box::DialogOpener; use crate::locales::trl; @@ -30,37 +29,6 @@ pub fn EditHours(opener: DialogOpener, hours: ReadSignal) -> impl Int } } -#[component] -pub fn closing_days(opener: DialogOpener) -> impl IntoView { - let update_days = create_server_action::(); - - view! { - - -
    -
    - - - - -
    -
    -
    - } -} - #[component] pub fn del_closing_days(opener: DialogOpener) -> impl IntoView { let delete = create_server_action::(); diff --git a/src/pages/mod.rs b/src/pages/mod.rs index 1695663..aa1088d 100644 --- a/src/pages/mod.rs +++ b/src/pages/mod.rs @@ -22,4 +22,5 @@ mod mail_view; pub mod all_reservations; pub mod customers; pub mod appearance_settings; +mod closing_days; diff --git a/src/pages/opening_hours.rs b/src/pages/opening_hours.rs index 8dd7064..9dabd5d 100644 --- a/src/pages/opening_hours.rs +++ b/src/pages/opening_hours.rs @@ -1,10 +1,10 @@ use chrono::Weekday; use leptos::*; use crate::backend::data::{DayHours, WeekHours}; -use crate::backend::opening_hours::{get_closing_time, get_hours}; +use crate::backend::opening_hours::get_hours; use crate::components::modal_box::DialogOpener; -use crate::locales::{loc_date, show_day, trl}; -use crate::pages::hours_edit::{ClosingDays, DelClosingDays, EditHours}; +use crate::locales::{show_day, trl}; +use crate::pages::hours_edit::{DelClosingDays, EditHours}; fn show_time(tm: &str) -> impl Fn() -> String { if tm.is_empty() { @@ -17,15 +17,12 @@ fn show_time(tm: &str) -> impl Fn() -> String { #[component] pub fn OpeningHours() -> impl IntoView { let editor = DialogOpener::new(); - let closing_editor = DialogOpener::new(); let closing_delete = DialogOpener::new(); let hours = create_blocking_resource(move || editor.visible(), move |_| {get_hours()}); - let closing_days = create_blocking_resource(move || closing_editor.visible() | closing_delete.visible(), move |_| get_closing_time()); let hrs = create_rw_signal(WeekHours::default()); view! { -
    @@ -68,28 +65,6 @@ pub fn OpeningHours() -> impl IntoView { }}

    -
    - {trl("Closing days: ")} - {trl("Loading...")}

    }> - { - closing_days.get().map(|cd| match cd { - Ok(cd) => { - if let Some(cd) = cd { - view! {

    {loc_date(cd.from_date)}" - "{loc_date(cd.to_date)}

    } - } else { - view! {

    } - } - } - Err(_) => {view! {

    }}}) - } -
    - - -
    } diff --git a/src/pages/public.rs b/src/pages/public.rs index a4c1ef1..63abbea 100644 --- a/src/pages/public.rs +++ b/src/pages/public.rs @@ -22,12 +22,15 @@ fn time_selector( slots: RwSignal>, price: RwSignal, day: ReadSignal, - closing_days: Option) -> impl IntoView { - let closed = if let Some(c) = closing_days { - day.get() >= c.from_date && day.get() <= c.to_date - } else { - false - }; + closing_days: Vec) -> impl IntoView { + let mut closed = false; + for cd in closing_days { + if day.get() >= cd.from_date && day.get() <= cd.to_date { + closed = true; + break + } + } + let checks = if !closed { hours.into_iter().map(|h| { match property.slot { diff --git a/src/pages/settings.rs b/src/pages/settings.rs index e72479b..40017da 100644 --- a/src/pages/settings.rs +++ b/src/pages/settings.rs @@ -1,5 +1,6 @@ use leptos::*; use crate::locales::trl; +use crate::pages::closing_days::ClosingDays; use crate::pages::company_info::CompanyInfo; use crate::pages::opening_hours::OpeningHours; use crate::pages::users::Users; @@ -25,5 +26,11 @@ pub fn Settings() -> impl IntoView { +
    +
    + +
    + +
    } } \ No newline at end of file