mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-12-03 14:24:23 +01:00
(feat) add product to cart in product page
This commit is contained in:
parent
8d414a3172
commit
aeae5f7aa0
@ -28,7 +28,9 @@ const CartButton: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="cart-button" onClick={showCart}>
|
<div className="cart-button" onClick={showCart}>
|
||||||
<i className="fas fa-cart-arrow-down" />
|
<i className="fas fa-cart-arrow-down" />
|
||||||
<span>{cart?.order_items_attributes?.length}</span>
|
{cart && cart.order_items_attributes.length > 0 &&
|
||||||
|
<span>{cart.order_items_attributes.length}</span>
|
||||||
|
}
|
||||||
<p>{t('app.public.cart_button.my_cart')}</p>
|
<p>{t('app.public.cart_button.my_cart')}</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -11,13 +11,14 @@ import noImage from '../../../../images/no_image.png';
|
|||||||
interface StoreProductItemProps {
|
interface StoreProductItemProps {
|
||||||
product: Product,
|
product: Product,
|
||||||
cart: Order,
|
cart: Order,
|
||||||
onSuccessAddProductToCart: (cart: Order) => void
|
onSuccessAddProductToCart: (cart: Order) => void,
|
||||||
|
onError: (message: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component shows a product item in store
|
* This component shows a product item in store
|
||||||
*/
|
*/
|
||||||
export const StoreProductItem: React.FC<StoreProductItemProps> = ({ product, cart, onSuccessAddProductToCart }) => {
|
export const StoreProductItem: React.FC<StoreProductItemProps> = ({ product, cart, onSuccessAddProductToCart, onError }) => {
|
||||||
const { t } = useTranslation('public');
|
const { t } = useTranslation('public');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +38,7 @@ export const StoreProductItem: React.FC<StoreProductItemProps> = ({ product, car
|
|||||||
const addProductToCart = (e: React.BaseSyntheticEvent) => {
|
const addProductToCart = (e: React.BaseSyntheticEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
CartAPI.addItem(cart, product.id, 1).then(onSuccessAddProductToCart);
|
CartAPI.addItem(cart, product.id, 1).then(onSuccessAddProductToCart).catch(onError);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,24 +7,30 @@ import { Loader } from '../base/loader';
|
|||||||
import { IApplication } from '../../models/application';
|
import { IApplication } from '../../models/application';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { Product } from '../../models/product';
|
import { Product } from '../../models/product';
|
||||||
|
import { User } from '../../models/user';
|
||||||
import ProductAPI from '../../api/product';
|
import ProductAPI from '../../api/product';
|
||||||
|
import CartAPI from '../../api/cart';
|
||||||
import noImage from '../../../../images/no_image.png';
|
import noImage from '../../../../images/no_image.png';
|
||||||
import { FabButton } from '../base/fab-button';
|
import { FabButton } from '../base/fab-button';
|
||||||
|
import useCart from '../../hooks/use-cart';
|
||||||
import { FilePdf, Minus, Plus } from 'phosphor-react';
|
import { FilePdf, Minus, Plus } from 'phosphor-react';
|
||||||
|
|
||||||
declare const Application: IApplication;
|
declare const Application: IApplication;
|
||||||
|
|
||||||
interface StoreProductProps {
|
interface StoreProductProps {
|
||||||
productSlug: string,
|
productSlug: string,
|
||||||
|
onSuccess: (message: string) => void,
|
||||||
onError: (message: string) => void,
|
onError: (message: string) => void,
|
||||||
|
currentUser?: User
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component shows a product
|
* This component shows a product
|
||||||
*/
|
*/
|
||||||
export const StoreProduct: React.FC<StoreProductProps> = ({ productSlug, onError }) => {
|
export const StoreProduct: React.FC<StoreProductProps> = ({ productSlug, currentUser, onSuccess, onError }) => {
|
||||||
const { t } = useTranslation('public');
|
const { t } = useTranslation('public');
|
||||||
|
|
||||||
|
const { cart, setCart } = useCart(currentUser);
|
||||||
const [product, setProduct] = useState<Product>();
|
const [product, setProduct] = useState<Product>();
|
||||||
const [showImage, setShowImage] = useState<number>(null);
|
const [showImage, setShowImage] = useState<number>(null);
|
||||||
const [toCartCount, setToCartCount] = useState<number>(0);
|
const [toCartCount, setToCartCount] = useState<number>(0);
|
||||||
@ -36,11 +42,13 @@ export const StoreProduct: React.FC<StoreProductProps> = ({ productSlug, onError
|
|||||||
ProductAPI.get(productSlug).then(data => {
|
ProductAPI.get(productSlug).then(data => {
|
||||||
setProduct(data);
|
setProduct(data);
|
||||||
const productImage = _.find(data.product_images_attributes, { is_main: true });
|
const productImage = _.find(data.product_images_attributes, { is_main: true });
|
||||||
|
if (productImage) {
|
||||||
setShowImage(productImage.id);
|
setShowImage(productImage.id);
|
||||||
|
}
|
||||||
setToCartCount(data.quantity_min ? data.quantity_min : 1);
|
setToCartCount(data.quantity_min ? data.quantity_min : 1);
|
||||||
setDisplayToggle(descContainer.current.offsetHeight < descContainer.current.scrollHeight);
|
setDisplayToggle(descContainer.current.offsetHeight < descContainer.current.scrollHeight);
|
||||||
}).catch(() => {
|
}).catch((e) => {
|
||||||
onError(t('app.public.store_product.unexpected_error_occurred'));
|
onError(t('app.public.store_product.unexpected_error_occurred') + e);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -107,7 +115,10 @@ export const StoreProduct: React.FC<StoreProductProps> = ({ productSlug, onError
|
|||||||
* Add product to cart
|
* Add product to cart
|
||||||
*/
|
*/
|
||||||
const addToCart = () => {
|
const addToCart = () => {
|
||||||
console.log('Add', toCartCount, 'to cart');
|
CartAPI.addItem(cart, product.id, toCartCount).then(data => {
|
||||||
|
setCart(data);
|
||||||
|
onSuccess(t('app.public.store.add_to_cart_success'));
|
||||||
|
}).catch(onError);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (product) {
|
if (product) {
|
||||||
@ -187,12 +198,12 @@ export const StoreProduct: React.FC<StoreProductProps> = ({ productSlug, onError
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StoreProductWrapper: React.FC<StoreProductProps> = ({ productSlug, onError }) => {
|
const StoreProductWrapper: React.FC<StoreProductProps> = (props) => {
|
||||||
return (
|
return (
|
||||||
<Loader>
|
<Loader>
|
||||||
<StoreProduct productSlug={productSlug} onError={onError} />
|
<StoreProduct {...props} />
|
||||||
</Loader>
|
</Loader>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Application.Components.component('storeProduct', react2angular(StoreProductWrapper, ['productSlug', 'onError']));
|
Application.Components.component('storeProduct', react2angular(StoreProductWrapper, ['productSlug', 'currentUser', 'onSuccess', 'onError']));
|
||||||
|
@ -11,7 +11,6 @@ import ProductCategoryAPI from '../../api/product-category';
|
|||||||
import MachineAPI from '../../api/machine';
|
import MachineAPI from '../../api/machine';
|
||||||
import { StoreProductItem } from './store-product-item';
|
import { StoreProductItem } from './store-product-item';
|
||||||
import useCart from '../../hooks/use-cart';
|
import useCart from '../../hooks/use-cart';
|
||||||
import { emitCustomEvent } from 'react-custom-events';
|
|
||||||
import { User } from '../../models/user';
|
import { User } from '../../models/user';
|
||||||
import { Order } from '../../models/order';
|
import { Order } from '../../models/order';
|
||||||
import { AccordionItem } from './accordion-item';
|
import { AccordionItem } from './accordion-item';
|
||||||
@ -67,10 +66,6 @@ const Store: React.FC<StoreProps> = ({ onError, onSuccess, currentUser }) => {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
emitCustomEvent('CartUpdate', cart);
|
|
||||||
}, [cart]);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create categories tree (parent/children)
|
* Create categories tree (parent/children)
|
||||||
*/
|
*/
|
||||||
@ -234,7 +229,7 @@ const Store: React.FC<StoreProps> = ({ onError, onSuccess, currentUser }) => {
|
|||||||
/>
|
/>
|
||||||
<div className="products-grid">
|
<div className="products-grid">
|
||||||
{products.map((product) => (
|
{products.map((product) => (
|
||||||
<StoreProductItem key={product.id} product={product} cart={cart} onSuccessAddProductToCart={addToCart} />
|
<StoreProductItem key={product.id} product={product} cart={cart} onSuccessAddProductToCart={addToCart} onError={onError} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
import { emitCustomEvent } from 'react-custom-events';
|
||||||
import { Order } from '../models/order';
|
import { Order } from '../models/order';
|
||||||
import CartAPI from '../api/cart';
|
import CartAPI from '../api/cart';
|
||||||
import { getCartToken, setCartToken } from '../lib/cart-token';
|
import { getCartToken, setCartToken } from '../lib/cart-token';
|
||||||
@ -13,7 +14,7 @@ export default function useCart (user?: User) {
|
|||||||
async function createCart () {
|
async function createCart () {
|
||||||
const currentCartToken = getCartToken();
|
const currentCartToken = getCartToken();
|
||||||
const data = await CartAPI.create(currentCartToken);
|
const data = await CartAPI.create(currentCartToken);
|
||||||
setCart(data);
|
_setCart(data);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setCartToken(data.token);
|
setCartToken(data.token);
|
||||||
}
|
}
|
||||||
@ -30,7 +31,7 @@ export default function useCart (user?: User) {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const currentCartToken = getCartToken();
|
const currentCartToken = getCartToken();
|
||||||
const data = await CartAPI.create(currentCartToken);
|
const data = await CartAPI.create(currentCartToken);
|
||||||
setCart(data);
|
_setCart(data);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,5 +41,10 @@ export default function useCart (user?: User) {
|
|||||||
}
|
}
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
return { loading, cart, error, setCart, reloadCart };
|
const _setCart = (data: Order) => {
|
||||||
|
setCart(data);
|
||||||
|
emitCustomEvent('CartUpdate', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { loading, cart, error, setCart: _setCart, reloadCart };
|
||||||
}
|
}
|
||||||
|
@ -13,5 +13,5 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="m-lg">
|
<section class="m-lg">
|
||||||
<store-product product-slug="productSlug" on-error="onError" on-success="onSuccess" />
|
<store-product product-slug="productSlug" current-user="currentUser" on-error="onError" on-success="onSuccess" />
|
||||||
</section>
|
</section>
|
||||||
|
Loading…
Reference in New Issue
Block a user