Improved closing days. Add more than one closing days interval is now possible.

This commit is contained in:
2025-03-24 11:43:16 +01:00
parent 2cb0a31abf
commit 0f940a9f5e
11 changed files with 174 additions and 84 deletions
+116
View File
@@ -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<ClosingTime>, opener: DialogOpener) -> impl IntoView {
let delete = create_server_action::<DeleteClosingTime>();
view! {
<QuestionDialog opener=opener action=delete title="Delete closing days">
<input type="hidden" prop:value={move || closing_time.get().id()} name="id"/>
<div>{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)}"?"</div>
</QuestionDialog>
}
}
#[component]
pub fn insert_closing_days(opener: DialogOpener) -> impl IntoView {
let insert_day = create_server_action::<InsertClosingTime>();
view! {
<DataForm opener=opener action=insert_day 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 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! {
<DelClosingDay closing_time=time_to_del.read_only() opener=delete_dialog/>
<InsertClosingDays opener=editor/>
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title"><i class="bx bx-calendar-x"></i>" "{trl("Closing days")}</h5>
<Transition fallback=move || view! {<p>{trl("Loading...")}</p> }>
<table class="table card-table">
<thead>
<tr>
<th>{trl("From")}</th>
<th>{trl("To")}</th>
<th>{trl("Actions")}</th>
</tr>
</thead>
{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! {<tbody class="table-border-bottom-0">
<tr><td colspan=3>{trl(&err)}</td></tr></tbody>}}
Ok(c) => {
view! {<tbody class="table-border-bottom-0">
<For each=move || c.clone()
key=|ct| ct.id()
children=move |ct: ClosingTime| {
let ct_delete = ct.clone();
view! {
<tr>
<td>{loc_date(ct.from_date)}</td>
<td>{loc_date(ct.to_date)}</td>
<td>
<a class="dropdown-item text-danger" href="javascript:void(0);" on:click=move |_| {
time_to_del.set(ct_delete.clone());
delete_dialog.show();
}>
<i class="bx bx-trash me-1"></i> {trl("Delete")}</a>
</td>
</tr>
}
}/></tbody>
}
}
})
}}
</table>
</Transition>
<a href="#" class="card-link" on:click=move |_| editor.show()>
<i class="bx bx-plus-circle fs-4 lh-0"></i>
</a>
</div>
</div>
}
}
+1 -33
View File
@@ -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<WeekHours>) -> impl Int
}
}
#[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>();
+1
View File
@@ -22,4 +22,5 @@ mod mail_view;
pub mod all_reservations;
pub mod customers;
pub mod appearance_settings;
mod closing_days;
+3 -28
View File
@@ -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! {
<EditHours opener=editor hours=hrs.read_only() />
<ClosingDays opener=closing_editor/>
<DelClosingDays opener=closing_delete/>
<div class="card mb-3">
<div class="card-body">
@@ -68,28 +65,6 @@ 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>
}
+9 -6
View File
@@ -22,12 +22,15 @@ fn time_selector(
slots: RwSignal<Vec<String>>,
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
};
closing_days: Vec<ClosingTime>) -> 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 {
+7
View File
@@ -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 {
<Properties/>
</div>
</div>
<div class="row mb-5">
<div class="col-md">
<ClosingDays/>
</div>
</div>
}
}