2022-08-25 16:23:00 +02:00
|
|
|
import React, { useState } from 'react';
|
2022-08-19 19:59:13 +02:00
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import { react2angular } from 'react2angular';
|
|
|
|
import { Loader } from '../base/loader';
|
|
|
|
import { IApplication } from '../../models/application';
|
|
|
|
import { FabButton } from '../base/fab-button';
|
|
|
|
import useCart from '../../hooks/use-cart';
|
|
|
|
import FormatLib from '../../lib/format';
|
|
|
|
import CartAPI from '../../api/cart';
|
2022-08-20 20:49:51 +02:00
|
|
|
import { User } from '../../models/user';
|
2022-08-25 08:52:17 +02:00
|
|
|
import { PaymentModal } from '../payment/stripe/payment-modal';
|
|
|
|
import { PaymentMethod } from '../../models/payment';
|
|
|
|
import { Order } from '../../models/order';
|
|
|
|
import { MemberSelect } from '../user/member-select';
|
2022-08-25 20:50:15 +02:00
|
|
|
import { CouponInput } from '../coupon/coupon-input';
|
2022-08-19 19:59:13 +02:00
|
|
|
|
|
|
|
declare const Application: IApplication;
|
|
|
|
|
|
|
|
interface StoreCartProps {
|
|
|
|
onError: (message: string) => void,
|
2022-08-25 08:52:17 +02:00
|
|
|
currentUser?: User,
|
2022-08-19 19:59:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This component shows user's cart
|
|
|
|
*/
|
2022-08-20 20:49:51 +02:00
|
|
|
const StoreCart: React.FC<StoreCartProps> = ({ onError, currentUser }) => {
|
2022-08-19 19:59:13 +02:00
|
|
|
const { t } = useTranslation('public');
|
|
|
|
|
2022-08-25 16:23:00 +02:00
|
|
|
const { cart, setCart } = useCart(currentUser);
|
2022-08-25 08:52:17 +02:00
|
|
|
const [paymentModal, setPaymentModal] = useState<boolean>(false);
|
2022-08-20 20:49:51 +02:00
|
|
|
|
2022-08-19 19:59:13 +02:00
|
|
|
/**
|
|
|
|
* Remove the product from cart
|
|
|
|
*/
|
|
|
|
const removeProductFromCart = (item) => {
|
|
|
|
return (e: React.BaseSyntheticEvent) => {
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
CartAPI.removeItem(cart, item.orderable_id).then(data => {
|
|
|
|
setCart(data);
|
2022-08-26 11:57:53 +02:00
|
|
|
}).catch(onError);
|
2022-08-19 19:59:13 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2022-08-20 18:47:15 +02:00
|
|
|
/**
|
|
|
|
* Change product quantity
|
|
|
|
*/
|
|
|
|
const changeProductQuantity = (item) => {
|
|
|
|
return (e: React.BaseSyntheticEvent) => {
|
|
|
|
CartAPI.setQuantity(cart, item.orderable_id, e.target.value).then(data => {
|
|
|
|
setCart(data);
|
2022-08-26 11:57:53 +02:00
|
|
|
}).catch(onError);
|
2022-08-20 18:47:15 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checkout cart
|
|
|
|
*/
|
|
|
|
const checkout = () => {
|
2022-08-25 08:52:17 +02:00
|
|
|
setPaymentModal(true);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open/closes the payment modal
|
|
|
|
*/
|
|
|
|
const togglePaymentModal = (): void => {
|
|
|
|
setPaymentModal(!paymentModal);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open/closes the payment modal
|
|
|
|
*/
|
|
|
|
const handlePaymentSuccess = (data: Order): void => {
|
2022-08-26 12:04:19 +02:00
|
|
|
if (data.payment_state === 'paid') {
|
|
|
|
setPaymentModal(false);
|
|
|
|
window.location.href = '/#!/store';
|
|
|
|
} else {
|
|
|
|
onError('Erreur inconnue after payment, please conntact admin');
|
|
|
|
}
|
2022-08-25 08:52:17 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Change cart's customer by admin/manger
|
|
|
|
*/
|
|
|
|
const handleChangeMember = (userId: number): void => {
|
|
|
|
CartAPI.setCustomer(cart, userId).then(data => {
|
|
|
|
setCart(data);
|
2022-08-26 11:57:53 +02:00
|
|
|
}).catch(onError);
|
2022-08-25 08:52:17 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the current operator has administrative rights or is a normal member
|
|
|
|
*/
|
|
|
|
const isPrivileged = (): boolean => {
|
|
|
|
return (currentUser?.role === 'admin' || currentUser?.role === 'manager');
|
2022-08-20 18:47:15 +02:00
|
|
|
};
|
|
|
|
|
2022-08-25 16:23:00 +02:00
|
|
|
/**
|
|
|
|
* Check if the current cart is empty ?
|
|
|
|
*/
|
|
|
|
const cartIsEmpty = (): boolean => {
|
|
|
|
return cart && cart.order_items_attributes.length === 0;
|
|
|
|
};
|
|
|
|
|
2022-08-19 19:59:13 +02:00
|
|
|
return (
|
|
|
|
<div className="store-cart">
|
2022-08-25 16:23:00 +02:00
|
|
|
{cart && cartIsEmpty() && <p>{t('app.public.store_cart.cart_is_empty')}</p>}
|
2022-08-19 19:59:13 +02:00
|
|
|
{cart && cart.order_items_attributes.map(item => (
|
|
|
|
<div key={item.id}>
|
|
|
|
<div>{item.orderable_name}</div>
|
|
|
|
<div>{FormatLib.price(item.amount)}</div>
|
|
|
|
<div>{item.quantity}</div>
|
2022-08-20 18:47:15 +02:00
|
|
|
<select value={item.quantity} onChange={changeProductQuantity(item)}>
|
|
|
|
{Array.from({ length: 100 }, (_, i) => i + 1).map(v => (
|
|
|
|
<option key={v} value={v}>{v}</option>
|
|
|
|
))}
|
|
|
|
</select>
|
2022-08-19 19:59:13 +02:00
|
|
|
<div>{FormatLib.price(item.quantity * item.amount)}</div>
|
|
|
|
<FabButton className="delete-btn" onClick={removeProductFromCart(item)}>
|
2022-08-20 18:47:15 +02:00
|
|
|
<i className="fa fa-trash" />
|
2022-08-19 19:59:13 +02:00
|
|
|
</FabButton>
|
|
|
|
</div>
|
|
|
|
))}
|
2022-08-26 10:46:30 +02:00
|
|
|
{cart && !cartIsEmpty() && <CouponInput user={cart.user} amount={cart.total} />}
|
|
|
|
{cart && !cartIsEmpty() && <p>Totale: {FormatLib.price(cart.total)}</p>}
|
2022-08-25 16:23:00 +02:00
|
|
|
{cart && !cartIsEmpty() && isPrivileged() && <MemberSelect defaultUser={cart.user} onSelected={handleChangeMember} />}
|
|
|
|
{cart && !cartIsEmpty() &&
|
2022-08-25 08:52:17 +02:00
|
|
|
<FabButton className="checkout-btn" onClick={checkout} disabled={!cart.user || cart.order_items_attributes.length === 0}>
|
|
|
|
{t('app.public.store_cart.checkout')}
|
|
|
|
</FabButton>
|
|
|
|
}
|
2022-08-25 16:23:00 +02:00
|
|
|
{cart && !cartIsEmpty() && cart.user && <div>
|
2022-08-25 08:52:17 +02:00
|
|
|
<PaymentModal isOpen={paymentModal}
|
|
|
|
toggleModal={togglePaymentModal}
|
|
|
|
afterSuccess={handlePaymentSuccess}
|
|
|
|
onError={onError}
|
2022-08-25 16:23:00 +02:00
|
|
|
cart={{ customer_id: cart.user.id, items: [], payment_method: PaymentMethod.Card }}
|
2022-08-25 08:52:17 +02:00
|
|
|
order={cart}
|
|
|
|
operator={currentUser}
|
|
|
|
customer={cart.user}
|
2022-08-25 16:23:00 +02:00
|
|
|
updateCart={() => 'dont need update shopping cart'} />
|
2022-08-25 08:52:17 +02:00
|
|
|
</div>}
|
2022-08-19 19:59:13 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2022-08-20 20:49:51 +02:00
|
|
|
const StoreCartWrapper: React.FC<StoreCartProps> = (props) => {
|
2022-08-19 19:59:13 +02:00
|
|
|
return (
|
|
|
|
<Loader>
|
2022-08-20 20:49:51 +02:00
|
|
|
<StoreCart {...props} />
|
2022-08-19 19:59:13 +02:00
|
|
|
</Loader>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2022-08-20 20:49:51 +02:00
|
|
|
Application.Components.component('storeCart', react2angular(StoreCartWrapper, ['onError', 'currentUser']));
|