diff --git a/.gitignore b/.gitignore index 959b2ab..3b954cf 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ playwright/.cache/ /.idea/modules.xml /.idea/rezervovator.iml /.idea/vcs.xml +/.settings/ +/.vscode/ diff --git a/Cargo.lock b/Cargo.lock index 7e1698b..08f3c50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,7 +206,7 @@ dependencies = [ "serde_urlencoded", "smallvec", "socket2 0.5.4", - "time 0.3.22", + "time", "url", ] @@ -658,17 +658,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", - "time 0.1.45", + "serde", "wasm-bindgen", - "winapi", + "windows-targets", ] [[package]] @@ -808,7 +808,7 @@ dependencies = [ "rand", "sha2 0.10.7", "subtle", - "time 0.3.22", + "time", "version_check", ] @@ -1233,7 +1233,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -1636,9 +1636,9 @@ dependencies = [ [[package]] name = "leptos" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3885e75a25bbf43c95350cf2f6b9f5228a3d911e28512c44c2a6c8aa49e9c9" +checksum = "f98f0fe11faa66358ff8c2ee48881c54f8f216ecddabfc5b69cdc2e90c8e337b" dependencies = [ "cfg-if", "leptos_config", @@ -1656,9 +1656,9 @@ dependencies = [ [[package]] name = "leptos_actix" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd04ab9afac818fe45695b8e1f103714e612135b42519a21761c730fc9223c14" +checksum = "7f50f8c459143ef36c6dce5786e33e48d46dfb6829af87c985d65fb3b0b402aa" dependencies = [ "actix-http", "actix-web", @@ -1676,9 +1676,9 @@ dependencies = [ [[package]] name = "leptos_config" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3936a83035a4ec03487792d8c9c2c5ad00c269d09701d102630ac5c31caa463" +checksum = "e0f0e1a9a583d943b19c740c82a3ec69224c979af90f40738d93ec59ee1475bb" dependencies = [ "config", "regex", @@ -1689,9 +1689,9 @@ dependencies = [ [[package]] name = "leptos_dom" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbea8aeea07633b3559818fa963c03857751fbafc6bb4a73c995662836070e1" +checksum = "111391d1ccbc3355344f90f0893f4137db13a7f98d53fede0a3613c522ebaf19" dependencies = [ "async-recursion", "cfg-if", @@ -1719,9 +1719,9 @@ dependencies = [ [[package]] name = "leptos_hot_reload" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b56ec18e255737108b4f4d570c1c4f036f54a9989befe2658758500b636ebda4" +checksum = "a6902fabee84955a85a6cdebf8ddfbfb134091087b172e32ebb26e571d4640ca" dependencies = [ "anyhow", "camino", @@ -1737,9 +1737,9 @@ dependencies = [ [[package]] name = "leptos_integration_utils" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e1faf41644272929c47993af12928a51c0a03a1ed7ee55afcacf4a3a02073c" +checksum = "eb816f3c809227b090b538994368a756d494c829b07c1bd312d07263552b8c87" dependencies = [ "futures", "leptos", @@ -1751,9 +1751,9 @@ dependencies = [ [[package]] name = "leptos_macro" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae8be584ba63e002cec113e0a831f2ba17ad452104781a2b1b65555db049779" +checksum = "e68201041cc5af68f7eb35015336827a36c543d87dcf2403117d7244db1f14a0" dependencies = [ "attribute-derive", "cfg-if", @@ -1774,9 +1774,9 @@ dependencies = [ [[package]] name = "leptos_meta" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013e23a79d48c6eee6063b162e5ba0beb7d1a42c07361e4c16effb916160a5f0" +checksum = "b64d2b4bd0ab25a4897179ee603f2fa8178da6c9f97ef3efd4fa46580fd7efc1" dependencies = [ "cfg-if", "indexmap 2.0.0", @@ -1788,15 +1788,16 @@ dependencies = [ [[package]] name = "leptos_reactive" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ec5366c79892fa8232dcfa6f05d610d0fd780af155fea8c466e77da18e744f" +checksum = "282e84ae3e3eb30ab1eb1c881bfeea8a3cb6d6c683dc99f26f2f69ee240b148d" dependencies = [ "base64 0.21.2", "cfg-if", "futures", "indexmap 2.0.0", "js-sys", + "paste", "pin-project", "rustc-hash", "self_cell", @@ -1814,14 +1815,15 @@ dependencies = [ [[package]] name = "leptos_router" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55951a1e4ee0b9c26e4ebc0c09ecc4b7fffbefecb912c72db0c5dfa33b1584c" +checksum = "d5ca4422fdfba8af03d347d346f9364a4393ad36e227a018567192395285cf65" dependencies = [ "cached", "cfg-if", "common_macros", "gloo-net", + "itertools 0.11.0", "js-sys", "lazy_static", "leptos", @@ -1845,9 +1847,9 @@ dependencies = [ [[package]] name = "leptos_server" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f4f7221a323c029877ffb09e97d38cc805f1a5821f9554ecf0e7f6852100c" +checksum = "e67f3810352bab860bcfa85f1760de4bd6e82cd72b14a97779d9168d37661bbf" dependencies = [ "inventory", "lazy_static", @@ -1986,9 +1988,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "mime" @@ -2029,7 +2031,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys", ] @@ -2436,9 +2438,21 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -2447,9 +2461,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rend" @@ -2511,6 +2525,7 @@ dependencies = [ "leptos_meta", "leptos_router", "pwhash", + "regex", "rust_decimal", "serde", "sqlx", @@ -2809,9 +2824,9 @@ dependencies = [ [[package]] name = "server_fn" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29eefae61211e81059a092a3428612c475a3a28e0ea4fb3fd49b0a940d837f84" +checksum = "0186f969a1f9572af27159b8273252abf9a6a38934130fe6f3ae0e439d48cf14" dependencies = [ "ciborium", "const_format", @@ -2834,9 +2849,9 @@ dependencies = [ [[package]] name = "server_fn_macro" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f68140099f8e55bd526dc176d17d341189bf669d45216c4797ddc344610a84a4" +checksum = "1dbc70e4f185ff2b5c11f02a91baf830f33e456e0571d0680d1d76999ed242ed" dependencies = [ "const_format", "proc-macro-error", @@ -2849,9 +2864,9 @@ dependencies = [ [[package]] name = "server_fn_macro_default" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee874f357d640ad221ba0c27c2559fa3d1434f7f7bbf688a34118518c5924b7" +checksum = "d8aaf8cf1f5dde82d3f37548732a4852f65d5279b4ae40add5a2a3c9e559f662" dependencies = [ "server_fn_macro", "syn 2.0.28", @@ -3312,17 +3327,6 @@ dependencies = [ "syn 2.0.28", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.22" @@ -3650,12 +3654,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index e7b1719..724fcb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,21 +12,22 @@ actix-web = { version = "4.4.0", optional = true, features = ["macros"] } actix-session = { version = "0.8.0", optional = true, features = ["cookie-session"] } console_error_panic_hook = "0.1" cfg-if = "1" -leptos = { version = "0.5.0" } -leptos_meta = { version = "0.5.0" } -leptos_actix = { version = "0.5.0", optional = true } -leptos_router = { version = "0.5.0" } +leptos = { version = "0.5.2" } +leptos_meta = { version = "0.5.2" } +leptos_actix = { version = "0.5.2", optional = true } +leptos_router = { version = "0.5.2" } serde = { version = "1", features = ["derive"] } wasm-bindgen = "=0.2.87" web-sys = { version = "0.3.61", features = ["Navigator"] } lazy_static = "1.4.0" -chrono = "0.4.26" +chrono = { version = "0.4.31", features = ["serde"]} sqlx = { version = "0.7.1", optional = true, features = ["runtime-tokio-rustls", "postgres", "chrono", "rust_decimal"] } rust_decimal = "1.31.0" uuid = {version = "1.4.1", features = ["v4"]} validator = {version = "0.16.1", features = ["derive"]} pwhash = "1.0.0" futures-util = "0.3.28" +regex = "1.10.2" [features] csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"] diff --git a/src/backend/data.rs b/src/backend/data.rs index d028c97..4acc5ae 100644 --- a/src/backend/data.rs +++ b/src/backend/data.rs @@ -1,9 +1,14 @@ //use chrono::{NaiveDate, NaiveTime, Weekday}; //use rust_decimal::Decimal; #![allow(unused_variables)] + +use chrono::{NaiveTime, Weekday}; +use lazy_static::lazy_static; +use regex::Regex; use serde::{Deserialize, Serialize}; //use uuid::Uuid; -use validator::Validate; +use validator::{Validate, ValidationError}; +use crate::error::AppError; #[derive(Serialize, Deserialize, Clone, Debug)] pub enum ApiResponse { @@ -114,6 +119,176 @@ impl PwdChange { } } +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Default)] +#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))] +pub struct OpeningHour { + id: i32, + pub day: i32, + pub from: NaiveTime, + pub to: NaiveTime, + pub discount: Option +} + +impl OpeningHour { + pub fn id(&self) -> i32 { + self.id + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct DayHours(pub Vec); + +impl DayHours { + + pub fn try_new(hours: &str) -> Result { + if hours.is_empty() { + return Ok(Self(Vec::new())) + } + + let times = hours.split(",") + .map(|h| h.trim()) + .map(|h| DayHour::try_from(h)) + .collect::>(); + + if times.contains(&Err(AppError::HourParseError)) { + return Err(AppError::HourParseError) + } + + Ok(Self(times.into_iter().map(|h| h.unwrap()).collect())) + } + + pub fn hours(&self) -> &Vec { + &self.0 + } +} + +impl ToString for DayHours { + fn to_string(&self) -> String { + if self.0.is_empty() { + return "".to_string() + } + + self.0.iter().map(|h| { + let discount = if let Some(d) = h.discount() { + format!(" ({})", d).to_string() + } else { "".to_string() }; + format!("{} - {}{}", h.from().format("%H:%M"), h.to().format("%H:%M"), discount).to_string()}) + .collect::>() + .join(", ") + } +} + +#[derive(Eq, PartialEq, Serialize, Deserialize, Clone, Debug)] +pub struct DayHour { + from: NaiveTime, + to: NaiveTime, + discount: Option +} + +impl DayHour { + pub fn new(from: NaiveTime, to: NaiveTime, discount: Option) -> Self { + Self { from, to, discount } + } + + pub fn from(&self) -> NaiveTime { + self.from + } + pub fn to(&self) -> NaiveTime { + self.to + } + pub fn discount(&self) -> Option { + self.discount + } +} + +impl TryFrom for DayHour { + type Error = AppError; + + fn try_from(value: String) -> Result { + value.as_str().try_into() + } +} + +impl TryFrom<&str> for DayHour { + type Error = AppError; + + fn try_from(value: &str) -> Result { + if value.is_empty() { + return Err(AppError::HourParseError) + } + + let times = value.split("-") + .map(|t| t.trim()).collect::>(); + + if times.len() != 2 { + return Err(AppError::HourParseError) + } + + let from = NaiveTime::parse_from_str(times.get(0).unwrap(), "%H:%M"); + let to = NaiveTime::parse_from_str(times.get(1).unwrap(), "%H:%M"); + + if from.is_err() || to.is_err() { + return Err(AppError::HourParseError) + } + + Ok(DayHour { + from: from.unwrap(), + to: to.unwrap(), + discount: None + }) + } +} + +fn validate_hours(value: &WeekHours) -> Result<(), ValidationError> { + if value.hours().is_empty() { + return Ok(()) + } + if let Ok(h) = DayHours::try_new(value.hours()) { + for hr in h.hours() { + if hr.from() >= hr.to() { return Err(ValidationError::new("TO_BEFORE_FROM")) } + } + Ok(()) + } else { + Ok(()) + } +} + +lazy_static! { + static ref RE_HOURS: Regex = Regex::new(r"^$|(^\d{2}:\d{2} ?- ?\d{2}:\d{2} ?(\(\d+\))?,? ?)+").unwrap(); +} + +#[derive(Clone, Serialize, Deserialize, Debug, Validate)] +#[validate(schema(function = "validate_hours", message = "Time 'to' must be after time 'from'"))] +pub struct WeekHours { + day: Weekday, + #[validate(regex(path = "RE_HOURS", message = "Hours must be in HH:MM - HH:MM format"))] + hours: String +} + +impl Default for WeekHours { + fn default() -> Self { + Self { + day: Weekday::Mon, + hours: String::default() + } + } +} + +impl WeekHours { + pub fn new(day: Weekday, hours: Vec) -> Self { + Self { + day, + hours: DayHours(hours).to_string() + } + } + pub fn day(&self) -> Weekday { + self.day + } + pub fn hours(&self) -> &str { + &self.hours + } +} + /*pub struct Property { id: u16, name: String, @@ -135,14 +310,6 @@ pub struct Message { text: String, } -pub struct OpeningHour { - id: u16, - day: Weekday, - from: NaiveTime, - to: NaiveTime, - discount: u8 -} - pub struct Customer { id: u128, full_name: String, diff --git a/src/backend/mod.rs b/src/backend/mod.rs index b46214f..4c13b9b 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -4,6 +4,7 @@ pub mod data; pub mod company; pub mod user; pub mod auth_middleware; +pub mod opening_hours; #[macro_export] macro_rules! perm_check { diff --git a/src/backend/opening_hours.rs b/src/backend/opening_hours.rs new file mode 100644 index 0000000..3bfde4f --- /dev/null +++ b/src/backend/opening_hours.rs @@ -0,0 +1,69 @@ +use std::collections::HashMap; +use chrono::Weekday; +use leptos::*; +use validator::Validate; +use crate::backend::data::{ApiResponse, DayHour, WeekHours}; +use crate::components::data_form::ForValidation; + +#[server] +pub async fn get_hours() -> Result>, ServerFnError> { + use crate::backend::get_pool; + use crate::backend::data::OpeningHour; + + let pool = get_pool().await?; + let hours = sqlx::query_as::<_, OpeningHour>("SELECT * FROM opening_hour").fetch_all(&pool).await?; + + let mut ret: HashMap> = hours.into_iter().fold(HashMap::new(), |mut map, v| { + map.entry(Weekday::try_from(v.day as u8).unwrap_or(Weekday::Mon)) + .and_modify(|h| h.push(DayHour::new(v.from, v.to, v.discount))) + .or_insert(vec![DayHour::new(v.from, v.to, v.discount)]); + map + }); + + for d in 0..6 { + if let None = ret.get(&Weekday::try_from(d as u8).unwrap()) { + ret.insert(Weekday::try_from(d as u8).unwrap(), Vec::new()); + } + } + + Ok(ret) +} + +#[server] +pub async fn update_hours(hours: WeekHours) -> Result, ServerFnError> { + use crate::perm_check; + use crate::backend::get_pool; + use crate::backend::data::DayHours; + + perm_check!(is_admin); + + let hr = DayHours::try_new(hours.hours())?; + let pool = get_pool().await?; + let day = hours.day(); + let mut tx = pool.begin().await?; + + sqlx::query("DELETE FROM opening_hour WHERE day = $1") + .bind(day.num_days_from_monday() as i32) + .execute(&mut *tx) + .await?; + + for h in hr.hours() { + sqlx::query(r#"INSERT INTO opening_hour(day, "from", "to", discount) VALUES($1, $2, $3, $4)"#) + .bind(day.num_days_from_monday() as i32) + .bind(h.from()) + .bind(h.to()) + .bind(h.discount()) + .execute(&mut *tx) + .await?; + } + + tx.commit().await?; + + Ok(ApiResponse::Data(())) +} + +impl ForValidation for UpdateHours { + fn entity(&self) -> &dyn Validate { + &self.hours + } +} \ No newline at end of file diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..0c30e9c --- /dev/null +++ b/src/error.rs @@ -0,0 +1,22 @@ +use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; + +#[derive(Debug, Eq, PartialEq)] +pub enum AppError { + HourParseError +} + +impl AppError { + fn as_string(&self) -> String { + //match self { AppError::HourParseError => {"Hour parse error"} } + "Hours parse error".to_string() + } +} + +impl Display for AppError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.as_string()) + } +} + +impl Error for AppError {} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 5f47edd..86ad729 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ pub mod backend; mod pages; mod components; mod validator; +pub mod error; use cfg_if::cfg_if; diff --git a/src/locales/catalogues.rs b/src/locales/catalogues.rs index fdb57ac..93260b9 100644 --- a/src/locales/catalogues.rs +++ b/src/locales/catalogues.rs @@ -16,6 +16,15 @@ lazy_static! { ("Name cannot be empty", "Jméno nesmí být prázdné"), ("Invalid old password", "Neplatné staré heslo"), ("Please sign-in to your account", "Přihlaste se prosím k uživatelskému účtu"), + ("Closed", "Zavřeno"), + ("Monday", "Pondělí"), + ("Tuesday", "Úterý"), + ("Wednesday", "Středa"), + ("Thursday", "Čtvrtek"), + ("Friday", "Pátek"), + ("Saturday", "Sobota"), + ("Sunday", "Neděle"), + ("Opening hours", "Otvírací hodiny"), ])), ("sk", HashMap::from( [ ("Dashboard", "Prehlad"), diff --git a/src/pages/hours_edit.rs b/src/pages/hours_edit.rs new file mode 100644 index 0000000..d567a60 --- /dev/null +++ b/src/pages/hours_edit.rs @@ -0,0 +1,29 @@ +use leptos::*; +use crate::backend::data::WeekHours; +use crate::backend::opening_hours::UpdateHours; +use crate::components::data_form::DataForm; +use crate::components::modal_box::DialogOpener; + +#[component] +pub fn EditHours(opener: DialogOpener, hours: ReadSignal) -> impl IntoView { + let update_hours = create_server_action::(); + + view! { + + +
+
+ + +
+
+
+ } +} \ No newline at end of file diff --git a/src/pages/mod.rs b/src/pages/mod.rs index 045ff92..8f26323 100644 --- a/src/pages/mod.rs +++ b/src/pages/mod.rs @@ -1,11 +1,14 @@ pub mod home_page; pub mod settings; -pub mod company_info; +mod company_info; mod company_edit; pub mod login; pub mod public; pub mod profile_edit; pub mod change_pwd; -pub mod users; -pub mod user_edit; -pub mod user_delete; +mod users; +mod user_edit; +mod user_delete; +mod opening_hours; +mod hours_edit; + diff --git a/src/pages/opening_hours.rs b/src/pages/opening_hours.rs new file mode 100644 index 0000000..d3f23ae --- /dev/null +++ b/src/pages/opening_hours.rs @@ -0,0 +1,81 @@ +use chrono::Weekday; +use leptos::*; +use crate::backend::data::{DayHours, WeekHours}; +use crate::backend::opening_hours::get_hours; +use crate::components::modal_box::DialogOpener; +use crate::locales::trl; +use crate::pages::hours_edit::EditHours; + +fn show_time(tm: &str) -> impl Fn() -> String { + if tm.is_empty() { + trl("Closed") + } else { + trl(tm) + } +} + +fn show_day(day: &Weekday) -> impl Fn() -> String { + match day { + Weekday::Mon => { trl("Monday") } + Weekday::Tue => { trl("Tuesday") } + Weekday::Wed => { trl("Wednesday") } + Weekday::Thu => { trl("Thursday") } + Weekday::Fri => { trl("Friday") } + Weekday::Sat => { trl("Saturday") } + Weekday::Sun => { trl("Sunday") } + } +} + +#[component] +pub fn OpeningHours() -> impl IntoView { + let editor = DialogOpener::new(); + let hours = create_blocking_resource(move || editor.visible(), move |_| {get_hours()}); + let hrs = create_rw_signal(WeekHours::default()); + + view! { + +
+
+
" "{trl("Opening hours")}
+

+ {trl("Loading...")}

}> + {move || { + hours.get().map(|h| match h { + Ok(h) => { + let h = create_rw_signal(h); + let d = create_rw_signal((0..7).collect::>()); + view! { +
+ + + + + + + } + } + /> +
{show_day(&week_day)}{show_time(&DayHours(hr_day).to_string())}
+
+ } + } + Err(e) => {view! {

{trl("Error loading data")}

+

{e.to_string()}

+ }} + }) + }} + +

+
+
+ } +} \ No newline at end of file diff --git a/src/pages/settings.rs b/src/pages/settings.rs index 2ed9a86..aaf515e 100644 --- a/src/pages/settings.rs +++ b/src/pages/settings.rs @@ -1,6 +1,7 @@ use leptos::*; use crate::locales::trl; use crate::pages::company_info::CompanyInfo; +use crate::pages::opening_hours::OpeningHours; use crate::pages::users::Users; #[component] @@ -15,5 +16,13 @@ pub fn Settings() -> impl IntoView { +
+
+ +
+
+ +
+
} } \ No newline at end of file