Add to shopping cart

This commit is contained in:
Adrian Woźniak 2022-05-15 19:33:06 +02:00
parent e215bbe003
commit ad924abd3f
No known key found for this signature in database
GPG Key ID: 0012845A89C7352B
7 changed files with 51 additions and 20 deletions

View File

@ -136,7 +136,10 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
} }
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
Msg::Debug(msg) => { Msg::Debug(msg) => {
crate::debug::update(msg, model); debug::update(msg, model);
}
Msg::Cart(msg) => {
shopping_cart::update(msg, model, orders);
} }
} }
} }

View File

@ -15,6 +15,7 @@ pub enum Msg {
UrlChanged(subs::UrlChanged), UrlChanged(subs::UrlChanged),
Shared(shared::SharedMsg), Shared(shared::SharedMsg),
Session(crate::session::SessionMsg), Session(crate::session::SessionMsg),
Cart(crate::shopping_cart::CartMsg),
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
Debug(crate::debug::DebugMsg), Debug(crate::debug::DebugMsg),
} }

View File

@ -1,11 +1,13 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use model::Quantity;
use seed::app::Orders; use seed::app::Orders;
use seed::prelude::*; use seed::prelude::*;
use seed::*; use seed::*;
use crate::api::NetRes; use crate::api::NetRes;
use crate::pages::Urls; use crate::pages::Urls;
use crate::shopping_cart::CartMsg;
#[derive(Debug)] #[derive(Debug)]
pub struct ListingPage { pub struct ListingPage {
@ -20,7 +22,7 @@ pub struct ListingPage {
#[derive(Debug)] #[derive(Debug)]
pub enum Msg { pub enum Msg {
FetchProducts, FetchProducts,
ProductFetched(crate::api::NetRes<model::api::Products>), ProductFetched(NetRes<model::api::Products>),
} }
pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> ListingPage { pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> ListingPage {
@ -69,11 +71,15 @@ fn filter_products(model: &mut ListingPage) {
.collect(); .collect();
} }
pub fn update(msg: Msg, model: &mut ListingPage, orders: &mut impl Orders<Msg>) { pub fn update(msg: Msg, model: &mut ListingPage, orders: &mut impl Orders<crate::Msg>) {
match msg { match msg {
Msg::FetchProducts => { Msg::FetchProducts => {
orders.skip().perform_cmd({ orders.skip().perform_cmd({
async { Msg::ProductFetched(crate::api::public::fetch_products().await) } async {
crate::Msg::Public(
Msg::ProductFetched(crate::api::public::fetch_products().await).into(),
)
}
}); });
} }
Msg::ProductFetched(NetRes::Success(products)) => { Msg::ProductFetched(NetRes::Success(products)) => {
@ -109,7 +115,7 @@ pub fn update(msg: Msg, model: &mut ListingPage, orders: &mut impl Orders<Msg>)
} }
pub fn view(model: &crate::Model, page: &ListingPage) -> Node<crate::Msg> { pub fn view(model: &crate::Model, page: &ListingPage) -> Node<crate::Msg> {
let products: Vec<Node<Msg>> = if page.visible_products.is_empty() { let products: Vec<Node<crate::Msg>> = if page.visible_products.is_empty() {
page.product_ids page.product_ids
.iter() .iter()
.filter_map(|id| page.products.get(id)) .filter_map(|id| page.products.get(id))
@ -135,7 +141,7 @@ pub fn view(model: &crate::Model, page: &ListingPage) -> Node<crate::Msg> {
] ]
} }
fn product(model: &crate::Model, product: &model::api::Product) -> Node<Msg> { fn product(model: &crate::Model, product: &model::api::Product) -> Node<crate::Msg> {
use rusty_money::{iso, Money}; use rusty_money::{iso, Money};
let price = Money::from_minor(**product.price as i64, iso::PLN).to_string(); let price = Money::from_minor(**product.price as i64, iso::PLN).to_string();
@ -151,6 +157,9 @@ fn product(model: &crate::Model, product: &model::api::Product) -> Node<Msg> {
.product() .product()
.add_path_part((*product.id as i32).to_string()); .add_path_part((*product.id as i32).to_string());
let quantity_unit = product.quantity_unit;
let product_id = product.id;
div![ div![
C!["w-full px-4 lg:px-0"], C!["w-full px-4 lg:px-0"],
div![ div![
@ -181,7 +190,16 @@ fn product(model: &crate::Model, product: &model::api::Product) -> Node<Msg> {
C!["flex items-center justify-between"], C!["flex items-center justify-between"],
a![ a![
C!["px-6 py-2 text-sm text-white bg-indigo-500 rounded-lg outline-none hover:bg-indigo-600 ring-indigo-300"], C!["px-6 py-2 text-sm text-white bg-indigo-500 rounded-lg outline-none hover:bg-indigo-600 ring-indigo-300"],
model.i18n.t("Add to Cart") ev(Ev::Click, move |ev| {
ev.prevent_default();
ev.stop_propagation();
crate::Msg::from(CartMsg::AddItem {
product_id,
quantity_unit,
quantity: Quantity::try_from(1).unwrap_or_default()
})
}),
model.i18n.t("Add to Cart"),
], ],
div![C!["mt-1 text-xl font-semibold"], price], div![C!["mt-1 text-xl font-semibold"], price],
] ]

View File

@ -5,7 +5,7 @@ use crate::api::NetRes;
#[derive(Debug)] #[derive(Debug)]
pub enum Msg { pub enum Msg {
ProductFetched(crate::api::NetRes<model::api::Product>), ProductFetched(NetRes<model::api::Product>),
SelectImage(usize), SelectImage(usize),
} }
@ -33,7 +33,7 @@ pub fn init(mut url: Url, orders: &mut impl Orders<Msg>) -> ProductPage {
pub fn page_changed(_url: Url, _model: &mut ProductPage) {} pub fn page_changed(_url: Url, _model: &mut ProductPage) {}
pub fn update(msg: Msg, model: &mut ProductPage, _orders: &mut impl Orders<Msg>) { pub fn update(msg: Msg, model: &mut ProductPage, _orders: &mut impl Orders<crate::Msg>) {
match msg { match msg {
Msg::ProductFetched(NetRes::Success(product)) => { Msg::ProductFetched(NetRes::Success(product)) => {
model.product = Some(product); model.product = Some(product);

View File

@ -25,7 +25,7 @@ pub fn init(mut _url: Url, _orders: &mut impl Orders<Msg>) -> SignInPage {
pub fn page_changed(_url: Url, _model: &mut SignInPage) {} pub fn page_changed(_url: Url, _model: &mut SignInPage) {}
pub fn update(_msg: Msg, _model: &mut SignInPage, _orders: &mut impl Orders<Msg>) {} pub fn update(_msg: Msg, _model: &mut SignInPage, _orders: &mut impl Orders<crate::Msg>) {}
pub fn view(model: &crate::Model, page: &SignInPage) -> Node<crate::Msg> { pub fn view(model: &crate::Model, page: &SignInPage) -> Node<crate::Msg> {
let home = Urls::new(&model.url).home(); let home = Urls::new(&model.url).home();

View File

@ -35,7 +35,7 @@ pub fn init(mut _url: Url, _orders: &mut impl Orders<Msg>) -> SignUpPage {
pub fn page_changed(_url: Url, _model: &mut SignUpPage) {} pub fn page_changed(_url: Url, _model: &mut SignUpPage) {}
pub fn update(msg: Msg, model: &mut SignUpPage, orders: &mut impl Orders<Msg>) { pub fn update(msg: Msg, model: &mut SignUpPage, orders: &mut impl Orders<crate::Msg>) {
match msg { match msg {
Msg::LoginChanged(value) => { Msg::LoginChanged(value) => {
model.login = Login::new(value); model.login = Login::new(value);
@ -58,14 +58,17 @@ pub fn update(msg: Msg, model: &mut SignUpPage, orders: &mut impl Orders<Msg>) {
let password_confirmation = model.password_confirmation.clone(); let password_confirmation = model.password_confirmation.clone();
orders.perform_cmd(async move { orders.perform_cmd(async move {
Msg::AccountCreated( crate::Msg::Public(
crate::api::public::sign_up(model::api::CreateAccountInput { Msg::AccountCreated(
email, crate::api::public::sign_up(model::api::CreateAccountInput {
login, email,
password, login,
password_confirmation, password,
}) password_confirmation,
.await, })
.await,
)
.into(),
) )
}); });
} }

View File

@ -18,7 +18,13 @@ pub enum CartMsg {
}, },
} }
pub type Items = indexmap::IndexMap<model::ProductId, Item>; impl From<CartMsg> for Msg {
fn from(msg: CartMsg) -> Self {
Msg::Cart(msg)
}
}
pub type Items = indexmap::IndexMap<ProductId, Item>;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Item { pub struct Item {