Start cart

This commit is contained in:
Adrian Woźniak 2022-05-15 14:05:26 +02:00
parent 09d7369b0c
commit e215bbe003
No known key found for this signature in database
GPG Key ID: 0012845A89C7352B
7 changed files with 138 additions and 34 deletions

View File

@ -8,6 +8,7 @@ mod model;
mod pages;
pub mod session;
pub mod shared;
pub mod shopping_cart;
use seed::empty;
use seed::prelude::*;
@ -81,10 +82,12 @@ fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
.and_then(|el: web_sys::Element| el.get_attribute("href")),
shared: shared::Model::default(),
i18n: I18n::load(),
cart: Default::default(),
#[cfg(debug_assertions)]
debug_modal: false,
};
shopping_cart::init(&mut model, orders);
session::init(&mut model, orders);
shared::init(&mut model, orders);
@ -101,7 +104,7 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
orders.skip();
}
Msg::Shared(msg) => {
shared::update(msg, &mut model.shared, orders);
shared::update(msg, model, orders);
}
Msg::UrlChanged(subs::UrlChanged(url)) => model.page.page_changed(url, orders),
Msg::Public(pages::public::Msg::Listing(msg)) => {

View File

@ -1,6 +1,6 @@
use seed::Url;
use crate::{I18n, Page};
use crate::{I18n, Page, shopping_cart};
#[derive(Debug)]
pub struct Model {
@ -10,6 +10,7 @@ pub struct Model {
pub logo: Option<String>,
pub shared: crate::shared::Model,
pub i18n: I18n,
pub cart: shopping_cart::ShoppingCart,
#[cfg(debug_assertions)]
pub debug_modal: bool,
}

View File

@ -13,7 +13,7 @@ pub enum Msg {
Public(public::Msg),
Admin(admin::Msg),
UrlChanged(subs::UrlChanged),
Shared(shared::Msg),
Shared(shared::SharedMsg),
Session(crate::session::SessionMsg),
#[cfg(debug_assertions)]
Debug(crate::debug::DebugMsg),

View File

@ -2,8 +2,9 @@ use chrono::{NaiveDateTime, TimeZone};
use model::{AccessTokenString, RefreshTokenString};
use seed::prelude::*;
use crate::pages::AdminPage;
use crate::shared::notification::NotificationMsg;
use crate::{Model, Msg};
use crate::{pages, Model, Msg, Page, PublicPage};
#[derive(Debug)]
pub enum SessionMsg {
@ -29,11 +30,40 @@ pub fn init(model: &mut Model, orders: &mut impl Orders<Msg>) {
.ok()
.map(model::RefreshTokenString::new);
model.shared.exp = LocalStorage::get::<_, String>("exp").ok().and_then(|s| {
seed::log!("Parsing ", s);
chrono::DateTime::parse_from_rfc3339(&s)
.ok()
.map(|t| t.naive_utc())
})
});
redirect_on_session(model, orders);
}
pub fn redirect_on_session(model: &Model, orders: &mut impl Orders<Msg>) {
seed::log!(&model.page, model.shared.me.is_some());
match &model.page {
Page::Admin(admin) => match admin {
AdminPage::Landing => {}
AdminPage::Dashboard => {}
AdminPage::Products => {}
AdminPage::Product => {}
},
Page::Public(public) if model.shared.me.is_some() => match public {
PublicPage::SignUp(_) | PublicPage::SignIn(_) => {
let url = model.url.clone().set_path(&[] as &[&str]);
url.go_and_push();
orders.send_msg(crate::Msg::UrlChanged(subs::UrlChanged(url)));
orders.force_render_now();
}
_ => {}
},
Page::Public(public) => match public {
PublicPage::Listing(_) => {}
PublicPage::Product(_) => {}
PublicPage::SignIn(_) => {}
PublicPage::SignUp(_) => {}
PublicPage::ShoppingCart => {}
PublicPage::Checkout => {}
},
}
}
pub fn update(msg: SessionMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
@ -103,7 +133,7 @@ pub fn update(msg: SessionMsg, model: &mut Model, orders: &mut impl Orders<Msg>)
errors.into_iter().for_each(|msg| {
orders
.skip()
.send_msg(Msg::Shared(crate::shared::Msg::Notification(
.send_msg(Msg::Shared(crate::shared::SharedMsg::Notification(
NotificationMsg::Error(msg),
)));
});
@ -133,7 +163,7 @@ pub fn update(msg: SessionMsg, model: &mut Model, orders: &mut impl Orders<Msg>)
_ => {
orders
.skip()
.send_msg(Msg::Shared(crate::shared::Msg::Notification(
.send_msg(Msg::Shared(crate::shared::SharedMsg::Notification(
NotificationMsg::Error("Request failed".into()),
)));
}

View File

@ -1,15 +1,17 @@
use seed::app::Orders;
use crate::session::redirect_on_session;
pub mod notification;
pub mod view;
#[derive(Debug)]
pub enum Msg {
pub enum SharedMsg {
LoadMe,
MeLoaded(crate::api::NetRes<model::Account>),
SignIn(model::api::SignInInput),
SignedIn(crate::api::NetRes<model::api::SessionOutput>),
Notification(crate::shared::notification::NotificationMsg),
Notification(notification::NotificationMsg),
}
#[derive(Debug, Default)]
@ -22,38 +24,38 @@ pub struct Model {
}
pub fn init(_model: &mut crate::Model, orders: &mut impl Orders<crate::Msg>) {
orders.send_msg(crate::Msg::Shared(Msg::LoadMe));
orders.send_msg(crate::Msg::Shared(SharedMsg::LoadMe));
}
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<crate::Msg>) {
pub fn update(msg: SharedMsg, model: &mut crate::Model, orders: &mut impl Orders<crate::Msg>) {
match msg {
Msg::LoadMe => {
seed::log!("1");
if let Some(token) = model.access_token.as_ref().cloned() {
seed::log!("2");
SharedMsg::LoadMe => {
if let Some(token) = model.shared.access_token.as_ref().cloned() {
orders.skip().perform_cmd(async move {
seed::log!("3");
Msg::MeLoaded(crate::api::public::fetch_me(token).await)
crate::Msg::Shared(SharedMsg::MeLoaded(
crate::api::public::fetch_me(token).await,
))
});
}
}
Msg::MeLoaded(crate::api::NetRes::Success(account)) => {
model.me = Some(account);
SharedMsg::MeLoaded(crate::api::NetRes::Success(account)) => {
model.shared.me = Some(account);
redirect_on_session(model, orders);
}
Msg::MeLoaded(crate::api::NetRes::Error(_error)) => {}
Msg::MeLoaded(crate::api::NetRes::Http(_error)) => {}
Msg::SignIn(input) => {
orders
.skip()
.perform_cmd(async { Msg::SignedIn(crate::api::public::sign_in(input).await) });
SharedMsg::MeLoaded(crate::api::NetRes::Error(_error)) => {}
SharedMsg::MeLoaded(crate::api::NetRes::Http(_error)) => {}
SharedMsg::SignIn(input) => {
orders.skip().perform_cmd(async {
SharedMsg::SignedIn(crate::api::public::sign_in(input).await)
});
}
Msg::SignedIn(crate::api::NetRes::Success(pair)) => {
handle_auth_pair(pair, model, orders);
SharedMsg::SignedIn(crate::api::NetRes::Success(pair)) => {
handle_auth_pair(pair, &mut model.shared, orders);
}
Msg::SignedIn(crate::api::NetRes::Error(_err)) => {}
Msg::SignedIn(crate::api::NetRes::Http(_err)) => {}
Msg::Notification(msg) => {
notification::update(msg, model, orders);
SharedMsg::SignedIn(crate::api::NetRes::Error(_err)) => {}
SharedMsg::SignedIn(crate::api::NetRes::Http(_err)) => {}
SharedMsg::Notification(msg) => {
notification::update(msg, &mut model.shared, orders);
}
}
}

View File

@ -13,7 +13,7 @@ pub enum NotificationMsg {
Clear,
}
impl From<NotificationMsg> for shared::Msg {
impl From<NotificationMsg> for shared::SharedMsg {
fn from(msg: NotificationMsg) -> Self {
Self::Notification(msg)
}
@ -152,7 +152,7 @@ pub fn message(id: uuid::Uuid, message: &str, icon: Type) -> Node<Msg> {
ev(Ev::Click, move |ev| {
ev.prevent_default();
ev.stop_propagation();
Msg::Shared(shared::Msg::Notification(NotificationMsg::Close(id)))
Msg::Shared(shared::SharedMsg::Notification(NotificationMsg::Close(id)))
})
]
]

68
web/src/shopping_cart.rs Normal file
View File

@ -0,0 +1,68 @@
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,
},
}
pub type Items = indexmap::IndexMap<model::ProductId, Item>;
#[derive(Debug, Serialize, Deserialize)]
pub struct Item {
product_id: ProductId,
quantity: Quantity,
quantity_unit: QuantityUnit,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ShoppingCart {
pub cart_id: Option<model::ShoppingCartId>,
pub items: Items,
}
pub fn init(model: &mut Model, _orders: &mut impl Orders<Msg>) {
model.cart = load_local();
}
pub fn update(msg: CartMsg, model: &mut Model, _orders: &mut impl Orders<Msg>) {
match msg {
CartMsg::AddItem {
quantity,
quantity_unit,
product_id,
} => {
{
let items: &mut Items = &mut model.cart.items;
let entry = 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::ModifyItem { .. } => {}
}
}
fn load_local() -> ShoppingCart {
LocalStorage::get("ct").unwrap_or_default()
}
fn store_local(cart: &ShoppingCart) {
LocalStorage::insert("ct", cart).ok();
}