You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
4.8 KiB
Rust

use std::collections::HashMap;
use cfg_if::cfg_if;
use chrono::Weekday;
use leptos::*;
use validator::Validate;
use crate::backend::data::{ApiResponse, ClosingTime, DayHour, WeekHours};
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<Vec<DayHour>, AppError> {
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 WHERE day = $1")
.bind(day.num_days_from_monday() as i32)
.fetch_all(&pool)
.await?;
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]
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 get_hours_for_day(day: Weekday) -> Result<Vec<DayHour>, ServerFnError> {
Ok(hours_for_day(day).await?)
}
#[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
}
}
#[server]
pub async fn get_closing_time() -> Result<Option<ClosingTime>, ServerFnError> {
use crate::backend::get_pool;
use sqlx::{Error, query_as};
let pool = get_pool().await?;
let ct = query_as::<_, ClosingTime>("SELECT * FROM closing_time ORDER BY from_date")
.fetch_one(&pool)
.await;
Ok(if let Err(ref e) = ct {
if matches!(e, Error::RowNotFound) {
None
} else {
Some(ct?)
}
} else {
Some(ct?)
})
}
#[server]
pub async fn get_closing_times() -> Result<Vec<ClosingTime>, 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<ApiResponse<()>, ServerFnError> {
use crate::perm_check;
use crate::backend::get_pool;
perm_check!(is_admin);
let pool = get_pool().await?;
sqlx::query("INSERT INTO closing_time(from_date, to_date) VALUES($1, $2)")
.bind(time.from_date)
.bind(time.to_date)
.execute(&pool)
.await?;
Ok(ApiResponse::Data(()))
}
impl ForValidation for InsertClosingTime {
fn entity(&self) -> &dyn Validate {
&self.time
}
}
#[server]
pub async fn delete_closing_time(id: i32) -> Result<ApiResponse<()>, 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 WHERE id = $1")
.bind(id)
.execute(&pool)
.await?;
Ok(ApiResponse::Data(()))
}