Start cart
This commit is contained in:
parent
09d7369b0c
commit
e215bbe003
@ -8,6 +8,7 @@ mod model;
|
|||||||
mod pages;
|
mod pages;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
pub mod shared;
|
pub mod shared;
|
||||||
|
pub mod shopping_cart;
|
||||||
|
|
||||||
use seed::empty;
|
use seed::empty;
|
||||||
use seed::prelude::*;
|
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")),
|
.and_then(|el: web_sys::Element| el.get_attribute("href")),
|
||||||
shared: shared::Model::default(),
|
shared: shared::Model::default(),
|
||||||
i18n: I18n::load(),
|
i18n: I18n::load(),
|
||||||
|
cart: Default::default(),
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
debug_modal: false,
|
debug_modal: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
shopping_cart::init(&mut model, orders);
|
||||||
session::init(&mut model, orders);
|
session::init(&mut model, orders);
|
||||||
shared::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();
|
orders.skip();
|
||||||
}
|
}
|
||||||
Msg::Shared(msg) => {
|
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::UrlChanged(subs::UrlChanged(url)) => model.page.page_changed(url, orders),
|
||||||
Msg::Public(pages::public::Msg::Listing(msg)) => {
|
Msg::Public(pages::public::Msg::Listing(msg)) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use seed::Url;
|
use seed::Url;
|
||||||
|
|
||||||
use crate::{I18n, Page};
|
use crate::{I18n, Page, shopping_cart};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
@ -10,6 +10,7 @@ pub struct Model {
|
|||||||
pub logo: Option<String>,
|
pub logo: Option<String>,
|
||||||
pub shared: crate::shared::Model,
|
pub shared: crate::shared::Model,
|
||||||
pub i18n: I18n,
|
pub i18n: I18n,
|
||||||
|
pub cart: shopping_cart::ShoppingCart,
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub debug_modal: bool,
|
pub debug_modal: bool,
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ pub enum Msg {
|
|||||||
Public(public::Msg),
|
Public(public::Msg),
|
||||||
Admin(admin::Msg),
|
Admin(admin::Msg),
|
||||||
UrlChanged(subs::UrlChanged),
|
UrlChanged(subs::UrlChanged),
|
||||||
Shared(shared::Msg),
|
Shared(shared::SharedMsg),
|
||||||
Session(crate::session::SessionMsg),
|
Session(crate::session::SessionMsg),
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
Debug(crate::debug::DebugMsg),
|
Debug(crate::debug::DebugMsg),
|
||||||
|
@ -2,8 +2,9 @@ use chrono::{NaiveDateTime, TimeZone};
|
|||||||
use model::{AccessTokenString, RefreshTokenString};
|
use model::{AccessTokenString, RefreshTokenString};
|
||||||
use seed::prelude::*;
|
use seed::prelude::*;
|
||||||
|
|
||||||
|
use crate::pages::AdminPage;
|
||||||
use crate::shared::notification::NotificationMsg;
|
use crate::shared::notification::NotificationMsg;
|
||||||
use crate::{Model, Msg};
|
use crate::{pages, Model, Msg, Page, PublicPage};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SessionMsg {
|
pub enum SessionMsg {
|
||||||
@ -29,11 +30,40 @@ pub fn init(model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
.ok()
|
.ok()
|
||||||
.map(model::RefreshTokenString::new);
|
.map(model::RefreshTokenString::new);
|
||||||
model.shared.exp = LocalStorage::get::<_, String>("exp").ok().and_then(|s| {
|
model.shared.exp = LocalStorage::get::<_, String>("exp").ok().and_then(|s| {
|
||||||
seed::log!("Parsing ", s);
|
|
||||||
chrono::DateTime::parse_from_rfc3339(&s)
|
chrono::DateTime::parse_from_rfc3339(&s)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|t| t.naive_utc())
|
.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>) {
|
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| {
|
errors.into_iter().for_each(|msg| {
|
||||||
orders
|
orders
|
||||||
.skip()
|
.skip()
|
||||||
.send_msg(Msg::Shared(crate::shared::Msg::Notification(
|
.send_msg(Msg::Shared(crate::shared::SharedMsg::Notification(
|
||||||
NotificationMsg::Error(msg),
|
NotificationMsg::Error(msg),
|
||||||
)));
|
)));
|
||||||
});
|
});
|
||||||
@ -133,7 +163,7 @@ pub fn update(msg: SessionMsg, model: &mut Model, orders: &mut impl Orders<Msg>)
|
|||||||
_ => {
|
_ => {
|
||||||
orders
|
orders
|
||||||
.skip()
|
.skip()
|
||||||
.send_msg(Msg::Shared(crate::shared::Msg::Notification(
|
.send_msg(Msg::Shared(crate::shared::SharedMsg::Notification(
|
||||||
NotificationMsg::Error("Request failed".into()),
|
NotificationMsg::Error("Request failed".into()),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
use seed::app::Orders;
|
use seed::app::Orders;
|
||||||
|
|
||||||
|
use crate::session::redirect_on_session;
|
||||||
|
|
||||||
pub mod notification;
|
pub mod notification;
|
||||||
pub mod view;
|
pub mod view;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Msg {
|
pub enum SharedMsg {
|
||||||
LoadMe,
|
LoadMe,
|
||||||
MeLoaded(crate::api::NetRes<model::Account>),
|
MeLoaded(crate::api::NetRes<model::Account>),
|
||||||
SignIn(model::api::SignInInput),
|
SignIn(model::api::SignInInput),
|
||||||
SignedIn(crate::api::NetRes<model::api::SessionOutput>),
|
SignedIn(crate::api::NetRes<model::api::SessionOutput>),
|
||||||
Notification(crate::shared::notification::NotificationMsg),
|
Notification(notification::NotificationMsg),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -22,38 +24,38 @@ pub struct Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(_model: &mut crate::Model, orders: &mut impl Orders<crate::Msg>) {
|
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 {
|
match msg {
|
||||||
Msg::LoadMe => {
|
SharedMsg::LoadMe => {
|
||||||
seed::log!("1");
|
if let Some(token) = model.shared.access_token.as_ref().cloned() {
|
||||||
if let Some(token) = model.access_token.as_ref().cloned() {
|
|
||||||
seed::log!("2");
|
|
||||||
orders.skip().perform_cmd(async move {
|
orders.skip().perform_cmd(async move {
|
||||||
seed::log!("3");
|
crate::Msg::Shared(SharedMsg::MeLoaded(
|
||||||
Msg::MeLoaded(crate::api::public::fetch_me(token).await)
|
crate::api::public::fetch_me(token).await,
|
||||||
|
))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Msg::MeLoaded(crate::api::NetRes::Success(account)) => {
|
SharedMsg::MeLoaded(crate::api::NetRes::Success(account)) => {
|
||||||
model.me = Some(account);
|
model.shared.me = Some(account);
|
||||||
|
redirect_on_session(model, orders);
|
||||||
}
|
}
|
||||||
Msg::MeLoaded(crate::api::NetRes::Error(_error)) => {}
|
SharedMsg::MeLoaded(crate::api::NetRes::Error(_error)) => {}
|
||||||
Msg::MeLoaded(crate::api::NetRes::Http(_error)) => {}
|
SharedMsg::MeLoaded(crate::api::NetRes::Http(_error)) => {}
|
||||||
Msg::SignIn(input) => {
|
SharedMsg::SignIn(input) => {
|
||||||
orders
|
orders.skip().perform_cmd(async {
|
||||||
.skip()
|
SharedMsg::SignedIn(crate::api::public::sign_in(input).await)
|
||||||
.perform_cmd(async { Msg::SignedIn(crate::api::public::sign_in(input).await) });
|
});
|
||||||
}
|
}
|
||||||
Msg::SignedIn(crate::api::NetRes::Success(pair)) => {
|
SharedMsg::SignedIn(crate::api::NetRes::Success(pair)) => {
|
||||||
handle_auth_pair(pair, model, orders);
|
handle_auth_pair(pair, &mut model.shared, orders);
|
||||||
}
|
}
|
||||||
Msg::SignedIn(crate::api::NetRes::Error(_err)) => {}
|
SharedMsg::SignedIn(crate::api::NetRes::Error(_err)) => {}
|
||||||
Msg::SignedIn(crate::api::NetRes::Http(_err)) => {}
|
SharedMsg::SignedIn(crate::api::NetRes::Http(_err)) => {}
|
||||||
Msg::Notification(msg) => {
|
SharedMsg::Notification(msg) => {
|
||||||
notification::update(msg, model, orders);
|
notification::update(msg, &mut model.shared, orders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ pub enum NotificationMsg {
|
|||||||
Clear,
|
Clear,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NotificationMsg> for shared::Msg {
|
impl From<NotificationMsg> for shared::SharedMsg {
|
||||||
fn from(msg: NotificationMsg) -> Self {
|
fn from(msg: NotificationMsg) -> Self {
|
||||||
Self::Notification(msg)
|
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(Ev::Click, move |ev| {
|
||||||
ev.prevent_default();
|
ev.prevent_default();
|
||||||
ev.stop_propagation();
|
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
68
web/src/shopping_cart.rs
Normal 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();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user