front-hub/src/pages/Tariffs/TariffsPage.tsx
Nastya 291d059654
Some checks failed
Deploy / CreateImage (push) Failing after 1m0s
Deploy / DeployService (push) Has been skipped
новая система покупок
2025-07-20 13:39:47 +03:00

274 lines
8.8 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 SectionWrapper from "@components/SectionWrapper";
import {
Tariff,
calcTariffPrice,
getMessageFromFetchError,
} from "@frontend/kitui";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import {
Box,
IconButton,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import NumberIcon from "@root/components/NumberIcon";
import { useTariffStore } from "@root/stores/tariffs";
import { addTariffToCart, useUserStore } from "@root/stores/user";
import { currencyFormatter } from "@root/utils/currencyFormatter";
import { handleComponentError } from "@root/utils/handleComponentError";
import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation";
import { useCartTariffs } from "@root/utils/hooks/useCartTariffs";
import { enqueueSnackbar } from "notistack";
import { useState } from "react";
import { withErrorBoundary } from "react-error-boundary";
import { useLocation } from "react-router-dom";
import FreeTariffCard from "./FreeTariffCard";
import TariffCard from "./TariffCard";
import { useDiscounts } from "@root/api/price";
import { Select } from "@components/Select";
import { Tabs } from "@components/Tabs";
import { useRequestSquizCreate, RSCOpen, RSCClose } from "@root/stores/requestSquizCreate"
const subPagesTime = ["Базовый тариф PenaQuiz", 'Убрать логотип "PenaQuiz"'];
const subPagesVolume = ["Заявки квиз", 'Заказать создание квиза'];
const StepperText: Record<string, string> = {
volume: "Тарифы на объём",
time: "Тарифы на время",
};
function TariffPage() {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const location = useLocation();
const tariffs = useTariffStore((state) => state.tariffs);
const [selectedItemTime, setSelectedItemTime] = useState<number>(0);
const [selectedItemVolume, setSelectedItemVolume] = useState<number>(0);
const purchasesAmount =
useUserStore((state) => state.userAccount?.wallet.spent) ?? 0;
const userId = useUserStore((state) => state.user?._id) ?? "";
const userPrivilegies = useUserStore(store => store.quizUserAccount?.privileges);
const discounts = useDiscounts(userId);
const isUserNko =
useUserStore((state) => state.userAccount?.status) === "nko";
const currentTariffs = useCartTariffs();
const handleCustomBackNavigation = usePrevLocation(location);
const unit: string = String(location.pathname).slice(9);
function handleTariffItemClick(tariffId: string) {
addTariffToCart(tariffId)
.then(() => {
enqueueSnackbar("Тариф добавлен в корзину");
})
.catch((error) => {
const message = getMessageFromFetchError(error);
if (message) enqueueSnackbar(message);
});
}
const filteredTariffs = tariffs.filter((tariff) => {
if (tariff.privileges[0] === undefined || tariff.isDeleted || tariff.isCustom) return false;
if (unit === "time") {
if (selectedItemTime === 0 && tariff.privileges[0].privilegeId === "quizUnlimTime") return true
if (selectedItemTime === 1 && tariff.privileges[0].privilegeId === "squizHideBadge") return true
}
if (unit === "volume") {
if (selectedItemVolume === 0 && tariff.privileges[0].privilegeId === "quizCnt") return true
if (selectedItemVolume === 1 && tariff.privileges[0].privilegeId === "quizManual") return true
}
return false;
});
const createTariffElements = (
filteredTariffs: Tariff[],
addFreeTariff = false
) => {
const isCC = userPrivilegies?.quizManual?.amount !== undefined && userPrivilegies?.quizManual?.amount > 0 && unit === "volume" && selectedItemVolume === 1
const tariffElements = filteredTariffs
.filter((tariff) => tariff.privileges.length > 0)
.map((tariff, index) => {
const { priceBeforeDiscounts, priceAfterDiscounts } = calcTariffPrice(
tariff,
discounts ?? [],
purchasesAmount,
currentTariffs ?? [],
isUserNko,
userId,
);
return (
<TariffCard
key={tariff._id}
discount={
priceBeforeDiscounts - priceAfterDiscounts
? `${(
(priceBeforeDiscounts - priceAfterDiscounts) /
(priceBeforeDiscounts / 100)
).toFixed(0)}%`
: ""
}
icon={
<NumberIcon
number={index + 1}
color={
unit === "time"
? theme.palette.purple.main
: theme.palette.orange.main
}
backgroundColor={unit === "time" ? "#EEE4FC" : "#FEDFD0"}
/>
}
buttonProps={{
text: "Выбрать",
onClick: () => handleTariffItemClick(tariff._id),
}}
sendRequestToCreate={isCC ? RSCOpen : undefined}
headerText={tariff.name}
text={tariff.description || ""}
price={
<>
{priceBeforeDiscounts !== priceAfterDiscounts && (
<Typography variant="oldPrice">
{currencyFormatter.format(
Math.trunc(priceBeforeDiscounts) / 100
)}
</Typography>
)}
<Typography variant="price">
{currencyFormatter.format(
Math.trunc(priceAfterDiscounts) / 100
)}
</Typography>
</>
}
/>
);
});
if (addFreeTariff) {
if (tariffElements.length < 6)
tariffElements.push(<FreeTariffCard key="free_tariff_card" />);
else
tariffElements.splice(5, 0, <FreeTariffCard key="free_tariff_card" />);
}
return tariffElements;
};
return (
<SectionWrapper
maxWidth="lg"
sx={{
mt: "20px",
mb: upMd ? "100px" : "63px",
px: isTablet ? (isMobile ? "18px" : "40px") : "20px",
display: "flex",
flexDirection: "column",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
{isMobile && (
<IconButton
onClick={handleCustomBackNavigation}
sx={{
p: 0,
height: "28px",
width: "28px",
color: "black",
marginRight: "10px",
}}
>
<ArrowBackIcon />
</IconButton>
)}
<Typography
sx={{
marginBottom: "23px",
mt: "20px",
fontSize: isMobile ? "24px" : "36px",
fontWeight: "500",
}}
>
{StepperText[unit]}
</Typography>
</Box>
{unit === "time" && (
<>
{isMobile ? (
<Select
items={subPagesTime}
selectedItem={selectedItemTime}
setSelectedItem={setSelectedItemTime}
/>
) : (
<Tabs
items={subPagesTime}
selectedItem={selectedItemTime}
setSelectedItem={setSelectedItemTime}
/>
)}
</>
)}
{unit === "volume" && (
<>
{isMobile ? (
<Select
items={subPagesVolume}
selectedItem={selectedItemVolume}
setSelectedItem={setSelectedItemVolume}
/>
) : (
<Tabs
items={subPagesVolume}
selectedItem={selectedItemVolume}
setSelectedItem={setSelectedItemVolume}
/>
)}
</>
)}
<Box
sx={{
justifyContent: "left",
mt: "40px",
mb: "30px",
display: "grid",
gap: "40px",
gridTemplateColumns: `repeat(auto-fit, minmax(300px, ${
isTablet ? "436px" : "360px"
}))`,
}}
>
{createTariffElements(filteredTariffs, unit === "time" || (unit === "volume" && selectedItemVolume !== 1))}
</Box>
{/*{recentlyPurchased.length > 0 && (*/}
{/* <>*/}
{/* <Typography*/}
{/* sx={{*/}
{/* mt: "40px",*/}
{/* fontSize: isMobile ? "24px" : "36px",*/}
{/* fontWeight: "500",*/}
{/* }}*/}
{/* >*/}
{/* Ранее вы*/}
{/* </Typography>*/}
{/* <Slider items={createTariffElements(recentlyPurchased)} />*/}
{/* </>*/}
{/*)}*/}
</SectionWrapper>
);
}
export default withErrorBoundary(TariffPage, {
fallback: (
<Typography mt="8px" textAlign="center">
Ошибка загрузки тарифов
</Typography>
),
onError: handleComponentError,
});