adminFront/src/kitUI/Cart/Cart.tsx

292 lines
12 KiB
TypeScript
Raw Normal View History

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>,&nbsp;</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>,&nbsp;</span>
}
</span>
))}
2023-03-07 14:39:46 +00:00
&nbsp;
{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>
);
}