Opening hours completed. Leptos upgraded to 0.5.2.

main
Josef Rokos 1 year ago
parent e7af2d402d
commit 1de6b74665

2
.gitignore vendored

@ -15,3 +15,5 @@ playwright/.cache/
/.idea/modules.xml
/.idea/rezervovator.iml
/.idea/vcs.xml
/.settings/
/.vscode/

116
Cargo.lock generated

@ -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"

@ -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"]

@ -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<T> {
@ -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<i32>
}
impl OpeningHour {
pub fn id(&self) -> i32 {
self.id
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DayHours(pub Vec<DayHour>);
impl DayHours {
pub fn try_new(hours: &str) -> Result<Self, AppError> {
if hours.is_empty() {
return Ok(Self(Vec::new()))
}
let times = hours.split(",")
.map(|h| h.trim())
.map(|h| DayHour::try_from(h))
.collect::<Vec<_>>();
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<DayHour> {
&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::<Vec<String>>()
.join(", ")
}
}
#[derive(Eq, PartialEq, Serialize, Deserialize, Clone, Debug)]
pub struct DayHour {
from: NaiveTime,
to: NaiveTime,
discount: Option<i32>
}
impl DayHour {
pub fn new(from: NaiveTime, to: NaiveTime, discount: Option<i32>) -> Self {
Self { from, to, discount }
}
pub fn from(&self) -> NaiveTime {
self.from
}
pub fn to(&self) -> NaiveTime {
self.to
}
pub fn discount(&self) -> Option<i32> {
self.discount
}
}
impl TryFrom<String> for DayHour {
type Error = AppError;
fn try_from(value: String) -> Result<Self, Self::Error> {
value.as_str().try_into()
}
}
impl TryFrom<&str> for DayHour {
type Error = AppError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.is_empty() {
return Err(AppError::HourParseError)
}
let times = value.split("-")
.map(|t| t.trim()).collect::<Vec<_>>();
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<DayHour>) -> 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,

@ -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 {

@ -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<HashMap<Weekday, Vec<DayHour>>, 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<Weekday, Vec<DayHour>> = 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<ApiResponse<()>, 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
}
}

@ -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 {}

@ -4,6 +4,7 @@ pub mod backend;
mod pages;
mod components;
mod validator;
pub mod error;
use cfg_if::cfg_if;

@ -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"),

@ -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<WeekHours>) -> impl IntoView {
let update_hours = create_server_action::<UpdateHours>();
view! {
<DataForm opener=opener action=update_hours title="Edit hours">
<input type="hidden" value={move || hours.get().day().to_string()} name="hours[day]"/>
<div class="row">
<div class="col mb-3">
<label for="hours" class="form-label">"Hours"</label>
<input
type="text"
id="hours"
class="form-control"
placeholder="12:00 - 15:00, 17:00 - 21:00"
prop:value={move || hours.get().hours().to_string()}
name="hours[hours]"
/>
</div>
</div>
</DataForm>
}
}

@ -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;

@ -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! {
<EditHours opener=editor hours=hrs.read_only() />
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title"><i class="bx bxs-watch"></i>" "{trl("Opening hours")}</h5>
<p class="card-text">
<Transition fallback=move || view! {<p>{trl("Loading...")}</p> }>
{move || {
hours.get().map(|h| match h {
Ok(h) => {
let h = create_rw_signal(h);
let d = create_rw_signal((0..7).collect::<Vec<u8>>());
view! {
<div>
<table class="table card-table">
<For each=move || d.get() key=|day| *day
children=move |day| {
let week_day = Weekday::try_from(day).unwrap_or(Weekday::Mon);
let hr_c = h.get().get(&week_day).unwrap_or(&Vec::new()).clone();
let hr_day = hr_c.clone();
view! {
<tr>
<td>{show_day(&week_day)}</td>
<td>{show_time(&DayHours(hr_day).to_string())}</td>
<td><a href="javascript:void(0)" class="card-link" on:click = move |_| {
hrs.set(WeekHours::new(week_day, hr_c.clone()));
editor.show();
}><i class="bx bx-edit-alt me-1"></i></a></td>
</tr>
}
}
/>
</table>
</div>
}
}
Err(e) => {view! {<div><p>{trl("Error loading data")}</p>
<p>{e.to_string()}</p></div>
}}
})
}}
</Transition>
</p>
</div>
</div>
}
}

@ -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 {
<Users/>
</div>
</div>
<div class="row mb-5">
<div class="col-md">
<OpeningHours/>
</div>
<div class="col-md">
</div>
</div>
}
}
Loading…
Cancel
Save