frontPanel/src/pages/Tariffs/Tariffs.tsx

413 lines
12 KiB
TypeScript
Raw Normal View History

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";
2024-03-22 19:01:48 +00:00
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: "Доп. услуги",
};
2024-01-09 12:00:42 +00:00
function TariffPage() {
const theme = useTheme();
const token = useToken();
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(600));
2024-01-28 20:08:06 +00:00
const userId = useUserStore((state) => state.userId);
const navigate = useNavigate();
2024-01-09 12:00:42 +00:00
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();
2024-03-22 19:01:48 +00:00
const [promocodeField, setPromocodeField] = useState<string>("");
2024-01-09 12:00:42 +00:00
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",
2024-01-09 12:00:42 +00:00
});
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`,
2024-01-09 12:00:42 +00:00
});
tariffsList.push(...tariffsResult.tariffs);
2024-01-09 12:00:42 +00:00
}
return tariffsList;
};
useEffect(() => {
const get = async () => {
const user = await makeRequest({
method: "GET",
url: process.env.REACT_APP_DOMAIN + "/customer/account",
});
2024-01-09 12:00:42 +00:00
const tariffsList = await getTariffsList();
const discounts = await makeRequest({
method: "GET",
2024-04-04 00:10:08 +00:00
url: `${process.env.REACT_APP_DOMAIN}/price/discount/user/${userId}`,
});
setUser(user);
2024-01-09 12:00:42 +00:00
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");
2024-03-19 13:52:33 +00:00
link.href = `https://${isTestServer ? "s" : ""}hub.pena.digital/quizpayment?action=squizpay&dif=${
2024-04-05 22:47:40 +00:00
Math.floor((price * 100) - Math.floor(Number(user.wallet.cash)))
2024-04-01 14:49:00 +00:00
}&data=${token}&userid=${userId}`;
document.body.appendChild(link);
link.click();
}
};
2024-01-09 12:00:42 +00:00
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("/");
}
2024-03-22 19:01:48 +00:00
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" }}>
2024-03-19 06:56:21 +00:00
<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>
2024-03-22 19:01:48 +00:00
<Box
sx={{
p: "25px",
pb: 0,
}}
>
<CollapsiblePromocodeField
fieldValue={promocodeField}
onFieldChange={setPromocodeField}
onPromocodeApply={handleApplyPromocode}
/>
</Box>
2024-01-16 12:28:30 +00:00
<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"
>
2024-04-05 23:02:58 +00:00
Вы подтверждаете платёж в сумму {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("Я не смог удалить из корзины тариф :(");
}
});
};