frontPanel/src/pages/Tariffs/Tariffs.tsx

444 lines
12 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 { logout } from "@api/auth";
import { activatePromocode } from "@api/promocode";
import type { Tariff } from "@frontend/kitui";
import { useToken } from "@frontend/kitui";
import { makeRequest } from "@api/makeRequest";
import ArrowLeft from "@icons/questionsPage/arrowLeft";
import type { GetTariffsResponse } from "@model/tariff";
import {
Box,
Button,
Container,
IconButton,
Modal,
Paper,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import { clearQuizData } from "@root/quizes/store";
import { cleanAuthTicketData } from "@root/ticket";
import { clearUserData, useUserStore } from "@root/user";
import { LogoutButton } from "@ui_kit/LogoutButton";
import { useDomainDefine } from "@utils/hooks/useDomainDefine";
import { enqueueSnackbar } from "notistack";
import { useEffect, useState } from "react";
import { withErrorBoundary } from "react-error-boundary";
import { Link, useNavigate } from "react-router-dom";
import Logotip from "../../pages/Landing/images/icons/QuizLogo";
import CollapsiblePromocodeField from "./CollapsiblePromocodeField";
import { Tabs } from "./Tabs";
import { createTariffElements } from "./tariffsUtils/createTariffElements";
import { currencyFormatter } from "./tariffsUtils/currencyFormatter";
import { useWallet, setCash } from "@root/cash";
import { handleLogoutClick } from "@utils/HandleLogoutClick";
import { getDiscounts } from "@api/discounts";
import { cartApi } from "@api/cart";
import { getUser } from "@api/user";
import { getTariffs } from "@api/tariff";
import type { Discount } from "@model/discounts";
const StepperText: Record<string, string> = {
day: "Тарифы на время",
count: "Тарифы на объём",
dop: "Доп. услуги",
};
function TariffPage() {
const theme = useTheme();
const token = useToken();
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const userId = useUserStore((state) => state.userId);
const navigate = useNavigate();
const [tariffs, setTariffs] = useState<Tariff[]>([]);
const [user, setUser] = useState();
const [discounts, setDiscounts] = useState<Discount[]>([]);
const [openModal, setOpenModal] = useState({});
const { cashString, cashCop, cashRub } = useWallet();
const [selectedItem, setSelectedItem] = useState<"count" | "day" | "dop">(
"day",
);
const { isTestServer } = useDomainDefine();
const [promocodeField, setPromocodeField] = useState<string>("");
const getTariffsList = async (): Promise<Tariff[]> => {
const tariffsList: Tariff[] = [];
const [tariffsResponse, tariffsResponseError] = await getTariffs(1);
if (tariffsResponseError || !tariffsResponse) {
return tariffsList;
}
tariffsList.push(...tariffsResponse.tariffs);
for (let page = 2; page <= tariffsResponse.totalPages; page += 1) {
const [tariffsResult] = await getTariffs(1);
if (tariffsResult) {
tariffsList.push(...tariffsResult.tariffs);
}
}
return tariffsList;
};
useEffect(() => {
const get = async () => {
const [user, userError] = await getUser();
if (userError) {
return;
}
const tariffsList = await getTariffsList();
if (userId) {
const [discounts] = await getDiscounts(userId);
if (discounts?.length) {
setDiscounts(discounts);
}
}
setUser(user);
setTariffs(tariffsList);
let cs = currencyFormatter.format(Number(user.wallet.cash) / 100);
let cc = Number(user.wallet.cash);
let cr = Number(user.wallet.cash) / 100;
setCash(cs, cc, cr);
};
get();
}, []);
if (!user || !tariffs || !discounts) return <LoadingPage />;
const openModalHC = (tariffInfo: any) => setOpenModal(tariffInfo);
const tryBuy = async ({ id, price }: { id: string; price: number }) => {
openModalHC({});
//Если в корзине что-то было - выкладываем содержимое и запоминаем чо там лежало
if (user.cart.length > 0) {
outCart(user.cart);
}
//Добавляем желаемый тариф в корзину
const [_, addError] = await cartApi.add(id);
if (addError) {
//Развращаем товары в корзину
inCart();
return;
}
//Если нам хватает денежек - покупаем тариф
const [data, payError] = await cartApi.pay();
if (payError || !data) {
//если денег не хватило
if (payError?.includes("insufficient funds") || payError?.includes("Payment Required")) {
let cashDif = Number(payError.split(":")[1]);
console.log(payError)
console.log(cashDif)
var link = document.createElement("a");
link.href = `https://${isTestServer ? "s" : ""}hub.pena.digital/quizpayment?action=squizpay&dif=${cashDif}&data=${token}&userid=${userId}`;
document.body.appendChild(link);
console.log(link)
// link.click();
return;
}
//другая ошибка
enqueueSnackbar("Произошла ошибка. Попробуйте позже");
return;
}
setCash(
currencyFormatter.format(Number(data.wallet.cash) / 100),
Number(data.wallet.cash),
Number(data.wallet.cash) / 100,
);
enqueueSnackbar("Тариф успешно приобретён");
//Развращаем товары в корзину
inCart();
};
const filteredTariffs = tariffs.filter((tariff) => {
return (
tariff.privileges[0].serviceKey === "squiz" &&
!tariff.isDeleted &&
!tariff.isCustom &&
tariff.privileges[0]?.type === selectedItem
);
});
const filteredBadgeTariffs = tariffs.filter((tariff) => {
return (
tariff.privileges[0].serviceKey === "squiz" &&
!tariff.isDeleted &&
!tariff.isCustom &&
tariff.privileges[0].privilegeId === "squizHideBadge" &&
tariff.privileges[0]?.type === "day"
);
});
const filteredBaseTariffs = filteredTariffs.filter((tariff) => {
return tariff.privileges[0].privilegeId !== "squizHideBadge";
});
async function handleApplyPromocode() {
if (!promocodeField) return;
const [greetings, error] = await activatePromocode(promocodeField);
if (error) {
enqueueSnackbar(error);
return;
}
enqueueSnackbar(greetings);
if (!userId) {
return;
}
const [discounts, discountsError] = await getDiscounts(userId);
if (discountsError) {
throw new Error(discountsError);
}
if (discounts?.length) {
setDiscounts(discounts);
}
}
return (
<>
<Container
component="nav"
disableGutters
maxWidth={false}
sx={{
px: "16px",
display: "flex",
height: "80px",
alignItems: "center",
gap: isMobile ? "7px" : isTablet ? "20px" : "60px",
flexDirection: "row",
justifyContent: "space-between",
bgcolor: "white",
borderBottom: "1px solid #E3E3E3",
}}
>
<Link to="/">
<Logotip width={124} />
</Link>
<IconButton onClick={() => navigate("/list")}>
<ArrowLeft color="black" />
</IconButton>
<Box sx={{ display: "flex", ml: "auto" }}>
<Box sx={{ whiteSpace: "nowrap" }}>
<Typography
sx={{
fontSize: "12px",
lineHeight: "14px",
color: "gray",
}}
>
Мой баланс
</Typography>
<Typography
variant="body2"
color={"#7e2aea"}
fontSize={
isMobile ? (cashString.length > 9 ? "13px" : "16px") : "16px"
}
>
{cashString}
</Typography>
</Box>
<LogoutButton
onClick={() => {
navigate("/");
handleLogoutClick();
}}
sx={{
ml: "20px",
}}
/>
</Box>
</Container>
<Box
sx={{
p: "25px",
pb: 0,
}}
>
<CollapsiblePromocodeField
fieldValue={promocodeField}
onFieldChange={setPromocodeField}
onPromocodeApply={handleApplyPromocode}
/>
</Box>
<Tabs
names={Object.values(StepperText)}
items={Object.keys(StepperText)}
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
/>
<Box
sx={{
justifyContent: "left",
display: selectedItem === "dop" ? "flex" : "grid",
gap: "40px",
p: "20px",
gridTemplateColumns: `repeat(auto-fit, minmax(300px, ${
isTablet ? "436px" : "360px"
}))`,
flexDirection: selectedItem === "dop" ? "column" : undefined,
}}
>
{selectedItem === "day" &&
createTariffElements(
filteredBaseTariffs,
true,
user,
discounts,
openModalHC,
)}
{selectedItem === "count" &&
createTariffElements(
filteredTariffs,
true,
user,
discounts,
openModalHC,
)}
{selectedItem === "dop" && (
<>
<Typography fontWeight={500}>Убрать логотип "PenaQuiz"</Typography>
<Box
sx={{
justifyContent: "left",
display: "grid",
gap: "40px",
gridTemplateColumns: `repeat(auto-fit, minmax(300px, ${
isTablet ? "436px" : "360px"
}))`,
}}
>
{createTariffElements(
filteredBadgeTariffs,
false,
user,
discounts,
openModalHC,
)}
</Box>
</>
)}
</Box>
<Modal
open={Object.values(openModal).length > 0}
onClose={() => setOpenModal({})}
>
<Paper
sx={{
position: "absolute" as "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
boxShadow: 24,
p: 4,
display: "flex",
justifyContent: "center",
flexDirection: "column",
}}
>
<Typography
id="modal-modal-title"
variant="h6"
component="h2"
mb="20px"
>
Вы подтверждаете платёж в сумму{" "}
{openModal.price ? openModal.price.toFixed(2) : 0}
</Typography>
<Button variant="contained" onClick={() => tryBuy(openModal)}>
купить
</Button>
</Paper>
</Modal>
</>
);
}
export const Tariffs = withErrorBoundary(TariffPage, {
fallback: (
<Typography mt="8px" textAlign="center">
Ошибка загрузки тарифов
</Typography>
),
onError: () => {},
});
const LoadingPage = () => (
<Box
sx={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<Typography sx={{ textAlign: "center" }}>
{"Подождите, пожалуйста, идёт загрузка"}
</Typography>
</Box>
);
export const inCart = () => {
let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]");
if (Array.isArray(saveCart)) {
saveCart.forEach(async (id: string) => {
const [_, addError] = await cartApi.add(id);
if (addError) {
console.error(addError);
} else {
let index = saveCart.indexOf("green");
if (index !== -1) {
saveCart.splice(index, 1);
}
localStorage.setItem("saveCart", JSON.stringify(saveCart));
}
});
} else {
localStorage.setItem("saveCart", "[]");
}
};
const outCart = (cart: string[]) => {
//Сделаем муторно и подольше, зато при прерывании сессии данные потеряются минимально
cart.forEach(async (id: string) => {
const [_, deleteError] = await cartApi.delete(id);
if (deleteError) {
console.error(deleteError);
return;
}
let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]") || [];
saveCart = saveCart.push(id);
localStorage.setItem("saveCart", JSON.stringify(saveCart));
});
};