Add checkout notes
This commit is contained in:
parent
b1b4d083b7
commit
cafafb0f24
@ -1,3 +1,11 @@
|
||||
#[package]
|
||||
#name = "bazzar"
|
||||
#version = "0.1.0"
|
||||
#edition = "2021"
|
||||
#
|
||||
#[[bin]]
|
||||
#name = "api"
|
||||
#path = "./api/src/main.rs"
|
||||
[workspace]
|
||||
members = [
|
||||
"api",
|
||||
|
@ -94,7 +94,7 @@ impl CartManager {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(actix::Message)]
|
||||
#[derive(actix::Message, Debug)]
|
||||
#[rtype(result = "Result<Option<ShoppingCartItem>>")]
|
||||
pub struct ModifyItem {
|
||||
pub buyer_id: AccountId,
|
||||
@ -196,7 +196,7 @@ pub(crate) async fn remove_product(
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(actix::Message)]
|
||||
#[derive(actix::Message, Debug)]
|
||||
#[rtype(result = "Result<Vec<ShoppingCartItem>>")]
|
||||
pub struct ModifyCart {
|
||||
pub buyer_id: AccountId,
|
||||
@ -206,6 +206,7 @@ pub struct ModifyCart {
|
||||
cart_async_handler!(ModifyCart, modify_cart, Vec<ShoppingCartItem>);
|
||||
|
||||
async fn modify_cart(msg: ModifyCart, db: actix::Addr<Database>) -> Result<Vec<ShoppingCartItem>> {
|
||||
log::debug!("{:?}", msg);
|
||||
let _cart = query_db!(
|
||||
db,
|
||||
database_manager::EnsureActiveShoppingCart {
|
||||
@ -222,6 +223,7 @@ async fn modify_cart(msg: ModifyCart, db: actix::Addr<Database>) -> Result<Vec<S
|
||||
passthrough Error::Db,
|
||||
Error::CartNotAvailable
|
||||
);
|
||||
log::debug!("carts {:?}", carts);
|
||||
let cart = if carts.is_empty() {
|
||||
return Err(Error::CartNotAvailable);
|
||||
} else {
|
||||
@ -236,7 +238,7 @@ async fn modify_cart(msg: ModifyCart, db: actix::Addr<Database>) -> Result<Vec<S
|
||||
agg
|
||||
});
|
||||
|
||||
let mut items: Vec<model::ShoppingCartItem> = query_db!(
|
||||
let items: Vec<model::ShoppingCartItem> = query_db!(
|
||||
db,
|
||||
database_manager::CartItems {
|
||||
shopping_cart_id: cart.id
|
||||
@ -244,7 +246,10 @@ async fn modify_cart(msg: ModifyCart, db: actix::Addr<Database>) -> Result<Vec<S
|
||||
Error::CantModifyCart
|
||||
);
|
||||
|
||||
for item in items.drain_filter(|item| !existing.contains(&item.product_id)) {
|
||||
for item in items
|
||||
.into_iter()
|
||||
.filter(|item| !existing.contains(&item.product_id))
|
||||
{
|
||||
query_db!(
|
||||
db,
|
||||
database_manager::RemoveCartItem {
|
||||
@ -256,27 +261,10 @@ async fn modify_cart(msg: ModifyCart, db: actix::Addr<Database>) -> Result<Vec<S
|
||||
);
|
||||
}
|
||||
|
||||
let mut out = Vec::with_capacity(items.len());
|
||||
let mut out = Vec::with_capacity(msg.items.len());
|
||||
|
||||
for ShoppingCartItem {
|
||||
id: _,
|
||||
product_id,
|
||||
shopping_cart_id: _,
|
||||
quantity,
|
||||
quantity_unit,
|
||||
} in items
|
||||
{
|
||||
if let Some(item) = modify_item(
|
||||
ModifyItem {
|
||||
buyer_id: msg.buyer_id,
|
||||
product_id,
|
||||
quantity,
|
||||
quantity_unit,
|
||||
},
|
||||
db.clone(),
|
||||
)
|
||||
.await?
|
||||
{
|
||||
for item in msg.items {
|
||||
if let Some(item) = modify_item(item, db.clone()).await? {
|
||||
out.push(item);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ pub(crate) async fn all_account_orders(
|
||||
) -> Result<Vec<AccountOrder>> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, buyer_id, status, order_ext_id, service_order_id
|
||||
SELECT id, buyer_id, status, order_ext_id, service_order_id, checkout_notes
|
||||
FROM account_orders
|
||||
ORDER BY id DESC
|
||||
"#,
|
||||
@ -60,6 +60,7 @@ pub struct CreateAccountOrder {
|
||||
pub buyer_id: AccountId,
|
||||
pub items: Vec<create_order::OrderItem>,
|
||||
pub shopping_cart_id: ShoppingCartId,
|
||||
pub checkout_notes: Option<String>,
|
||||
}
|
||||
|
||||
db_async_handler!(
|
||||
@ -77,7 +78,7 @@ pub(crate) async fn create_account_order(
|
||||
r#"
|
||||
INSERT INTO account_orders (buyer_id, status)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id, buyer_id, status, order_ext_id, service_order_id
|
||||
RETURNING id, buyer_id, status, order_ext_id, service_order_id, checkout_notes
|
||||
"#,
|
||||
)
|
||||
.bind(msg.buyer_id)
|
||||
@ -113,6 +114,7 @@ RETURNING id, buyer_id, status, order_ext_id, service_order_id
|
||||
ShoppingCartSetState {
|
||||
id: msg.shopping_cart_id,
|
||||
state: ShoppingCartState::Closed,
|
||||
checkout_notes: msg.checkout_notes,
|
||||
},
|
||||
t,
|
||||
)
|
||||
@ -146,7 +148,7 @@ pub(crate) async fn update_account_order(
|
||||
UPDATE account_orders
|
||||
SET buyer_id = $2 AND status = $3 AND order_id = $4
|
||||
WHERE id = $1
|
||||
RETURNING id, buyer_id, status, order_ext_id, service_order_id
|
||||
RETURNING id, buyer_id, status, order_ext_id, service_order_id, checkout_notes
|
||||
"#,
|
||||
)
|
||||
.bind(msg.id)
|
||||
@ -183,7 +185,7 @@ pub(crate) async fn update_account_order_by_ext(
|
||||
UPDATE account_orders
|
||||
SET status = $2
|
||||
WHERE order_ext_id = $1
|
||||
RETURNING id, buyer_id, status, order_ext_id, service_order_id
|
||||
RETURNING id, buyer_id, status, order_ext_id, service_order_id, checkout_notes
|
||||
"#,
|
||||
)
|
||||
.bind(msg.order_ext_id)
|
||||
@ -207,7 +209,7 @@ db_async_handler!(FindAccountOrder, find_account_order, AccountOrder);
|
||||
pub(crate) async fn find_account_order(msg: FindAccountOrder, db: PgPool) -> Result<AccountOrder> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, buyer_id, status, order_ext_id, service_order_id
|
||||
SELECT id, buyer_id, status, order_ext_id, service_order_id, checkout_notes
|
||||
FROM account_orders
|
||||
WHERE id = $1
|
||||
"#,
|
||||
@ -239,7 +241,7 @@ pub(crate) async fn set_order_service_id(
|
||||
UPDATE account_orders
|
||||
SET service_order_id = $2
|
||||
WHERE id = $1
|
||||
RETURNING id, buyer_id, status, order_ext_id, service_order_id
|
||||
RETURNING id, buyer_id, status, order_ext_id, service_order_id, checkout_notes
|
||||
"#,
|
||||
)
|
||||
.bind(msg.id)
|
||||
|
@ -172,7 +172,7 @@ pub(crate) async fn update_shopping_cart_item(
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
UPDATE shopping_cart_items
|
||||
SET product_id = $2 AND shopping_cart_id = $3 AND quantity = $4 AND quantity_unit = $5
|
||||
SET product_id = $2, shopping_cart_id = $3, quantity = $4, quantity_unit = $5
|
||||
WHERE id = $1
|
||||
RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit
|
||||
"#,
|
||||
|
@ -30,7 +30,7 @@ pub(crate) async fn all_shopping_carts(
|
||||
) -> Result<Vec<ShoppingCart>> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, buyer_id, payment_method, state
|
||||
SELECT id, buyer_id, payment_method, state, checkout_notes
|
||||
FROM shopping_carts
|
||||
"#,
|
||||
)
|
||||
@ -62,9 +62,9 @@ pub(crate) async fn account_shopping_carts(
|
||||
if let Some(state) = msg.state {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, buyer_id, payment_method, state
|
||||
FROM shopping_carts
|
||||
WHERE buyer_id = $1 AND state = $2
|
||||
SELECT id, buyer_id, payment_method, state, checkout_notes
|
||||
FROM shopping_carts
|
||||
WHERE buyer_id = $1 AND state = $2
|
||||
"#,
|
||||
)
|
||||
.bind(msg.account_id)
|
||||
@ -72,7 +72,7 @@ SELECT id, buyer_id, payment_method, state
|
||||
} else {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, buyer_id, payment_method, state
|
||||
SELECT id, buyer_id, payment_method, state, checkout_notes
|
||||
FROM shopping_carts
|
||||
WHERE buyer_id = $1
|
||||
"#,
|
||||
@ -104,7 +104,7 @@ pub(crate) async fn create_shopping_cart(
|
||||
r#"
|
||||
INSERT INTO shopping_carts (buyer_id, payment_method)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id, buyer_id, payment_method, state
|
||||
RETURNING id, buyer_id, payment_method, state, checkout_notes
|
||||
"#,
|
||||
)
|
||||
.bind(msg.buyer_id)
|
||||
@ -137,7 +137,7 @@ pub(crate) async fn update_shopping_cart(
|
||||
UPDATE shopping_carts
|
||||
SET buyer_id = $2 AND payment_method = $2 AND state = $4
|
||||
WHERE id = $1
|
||||
RETURNING id, buyer_id, payment_method, state
|
||||
RETURNING id, buyer_id, payment_method, state, checkout_notes
|
||||
"#,
|
||||
)
|
||||
.bind(msg.id)
|
||||
@ -157,38 +157,31 @@ RETURNING id, buyer_id, payment_method, state
|
||||
pub struct ShoppingCartSetState {
|
||||
pub id: ShoppingCartId,
|
||||
pub state: ShoppingCartState,
|
||||
pub checkout_notes: Option<String>,
|
||||
}
|
||||
|
||||
db_async_handler!(
|
||||
ShoppingCartSetState,
|
||||
inner_shopping_cart_set_state,
|
||||
ShoppingCart
|
||||
shopping_cart_set_state,
|
||||
ShoppingCart,
|
||||
inner_shopping_cart_set_state
|
||||
);
|
||||
|
||||
async fn inner_shopping_cart_set_state(
|
||||
pub(crate) async fn shopping_cart_set_state(
|
||||
msg: ShoppingCartSetState,
|
||||
pool: PgPool,
|
||||
pool: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<ShoppingCart> {
|
||||
shopping_cart_set_state(msg, &pool).await
|
||||
}
|
||||
|
||||
pub(crate) async fn shopping_cart_set_state<'e, E>(
|
||||
msg: ShoppingCartSetState,
|
||||
pool: E,
|
||||
) -> Result<ShoppingCart>
|
||||
where
|
||||
E: sqlx::Executor<'e, Database = sqlx::Postgres>,
|
||||
{
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
UPDATE shopping_carts
|
||||
SET state = $2
|
||||
SET state = $2, checkout_notes = $3
|
||||
WHERE id = $1
|
||||
RETURNING id, buyer_id, payment_method, state
|
||||
RETURNING id, buyer_id, payment_method, state, checkout_notes
|
||||
"#,
|
||||
)
|
||||
.bind(msg.id)
|
||||
.bind(msg.state)
|
||||
.bind(msg.checkout_notes)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
@ -208,7 +201,7 @@ db_async_handler!(FindShoppingCart, find_shopping_cart, ShoppingCart);
|
||||
pub(crate) async fn find_shopping_cart(msg: FindShoppingCart, db: PgPool) -> Result<ShoppingCart> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, buyer_id, payment_method, state
|
||||
SELECT id, buyer_id, payment_method, state, checkout_notes
|
||||
FROM shopping_carts
|
||||
WHERE id = $1
|
||||
"#,
|
||||
@ -245,7 +238,7 @@ INSERT INTO shopping_carts (buyer_id, state)
|
||||
VALUES ($1, 'active')
|
||||
ON CONFLICT
|
||||
DO NOTHING
|
||||
RETURNING id, buyer_id, payment_method, state;
|
||||
RETURNING id, buyer_id, payment_method, state, checkout_notes
|
||||
"#,
|
||||
)
|
||||
.bind(msg.buyer_id)
|
||||
@ -259,7 +252,7 @@ RETURNING id, buyer_id, payment_method, state;
|
||||
};
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, buyer_id, payment_method, state
|
||||
SELECT id, buyer_id, payment_method, state, checkout_notes
|
||||
FROM shopping_carts
|
||||
WHERE buyer_id = $1 AND state = 'active'
|
||||
"#,
|
||||
|
@ -90,6 +90,7 @@ pub(crate) async fn create_order(
|
||||
quantity_unit: item.quantity_unit,
|
||||
})
|
||||
.collect(),
|
||||
checkout_notes: cart.checkout_notes
|
||||
},
|
||||
Error::CreateAccountOrder,
|
||||
Error::DatabaseInternal
|
||||
|
@ -231,6 +231,7 @@ pub(crate) async fn request_payment(
|
||||
})
|
||||
.collect(),
|
||||
shopping_cart_id: cart.id,
|
||||
checkout_notes: cart.checkout_notes,
|
||||
},
|
||||
Error::CreateOrder
|
||||
);
|
||||
|
4
api/i18n.toml
Normal file
4
api/i18n.toml
Normal file
@ -0,0 +1,4 @@
|
||||
available-locales = ["en", "pl"]
|
||||
default-locale = "en"
|
||||
fallback_language = "en"
|
||||
load-path = "locales"
|
0
api/locales/en.yml
Normal file
0
api/locales/en.yml
Normal file
0
api/locales/pl.yml
Normal file
0
api/locales/pl.yml
Normal file
@ -59,6 +59,7 @@ async fn server(opts: ServerOpts) -> Result<()> {
|
||||
let fs_manager = fs_manager::FsManager::build(app_config.clone())
|
||||
.await
|
||||
.expect("Failed to initialize file system storage");
|
||||
let cart_manager = cart_manager::CartManager::new(db.clone()).start();
|
||||
let addr = {
|
||||
let l = app_config.lock();
|
||||
let w = l.web();
|
||||
@ -87,6 +88,7 @@ async fn server(opts: ServerOpts) -> Result<()> {
|
||||
.app_data(Data::new(payment_manager.clone()))
|
||||
.app_data(Data::new(search_manager.clone()))
|
||||
.app_data(Data::new(fs_manager.clone()))
|
||||
.app_data(Data::new(cart_manager.clone()))
|
||||
.configure(routes::configure)
|
||||
.service({
|
||||
let l = app_config.lock();
|
||||
|
2
migrations/20220519112905_add_checkout_notes.sql
Normal file
2
migrations/20220519112905_add_checkout_notes.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE shopping_carts
|
||||
ADD checkout_notes TEXT;
|
2
migrations/20220519113031_add_checkout_notes_order.sql
Normal file
2
migrations/20220519113031_add_checkout_notes_order.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE account_orders
|
||||
ADD checkout_notes TEXT;
|
@ -38,6 +38,7 @@ impl From<(Vec<crate::AccountOrder>, Vec<crate::OrderItem>)> for AccountOrders {
|
||||
order_id,
|
||||
order_ext_id: _,
|
||||
service_order_id: _,
|
||||
checkout_notes,
|
||||
}| {
|
||||
AccountOrder {
|
||||
id,
|
||||
@ -45,6 +46,7 @@ impl From<(Vec<crate::AccountOrder>, Vec<crate::OrderItem>)> for AccountOrders {
|
||||
status,
|
||||
order_id,
|
||||
items: items.drain_filter(|item| item.order_id == id).collect(),
|
||||
checkout_notes,
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -63,6 +65,7 @@ impl From<(crate::AccountOrder, Vec<crate::OrderItem>)> for AccountOrder {
|
||||
order_id,
|
||||
order_ext_id: _,
|
||||
service_order_id: _,
|
||||
checkout_notes,
|
||||
},
|
||||
mut items,
|
||||
): (crate::AccountOrder, Vec<crate::OrderItem>),
|
||||
@ -73,6 +76,7 @@ impl From<(crate::AccountOrder, Vec<crate::OrderItem>)> for AccountOrder {
|
||||
status,
|
||||
order_id,
|
||||
items: items.drain_filter(|item| item.order_id == id).collect(),
|
||||
checkout_notes,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,6 +89,7 @@ pub struct AccountOrder {
|
||||
pub status: crate::OrderStatus,
|
||||
pub order_id: Option<crate::OrderId>,
|
||||
pub items: Vec<crate::OrderItem>,
|
||||
pub checkout_notes: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
||||
@ -125,6 +130,7 @@ pub struct ShoppingCart {
|
||||
pub payment_method: PaymentMethod,
|
||||
pub state: ShoppingCartState,
|
||||
pub items: Vec<ShoppingCartItem>,
|
||||
pub checkout_notes: String,
|
||||
}
|
||||
|
||||
impl From<(crate::ShoppingCart, Vec<crate::ShoppingCartItem>)> for ShoppingCart {
|
||||
@ -135,6 +141,7 @@ impl From<(crate::ShoppingCart, Vec<crate::ShoppingCartItem>)> for ShoppingCart
|
||||
buyer_id,
|
||||
payment_method,
|
||||
state,
|
||||
checkout_notes,
|
||||
},
|
||||
items,
|
||||
): (crate::ShoppingCart, Vec<crate::ShoppingCartItem>),
|
||||
@ -144,6 +151,7 @@ impl From<(crate::ShoppingCart, Vec<crate::ShoppingCartItem>)> for ShoppingCart
|
||||
buyer_id,
|
||||
payment_method,
|
||||
state,
|
||||
checkout_notes: checkout_notes.unwrap_or_default(),
|
||||
items: items
|
||||
.into_iter()
|
||||
.map(
|
||||
|
@ -856,6 +856,7 @@ pub struct AccountOrder {
|
||||
pub order_id: Option<OrderId>,
|
||||
pub order_ext_id: uuid::Uuid,
|
||||
pub service_order_id: Option<String>,
|
||||
pub checkout_notes: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
||||
@ -866,6 +867,7 @@ pub struct PublicAccountOrder {
|
||||
pub buyer_id: AccountId,
|
||||
pub status: OrderStatus,
|
||||
pub order_id: Option<OrderId>,
|
||||
pub checkout_notes: String,
|
||||
}
|
||||
|
||||
impl From<AccountOrder> for PublicAccountOrder {
|
||||
@ -877,6 +879,7 @@ impl From<AccountOrder> for PublicAccountOrder {
|
||||
order_id,
|
||||
order_ext_id: _,
|
||||
service_order_id: _,
|
||||
checkout_notes,
|
||||
}: AccountOrder,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -884,6 +887,7 @@ impl From<AccountOrder> for PublicAccountOrder {
|
||||
buyer_id,
|
||||
status,
|
||||
order_id,
|
||||
checkout_notes: checkout_notes.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -914,12 +918,13 @@ pub struct ShoppingCartId(pub RecordId);
|
||||
|
||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
||||
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShoppingCart {
|
||||
pub id: ShoppingCartId,
|
||||
pub buyer_id: AccountId,
|
||||
pub payment_method: PaymentMethod,
|
||||
pub state: ShoppingCartState,
|
||||
pub checkout_notes: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
||||
@ -930,7 +935,7 @@ pub struct ShoppingCart {
|
||||
pub struct ShoppingCartItemId(RecordId);
|
||||
|
||||
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShoppingCartItem {
|
||||
pub id: ShoppingCartItemId,
|
||||
pub product_id: ProductId,
|
||||
|
@ -25,7 +25,7 @@ wasm-bindgen = { version = "0.2.80", features = ["default"] }
|
||||
web-sys = { version = "0.3.57", features = ["Navigator"] }
|
||||
js-sys = { version = "0.3.57", features = [] }
|
||||
|
||||
indexmap = { version = "1", features = ["serde-1"] }
|
||||
indexmap = { version = "1", default-features = false, features = ["serde-1", "std"] }
|
||||
|
||||
rusty-money = { version = "0.4.1", features = ["iso"] }
|
||||
|
||||
|
@ -80,6 +80,7 @@ mod summary_left {
|
||||
use seed::*;
|
||||
|
||||
use crate::pages::public::shopping_cart::ShoppingCartPage;
|
||||
use crate::shopping_cart::CartMsg;
|
||||
|
||||
pub fn view(model: &crate::Model, page: &ShoppingCartPage) -> Node<crate::Msg> {
|
||||
div![
|
||||
@ -94,7 +95,16 @@ mod summary_left {
|
||||
]
|
||||
],
|
||||
div![C!["p-4"], p![C!["mb-4 italic"], model.i18n.t("If you have some information for the seller you can leave them in the box below")]],
|
||||
textarea![C!["w-full h-24 p-2 bg-gray-100 rounded border-none"]]
|
||||
textarea![
|
||||
C!["w-full h-24 p-2 bg-gray-100 rounded border-none"],
|
||||
ev(Ev::Change, move |ev| {
|
||||
ev.stop_propagation();
|
||||
let target = ev.target()?;
|
||||
let input = seed::to_textarea(&target);
|
||||
Some(crate::Msg::from(CartMsg::ChangeNotes(input.value())))
|
||||
}),
|
||||
model.cart.checkout_notes.as_str()
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ pub enum CartMsg {
|
||||
/// Send current non-empty cart to server
|
||||
Sync,
|
||||
SyncResult(NetRes<model::api::UpdateCartOutput>),
|
||||
ChangeNotes(String),
|
||||
}
|
||||
|
||||
impl From<CartMsg> for Msg {
|
||||
@ -44,6 +45,8 @@ pub struct Item {
|
||||
pub struct ShoppingCart {
|
||||
pub cart_id: Option<model::ShoppingCartId>,
|
||||
pub items: Items,
|
||||
#[serde(default)]
|
||||
pub checkout_notes: String,
|
||||
#[serde(skip)]
|
||||
pub hover: bool,
|
||||
}
|
||||
@ -70,6 +73,7 @@ pub fn update(msg: CartMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
entry.quantity_unit = quantity_unit;
|
||||
}
|
||||
store_local(&model.cart);
|
||||
sync_cart(model, orders);
|
||||
}
|
||||
CartMsg::ModifyItem {
|
||||
product_id,
|
||||
@ -89,10 +93,12 @@ pub fn update(msg: CartMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
entry.quantity_unit = quantity_unit;
|
||||
}
|
||||
store_local(&model.cart);
|
||||
sync_cart(model, orders);
|
||||
}
|
||||
CartMsg::Remove(product_id) => {
|
||||
model.cart.items.remove(&product_id);
|
||||
store_local(&model.cart);
|
||||
sync_cart(model, orders);
|
||||
}
|
||||
CartMsg::Hover => {
|
||||
model.cart.hover = true;
|
||||
@ -100,18 +106,30 @@ pub fn update(msg: CartMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
CartMsg::Leave => {
|
||||
model.cart.hover = false;
|
||||
}
|
||||
CartMsg::Sync => {
|
||||
if let Some(access_token) = model.shared.access_token.as_ref().cloned() {
|
||||
let items: Vec<Item> = model.cart.items.values().map(Clone::clone).collect();
|
||||
orders.perform_cmd(async {
|
||||
crate::Msg::from(CartMsg::SyncResult(
|
||||
crate::api::public::update_cart(access_token, items).await,
|
||||
))
|
||||
});
|
||||
}
|
||||
}
|
||||
CartMsg::Sync => sync_cart(model, orders),
|
||||
CartMsg::SyncResult(NetRes::Success(cart)) => {
|
||||
// cart.items
|
||||
let len = cart.items.len();
|
||||
model.cart.items = cart.items.into_iter().fold(
|
||||
IndexMap::with_capacity(len),
|
||||
|mut set,
|
||||
model::api::ShoppingCartItem {
|
||||
id: _,
|
||||
product_id,
|
||||
shopping_cart_id: _,
|
||||
quantity,
|
||||
quantity_unit,
|
||||
}| {
|
||||
set.insert(
|
||||
product_id,
|
||||
Item {
|
||||
product_id,
|
||||
quantity,
|
||||
quantity_unit,
|
||||
},
|
||||
);
|
||||
set
|
||||
},
|
||||
);
|
||||
}
|
||||
CartMsg::SyncResult(NetRes::Error(failure)) => {
|
||||
for msg in failure.errors {
|
||||
@ -121,6 +139,21 @@ pub fn update(msg: CartMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
CartMsg::SyncResult(NetRes::Http(_cart)) => {
|
||||
orders.send_msg(NotificationMsg::Error("Unable to sync cart".into()).into());
|
||||
}
|
||||
CartMsg::ChangeNotes(notes) => {
|
||||
model.cart.checkout_notes = notes;
|
||||
store_local(&model.cart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sync_cart(model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
if let Some(access_token) = model.shared.access_token.as_ref().cloned() {
|
||||
let items: Vec<Item> = model.cart.items.values().map(Clone::clone).collect();
|
||||
orders.perform_cmd(async {
|
||||
crate::Msg::from(CartMsg::SyncResult(
|
||||
crate::api::public::update_cart(access_token, items).await,
|
||||
))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user