Added checkbox to booking form - remember customer
This commit is contained in:
@@ -9,6 +9,8 @@ cfg_if! { if #[cfg(feature = "ssr")] {
|
|||||||
use sqlx::Error;
|
use sqlx::Error;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use leptos::expect_context;
|
use leptos::expect_context;
|
||||||
|
use leptos_actix::extract;
|
||||||
|
use actix_session::Session;
|
||||||
|
|
||||||
pub async fn find_customer_by_email(email: &str, tx: &mut Transaction<'_, Postgres>) -> Option<Customer> {
|
pub async fn find_customer_by_email(email: &str, tx: &mut Transaction<'_, Postgres>) -> Option<Customer> {
|
||||||
let customer = query_as::<_, Customer>("SELECT * FROM customer WHERE email = $1")
|
let customer = query_as::<_, Customer>("SELECT * FROM customer WHERE email = $1")
|
||||||
@@ -50,6 +52,12 @@ cfg_if! { if #[cfg(feature = "ssr")] {
|
|||||||
.await?;
|
.await?;
|
||||||
Ok(find_customer_by_email(email, tx).await.ok_or(Error::RowNotFound)?)
|
Ok(find_customer_by_email(email, tx).await.ok_or(Error::RowNotFound)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn remember_customer(customer: Customer) -> Result<(), ServerFnError> {
|
||||||
|
let session: Session = extract().await?;
|
||||||
|
session.insert("customer", customer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#[server]
|
#[server]
|
||||||
@@ -66,4 +74,18 @@ pub async fn get_customers() -> Result<ApiResponse<Vec<Customer>>, ServerFnError
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(ApiResponse::Data(customers))
|
Ok(ApiResponse::Data(customers))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn get_remembered() -> Result<Option<Customer>, ServerFnError> {
|
||||||
|
use actix_session::*;
|
||||||
|
use leptos_actix::extract;
|
||||||
|
|
||||||
|
let session = extract::<Session>().await;
|
||||||
|
|
||||||
|
if session.is_err() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(session.unwrap().get::<Customer>("customer").unwrap_or(None))
|
||||||
}
|
}
|
||||||
+5
-1
@@ -376,7 +376,8 @@ pub struct CrReservation {
|
|||||||
email: String,
|
email: String,
|
||||||
#[validate(length(min = 1,message = "Enter your phone number"))]
|
#[validate(length(min = 1,message = "Enter your phone number"))]
|
||||||
phone: String,
|
phone: String,
|
||||||
note: String
|
note: String,
|
||||||
|
remember: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
@@ -420,6 +421,9 @@ impl CrReservation {
|
|||||||
pub fn note(&self) -> &str {
|
pub fn note(&self) -> &str {
|
||||||
&self.note
|
&self.note
|
||||||
}
|
}
|
||||||
|
pub fn remember(&self) -> bool {
|
||||||
|
self.remember
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Default)]
|
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Default)]
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ pub async fn create_reservation(reservation: CrReservation, pow: String) -> Resu
|
|||||||
use crate::backend::customer::find_customer_by_email;
|
use crate::backend::customer::find_customer_by_email;
|
||||||
use crate::backend::customer::sync_customer_data;
|
use crate::backend::customer::sync_customer_data;
|
||||||
use crate::backend::customer::create_customer;
|
use crate::backend::customer::create_customer;
|
||||||
|
use crate::backend::customer::remember_customer;
|
||||||
use crate::backend::property::get_prop_by_id;
|
use crate::backend::property::get_prop_by_id;
|
||||||
use crate::backend::data::{TmCheck, ReservationState, Reservations};
|
use crate::backend::data::{TmCheck, ReservationState, Reservations};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -272,6 +273,15 @@ pub async fn create_reservation(reservation: CrReservation, pow: String) -> Resu
|
|||||||
|
|
||||||
Pow::validate(&pow)?;
|
Pow::validate(&pow)?;
|
||||||
|
|
||||||
|
if reservation.remember() {
|
||||||
|
remember_customer(Customer::new(
|
||||||
|
0,
|
||||||
|
reservation.full_name().to_string(),
|
||||||
|
reservation.email().to_string(),
|
||||||
|
reservation.phone().to_string(),
|
||||||
|
0)).await?;
|
||||||
|
}
|
||||||
|
|
||||||
let slots = reservation.slots().iter().fold(HashMap::new(), |mut map, s| {
|
let slots = reservation.slots().iter().fold(HashMap::new(), |mut map, s| {
|
||||||
let slot_str = s.split("|").collect::<Vec<_>>();
|
let slot_str = s.split("|").collect::<Vec<_>>();
|
||||||
map.entry(i32::from_str(slot_str.get(1).unwrap_or(&"")).unwrap_or(0))
|
map.entry(i32::from_str(slot_str.get(1).unwrap_or(&"")).unwrap_or(0))
|
||||||
|
|||||||
@@ -131,7 +131,8 @@ lazy_static! {
|
|||||||
("Active", "Aktivní"),
|
("Active", "Aktivní"),
|
||||||
("Are you sure you want to delete property ", "Opravdu chcete smazat předmět "),
|
("Are you sure you want to delete property ", "Opravdu chcete smazat předmět "),
|
||||||
("Delete property", "Smazat předmět"),
|
("Delete property", "Smazat předmět"),
|
||||||
("Are you sure you want to delete user ", "Opravdu chcete smazat uživatele ")
|
("Are you sure you want to delete user ", "Opravdu chcete smazat uživatele "),
|
||||||
|
("Remember for next time", "Zapamatovat pro příště")
|
||||||
])),
|
])),
|
||||||
("sk", HashMap::from( [
|
("sk", HashMap::from( [
|
||||||
("Dashboard", "Prehlad"),
|
("Dashboard", "Prehlad"),
|
||||||
|
|||||||
+25
-4
@@ -3,7 +3,8 @@ use leptos::*;
|
|||||||
use leptos_captcha::{Captcha, pow_dispatch};
|
use leptos_captcha::{Captcha, pow_dispatch};
|
||||||
use leptos_router::*;
|
use leptos_router::*;
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use crate::backend::data::{ApiResponse, DayHour, Reservation, ResProperty, SlotType, TmCheck};
|
use crate::backend::customer::get_remembered;
|
||||||
|
use crate::backend::data::{ApiResponse, Customer, DayHour, Reservation, ResProperty, SlotType, TmCheck};
|
||||||
use crate::backend::reservation::{CreateReservation, get_public_form_data, is_reserved};
|
use crate::backend::reservation::{CreateReservation, get_public_form_data, is_reserved};
|
||||||
use crate::backend::user::get_pow;
|
use crate::backend::user::get_pow;
|
||||||
use crate::components::data_form::ForValidation;
|
use crate::components::data_form::ForValidation;
|
||||||
@@ -100,6 +101,9 @@ pub fn Public() -> impl IntoView {
|
|||||||
let result_dlg = DialogOpener::new();
|
let result_dlg = DialogOpener::new();
|
||||||
let result = cr_reservation.value();
|
let result = cr_reservation.value();
|
||||||
let is_pending = create_rw_signal(None);
|
let is_pending = create_rw_signal(None);
|
||||||
|
let active_str = create_rw_signal("true".to_string());
|
||||||
|
let get_customer = create_blocking_resource(||(), move |_| get_remembered());
|
||||||
|
let customer = create_rw_signal(Customer::default());
|
||||||
|
|
||||||
create_effect(move |_| {
|
create_effect(move |_| {
|
||||||
day.set(Local::now().date_naive());
|
day.set(Local::now().date_naive());
|
||||||
@@ -157,6 +161,14 @@ pub fn Public() -> impl IntoView {
|
|||||||
</div>
|
</div>
|
||||||
<Transition fallback=|| view! {<p>{trl("Loading...")}</p> }>
|
<Transition fallback=|| view! {<p>{trl("Loading...")}</p> }>
|
||||||
{move || {
|
{move || {
|
||||||
|
get_customer.get().map(|c| match c {
|
||||||
|
Err(_) => {},
|
||||||
|
Ok(c) => {
|
||||||
|
if let Some(c) = c {
|
||||||
|
customer.set(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
form_data.get().map(|u| match u {
|
form_data.get().map(|u| match u {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
view! {<div>{e.to_string()}</div>}}
|
view! {<div>{e.to_string()}</div>}}
|
||||||
@@ -216,7 +228,7 @@ pub fn Public() -> impl IntoView {
|
|||||||
id="full_name"
|
id="full_name"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
placeholder={trl("Enter full name")}
|
placeholder={trl("Enter full name")}
|
||||||
//prop:value={move || opener.empty()}
|
prop:value={move || customer.get().full_name}
|
||||||
name="reservation[full_name]"
|
name="reservation[full_name]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -229,7 +241,7 @@ pub fn Public() -> impl IntoView {
|
|||||||
id="email"
|
id="email"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
placeholder={trl("Enter e-mail address")}
|
placeholder={trl("Enter e-mail address")}
|
||||||
//prop:value={move || opener.empty()}
|
prop:value={move || customer.get().email}
|
||||||
name="reservation[email]"
|
name="reservation[email]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -242,7 +254,7 @@ pub fn Public() -> impl IntoView {
|
|||||||
id="phone"
|
id="phone"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
placeholder={trl("Enter phone number")}
|
placeholder={trl("Enter phone number")}
|
||||||
//prop:value={move || opener.empty()}
|
prop:value={move || customer.get().phone}
|
||||||
name="reservation[phone]"
|
name="reservation[phone]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -260,6 +272,15 @@ pub fn Public() -> impl IntoView {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="remember"
|
||||||
|
class="form-check-input"
|
||||||
|
checked="true"
|
||||||
|
on:change=move |ev| active_str.set(if event_target_checked(&ev)
|
||||||
|
{ "true".to_string() } else { "false".to_string() }) />
|
||||||
|
<label for="remember" class="form-label">{trl("Remember for next time")}</label>
|
||||||
|
<input type="hidden" prop:value=active_str name="reservation[remember]"/>
|
||||||
<Captcha is_pending />
|
<Captcha is_pending />
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
|
|||||||
Reference in New Issue
Block a user