Implemented settings for properties of reservation. Fixed bugs on empty database.
This commit is contained in:
@@ -1,8 +1,29 @@
|
||||
use cfg_if::cfg_if;
|
||||
use leptos::*;
|
||||
use validator::Validate;
|
||||
use crate::backend::data::{ApiResponse, Company};
|
||||
use crate::components::data_form::ForValidation;
|
||||
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
use sqlx::{query_as, PgPool, query};
|
||||
use crate::error::AppError;
|
||||
use log::info;
|
||||
|
||||
pub async fn check_company(pool: &PgPool) -> Result<(), AppError> {
|
||||
let count: (i64,) = query_as("SELECT COUNT(id) FROM company")
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
|
||||
if count.0 == 0 {
|
||||
info!("Creating initial company");
|
||||
query("INSERT INTO company(name, street, house_number, zip_code, city) VALUES('Company name', '', '', '', '')")
|
||||
.execute(pool).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}}
|
||||
|
||||
#[server(GetCompany, "/api", "Url", "get_company")]
|
||||
pub async fn get_company() -> Result<ApiResponse<Company>, ServerFnError> {
|
||||
use crate::backend::AppData;
|
||||
|
||||
+45
-11
@@ -2,9 +2,11 @@
|
||||
//use rust_decimal::Decimal;
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use std::fmt::Display;
|
||||
use chrono::{NaiveTime, Weekday};
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use rust_decimal::Decimal;
|
||||
use serde::{Deserialize, Serialize};
|
||||
//use uuid::Uuid;
|
||||
use validator::{Validate, ValidationError};
|
||||
@@ -162,19 +164,21 @@ impl DayHours {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for DayHours {
|
||||
fn to_string(&self) -> String {
|
||||
impl Display for DayHours {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if self.0.is_empty() {
|
||||
return "".to_string()
|
||||
return write!(f, "{}", "".to_string())
|
||||
}
|
||||
|
||||
self.0.iter().map(|h| {
|
||||
let str = 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()})
|
||||
format!("{} - {}{}", h.from().format("%H:%M"), h.to().format("%H:%M"), discount).to_string()
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")
|
||||
.join(", ");
|
||||
write!(f, "{}", str)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,13 +293,43 @@ impl WeekHours {
|
||||
}
|
||||
}
|
||||
|
||||
/*pub struct Property {
|
||||
id: u16,
|
||||
name: String,
|
||||
description: String,
|
||||
price: Decimal
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Default)]
|
||||
#[cfg_attr(feature = "ssr", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "ssr", sqlx(type_name = "slot_type"))]
|
||||
pub enum SlotType {
|
||||
Quarter,
|
||||
Half,
|
||||
#[default]
|
||||
Hour,
|
||||
Day
|
||||
}
|
||||
|
||||
fn def_true() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Validate, Default)]
|
||||
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
|
||||
pub struct ResProperty {
|
||||
id: i32,
|
||||
#[validate(length(min = 1,message = "Name cannot be empty"))]
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub price: Decimal,
|
||||
pub slot: SlotType,
|
||||
#[serde(default = "def_true")]
|
||||
pub allow_multi: bool,
|
||||
#[serde(default = "def_true")]
|
||||
pub active: bool
|
||||
}
|
||||
|
||||
impl ResProperty {
|
||||
pub fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub enum MessageType {
|
||||
NewReservation,
|
||||
NewReservationCust,
|
||||
|
||||
@@ -4,6 +4,7 @@ pub mod company;
|
||||
pub mod user;
|
||||
pub mod auth_middleware;
|
||||
pub mod opening_hours;
|
||||
pub mod property;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! perm_check {
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
use leptos::*;
|
||||
use validator::Validate;
|
||||
use crate::backend::data::{ApiResponse, ResProperty};
|
||||
use crate::components::data_form::ForValidation;
|
||||
|
||||
#[server]
|
||||
pub async fn get_properties() -> Result<ApiResponse<Vec<ResProperty>>, ServerFnError> {
|
||||
use crate::backend::get_pool;
|
||||
|
||||
let pool = get_pool().await?;
|
||||
let props = sqlx::query_as::<_, ResProperty>("SELECT * FROM property").fetch_all(&pool).await?;
|
||||
|
||||
Ok(ApiResponse::Data(props))
|
||||
}
|
||||
|
||||
#[server]
|
||||
pub async fn create_property(property: ResProperty) ->Result<ApiResponse<()>, ServerFnError> {
|
||||
use crate::backend::get_pool;
|
||||
use crate::perm_check;
|
||||
|
||||
perm_check!(is_admin);
|
||||
|
||||
let pool = get_pool().await?;
|
||||
sqlx::query("INSERT INTO property(name, description, price, slot) VALUES($1, $2, $3, $4)")
|
||||
.bind(&property.name)
|
||||
.bind(&property.description)
|
||||
.bind(&property.price)
|
||||
.bind(&property.slot)
|
||||
.execute(&pool)
|
||||
.await?;
|
||||
|
||||
Ok(ApiResponse::Data(()))
|
||||
}
|
||||
|
||||
#[server]
|
||||
pub async fn edit_property(property: ResProperty) -> Result<ApiResponse<()>, ServerFnError> {
|
||||
use crate::backend::get_pool;
|
||||
use crate::perm_check;
|
||||
|
||||
perm_check!(is_admin);
|
||||
|
||||
let pool = get_pool().await?;
|
||||
sqlx::query("UPDATE property SET name = $1, description = $2, price = $3, active = $4, slot = $5 WHERE id = $6")
|
||||
.bind(&property.name)
|
||||
.bind(&property.description)
|
||||
.bind(&property.price)
|
||||
.bind(property.active)
|
||||
.bind(&property.slot)
|
||||
.bind(property.id())
|
||||
.execute(&pool)
|
||||
.await?;
|
||||
|
||||
Ok(ApiResponse::Data(()))
|
||||
}
|
||||
|
||||
#[server]
|
||||
pub async fn delete_property(id: i32) -> Result<ApiResponse<()>, ServerFnError> {
|
||||
use crate::backend::get_pool;
|
||||
use crate::perm_check;
|
||||
|
||||
perm_check!(is_admin);
|
||||
|
||||
let pool = get_pool().await?;
|
||||
sqlx::query("DELETE FROM property WHERE id = $1")
|
||||
.bind(id)
|
||||
.execute(&pool)
|
||||
.await?;
|
||||
|
||||
Ok(ApiResponse::Data(()))
|
||||
}
|
||||
|
||||
impl ForValidation for CreateProperty {
|
||||
fn entity(&self) -> &dyn Validate {
|
||||
&self.property
|
||||
}
|
||||
}
|
||||
|
||||
impl ForValidation for EditProperty {
|
||||
fn entity(&self) -> &dyn Validate {
|
||||
&self.property
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -9,6 +9,7 @@ cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
use actix_session::*;
|
||||
use leptos_actix::{extract, redirect};
|
||||
use log::{info, warn};
|
||||
use crate::error::AppError;
|
||||
|
||||
pub async fn has_admin_user(pool: &PgPool) -> Result<bool, Error> {
|
||||
let count: (i64,) = query_as(r#"SELECT COUNT(id) FROM "user" WHERE admin = $1"#)
|
||||
@@ -19,7 +20,7 @@ cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
Ok(count.0 > 0)
|
||||
}
|
||||
|
||||
pub async fn create_admin(pool: &PgPool) -> Result<(), Error> {
|
||||
pub async fn create_admin(pool: &PgPool) -> Result<(), AppError> {
|
||||
if !has_admin_user(pool).await? {
|
||||
let pwd = pwhash::bcrypt::hash("admin");
|
||||
query(r#"INSERT INTO "user"(login, password, full_name, admin) VALUES($1, $2, $3, $4)"#)
|
||||
@@ -44,6 +45,11 @@ cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
extract(|session: Session| async move {
|
||||
session.get::<User>("user").unwrap_or(None)
|
||||
}).await.unwrap_or(None)
|
||||
/*let mut usr = User::default();
|
||||
usr.full_name = Some("PokAdm".to_string());
|
||||
usr.admin = true;
|
||||
|
||||
Some(usr)*/
|
||||
}
|
||||
|
||||
pub async fn is_logged_in() -> bool {
|
||||
|
||||
Reference in New Issue
Block a user