front-hub/src/pages/Tariffs/TariffsPage.tsx

210 lines
7.6 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 { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material";
import SectionWrapper from "@components/SectionWrapper";
import { useTariffStore } from "@root/stores/tariffs";
import { enqueueSnackbar } from "notistack";
import { Select } from "@root/components/Select";
import { Tabs } from "@root/components/Tabs";
import TariffCard from "./TariffCard";
import NumberIcon from "@root/components/NumberIcon";
import { currencyFormatter } from "@root/utils/currencyFormatter";
import { calcIndividualTariffPrices } from "@root/utils/calcTariffPrices";
import { Tariff, getMessageFromFetchError } from "@frontend/kitui";
import FreeTariffCard from "./FreeTariffCard";
import { addTariffToCart, useUserStore } from "@root/stores/user";
import { useDiscountStore } from "@root/stores/discounts";
import { Slider } from "./slider";
import { useCartStore } from "@root/stores/cart";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation";
import { withErrorBoundary } from "react-error-boundary";
import { handleComponentError } from "@root/utils/handleComponentError";
import { useHistoryStore } from "@root/stores/history";
import { useRecentlyPurchasedTariffs } from "@utils/hooks/useRecentlyPurchasedTariffs";
const subPages = ["Шаблонизатор" , "Опросник"/* , "Сокращатель ссылок" */];
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 [selectedItem, setSelectedItem] = useState<number>(0);
const discounts = useDiscountStore((state) => state.discounts);
const purchasesAmount = useUserStore((state) => state.userAccount?.wallet.purchasesAmount) ?? 0;
const cartTariffMap = useCartStore((state) => state.cartTariffMap);
const isUserNko = useUserStore((state) => state.userAccount?.status) === "nko";
const historyData = useHistoryStore((state) => state.history);
const { recentlyPurchased } = useRecentlyPurchasedTariffs();
const handleCustomBackNavigation = usePrevLocation(location);
const unit: string = String(location.pathname).slice(9);
const currentTariffs = Object.values(cartTariffMap).filter((tariff): tariff is Tariff => typeof tariff === "object");
function handleTariffItemClick(tariffId: string) {
addTariffToCart(tariffId)
.then(() => {
enqueueSnackbar("Тариф добавлен в корзину");
})
.catch((error) => {
const message = getMessageFromFetchError(error);
if (message) enqueueSnackbar(message);
});
}
const filteredTariffs = tariffs.filter((tariff) => {
return (
tariff.privileges.map((p) => p.type).includes("day") === (unit === "time") &&
!tariff.isDeleted &&
!tariff.isCustom
);
});
const isCustomTariffs = tariffs.filter((tariff) => {
return (
tariff.privileges.map((p) => p.type).includes("day") === (unit === "time") && !tariff.isDeleted && tariff.isCustom
);
});
const tariffsFromHistory = tariffs.filter((tariff) => {
if (!historyData) return false;
const historyTariffIds = historyData.map((historyRecord) => (historyRecord.rawDetails[0] as any).Value[0][0].Value);
return historyTariffIds.includes(tariff._id);
});
const createTariffElements = (filteredTariffs: Tariff[], addFreeTariff = false) => {
const tariffElements = filteredTariffs
.filter((tariff) => tariff.privileges.length > 0)
.map((tariff, index) => {
const { priceBeforeDiscounts, priceAfterDiscounts } = calcIndividualTariffPrices(
tariff,
discounts,
purchasesAmount,
currentTariffs,
isUserNko
);
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),
}}
headerText={tariff.name}
text={tariff.description ? tariff.description : tariff.privileges.map((p) => `${p.name} - ${p.amount}`)}
price={
<>
{priceBeforeDiscounts !== priceAfterDiscounts && (
<Typography variant="oldPrice">{currencyFormatter.format(priceBeforeDiscounts / 100)}</Typography>
)}
<Typography variant="price">{currencyFormatter.format(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;
};
console.log(recentlyPurchased)
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>
{isMobile ? (
<Select items={subPages} selectedItem={selectedItem} setSelectedItem={setSelectedItem} />
) : (
<Tabs items={subPages} selectedItem={selectedItem} setSelectedItem={setSelectedItem} />
)}
<Box
sx={{
justifyContent: "left",
mt: "40px",
mb: "30px",
display: "grid",
gap: "40px",
gridTemplateColumns: `repeat(auto-fit, minmax(300px, ${isTablet ? "436px" : "360px"}))`,
}}
>
{createTariffElements(filteredTariffs, true)}
</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,
});