use model::{ProductId, Quantity, QuantityUnit}; use seed::prelude::*; use serde::{Deserialize, Serialize}; use crate::{Model, Msg}; #[derive(Debug)] pub enum CartMsg { AddItem { quantity: Quantity, quantity_unit: QuantityUnit, product_id: ProductId, }, ModifyItem { quantity: Quantity, quantity_unit: QuantityUnit, product_id: ProductId, }, Remove(ProductId), Hover, Leave, } impl From for Msg { fn from(msg: CartMsg) -> Self { Msg::Cart(msg) } } pub type Items = indexmap::IndexMap; #[derive(Debug, Serialize, Deserialize)] pub struct Item { pub product_id: ProductId, pub quantity: Quantity, pub quantity_unit: QuantityUnit, } #[derive(Debug, Default, Serialize, Deserialize)] pub struct ShoppingCart { pub cart_id: Option, pub items: Items, #[serde(skip)] pub hover: bool, } pub fn init(model: &mut Model, _orders: &mut impl Orders) { model.cart = load_local(); } pub fn update(msg: CartMsg, model: &mut Model, _orders: &mut impl Orders) { match msg { CartMsg::AddItem { quantity, quantity_unit, product_id, } => { { let items: &mut Items = &mut model.cart.items; let entry: &mut Item = items.entry(product_id).or_insert_with(|| Item { quantity: Quantity::from_u32(0), quantity_unit, product_id, }); entry.quantity = entry.quantity + quantity; entry.quantity_unit = quantity_unit; } store_local(&model.cart); } CartMsg::ModifyItem { product_id, quantity_unit, quantity, } => { if **quantity == 0 { model.cart.items.remove(&product_id); } else { let items: &mut Items = &mut model.cart.items; let entry: &mut Item = items.entry(product_id).or_insert_with(|| Item { quantity, quantity_unit, product_id, }); entry.quantity = quantity; entry.quantity_unit = quantity_unit; } store_local(&model.cart); } CartMsg::Remove(product_id) => { model.cart.items.remove(&product_id); store_local(&model.cart); } CartMsg::Hover => { model.cart.hover = true; } CartMsg::Leave => { model.cart.hover = false; } } } fn load_local() -> ShoppingCart { match LocalStorage::get("ct") { Ok(cart) => cart, Err(e) => { seed::error!("Storage error", e); ShoppingCart::default() } } } fn store_local(cart: &ShoppingCart) { LocalStorage::insert("ct", cart).ok(); }