Added setting for closing days.

This commit is contained in:
2024-05-26 21:07:09 +02:00
parent 084911c992
commit 9f9b716781
8 changed files with 236 additions and 50 deletions
+45 -2
View File
@@ -1,7 +1,8 @@
use chrono::Local;
use leptos::*;
use crate::backend::data::WeekHours;
use crate::backend::opening_hours::UpdateHours;
use crate::components::data_form::DataForm;
use crate::backend::opening_hours::{DeleteClosingTime, UpdateClosingTime, UpdateHours};
use crate::components::data_form::{DataForm, QuestionDialog};
use crate::components::modal_box::DialogOpener;
use crate::locales::trl;
@@ -27,4 +28,46 @@ pub fn EditHours(opener: DialogOpener, hours: ReadSignal<WeekHours>) -> impl Int
</div>
</DataForm>
}
}
#[component]
pub fn closing_days(opener: DialogOpener) -> impl IntoView {
let update_days = create_server_action::<UpdateClosingTime>();
view! {
<DataForm opener=opener action=update_days title="Closing days">
<input type="hidden" value=0 name="time[id]"/>
<div class="row">
<div class="col mb-3">
<label for="from_day" class="form-label">{trl("From")}</label>
<input
type="date"
id="from_day"
class="form-control"
prop:value={move || Local::now().date_naive().format("%Y-%m-%d").to_string()}
name="time[from_date]"
/>
<label for="to_day" class="form-label">{trl("To")}</label>
<input
type="date"
id="to_day"
class="form-control"
prop:value={move || Local::now().date_naive().format("%Y-%m-%d").to_string()}
name="time[to_date]"
/>
</div>
</div>
</DataForm>
}
}
#[component]
pub fn del_closing_days(opener: DialogOpener) -> impl IntoView {
let delete = create_server_action::<DeleteClosingTime>();
view! {
<QuestionDialog opener=opener action=delete title="Delete closing days">
<div>{trl("Are you sure you want to delete closing days?")}</div>
</QuestionDialog>
}
}
+30 -3
View File
@@ -1,10 +1,10 @@
use chrono::Weekday;
use leptos::*;
use crate::backend::data::{DayHours, WeekHours};
use crate::backend::opening_hours::get_hours;
use crate::backend::opening_hours::{get_closing_time, get_hours};
use crate::components::modal_box::DialogOpener;
use crate::locales::{show_day, trl};
use crate::pages::hours_edit::EditHours;
use crate::locales::{loc_date, show_day, trl};
use crate::pages::hours_edit::{ClosingDays, DelClosingDays, EditHours};
fn show_time(tm: &str) -> impl Fn() -> String {
if tm.is_empty() {
@@ -17,11 +17,16 @@ 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! {
<EditHours opener=editor hours=hrs.read_only() />
<ClosingDays opener=closing_editor/>
<DelClosingDays opener=closing_delete/>
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title"><i class="bx bxs-watch"></i>" "{trl("Opening hours")}</h5>
@@ -63,6 +68,28 @@ pub fn OpeningHours() -> impl IntoView {
}}
</Transition>
</p>
<div align="center">
{trl("Closing days: ")}
<Transition fallback=move || view! {<p>{trl("Loading...")}</p> }>
{
closing_days.get().map(|cd| match cd {
Ok(cd) => {
if let Some(cd) = cd {
view! {<p>{loc_date(cd.from_date)}" - "{loc_date(cd.to_date)}</p>}
} else {
view! {<p></p>}
}
}
Err(_) => {view! {<p></p>}}})
}
</Transition>
<a href="javascript:void(0)" class="card-link" on:click = move |_| {
closing_editor.show();
}><i class="bx bx-edit-alt me-1"></i></a>
<a class="card-link text-danger" href="javascript:void(0);" on:click=move |_| {
closing_delete.show();
}><i class="bx bx-trash me-1"></i> </a>
</div>
</div>
</div>
}
+55 -42
View File
@@ -5,7 +5,7 @@ use leptos_router::*;
use rust_decimal::Decimal;
use crate::backend::appearance::get_appearance;
use crate::backend::customer::get_remembered;
use crate::backend::data::{ApiResponse, Customer, DayHour, Reservation, ResProperty, SlotType, TmCheck};
use crate::backend::data::{ApiResponse, ClosingTime, Customer, DayHour, Reservation, ResProperty, SlotType, TmCheck};
use crate::backend::reservation::{CreateReservation, get_public_form_data, is_reserved};
use crate::backend::user::get_pow;
use crate::components::data_form::ForValidation;
@@ -20,51 +20,62 @@ fn time_selector(
reservations: Vec<Reservation>,
property: ResProperty,
slots: RwSignal<Vec<String>>,
price: RwSignal<Decimal>) -> impl IntoView {
let checks = hours.into_iter().map(|h| {
match property.slot {
SlotType::Quarter => {
let mut ret: Vec<TmCheck> = vec![];
logging::log!("quarter");
for n in 0..(h.to() - h.from()).num_minutes() * 4 / 60 {
ret.push(TmCheck {
from: h.from() + Duration::minutes(n * 15),
to: h.from() + Duration::minutes((n + 1) * 15)
});
price: RwSignal<Decimal>,
day: ReadSignal<NaiveDate>,
closing_days: Option<ClosingTime>) -> impl IntoView {
let closed = if let Some(c) = closing_days {
day.get() >= c.from_date && day.get() <= c.to_date
} else {
false
};
let checks = if !closed {
hours.into_iter().map(|h| {
match property.slot {
SlotType::Quarter => {
let mut ret: Vec<TmCheck> = vec![];
logging::log!("quarter");
for n in 0..(h.to() - h.from()).num_minutes() * 4 / 60 {
ret.push(TmCheck {
from: h.from() + Duration::minutes(n * 15),
to: h.from() + Duration::minutes((n + 1) * 15)
});
}
ret
}
ret
}
SlotType::Half => {
let mut ret: Vec<TmCheck> = vec![];
logging::log!("half");
for n in 0..(h.to() - h.from()).num_minutes() * 2 / 60 {
ret.push(TmCheck {
from: h.from() + Duration::minutes(n * 30),
to: h.from() + Duration::minutes((n + 1) * 30)
});
SlotType::Half => {
let mut ret: Vec<TmCheck> = vec![];
logging::log!("half");
for n in 0..(h.to() - h.from()).num_minutes() * 2 / 60 {
ret.push(TmCheck {
from: h.from() + Duration::minutes(n * 30),
to: h.from() + Duration::minutes((n + 1) * 30)
});
}
ret
}
ret
}
SlotType::Hour => {
let mut ret: Vec<TmCheck> = vec![];
for n in 0..(h.to() - h.from()).num_minutes() / 60 {
ret.push(TmCheck {
from: h.from() + Duration::minutes(n * 60),
to: h.from() + Duration::minutes((n + 1) * 60)
});
SlotType::Hour => {
let mut ret: Vec<TmCheck> = vec![];
for n in 0..(h.to() - h.from()).num_minutes() / 60 {
ret.push(TmCheck {
from: h.from() + Duration::minutes(n * 60),
to: h.from() + Duration::minutes((n + 1) * 60)
});
}
ret
}
SlotType::Day => {
let mut ret: Vec<TmCheck> = vec![];
ret.push(TmCheck {
from: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
to: NaiveTime::from_hms_opt(23, 59, 59).unwrap()
});
ret
}
ret
}
SlotType::Day => {
let mut ret: Vec<TmCheck> = vec![];
ret.push(TmCheck {
from: NaiveTime::from_hms_opt(0,0,0).unwrap(),
to: NaiveTime::from_hms_opt(23, 59, 59).unwrap()
});
ret
}
}
}).collect::<Vec<_>>().into_iter().flatten().collect::<Vec<_>>();
}).collect::<Vec<_>>().into_iter().flatten().collect::<Vec<_>>()
} else {
vec![]
};
let prop_id = property.id();
let closed = checks.is_empty();
@@ -222,6 +233,8 @@ pub fn Public() -> impl IntoView {
hours={data.hours.clone()}
reservations={data.reservations.clone()}
property={data.property.clone()}
day={day.read_only()}
closing_days={data.closing_days.clone()}
slots={slots}
price={price}/>
</div>