Fixing web
This commit is contained in:
parent
f98d1e6903
commit
ee5bc43962
@ -57,7 +57,7 @@ pub async fn modify_item(msg: modify_item::Input, db: Database) -> modify_item::
|
|||||||
};
|
};
|
||||||
|
|
||||||
let dbm = ActiveCartItemByProduct {
|
let dbm = ActiveCartItemByProduct {
|
||||||
product_id: msg.product_id,
|
product_variant_id: msg.product_variant_id,
|
||||||
};
|
};
|
||||||
let item: Option<model::ShoppingCartItem> = match dbm.run(&mut t).await {
|
let item: Option<model::ShoppingCartItem> = match dbm.run(&mut t).await {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
@ -83,7 +83,7 @@ pub async fn modify_item(msg: modify_item::Input, db: Database) -> modify_item::
|
|||||||
Some(item) => {
|
Some(item) => {
|
||||||
let dbm = UpdateShoppingCartItem {
|
let dbm = UpdateShoppingCartItem {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
product_id: msg.product_id,
|
product_variant_id: msg.product_variant_id,
|
||||||
shopping_cart_id: cart.id,
|
shopping_cart_id: cart.id,
|
||||||
quantity: msg.quantity,
|
quantity: msg.quantity,
|
||||||
quantity_unit: msg.quantity_unit,
|
quantity_unit: msg.quantity_unit,
|
||||||
@ -99,7 +99,7 @@ pub async fn modify_item(msg: modify_item::Input, db: Database) -> modify_item::
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let dbm = CreateShoppingCartItem {
|
let dbm = CreateShoppingCartItem {
|
||||||
product_id: msg.product_id,
|
product_variant_id: msg.product_variant_id,
|
||||||
shopping_cart_id: cart.id,
|
shopping_cart_id: cart.id,
|
||||||
quantity: msg.quantity,
|
quantity: msg.quantity,
|
||||||
quantity_unit: msg.quantity_unit,
|
quantity_unit: msg.quantity_unit,
|
||||||
@ -127,7 +127,7 @@ pub async fn remove_product(
|
|||||||
let dbm = RemoveCartItem {
|
let dbm = RemoveCartItem {
|
||||||
shopping_cart_id: msg.shopping_cart_id,
|
shopping_cart_id: msg.shopping_cart_id,
|
||||||
shopping_cart_item_id: Some(msg.shopping_cart_item_id),
|
shopping_cart_item_id: Some(msg.shopping_cart_item_id),
|
||||||
product_id: None,
|
product_variant_id: None,
|
||||||
};
|
};
|
||||||
let mut t = begin_t!(db);
|
let mut t = begin_t!(db);
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ pub async fn modify_cart(
|
|||||||
msg.items
|
msg.items
|
||||||
.iter()
|
.iter()
|
||||||
.fold(HashSet::with_capacity(msg.items.len()), |mut agg, item| {
|
.fold(HashSet::with_capacity(msg.items.len()), |mut agg, item| {
|
||||||
agg.insert(item.product_id);
|
agg.insert(item.product_variant_id);
|
||||||
agg
|
agg
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -202,12 +202,12 @@ pub async fn modify_cart(
|
|||||||
|
|
||||||
for item in items
|
for item in items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|item| !existing.contains(&item.product_id))
|
.filter(|item| !existing.contains(&item.product_variant_id))
|
||||||
{
|
{
|
||||||
let dbm = RemoveCartItem {
|
let dbm = RemoveCartItem {
|
||||||
shopping_cart_id: cart.id,
|
shopping_cart_id: cart.id,
|
||||||
shopping_cart_item_id: Some(item.id),
|
shopping_cart_item_id: Some(item.id),
|
||||||
product_id: None,
|
product_variant_id: None,
|
||||||
};
|
};
|
||||||
match dbm.run(&mut t).await {
|
match dbm.run(&mut t).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
@ -40,12 +40,14 @@ pub mod remove_product {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod modify_item {
|
pub mod modify_item {
|
||||||
|
use model::v2::ProductVariantId;
|
||||||
|
|
||||||
use super::Error;
|
use super::Error;
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
pub buyer_id: model::AccountId,
|
pub buyer_id: model::AccountId,
|
||||||
pub product_id: model::ProductId,
|
pub product_variant_id: ProductVariantId,
|
||||||
pub quantity: model::Quantity,
|
pub quantity: model::Quantity,
|
||||||
pub quantity_unit: model::QuantityUnit,
|
pub quantity_unit: model::QuantityUnit,
|
||||||
}
|
}
|
||||||
|
@ -290,6 +290,25 @@ pub struct Product {
|
|||||||
pub photos: Vec<Photo>,
|
pub photos: Vec<Photo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod v2 {
|
||||||
|
use crate::api::{Category, Photo};
|
||||||
|
|
||||||
|
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct ProductVariant {
|
||||||
|
pub id: crate::ProductVariantId,
|
||||||
|
pub product_id: crate::ProductId,
|
||||||
|
pub name: crate::ProductName,
|
||||||
|
pub short_description: crate::ProductShortDesc,
|
||||||
|
pub long_description: crate::ProductLongDesc,
|
||||||
|
pub category: Option<Category>,
|
||||||
|
pub price: crate::Price,
|
||||||
|
pub available: bool,
|
||||||
|
pub quantity_unit: crate::QuantityUnit,
|
||||||
|
pub deliver_days_flag: crate::Days,
|
||||||
|
pub photos: Vec<Photo>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'path>
|
impl<'path>
|
||||||
From<(
|
From<(
|
||||||
crate::Product,
|
crate::Product,
|
||||||
@ -452,7 +471,7 @@ pub struct DeleteItemOutput {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct UpdateItemInput {
|
pub struct UpdateItemInput {
|
||||||
pub product_id: ProductId,
|
pub product_variant_id: ProductVariantId,
|
||||||
pub quantity: Quantity,
|
pub quantity: Quantity,
|
||||||
pub quantity_unit: QuantityUnit,
|
pub quantity_unit: QuantityUnit,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use model::api::OrderAddressInput;
|
use model::api::OrderAddressInput;
|
||||||
|
use model::v2::ProductVariantId;
|
||||||
use model::{AccessTokenString, AddressId, PaymentMethod, RefreshTokenString};
|
use model::{AccessTokenString, AddressId, PaymentMethod, RefreshTokenString};
|
||||||
use seed::fetch::{Header, Method, Request};
|
use seed::fetch::{Header, Method, Request};
|
||||||
|
|
||||||
@ -66,12 +67,12 @@ pub async fn sign_up(input: model::api::CreateAccountInput) -> NetRes<model::api
|
|||||||
|
|
||||||
pub async fn update_cart_item(
|
pub async fn update_cart_item(
|
||||||
access_token: &AccessTokenString,
|
access_token: &AccessTokenString,
|
||||||
product_id: model::ProductId,
|
product_variant_id: ProductVariantId,
|
||||||
quantity: model::Quantity,
|
quantity: model::Quantity,
|
||||||
quantity_unit: model::QuantityUnit,
|
quantity_unit: model::QuantityUnit,
|
||||||
) -> NetRes<model::api::UpdateItemOutput> {
|
) -> NetRes<model::api::UpdateItemOutput> {
|
||||||
let input = model::api::UpdateItemInput {
|
let input = model::api::UpdateItemInput {
|
||||||
product_id,
|
product_variant_id,
|
||||||
quantity,
|
quantity,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
};
|
};
|
||||||
@ -97,11 +98,11 @@ pub async fn update_cart(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(
|
.map(
|
||||||
|crate::shopping_cart::Item {
|
|crate::shopping_cart::Item {
|
||||||
product_id,
|
product_variant_id,
|
||||||
quantity,
|
quantity,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
}| model::api::UpdateItemInput {
|
}| model::api::UpdateItemInput {
|
||||||
product_id,
|
product_variant_id,
|
||||||
quantity,
|
quantity,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use model::v2::ProductVariantId;
|
||||||
|
use model::ProductId;
|
||||||
use seed::Url;
|
use seed::Url;
|
||||||
|
|
||||||
use crate::{shopping_cart, I18n, Page};
|
use crate::{shopping_cart, I18n, Page};
|
||||||
@ -72,8 +74,10 @@ impl From<::model::api::Config> for Config {
|
|||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Products {
|
pub struct Products {
|
||||||
pub categories: Vec<model::api::Category>,
|
pub categories: Vec<model::api::Category>,
|
||||||
pub product_ids: Vec<model::ProductId>,
|
pub product_ids: Vec<ProductId>,
|
||||||
pub products: HashMap<model::ProductId, model::api::Product>,
|
pub products: HashMap<ProductId, model::api::Product>,
|
||||||
|
pub product_variant_ids: Vec<ProductVariantId>,
|
||||||
|
pub product_variants: HashMap<ProductVariantId, model::api::v2::ProductVariant>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Products {
|
impl Products {
|
||||||
@ -102,13 +106,18 @@ impl Products {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter_product_ids<F>(&self, filter: F) -> Vec<model::ProductId>
|
pub fn filter_product_variant_ids<F>(&self, filter: F) -> Vec<ProductVariantId>
|
||||||
where
|
where
|
||||||
F: Fn(&model::api::Product) -> bool,
|
F: Fn(&model::api::v2::ProductVariant) -> bool,
|
||||||
{
|
{
|
||||||
self.product_ids
|
self.product_variant_ids
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|id| self.products.get(id).filter(|&p| filter(p)).map(|p| p.id))
|
.filter_map(|id| {
|
||||||
|
self.product_variants
|
||||||
|
.get(id)
|
||||||
|
.filter(|&p| filter(p))
|
||||||
|
.map(|p| p.id)
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,18 +177,22 @@ mod left_side {
|
|||||||
.values()
|
.values()
|
||||||
.filter_map(|item: &Item| {
|
.filter_map(|item: &Item| {
|
||||||
page.products
|
page.products
|
||||||
.products
|
.product_variants
|
||||||
.get(&item.product_id)
|
.get(&item.product_variant_id)
|
||||||
.map(|product| (item, product))
|
.map(|product| (item, product))
|
||||||
})
|
})
|
||||||
.map(|(item, product)| product_view(model, product, item));
|
.map(|(item, variant)| product_view(model, variant, item));
|
||||||
div![
|
div![
|
||||||
C!["w-full mx-auto text-gray-800 font-light mb-6 border-b border-gray-200 pb-6"],
|
C!["w-full mx-auto text-gray-800 font-light mb-6 border-b border-gray-200 pb-6"],
|
||||||
products
|
products
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn product_view(model: &crate::Model, product: &model::api::Product, item: &Item) -> Node<Msg> {
|
fn product_view(
|
||||||
|
model: &crate::Model,
|
||||||
|
product: &model::api::v2::ProductVariant,
|
||||||
|
item: &Item,
|
||||||
|
) -> Node<Msg> {
|
||||||
let img = product
|
let img = product
|
||||||
.photos
|
.photos
|
||||||
.first()
|
.first()
|
||||||
@ -236,14 +240,14 @@ mod left_side {
|
|||||||
.cart
|
.cart
|
||||||
.items
|
.items
|
||||||
.values()
|
.values()
|
||||||
.filter_map(|item: &crate::shopping_cart::Item| {
|
.filter_map(|item: &Item| {
|
||||||
page.products
|
page.products
|
||||||
.products
|
.product_variants
|
||||||
.get(&item.product_id)
|
.get(&item.product_variant_id)
|
||||||
.map(|product| (item, product))
|
.map(|product| (item, product))
|
||||||
})
|
})
|
||||||
.map(
|
.map(
|
||||||
|(item, product): (&crate::shopping_cart::Item, &model::api::Product)| {
|
|(item, product): (&Item, &model::api::v2::ProductVariant)| {
|
||||||
**(product.price * item.quantity)
|
**(product.price * item.quantity)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use model::v2::ProductVariantId;
|
||||||
use model::Quantity;
|
use model::Quantity;
|
||||||
use seed::app::Orders;
|
use seed::app::Orders;
|
||||||
use seed::prelude::*;
|
use seed::prelude::*;
|
||||||
@ -14,7 +15,7 @@ use crate::shopping_cart::CartMsg;
|
|||||||
pub struct ListingPage {
|
pub struct ListingPage {
|
||||||
pub errors: Vec<String>,
|
pub errors: Vec<String>,
|
||||||
pub filters: HashSet<String>,
|
pub filters: HashSet<String>,
|
||||||
pub visible_products: Vec<model::ProductId>,
|
pub visible_product_variants: Vec<ProductVariantId>,
|
||||||
|
|
||||||
pub products: Products,
|
pub products: Products,
|
||||||
}
|
}
|
||||||
@ -31,7 +32,7 @@ pub fn init(url: Url, orders: &mut impl Orders<ListingMsg>) -> ListingPage {
|
|||||||
products: Products::default(),
|
products: Products::default(),
|
||||||
filters: url_to_filters(url),
|
filters: url_to_filters(url),
|
||||||
errors: vec![],
|
errors: vec![],
|
||||||
visible_products: vec![],
|
visible_product_variants: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,12 +55,12 @@ pub fn page_changed(url: Url, model: &mut ListingPage) {
|
|||||||
let ids = {
|
let ids = {
|
||||||
model
|
model
|
||||||
.products
|
.products
|
||||||
.filter_product_ids(|product| filter_product(&*model, product))
|
.filter_product_variant_ids(|product| filter_product(&*model, product))
|
||||||
};
|
};
|
||||||
model.visible_products = ids;
|
model.visible_product_variants = ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_product(model: &ListingPage, product: &model::api::Product) -> bool {
|
fn filter_product(model: &ListingPage, product: &model::api::v2::ProductVariant) -> bool {
|
||||||
product
|
product
|
||||||
.category
|
.category
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -83,8 +84,8 @@ pub fn update(msg: ListingMsg, model: &mut ListingPage, orders: &mut impl Orders
|
|||||||
model.products.update(products.0);
|
model.products.update(products.0);
|
||||||
let ids = model
|
let ids = model
|
||||||
.products
|
.products
|
||||||
.filter_product_ids(|product| filter_product(model, product));
|
.filter_product_variant_ids(|product| filter_product(model, product));
|
||||||
model.visible_products = ids;
|
model.visible_product_variants = ids;
|
||||||
}
|
}
|
||||||
ListingMsg::ProductsFetched(NetRes::Error(_))
|
ListingMsg::ProductsFetched(NetRes::Error(_))
|
||||||
| ListingMsg::ProductsFetched(NetRes::Http(_)) => {
|
| ListingMsg::ProductsFetched(NetRes::Http(_)) => {
|
||||||
@ -94,17 +95,17 @@ pub fn update(msg: ListingMsg, model: &mut ListingPage, orders: &mut impl Orders
|
|||||||
}
|
}
|
||||||
|
|
||||||
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<crate::Msg>> = if page.visible_products.is_empty() {
|
let products: Vec<Node<crate::Msg>> = if page.visible_product_variants.is_empty() {
|
||||||
page.products
|
page.products
|
||||||
.product_ids
|
.product_variant_ids
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|id| page.products.products.get(id))
|
.filter_map(|id| page.products.product_variants.get(id))
|
||||||
.map(|p| product(model, p))
|
.map(|p| product(model, p))
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
page.visible_products
|
page.visible_product_variants
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|id| page.products.products.get(id))
|
.filter_map(|id| page.products.product_variants.get(id))
|
||||||
.map(|p| product(model, p))
|
.map(|p| product(model, p))
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
@ -121,7 +122,7 @@ pub fn view(model: &crate::Model, page: &ListingPage) -> Node<crate::Msg> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn product(model: &crate::Model, product: &model::api::Product) -> Node<crate::Msg> {
|
fn product(model: &crate::Model, product: &model::api::v2::ProductVariant) -> Node<crate::Msg> {
|
||||||
use rusty_money::Money;
|
use rusty_money::Money;
|
||||||
|
|
||||||
let price = Money::from_minor(**product.price as i64, model.config.currency).to_string();
|
let price = Money::from_minor(**product.price as i64, model.config.currency).to_string();
|
||||||
@ -138,7 +139,7 @@ fn product(model: &crate::Model, product: &model::api::Product) -> Node<crate::M
|
|||||||
.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 quantity_unit = product.quantity_unit;
|
||||||
let product_id = product.id;
|
let product_variant_id = product.id;
|
||||||
|
|
||||||
div![
|
div![
|
||||||
C!["w-full px-4 lg:px-0"],
|
C!["w-full px-4 lg:px-0"],
|
||||||
@ -174,7 +175,7 @@ fn product(model: &crate::Model, product: &model::api::Product) -> Node<crate::M
|
|||||||
ev.prevent_default();
|
ev.prevent_default();
|
||||||
ev.stop_propagation();
|
ev.stop_propagation();
|
||||||
crate::Msg::from(CartMsg::AddItem {
|
crate::Msg::from(CartMsg::AddItem {
|
||||||
product_id,
|
product_variant_id,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
quantity: Quantity::try_from(1).unwrap_or_default()
|
quantity: Quantity::try_from(1).unwrap_or_default()
|
||||||
})
|
})
|
||||||
|
@ -167,14 +167,15 @@ mod summary_right {
|
|||||||
.values()
|
.values()
|
||||||
.filter_map(|item: &crate::shopping_cart::Item| {
|
.filter_map(|item: &crate::shopping_cart::Item| {
|
||||||
page.products
|
page.products
|
||||||
.products
|
.product_variants
|
||||||
.get(&item.product_id)
|
.get(&item.product_variant_id)
|
||||||
.map(|product| (item, product))
|
.map(|product| (item, product))
|
||||||
})
|
})
|
||||||
.map(
|
.map(
|
||||||
|(item, product): (&crate::shopping_cart::Item, &model::api::Product)| {
|
|(item, product): (
|
||||||
**(product.price * item.quantity)
|
&crate::shopping_cart::Item,
|
||||||
},
|
&model::api::v2::ProductVariant,
|
||||||
|
)| { **(product.price * item.quantity) },
|
||||||
)
|
)
|
||||||
.sum::<i32>() as i64;
|
.sum::<i32>() as i64;
|
||||||
div![
|
div![
|
||||||
@ -391,12 +392,12 @@ fn products_body(model: &crate::Model, page: &ShoppingCartPage) -> Node<crate::M
|
|||||||
.values()
|
.values()
|
||||||
.filter_map(|item: &crate::shopping_cart::Item| {
|
.filter_map(|item: &crate::shopping_cart::Item| {
|
||||||
page.products
|
page.products
|
||||||
.products
|
.product_variants
|
||||||
.get(&item.product_id)
|
.get(&item.product_variant_id)
|
||||||
.map(|product| (item, product))
|
.map(|product| (item, product))
|
||||||
})
|
})
|
||||||
.map(
|
.map(
|
||||||
|(item, product): (&crate::shopping_cart::Item, &model::api::Product)| {
|
|(item, product): (&crate::shopping_cart::Item, &model::api::v2::ProductVariant)| {
|
||||||
item_view(model, item, product)
|
item_view(model, item, product)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -406,7 +407,7 @@ fn products_body(model: &crate::Model, page: &ShoppingCartPage) -> Node<crate::M
|
|||||||
fn item_view(
|
fn item_view(
|
||||||
model: &crate::Model,
|
model: &crate::Model,
|
||||||
item: &crate::shopping_cart::Item,
|
item: &crate::shopping_cart::Item,
|
||||||
product: &model::api::Product,
|
product: &model::api::v2::ProductVariant,
|
||||||
) -> Node<crate::Msg> {
|
) -> Node<crate::Msg> {
|
||||||
use rusty_money::Money;
|
use rusty_money::Money;
|
||||||
|
|
||||||
@ -416,7 +417,7 @@ fn item_view(
|
|||||||
.map(|photo| photo.url.as_str())
|
.map(|photo| photo.url.as_str())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let product_id = product.id;
|
let product_variant_id = product.id;
|
||||||
let quantity_unit = product.quantity_unit;
|
let quantity_unit = product.quantity_unit;
|
||||||
let product_url = Urls::new(&model.url)
|
let product_url = Urls::new(&model.url)
|
||||||
.product()
|
.product()
|
||||||
@ -441,7 +442,7 @@ fn item_view(
|
|||||||
ev(Ev::Submit, move |ev| {
|
ev(Ev::Submit, move |ev| {
|
||||||
ev.prevent_default();
|
ev.prevent_default();
|
||||||
ev.stop_propagation();
|
ev.stop_propagation();
|
||||||
crate::Msg::from(CartMsg::Remove(product_id))
|
crate::Msg::from(CartMsg::Remove(product_variant_id))
|
||||||
}),
|
}),
|
||||||
button![
|
button![
|
||||||
attrs![At::Type => "submit", At::Class => "text-gray-700 md:ml-4 text-red-600"],
|
attrs![At::Type => "submit", At::Class => "text-gray-700 md:ml-4 text-red-600"],
|
||||||
@ -449,7 +450,7 @@ fn item_view(
|
|||||||
ev(Ev::Click, move |ev| {
|
ev(Ev::Click, move |ev| {
|
||||||
ev.prevent_default();
|
ev.prevent_default();
|
||||||
ev.stop_propagation();
|
ev.stop_propagation();
|
||||||
crate::Msg::from(CartMsg::Remove(product_id))
|
crate::Msg::from(CartMsg::Remove(product_variant_id))
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -474,7 +475,7 @@ fn item_view(
|
|||||||
let quantity = Quantity::from_u32(value);
|
let quantity = Quantity::from_u32(value);
|
||||||
|
|
||||||
Some(crate::Msg::from(CartMsg::ModifyItem {
|
Some(crate::Msg::from(CartMsg::ModifyItem {
|
||||||
product_id,
|
product_variant_id,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
quantity,
|
quantity,
|
||||||
}))
|
}))
|
||||||
|
@ -125,8 +125,19 @@ pub mod cart_dropdown {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! filter_product_variants {
|
||||||
|
($model: expr, $products: expr) => {
|
||||||
|
$model
|
||||||
|
.cart
|
||||||
|
.items
|
||||||
|
.values()
|
||||||
|
.filter_map(|item: &Item| filter_product(item, $products, item.product_variant_id))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn view(model: &Model, products: &crate::model::Products) -> Node<Msg> {
|
pub fn view(model: &Model, products: &crate::model::Products) -> Node<Msg> {
|
||||||
let items = filter_products!(model, products).map(|(it, product)| item(model, it, product));
|
let items =
|
||||||
|
filter_product_variants!(model, products).map(|(it, product)| item(model, it, product));
|
||||||
div![
|
div![
|
||||||
C![
|
C![
|
||||||
"absolute w-full rounded-b border-t-0 z-10",
|
"absolute w-full rounded-b border-t-0 z-10",
|
||||||
@ -201,7 +212,7 @@ pub mod cart_dropdown {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn checkout(model: &Model, products: &crate::model::Products) -> Node<Msg> {
|
fn checkout(model: &Model, products: &crate::model::Products) -> Node<Msg> {
|
||||||
let sum: i32 = filter_products!(model, products)
|
let sum: i32 = filter_product_variants!(model, products)
|
||||||
.map(|(item, product): (&Item, &model::api::Product)| **item.quantity * **product.price)
|
.map(|(item, product): (&Item, &model::api::Product)| **item.quantity * **product.price)
|
||||||
.sum();
|
.sum();
|
||||||
let sum = rusty_money::Money::from_minor(sum as i64, model.config.currency);
|
let sum = rusty_money::Money::from_minor(sum as i64, model.config.currency);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use model::v2::ProductVariantId;
|
||||||
use model::{PaymentMethod, ProductId, Quantity, QuantityUnit};
|
use model::{PaymentMethod, ProductId, Quantity, QuantityUnit};
|
||||||
use seed::prelude::*;
|
use seed::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -10,14 +11,14 @@ pub enum CartMsg {
|
|||||||
AddItem {
|
AddItem {
|
||||||
quantity: Quantity,
|
quantity: Quantity,
|
||||||
quantity_unit: QuantityUnit,
|
quantity_unit: QuantityUnit,
|
||||||
product_id: ProductId,
|
product_variant_id: ProductVariantId,
|
||||||
},
|
},
|
||||||
ModifyItem {
|
ModifyItem {
|
||||||
quantity: Quantity,
|
quantity: Quantity,
|
||||||
quantity_unit: QuantityUnit,
|
quantity_unit: QuantityUnit,
|
||||||
product_id: ProductId,
|
product_variant_id: ProductVariantId,
|
||||||
},
|
},
|
||||||
Remove(ProductId),
|
Remove(ProductVariantId),
|
||||||
Hover,
|
Hover,
|
||||||
Leave,
|
Leave,
|
||||||
/// Send current non-empty cart to server
|
/// Send current non-empty cart to server
|
||||||
@ -38,7 +39,7 @@ pub type Items = indexmap::IndexMap<ProductId, Item>;
|
|||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
#[serde(rename = "i")]
|
#[serde(rename = "i")]
|
||||||
pub product_id: ProductId,
|
pub product_variant_id: ProductVariantId,
|
||||||
#[serde(rename = "q")]
|
#[serde(rename = "q")]
|
||||||
pub quantity: Quantity,
|
pub quantity: Quantity,
|
||||||
#[serde(rename = "u")]
|
#[serde(rename = "u")]
|
||||||
@ -68,14 +69,14 @@ pub fn update(msg: CartMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
CartMsg::AddItem {
|
CartMsg::AddItem {
|
||||||
quantity,
|
quantity,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
product_id,
|
product_variant_id,
|
||||||
} => {
|
} => {
|
||||||
{
|
{
|
||||||
let items: &mut Items = &mut model.cart.items;
|
let items: &mut Items = &mut model.cart.items;
|
||||||
let entry: &mut Item = items.entry(product_id).or_insert_with(|| Item {
|
let entry: &mut Item = items.entry(product_variant_id).or_insert_with(|| Item {
|
||||||
quantity: Quantity::from_u32(0),
|
quantity: Quantity::from_u32(0),
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
product_id,
|
product_variant_id,
|
||||||
});
|
});
|
||||||
entry.quantity = entry.quantity + quantity;
|
entry.quantity = entry.quantity + quantity;
|
||||||
entry.quantity_unit = quantity_unit;
|
entry.quantity_unit = quantity_unit;
|
||||||
@ -84,18 +85,18 @@ pub fn update(msg: CartMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
sync_cart(model, orders);
|
sync_cart(model, orders);
|
||||||
}
|
}
|
||||||
CartMsg::ModifyItem {
|
CartMsg::ModifyItem {
|
||||||
product_id,
|
product_variant_id,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
quantity,
|
quantity,
|
||||||
} => {
|
} => {
|
||||||
if **quantity == 0 {
|
if **quantity == 0 {
|
||||||
model.cart.items.remove(&product_id);
|
model.cart.items.remove(&product_variant_id);
|
||||||
} else {
|
} else {
|
||||||
let items: &mut Items = &mut model.cart.items;
|
let items: &mut Items = &mut model.cart.items;
|
||||||
let entry: &mut Item = items.entry(product_id).or_insert_with(|| Item {
|
let entry: &mut Item = items.entry(product_variant_id).or_insert_with(|| Item {
|
||||||
quantity,
|
quantity,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
product_id,
|
product_variant_id,
|
||||||
});
|
});
|
||||||
entry.quantity = quantity;
|
entry.quantity = quantity;
|
||||||
entry.quantity_unit = quantity_unit;
|
entry.quantity_unit = quantity_unit;
|
||||||
@ -125,15 +126,15 @@ pub fn update(msg: CartMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
|mut set,
|
|mut set,
|
||||||
model::api::ShoppingCartItem {
|
model::api::ShoppingCartItem {
|
||||||
id: _,
|
id: _,
|
||||||
product_id,
|
product_variant_id,
|
||||||
shopping_cart_id: _,
|
shopping_cart_id: _,
|
||||||
quantity,
|
quantity,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
}| {
|
}| {
|
||||||
set.insert(
|
set.insert(
|
||||||
product_id,
|
product_variant_id,
|
||||||
Item {
|
Item {
|
||||||
product_id,
|
product_variant_id,
|
||||||
quantity,
|
quantity,
|
||||||
quantity_unit,
|
quantity_unit,
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user