adminFront/src/kitUI/Cart/Cart.tsx
2024-05-23 15:01:51 +03:00

264 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { calcCart } from "@frontend/kitui";
import Input from "@kitUI/input";
import {
Alert,
Box,
Button,
Checkbox,
FormControlLabel,
Paper,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import { useDiscounts } from "@root/api/discounts/swr";
import { useAllPromocodes } from "@root/api/promocode/swr";
import { requestDiscounts } from "@root/services/discounts.service";
import { requestPrivileges } from "@root/services/privilegies.service";
import { setCartData, useCartStore } from "@root/stores/cart";
import { useTariffStore } from "@root/stores/tariffs";
import { createDiscountFromPromocode } from "@root/utils/createDiscountFromPromocode";
import { currencyFormatter } from "@root/utils/currencyFormatter";
import { useState } from "react";
import CartItemRow from "./CartItemRow";
export default function Cart() {
const theme = useTheme();
const mobile = useMediaQuery(theme.breakpoints.down(400));
const discounts = useDiscounts();
const promocodes = useAllPromocodes();
const cartData = useCartStore((store) => store.cartData);
const tariffs = useTariffStore((state) => state.tariffs);
const [couponField, setCouponField] = useState<string>("");
const [loyaltyField, setLoyaltyField] = useState<string>("");
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const [isNonCommercial, setIsNonCommercial] = useState<boolean>(false);
const selectedTariffIds = useTariffStore((state) => state.selectedTariffIds);
async function handleCalcCartClick() {
await requestPrivileges();
await requestDiscounts();
const cartTariffs = tariffs.filter((tariff) => selectedTariffIds.includes(tariff._id));
let loyaltyValue = parseInt(loyaltyField);
if (!isFinite(loyaltyValue)) loyaltyValue = 0;
const promocode = promocodes.find((promocode) => {
if (promocode.dueTo < Date.now() / 1000) return false;
return promocode.codeword === couponField.trim();
});
const userId = crypto.randomUUID();
const discountsWithPromocodeDiscount = promocode
? [...discounts, createDiscountFromPromocode(promocode, userId)]
: discounts;
try {
const cartData = calcCart(cartTariffs, discountsWithPromocodeDiscount, loyaltyValue, userId);
setErrorMessage(null);
setCartData(cartData);
} catch (error: any) {
setErrorMessage(error.message);
setCartData(null);
}
}
return (
<Box
component="section"
sx={{
border: "1px solid white",
display: "flex",
flexDirection: "column",
alignItems: "center",
width: "100%",
pb: "20px",
borderRadius: "4px",
}}
>
<Typography variant="caption">корзина</Typography>
<Paper
variant="bar"
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: "20px",
flexDirection: mobile ? "column" : undefined,
}}
>
<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,
}}
/>
<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,
},
}}
/>
</Box>
{/* {cartTotal?.couponState &&
(cartTotal.couponState === "applied" ? (
<Alert severity="success">Купон применен!</Alert>
) : (
<Alert severity="error">Подходящий купон не найден!</Alert>
))
} */}
<Box
sx={{
border: "1px solid white",
padding: "3px",
display: "flex",
flexDirection: "column",
ml: mobile ? 0 : "auto",
}}
>
<Input
label="лояльность"
size="small"
type="number"
value={loyaltyField}
onChange={(e) => setLoyaltyField(e.target.value)}
InputProps={{
style: {
backgroundColor: theme.palette.content.main,
color: theme.palette.secondary.main,
},
}}
InputLabelProps={{
style: {
color: theme.palette.secondary.main,
},
}}
/>
</Box>
<Button onClick={handleCalcCartClick}>рассчитать</Button>
</Paper>
{cartData?.services.length && (
<>
<Table
sx={{
width: "90%",
margin: "5px",
border: "2px solid",
borderColor: theme.palette.secondary.main,
}}
aria-label="simple table"
>
<TableHead>
<TableRow
sx={{
borderBottom: "2px solid",
borderColor: theme.palette.grayLight.main,
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>
{cartData.services.flatMap((service) =>
service.tariffs.map((tariffCartData) => {
const appliedDiscounts = tariffCartData.privileges
.flatMap((privilege) => Array.from(privilege.appliedDiscounts))
.sort((a, b) => a.Layer - b.Layer);
return (
<CartItemRow
key={tariffCartData.id}
tariffCartData={tariffCartData}
appliedDiscounts={appliedDiscounts}
/>
);
})
)}
</TableBody>
</Table>
<Typography
id="transition-modal-title"
variant="h6"
sx={{
fontWeight: "normal",
textAlign: "center",
marginTop: "10px",
}}
>
ИТОГО: <span>{currencyFormatter.format(cartData.priceAfterDiscounts / 100)}</span>
</Typography>
</>
)}
{errorMessage !== null && (
<Alert variant="filled" severity="error" sx={{ mt: "20px" }}>
{errorMessage}
</Alert>
)}
</Box>
);
}