343 lines
10 KiB
TypeScript
343 lines
10 KiB
TypeScript
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||
import { makeRequest, useToken } from "@frontend/kitui";
|
||
import { useEffect, useState } from "react";
|
||
import type { GetTariffsResponse } from "@model/tariff";
|
||
import { clearAuthToken } from "@frontend/kitui";
|
||
import { logout } from "@api/auth";
|
||
import ArrowDown from "../../assets/icons/ArrowDownIcon";
|
||
|
||
import {
|
||
Box,
|
||
Button,
|
||
Container,
|
||
Modal,
|
||
Paper,
|
||
Typography,
|
||
useMediaQuery,
|
||
useTheme,
|
||
IconButton,
|
||
} from "@mui/material";
|
||
import { enqueueSnackbar } from "notistack";
|
||
import { getMessageFromFetchError } from "@frontend/kitui";
|
||
import { withErrorBoundary } from "react-error-boundary";
|
||
import { createTariffElements } from "./tariffsUtils/createTariffElements";
|
||
import HeaderFull from "@ui_kit/Header/HeaderFull";
|
||
import Logotip from "../../pages/Landing/images/icons/QuizLogo";
|
||
import { LogoutButton } from "@ui_kit/LogoutButton";
|
||
import { clearUserData, useUserStore } from "@root/user";
|
||
import ArrowLeft from "@icons/questionsPage/arrowLeft";
|
||
import { currencyFormatter } from "./tariffsUtils/currencyFormatter";
|
||
|
||
import type { Tariff } from "@frontend/kitui";
|
||
import { Tabs } from "./Tabs";
|
||
import { cleanAuthTicketData } from "@root/ticket";
|
||
import { useDomainDefine } from "@utils/hooks/useDomainDefine";
|
||
|
||
const StepperText: Record<string, string> = {
|
||
count: "Тарифы на объём",
|
||
day: "Тарифы на время",
|
||
};
|
||
|
||
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 location = useLocation();
|
||
const navigate = useNavigate();
|
||
|
||
const [tariffs, setTariffs] = useState<Tariff[]>([]);
|
||
const [user, setUser] = useState();
|
||
const [discounts, setDiscounts] = useState();
|
||
const [cartTariffMap, setCartTariffMap] = useState();
|
||
const [openModal, setOpenModal] = useState({});
|
||
const [cash, setCash] = useState("0");
|
||
const [selectedItem, setSelectedItem] = useState<"count" | "day">("count");
|
||
const { isTestServer } = useDomainDefine();
|
||
|
||
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/discounts",
|
||
});
|
||
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 }) => {
|
||
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 <= 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=${
|
||
(price - Number(user.wallet.cash)) * 100
|
||
}&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
|
||
);
|
||
});
|
||
|
||
async function handleLogoutClick() {
|
||
const [, logoutError] = await logout();
|
||
|
||
if (logoutError) {
|
||
return enqueueSnackbar(logoutError);
|
||
}
|
||
|
||
cleanAuthTicketData();
|
||
clearAuthToken();
|
||
clearUserData();
|
||
navigate("/");
|
||
}
|
||
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" }} onClick={() => console.log(cash)}>
|
||
<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>
|
||
<Tabs
|
||
names={Object.values(StepperText)}
|
||
items={Object.keys(StepperText)}
|
||
selectedItem={selectedItem}
|
||
setSelectedItem={setSelectedItem}
|
||
/>
|
||
|
||
<Box
|
||
sx={{
|
||
justifyContent: "left",
|
||
display: "grid",
|
||
gap: "40px",
|
||
p: "20px",
|
||
gridTemplateColumns: `repeat(auto-fit, minmax(300px, ${
|
||
isTablet ? "436px" : "360px"
|
||
}))`,
|
||
}}
|
||
>
|
||
{createTariffElements(
|
||
filteredTariffs,
|
||
true,
|
||
user,
|
||
discounts,
|
||
openModalHC,
|
||
)}
|
||
</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} ₽
|
||
</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("Я не смог удалить из корзины тариф :(");
|
||
}
|
||
});
|
||
};
|