2023-03-06 13:25:33 +00:00
|
|
|
|
import theme from "@theme";
|
2023-03-14 08:28:42 +00:00
|
|
|
|
import { Button, Paper, Box, Typography, TableHead, TableRow, TableCell, TableBody, Table, Tooltip, Alert, Checkbox, FormControlLabel } from "@mui/material";
|
2023-03-06 13:25:33 +00:00
|
|
|
|
import Input from "@kitUI/input";
|
|
|
|
|
import { useCartStore } from "@root/stores/cart";
|
|
|
|
|
import { useState } from "react";
|
|
|
|
|
import { GridSelectionModel } from "@mui/x-data-grid";
|
|
|
|
|
import { testUser } from "@root/stores/mocks/user";
|
|
|
|
|
import { useDiscountStore } from "@root/stores/discounts";
|
2023-03-09 09:01:40 +00:00
|
|
|
|
import { calcCartData, createCartItem, findDiscountFactor, formatDiscountFactor } from "./calc";
|
2023-03-06 13:25:33 +00:00
|
|
|
|
import { useTariffStore } from "@root/stores/tariffs";
|
|
|
|
|
import { AnyDiscount, CartItemTotal } from "@root/model/cart";
|
|
|
|
|
|
2023-03-09 08:51:51 +00:00
|
|
|
|
|
2023-03-06 13:25:33 +00:00
|
|
|
|
interface Props {
|
|
|
|
|
selectedTariffs: GridSelectionModel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function Cart({ selectedTariffs }: Props) {
|
|
|
|
|
const tariffs = useTariffStore(store => store.tariffs);
|
|
|
|
|
const discounts = useDiscountStore(store => store.discounts);
|
|
|
|
|
const cartTotal = useCartStore(state => state.cartTotal);
|
|
|
|
|
const setCartTotal = useCartStore(store => store.setCartTotal);
|
|
|
|
|
const [couponField, setCouponField] = useState<string>("");
|
2023-03-09 08:51:51 +00:00
|
|
|
|
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
2023-03-14 08:28:42 +00:00
|
|
|
|
const [isNonCommercial, setIsNonCommercial] = useState<boolean>(false);
|
2023-03-06 13:25:33 +00:00
|
|
|
|
// const [coupon, setCoupon] = useState<string | undefined>();
|
|
|
|
|
|
|
|
|
|
const cartRows = cartTotal?.items.map(cartItemTotal => {
|
2023-03-08 10:52:16 +00:00
|
|
|
|
const service = cartItemTotal.tariff.privilege.serviceKey;
|
|
|
|
|
const serviceDiscount = cartTotal.discountsByService[service];
|
|
|
|
|
|
2023-03-06 13:25:33 +00:00
|
|
|
|
const envolvedDiscountsElement = (
|
|
|
|
|
<Box>
|
2023-03-09 09:01:40 +00:00
|
|
|
|
{cartItemTotal.envolvedDiscounts.map((discount, index, arr) => (
|
|
|
|
|
<span key={discount._id}>
|
|
|
|
|
<DiscountTooltip
|
|
|
|
|
discount={discount}
|
|
|
|
|
cartItemTotal={cartItemTotal}
|
|
|
|
|
/>
|
|
|
|
|
{index < arr.length - (serviceDiscount ? 0 : 1) &&
|
|
|
|
|
<span>, </span>
|
|
|
|
|
}
|
|
|
|
|
</span>
|
|
|
|
|
))}
|
2023-03-08 10:52:16 +00:00
|
|
|
|
{serviceDiscount &&
|
|
|
|
|
<span>
|
|
|
|
|
<DiscountTooltip
|
|
|
|
|
discount={serviceDiscount}
|
|
|
|
|
cartItemTotal={cartItemTotal}
|
|
|
|
|
/>
|
|
|
|
|
</span>
|
|
|
|
|
}
|
2023-03-06 13:25:33 +00:00
|
|
|
|
</Box>
|
|
|
|
|
);
|
|
|
|
|
|
2023-03-08 10:52:16 +00:00
|
|
|
|
const totalIncludingServiceDiscount = cartItemTotal.totalPrice * (serviceDiscount?.target.factor || 1);
|
|
|
|
|
|
2023-03-06 13:25:33 +00:00
|
|
|
|
return {
|
|
|
|
|
id: cartItemTotal.tariff.id,
|
|
|
|
|
tariffName: cartItemTotal.tariff.name,
|
|
|
|
|
privilegeDesc: cartItemTotal.tariff.privilege.description,
|
|
|
|
|
envolvedDiscounts: envolvedDiscountsElement,
|
2023-03-08 10:52:16 +00:00
|
|
|
|
price: totalIncludingServiceDiscount,
|
2023-03-06 13:25:33 +00:00
|
|
|
|
};
|
|
|
|
|
});
|
2023-03-08 10:52:16 +00:00
|
|
|
|
|
2023-03-14 08:28:42 +00:00
|
|
|
|
const cartDiscounts = cartTotal?.envolvedCartDiscounts;
|
|
|
|
|
const cartDiscountsResultFactor = cartDiscounts && cartDiscounts?.length > 1 && cartDiscounts.reduce((acc, discount) => acc * findDiscountFactor(discount), 1);
|
2023-03-06 13:25:33 +00:00
|
|
|
|
|
2023-03-07 14:39:46 +00:00
|
|
|
|
const envolvedCartDiscountsElement = cartDiscounts && (
|
2023-03-06 13:25:33 +00:00
|
|
|
|
<Box sx={{
|
|
|
|
|
display: "inline-flex",
|
|
|
|
|
flexWrap: "wrap",
|
|
|
|
|
}}>
|
2023-03-07 14:39:46 +00:00
|
|
|
|
{cartDiscounts?.map((discount, index, arr) => (
|
|
|
|
|
<span key={discount._id}>
|
2023-03-06 13:25:33 +00:00
|
|
|
|
<DiscountTooltip
|
2023-03-07 14:39:46 +00:00
|
|
|
|
discount={discount}
|
2023-03-06 13:25:33 +00:00
|
|
|
|
/>
|
|
|
|
|
{index < arr.length - 1 &&
|
|
|
|
|
<span>, </span>
|
|
|
|
|
}
|
|
|
|
|
</span>
|
|
|
|
|
))}
|
2023-03-07 14:39:46 +00:00
|
|
|
|
|
|
|
|
|
{cartDiscountsResultFactor && `= ${formatDiscountFactor(cartDiscountsResultFactor)}`}
|
2023-03-06 13:25:33 +00:00
|
|
|
|
</Box>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
function handleCalcCartClick() {
|
|
|
|
|
const cartTariffs = tariffs.filter(tariff => selectedTariffs.includes(tariff.id));
|
|
|
|
|
const cartItems = cartTariffs.map(tariff => createCartItem(tariff));
|
2023-03-14 08:28:42 +00:00
|
|
|
|
const cartData = calcCartData(testUser, cartItems, discounts, isNonCommercial, couponField);
|
2023-03-09 08:51:51 +00:00
|
|
|
|
|
|
|
|
|
if (cartData instanceof Error) {
|
|
|
|
|
setErrorMessage(cartData.message);
|
|
|
|
|
return setCartTotal(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setErrorMessage(null);
|
|
|
|
|
setCartTotal(cartData);
|
2023-03-06 13:25:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Box
|
|
|
|
|
component="section"
|
|
|
|
|
sx={{
|
|
|
|
|
border: "1px solid white",
|
|
|
|
|
display: "flex",
|
|
|
|
|
flexDirection: "column",
|
|
|
|
|
alignItems: "center",
|
2023-03-09 08:51:51 +00:00
|
|
|
|
width: "100%",
|
|
|
|
|
pb: "20px",
|
|
|
|
|
borderRadius: "4px",
|
2023-03-06 13:25:33 +00:00
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Typography variant="caption">
|
|
|
|
|
корзина
|
|
|
|
|
</Typography>
|
|
|
|
|
<Paper
|
|
|
|
|
variant="bar"
|
2023-03-14 08:28:42 +00:00
|
|
|
|
sx={{
|
|
|
|
|
display: "flex",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
justifyContent: "space-between",
|
|
|
|
|
gap: "20px",
|
|
|
|
|
}}
|
2023-03-06 13:25:33 +00:00
|
|
|
|
>
|
|
|
|
|
<Box
|
|
|
|
|
sx={{
|
|
|
|
|
border: "1px solid white",
|
|
|
|
|
padding: "3px",
|
|
|
|
|
display: "flex",
|
|
|
|
|
flexDirection: "column"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Input
|
|
|
|
|
label="промокод"
|
|
|
|
|
size="small"
|
|
|
|
|
value={couponField}
|
|
|
|
|
onChange={e => setCouponField(e.target.value)}
|
|
|
|
|
InputProps={{
|
|
|
|
|
style: {
|
|
|
|
|
backgroundColor: theme.palette.content.main,
|
|
|
|
|
color: theme.palette.secondary.main,
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
InputLabelProps={{
|
|
|
|
|
style: {
|
|
|
|
|
color: theme.palette.secondary.main
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
{/* <Button
|
|
|
|
|
sx={{ maxWidth: "140px" }}
|
|
|
|
|
onClick={() => setCoupon(couponField)}
|
|
|
|
|
>применить промокод</Button> */}
|
|
|
|
|
</Box>
|
2023-03-14 08:28:42 +00:00
|
|
|
|
<FormControlLabel
|
|
|
|
|
checked={isNonCommercial}
|
|
|
|
|
onChange={(e, checked) => setIsNonCommercial(checked)}
|
|
|
|
|
control={<Checkbox
|
|
|
|
|
sx={{
|
|
|
|
|
color: theme.palette.secondary.main,
|
|
|
|
|
"&.Mui-checked": {
|
|
|
|
|
color: theme.palette.secondary.main,
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
/>}
|
|
|
|
|
label="НКО"
|
|
|
|
|
sx={{
|
|
|
|
|
color: theme.palette.secondary.main,
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<Button onClick={handleCalcCartClick} sx={{ ml: "auto" }}>рассчитать</Button>
|
2023-03-06 13:25:33 +00:00
|
|
|
|
</Paper>
|
|
|
|
|
|
2023-03-09 08:51:51 +00:00
|
|
|
|
{cartTotal?.items && cartTotal.items.length > 0 &&
|
|
|
|
|
<>
|
|
|
|
|
<Table sx={{
|
|
|
|
|
width: "90%",
|
|
|
|
|
margin: "5px",
|
|
|
|
|
border: "2px solid",
|
|
|
|
|
borderColor: theme.palette.secondary.main,
|
|
|
|
|
}} aria-label="simple table">
|
|
|
|
|
<TableHead>
|
|
|
|
|
<TableRow sx={{
|
2023-03-06 13:25:33 +00:00
|
|
|
|
borderBottom: "2px solid",
|
|
|
|
|
borderColor: theme.palette.grayLight.main,
|
2023-03-09 08:51:51 +00:00
|
|
|
|
height: "100px"
|
|
|
|
|
}}>
|
|
|
|
|
<TableCell>
|
|
|
|
|
<Typography
|
|
|
|
|
variant="h4"
|
|
|
|
|
sx={{ color: theme.palette.secondary.main }}
|
|
|
|
|
>Имя</Typography>
|
|
|
|
|
</TableCell>
|
|
|
|
|
<TableCell>
|
|
|
|
|
<Typography
|
|
|
|
|
variant="h4"
|
|
|
|
|
sx={{ color: theme.palette.secondary.main }}
|
|
|
|
|
>Описание</Typography>
|
|
|
|
|
</TableCell>
|
|
|
|
|
<TableCell>
|
|
|
|
|
<Typography
|
|
|
|
|
variant="h4"
|
|
|
|
|
sx={{ color: theme.palette.secondary.main }}
|
|
|
|
|
>Скидки</Typography>
|
|
|
|
|
</TableCell>
|
|
|
|
|
<TableCell>
|
|
|
|
|
<Typography
|
|
|
|
|
variant="h4"
|
|
|
|
|
sx={{ color: theme.palette.secondary.main }}
|
|
|
|
|
>стоимость</Typography>
|
|
|
|
|
</TableCell>
|
|
|
|
|
</TableRow>
|
|
|
|
|
</TableHead>
|
|
|
|
|
<TableBody>
|
|
|
|
|
{cartRows?.map(row => (
|
|
|
|
|
<TableRow
|
|
|
|
|
key={row.id}
|
|
|
|
|
sx={{
|
|
|
|
|
borderBottom: "2px solid",
|
|
|
|
|
borderColor: theme.palette.grayLight.main,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<TableCell sx={{
|
|
|
|
|
color: theme.palette.secondary.main,
|
|
|
|
|
}}>{row.tariffName}</TableCell>
|
|
|
|
|
<TableCell sx={{
|
|
|
|
|
color: theme.palette.secondary.main,
|
|
|
|
|
}}>{row.privilegeDesc}</TableCell>
|
|
|
|
|
<TableCell sx={{
|
|
|
|
|
color: theme.palette.secondary.main,
|
|
|
|
|
}}>{row.envolvedDiscounts}</TableCell>
|
|
|
|
|
<TableCell sx={{
|
|
|
|
|
color: theme.palette.secondary.main,
|
|
|
|
|
}}>{row.price.toFixed(2)} ₽</TableCell>
|
|
|
|
|
</TableRow>
|
|
|
|
|
))}
|
|
|
|
|
</TableBody>
|
|
|
|
|
</Table>
|
2023-03-06 13:25:33 +00:00
|
|
|
|
|
2023-03-09 08:51:51 +00:00
|
|
|
|
<Typography id="transition-modal-title" variant="h6" sx={{
|
|
|
|
|
fontWeight: "normal",
|
|
|
|
|
textAlign: "center",
|
|
|
|
|
marginTop: "15px",
|
|
|
|
|
fontSize: "16px"
|
|
|
|
|
}}>
|
|
|
|
|
Скидки корзины: {envolvedCartDiscountsElement}
|
|
|
|
|
</Typography>
|
|
|
|
|
|
|
|
|
|
<Typography id="transition-modal-title" variant="h6" sx={{
|
|
|
|
|
fontWeight: "normal",
|
|
|
|
|
textAlign: "center",
|
|
|
|
|
marginTop: "10px"
|
|
|
|
|
}}>
|
|
|
|
|
ИТОГО: <span>{cartTotal?.totalPrice.toFixed(2)} ₽</span>
|
|
|
|
|
</Typography>
|
|
|
|
|
</>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{errorMessage !== null &&
|
|
|
|
|
<Alert variant="filled" severity="error" sx={{ mt: "20px" }}>
|
|
|
|
|
{errorMessage}
|
|
|
|
|
</Alert>
|
|
|
|
|
}
|
2023-03-06 13:25:33 +00:00
|
|
|
|
|
|
|
|
|
</Box>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-07 14:39:46 +00:00
|
|
|
|
function DiscountTooltip({ discount, cartItemTotal }: {
|
|
|
|
|
discount: AnyDiscount;
|
2023-03-06 13:25:33 +00:00
|
|
|
|
cartItemTotal?: CartItemTotal;
|
|
|
|
|
}) {
|
2023-03-07 14:39:46 +00:00
|
|
|
|
const discountText = formatDiscountFactor(findDiscountFactor(discount, cartItemTotal?.tariff.privilege.privilegeId));
|
2023-03-06 13:25:33 +00:00
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Tooltip title={
|
|
|
|
|
<>
|
|
|
|
|
<Typography>Скидка: {discount?.name}</Typography>
|
|
|
|
|
<Typography>{discount?.description}</Typography>
|
|
|
|
|
<Typography>-------</Typography>
|
|
|
|
|
<Typography>layer: {discount?.layer}</Typography>
|
|
|
|
|
<Typography>id: {discount?._id}</Typography>
|
|
|
|
|
</>
|
|
|
|
|
}>
|
|
|
|
|
<span>{discountText}</span>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
);
|
|
|
|
|
}
|