frontPanel/src/pages/Tariffs/Tariffs.tsx
2024-04-06 02:02:58 +03:00

413 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 { clearAuthToken, makeRequest, useToken } from "@frontend/kitui";
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";
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();
const [openModal, setOpenModal] = useState({});
const [cash, setCash] = useState("0");
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 { tariffs, totalPages } = await makeRequest<
never,
GetTariffsResponse
>({
method: "GET",
url: process.env.REACT_APP_DOMAIN + "/strator/tariff?page=1&limit=100",
});
tariffsList.push(...tariffs);
for (let page = 2; page <= totalPages; page += 1) {
const tariffsResult = await makeRequest<never, GetTariffsResponse>({
method: "GET",
url:
process.env.REACT_APP_DOMAIN +
`/strator/tariff?page=${page}&limit=100`,
});
tariffsList.push(...tariffsResult.tariffs);
}
return tariffsList;
};
useEffect(() => {
const get = async () => {
const user = await makeRequest({
method: "GET",
url: process.env.REACT_APP_DOMAIN + "/customer/account",
});
const tariffsList = await getTariffsList();
const discounts = await makeRequest({
method: "GET",
url: `${process.env.REACT_APP_DOMAIN}/price/discount/user/${userId}`,
});
setUser(user);
setTariffs(tariffsList);
setDiscounts(discounts.Discounts);
let c = currencyFormatter.format(Number(user.wallet.cash) / 100);
setCash(c);
};
get();
}, []);
if (!user || !tariffs || !discounts) return <LoadingPage />;
const openModalHC = (tariffInfo: any) => setOpenModal(tariffInfo);
const tryBuy = async ({ id, price }: { id: string; price: number }) => {
console.log("цена", price)
console.log("мои деньги", (user.wallet.cash / 100))
openModalHC({});
//Если в корзине что-то было - выкладываем содержимое и запоминаем чо там лежало
if (user.cart.length > 0) {
outCart(user.cart);
}
//Добавляем желаемый тариф в корзину
await makeRequest({
method: "PATCH",
url: process.env.REACT_APP_DOMAIN + `/customer/cart?id=${id}`,
});
//Если нам хватает денежек - покупаем тариф
if ((price * 100) <= user.wallet.cash) {
try {
const data = await makeRequest({
method: "POST",
url: process.env.REACT_APP_DOMAIN + "/customer/cart/pay",
});
setCash(currencyFormatter.format(Number(data.wallet.cash) / 100));
enqueueSnackbar("Тариф успешно приобретён");
} catch (e) {
enqueueSnackbar("Произошла ошибка. Попробуйте позже");
}
//Развращаем товары в корзину
inCart();
} else {
//Деняк не хватило
// history.pushState({}, null, "https://hub.pena.digital/wallet?action=squizpay");
var link = document.createElement("a");
link.href = `https://${isTestServer ? "s" : ""}hub.pena.digital/quizpayment?action=squizpay&dif=${
Math.floor((price * 100) - Math.floor(Number(user.wallet.cash)))
}&data=${token}&userid=${userId}`;
document.body.appendChild(link);
link.click();
}
};
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 handleLogoutClick() {
const [, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
cleanAuthTicketData();
clearAuthToken();
clearUserData();
clearQuizData();
navigate("/");
}
function handleApplyPromocode() {
if (!promocodeField) return;
activatePromocode(promocodeField)
.then((response) => {
enqueueSnackbar(response);
})
.catch((error) => {
enqueueSnackbar(error.message);
});
}
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 ? (cash.length > 9 ? "13px" : "16px") : "16px"}
>
{cash}
</Typography>
</Box>
<LogoutButton
onClick={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: "100%",
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) => {
try {
await makeRequest({
method: "PATCH",
url: process.env.REACT_APP_DOMAIN + `/customer/cart?id=${id}`,
});
let index = saveCart.indexOf("green");
if (index !== -1) {
saveCart.splice(index, 1);
}
localStorage.setItem("saveCart", JSON.stringify(saveCart));
} catch (e) {
console.log("Я не смог добавить тариф в корзину :( " + id);
}
});
} else {
localStorage.setItem("saveCart", "[]");
}
};
const outCart = (cart: string[]) => {
//Сделаем муторно и подольше, зато при прерывании сессии данные потеряются минимально
cart.forEach(async (id: string) => {
try {
await makeRequest({
method: "DELETE",
url: process.env.REACT_APP_DOMAIN + `/customer/cart?id=${id}`,
});
let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]");
saveCart = saveCart.push(id);
localStorage.setItem("saveCart", JSON.stringify(saveCart));
} catch (e) {
console.log("Я не смог удалить из корзины тариф :(");
}
});
};