Merge branch 'dev' into 'staging'

Dev

See merge request frontend/marketplace!228
This commit is contained in:
Nastya 2024-08-18 21:47:14 +00:00
commit 841352a698
21 changed files with 728 additions and 78 deletions

@ -19,6 +19,7 @@
"@frontend/kitui": "^1.0.85",
"@mui/icons-material": "^5.10.14",
"@mui/material": "^5.10.14",
"@mui/x-date-pickers": "^7.13.0",
"@popperjs/core": "^2.11.8",
"axios": "^1.4.0",
"buffer": "^6.0.3",

@ -8,6 +8,7 @@ import type {
} from "@root/model/privilege";
import type { GetTariffsResponse } from "@root/model/tariff";
import { removeTariffFromCart } from "@root/stores/user";
import axios from "axios";
interface CreateTariffBody {
name: string;
@ -134,3 +135,24 @@ export const getTariffArray = async (tariffIds: string[] | undefined) => {
return tariffs;
};
const apiUrl = process.env.REACT_APP_DOMAIN + "/requestquiz";
export async function sendContactFormRequest(body: {
contact: string;
whoami: string;
}) {
try {
const a = await axios(apiUrl + "/callme", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
});
return [a];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка при отправке запроса. ${error}`];
}
}

@ -23,12 +23,20 @@ export const sendPayment = async ({
body,
fromSquiz,
paymentPurpose,
cc
}: {
userId: string;
body: PaymentBody;
fromSquiz: boolean;
paymentPurpose: "paycart" | "replenishwallet";
cc?: boolean
}): Promise<[SendPaymentResponse | null, string?]> => {
let returnLink = `${isLocalhost ? "localhost:3000" : `https://${isStaging}hub.pena.digital`}/afterpay?from=${
fromSquiz ? "quiz" : "hub"
}&purpose=${paymentPurpose}&userid=${userId}`
if (cc) returnLink = returnLink + "&cc=true"
const reqeustBody = {
currency: "RUB",
bankCard: {
@ -40,9 +48,7 @@ export const sendPayment = async ({
},
phoneNumber: "79000000000",
login: "login_test",
returnUrl: `${isLocalhost ? "localhost:3000" : `https://${isStaging}hub.pena.digital`}/afterpay?from=${
fromSquiz ? "quiz" : "hub"
}&purpose=${paymentPurpose}&userid=${userId}`,
returnUrl: returnLink,
...body,
};

@ -0,0 +1,38 @@
import { useLocation } from "react-router-dom";
import { Box, SxProps, Theme } from "@mui/material";
interface Props {
sx?: SxProps<Theme>;
}
export default function CloseIcon({ sx }: Props) {
const location = useLocation();
return (
<Box
sx={{
width: "30px",
height: "30px",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexShrink: 0,
"&:hover path": {
stroke: "#7E2AEA",
},
...sx
}}
>
<svg
width="26"
height="26"
viewBox="0 0 26 26"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L25 25M1 25L25 1"
stroke={location.pathname === "/" ? "white" : "black"}
/>
</svg>
</Box>
);
}

@ -0,0 +1,152 @@
import type { ChangeEvent, FocusEvent, KeyboardEvent } from "react";
import React, { useEffect, useState } from "react";
import type { InputProps, SxProps, Theme } from "@mui/material";
import {
Box,
FormControl,
Input,
InputLabel,
Typography,
useTheme,
} from "@mui/material";
interface CustomTextFieldProps {
placeholder: string;
id?: string;
value?: string;
error?: string;
emptyError?: boolean;
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
text?: string;
maxLength?: number;
sx?: SxProps<Theme>;
sxForm?: SxProps<Theme>;
InputProps?: Partial<InputProps>;
type?: string;
rows?: number;
className?: string;
disabled?: boolean;
}
export default function CustomTextField({
placeholder,
id,
value = "",
onChange,
onKeyDown,
onBlur,
text,
sx,
error,
emptyError,
InputProps,
maxLength = 200,
type = "",
rows = 0,
sxForm,
className,
disabled,
}: CustomTextFieldProps) {
const theme = useTheme();
const [inputValue, setInputValue] = useState("");
const [isInputActive, setIsInputActive] = useState(false);
useEffect(() => {
setInputValue(value);
}, [value]);
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.value.length <= maxLength) {
const inputValue = event.target.value;
if (type === "number") {
setInputValue(inputValue.replace(/\D/g, ""));
} else {
setInputValue(inputValue);
}
if (onChange) {
onChange(event);
}
}
};
const handleInputFocus = () => {
setIsInputActive(true);
};
const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {
setIsInputActive(false);
if (onBlur) {
onBlur(event);
}
};
return (
<FormControl
fullWidth
variant="standard"
sx={{ p: 0, ...sxForm }}
className={className || ""}
>
{error && (
<InputLabel
sx={{
fontSize: "13.5px",
marginTop: "3px",
}}
>
{error}
</InputLabel>
)}
<Input
id={id}
defaultValue={text}
fullWidth
value={inputValue}
placeholder={placeholder}
onChange={handleInputChange}
error={!!error || emptyError}
onFocus={handleInputFocus}
onBlur={handleInputBlur}
onKeyDown={onKeyDown}
multiline={rows > 0}
rows={rows}
disabled={disabled}
disableUnderline
sx={{
maxLength: maxLength,
borderRadius: "10px",
fontSize: "18px",
lineHeight: "21px",
p: "13px",
border: `${isInputActive ? "black 2px" : "#9A9AAF 1px"} solid`,
backgroundColor: theme.palette.background.default,
height: "48px",
...sx,
}}
data-cy="textfield"
/>
{isInputActive && inputValue.length >= maxLength - 7 && (
<Box
sx={{
display: "flex",
marginTop: "5px",
marginLeft: "auto",
position: "absolute",
bottom: "-25px",
right: "0",
}}
>
<Typography fontSize="14px">{inputValue.length}</Typography>
<span>/</span>
<Typography fontSize="14px">{maxLength}</Typography>
</Box>
)}
</FormControl>
);
}

@ -0,0 +1,50 @@
import { IconButton, SxProps } from "@mui/material";
type InfoProps = {
width?: number;
height?: number;
sx?: SxProps;
onClick?: any;
className?: string;
color?: string;
};
export default function InfoButton({
width = 20,
height = 20,
sx,
onClick,
className,
color = "#7e2aea",
}: InfoProps) {
return (
<IconButton sx={sx} className={className} onClick={onClick}>
<svg
width={width}
height={height}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10 19C14.9706 19 19 14.9706 19 10C19 5.02944 14.9706 1 10 1C5.02944 1 1 5.02944 1 10C1 14.9706 5.02944 19 10 19Z"
stroke={color}
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M9.25 9.25H10V14.5H10.75"
stroke={color}
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M9.8125 7C10.4338 7 10.9375 6.49632 10.9375 5.875C10.9375 5.25368 10.4338 4.75 9.8125 4.75C9.19118 4.75 8.6875 5.25368 8.6875 5.875C8.6875 6.49632 9.19118 7 9.8125 7Z"
fill={color}
/>
</svg>
</IconButton>
);
}

@ -72,10 +72,10 @@ export const Select = ({ items, selectedItem, setSelectedItem }: SelectProps) =>
className="select"
value=""
open={opened}
onClick={() => setOpened((isOpened) => !isOpened)}
MenuProps={{ disablePortal: true }}
sx={{ width: "100%",zIndex: 1, }}
onChange={selectItem}
onClick={() => setOpened((isOpened) => !isOpened)}
>
{items.map((item, index) => (
<MenuItem key={item + index} value={index} sx={{ padding: "12px" }}>

@ -9,6 +9,7 @@ import {
useNavigate,
} from "react-router-dom";
import { CssBaseline, ThemeProvider } from "@mui/material";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
import Faq from "./pages/Faq/Faq";
import Wallet from "./pages/Wallet";
import Payment from "./pages/Payment/Payment";
@ -44,6 +45,7 @@ import {
useUserFetcher,
} from "@frontend/kitui";
import { pdfjs } from "react-pdf";
import { ruRU } from "@mui/x-date-pickers/locales";
import { theme } from "./utils/theme";
import PPofData from "@root/docs/PPofData";
import Docs from "@root/docs/docs";
@ -60,9 +62,12 @@ import { usePipeSubscriber } from "./utils/hooks/usePipeSubscriber";
import moment from "moment";
import { payCart } from "./api/cart";
import { useAfterPay } from "./utils/hooks/useAutoPay";
import { LocalizationProvider } from "@mui/x-date-pickers";
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;
const localeText =
ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
const App = () => {
const location = useLocation();
const user = useUserStore(state => state.user);
@ -213,11 +218,17 @@ const root = ReactDOM.createRoot(
root.render(
// <React.StrictMode>
<ThemeProvider theme={theme}>
<LocalizationProvider
dateAdapter={AdapterMoment}
adapterLocale="ru"
localeText={localeText}
>
<BrowserRouter>
<CssBaseline />
<SnackbarProvider />
<App />
</BrowserRouter>
</LocalizationProvider>
</ThemeProvider>
// </React.StrictMode>
);

@ -63,10 +63,8 @@ export default function DocumentItem({
useEffect(() => {
if (typeof documentUrl === 'string') {
if (!documentUrl.includes("pena.digital")) {
console.log(documentUrl)
fetch(documentUrl)
.then(e => {
console.log(e)
setReadyShowDocument(true)
})
.catch(e => console.log(e))

@ -43,10 +43,8 @@ export default function DocumentUploadItem({
useEffect(() => {
if (typeof urlOrFile === 'string') {
if (!urlOrFile.includes("pena.digital")) {
console.log(documentUrl)
fetch(documentUrl)
.then(e => {
console.log(e)
setReadyShowDocument(true)
})
.catch(e => console.log(e))

@ -21,9 +21,6 @@ export default function UserFields({
const { settingsFields, user } = useUserStore((state) => state)
const a = useUserStore((state) => state)
console.log(a)
console.log(settingsFields)
const textFieldProps = {
gap: upMd ? "16px" : "10px",
color: "#F2F3F7",

@ -17,9 +17,6 @@ export default () => {
const domain = (host.includes("s") ? "s" : "") + from;
const pathname = from.includes("hub") ? "/tariffs" : "/list";
console.log(from, " from")
console.log(`https://${domain}.pena.digital${pathname}?purpose=${purpose}&userid=${userId}`)
document.location.href = `https://${domain}.pena.digital${pathname}?purpose=${purpose}&userid=${userId}`
return <></>;
};

@ -70,9 +70,7 @@ export default function Payment() {
const [paymentValueField, setPaymentValueField] = useState<string>("0");
const [fromSquiz, setIsFromSquiz] = useState<boolean>(false);
console.log("fromSquiz")
console.log(fromSquiz)
const [cc, setCC] = useState<boolean>(false);
const [warnModalOpen, setWarnModalOpen] = useState<boolean>(false);
@ -93,12 +91,8 @@ export default function Payment() {
}
}, [])
console.log(siteReadyPayCart)
console.log(notEnoughMoneyAmount)
//Тут записываем начальную сумму в инпут (если стоит флаг что мы в процессе покупки)
useEffect(() => {
console.log(siteReadyPayCart)
console.log(notEnoughMoneyAmount)
if (siteReadyPayCart !== null && siteReadyPayCart[userId] !== undefined && calcTimeOfReadyPayCart(siteReadyPayCart[userId]))
setPaymentValueField((notEnoughMoneyAmount / 100).toString());//Сколько нехватило на хабе
}, [notEnoughMoneyAmount, siteReadyPayCart])
@ -108,10 +102,9 @@ export default function Payment() {
const params = new URLSearchParams(window.location.search);
const fromSquiz = params.get("action");
const userid = params.get("user");
console.log(fromSquiz)
console.log(fromSquiz === "squizpay")
console.log(userid)
console.log(userid !== null)
const currentCC = params.get("cc");
if (currentCC) setCC(true)
if (fromSquiz === "squizpay" && userid !== null) {
setIsFromSquiz(true);
}
@ -175,6 +168,7 @@ export default function Payment() {
),
},
paymentPurpose: notEnoughMoneyAmount ? "paycart" : "replenishwallet",
cc
});
if (sendPaymentError) {

@ -21,12 +21,12 @@ import { clearCustomTariffs } from "@root/stores/customTariffs";
import { clearTickets } from "@root/stores/tickets";
import { setNotEnoughMoneyAmount, startPayCartProcess } from "@stores/notEnoughMoneyAmount"
console.log("выясняю парамсы")
const params = new URLSearchParams(window.location.search);
let action = params.get("action");
let dif = params.get("dif");
let token = params.get("data");
let userId = params.get("userid");
let currentCC = params.get("cc");
let first = true;
@ -42,7 +42,9 @@ export default function QuizPayment() {
if (fromSquiz === "squizpay") {
setNotEnoughMoneyAmount(Number(params.get("dif") || 0));//Сколько нехватило на квизе
startPayCartProcess(userId)
navigate(`/payment?action=${action}&dif=${dif}&user=${userId}`, {
let link = `/payment?action=${action}&dif=${dif}&user=${userId}`
if (currentCC) link = link + "&cc=true"
navigate(link, {
replace: true,
});
}
@ -53,7 +55,6 @@ export default function QuizPayment() {
if (first) {
console.log("чищу урл")
navigate(`/quizpayment`, {
replace: true,
});
@ -76,22 +77,9 @@ export default function QuizPayment() {
}
// setAuthToken(data.data.accessToken)
console.log("собираюсь задать юзера и токен")
setUserId(userId);
setAuthToken(token);
// useUserFetcher({
// url: process.env.REACT_APP_DOMAIN + `/user/${userId}`,
// userId,
// onNewUser: (user) => {
// setUser(user)
// navigate(`/payment?action=${action}&dif=${dif}`, { replace: true })
// },
// onError: () => { },
// })
return;
})();
} else {

@ -42,8 +42,6 @@ function TariffConstructor() {
}}
>
{Object.entries(customTariffs).filter(([serviceKey]) => serviceKey === "squiz").map(([serviceKey, privileges], index) => {
console.log("privileges")
console.log(privileges)
return (
<Box key={serviceKey}>
<Box

@ -53,8 +53,6 @@ export default function TariffPrivilegeSlider({ privilege }: Props) {
);
function handleSliderChange(measurement: PrivilegeName) {
console.log(measurement)
console.log(sliderSettingsByType)
return (value: number | number[]) => {
if (Number(value) < Number(sliderSettingsByType[measurement]?.min)) {

@ -0,0 +1,316 @@
import { Box, Button, IconButton, Modal, Typography, useMediaQuery, useTheme } from "@mui/material"
import { Form, Formik, useFormik } from "formik"
import CustomTextField from "@components/CustomTextField"
import InfoButton from "@components/InfoButton";
import { sendContactFormRequest } from "@api/tariff"
import { TimePicker } from "@mui/x-date-pickers"
import moment, { Moment } from "moment"
import { enqueueSnackbar } from "notistack"
import { useState } from "react"
import CloseIcon from "@root/assets/Icons/CloseIcon";
interface Props {
open: boolean
onClose: () => void
}
interface Values {
contact: string;
dogiebusiness: string;
imagination: string;
name: string;
time?: Moment | null;
}
const initialValues: Values = {
contact: "",//phone number
// whoami: {},
dogiebusiness: "",
imagination: "",
name: "",
time: null
};
interface FP {
title: string
desc?: string
placeholder: string
value: string
onChange: any
rows?: number
}
const Field = ({
title,
desc,
placeholder,
value,
onChange,
rows,
}: FP) => {
return (
<Box
sx={{
m: "15px 0"
}}
>
<Typography
sx={{
fontSize: "18px",
fontWeight: 500,
lineHeight: "21.33px",
mb: "10px",
}}
>{title}</Typography>
{desc && <Typography
sx={{
fontSize: "18px",
mb: "10px",
color: "#9A9AAF"
}}
>{desc}</Typography>}
<CustomTextField
value={value}
placeholder={placeholder}
maxLength={200}
onChange={onChange}
rows={rows || 0}
sx={rows !== undefined ? { height: "68px" } : {}}
/>
</Box>
)
}
export const ModalRequestCreate = ({
open,
onClose
}: Props) => {
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.down(650));
const [isSending, setIsSending] = useState(false)
if (isSending) return (
<Modal
open={open}
onClose={onClose}
>
<Box sx={{
position: 'absolute' as 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
bgcolor: 'background.paper',
boxShadow: 24,
width: isMobile ? "343px" : "418px",
borderRadius: "10px",
p: "50px"
}}>
<Typography
sx={{
fontSize: "24px",
fontWeight: 500,
lineHeight: "28.44px",
textAlign: "center"
}}
>Спасибо за заявку!</Typography>
<Typography
sx={{
fontSize: "18px",
lineHeight: "21.33px",
color: "#4D4D4D",
m: "5px 0 30px 0"
}}
>С вами свяжутся в течение 24 часов</Typography>
<Button
variant="contained"
fullWidth
onClick={onClose}
sx={{
py: "12px",
"&:hover": {
backgroundColor: "#581CA7",
},
"&:active": {
color: "white",
backgroundColor: "black",
},
}}
>Ок</Button>
</Box>
</Modal>
)
return (
<Modal
open={open}
onClose={onClose}
>
<Box sx={{
position: 'absolute' as 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
bgcolor: 'background.paper',
boxShadow: 24,
width: isMobile ? "344px" : "620px",
borderRadius: "10px"
}}>
<Box>
<Box
sx={{
width: "100%",
height: "68px",
backgroundColor: theme.palette.background.default,
borderRadius: "10px 10px 0 0"
}}
>
<Typography
sx={{
fontSize: "18px",
padding: "20px",
color: "#F2F3F7",
borderRadius: "10px 10px 0 0"
}}
>
Заполните форму, чтобы оставить заявку на создание квиза
</Typography>
</Box>
<IconButton
onClick={onClose}
sx={{
width: "12px",
height: "12px",
position: "absolute",
right: "15px",
top: "15px",
}}
>
<CloseIcon sx={{ width: "12px", height: "12px", transform: "scale(1.5)" }} />
</IconButton>
</Box>
<Box
sx={{
p: "15px 70px 50px 50px",
}}
>
<Formik
initialValues={initialValues}
onSubmit={async (values, formikHelpers) => {
if (values.contact.length < 8) return enqueueSnackbar("Пожалуйста, оставьте контактные данные")
const resp = await sendContactFormRequest({
contact: values.contact,
whoami: JSON.stringify({
dogiebusiness: values.dogiebusiness,
imagination: values.imagination,
name: values.name,
time: moment(values.time).format("hh:mm")
})
})
//@ts-ignore
if (resp[0]?.status === 200) {
enqueueSnackbar("Запрос успешно отправлен")
setIsSending(true)
}
if (resp[1]) {
//@ts-ignore
enqueueSnackbar(resp[1])
}
}}
>
{({ values, isSubmitting, setFieldValue }) => (<>
<Form>
<Field
title="Ваше имя"
placeholder="Иван"
value={values.name}
onChange={({ target }: any) => setFieldValue("name", target.value)}
/>
<Field
title="Какой у вас бизнес?"
placeholder="Логистика"
value={values.dogiebusiness}
onChange={({ target }: any) => setFieldValue("dogiebusiness", target.value)}
/>
<Field
title="Ваши контактные данные"
placeholder="Не менее 8 символов"
value={values.contact}
onChange={({ target }: any) => setFieldValue("contact", target.value)}
desc="(Telegram, WhatsApp, номер телефона)"
/>
<Field
title="Ваши пожелания к квизу"
placeholder="Введите свой текст здесь"
value={values.imagination}
onChange={({ target }: any) => setFieldValue("imagination", target.value)}
rows={2}
/>
<Box
sx={{
m: "15px 0"
}}
>
<Typography
sx={{
fontSize: "18px",
fontWeight: 500,
lineHeight: "21.33px",
mb: "10px",
}}
>Во сколько вам можно позвонить? </Typography>
<Typography
sx={{
fontSize: "18px",
mb: "10px",
color: "#9A9AAF"
}}
>Москва (GMT+3)</Typography>
<TimePicker
onChange={(e) => setFieldValue("time", e)}
ampm={false}
value={values.time}
views={['hours', 'minutes']} format="hh:mm"
/>
</Box>
<Box
sx={{
display: "flex"
}}>
<Button
variant="contained"
fullWidth
type="submit"
disabled={isSubmitting}
sx={{
py: "12px",
"&:hover": {
backgroundColor: "#581CA7",
},
"&:active": {
color: "white",
backgroundColor: "black",
},
}}
>Отправить</Button>
<InfoButton sx={{
ml: "15px",
width: "48px"
}} />
</Box>
</Form>
</>)}
</Formik>
</Box>
</Box>
</Modal >
)
}

@ -28,8 +28,10 @@ import TariffCard from "./TariffCard";
import { useDiscounts } from "@root/api/price";
import { Select } from "@components/Select";
import { Tabs } from "@components/Tabs";
import { ModalRequestCreate } from "./ModalRequestCreate";
const subPages = ["Базовый тариф PenaQuiz", 'Убрать логотип "PenaQuiz"'];
const subPagesTime = ["Базовый тариф PenaQuiz", 'Убрать логотип "PenaQuiz"'];
const subPagesVolume = ["Заявки quiz", 'Заказать создание quiz'];
const StepperText: Record<string, string> = {
volume: "Тарифы на объём",
@ -43,10 +45,13 @@ function TariffPage() {
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const location = useLocation();
const tariffs = useTariffStore((state) => state.tariffs);
const [selectedItem, setSelectedItem] = useState<number>(0);
const [selectedItemTime, setSelectedItemTime] = useState<number>(0);
const [selectedItemVolume, setSelectedItemVolume] = useState<number>(0);
const [isRequestCreate, setIsRequestCreate] = useState(false);
const purchasesAmount =
useUserStore((state) => state.userAccount?.wallet.spent) ?? 0;
const userId = useUserStore((state) => state.user?._id) ?? "";
const userPrivilegies = useUserStore(store => store);
const discounts = useDiscounts(userId);
const isUserNko =
useUserStore((state) => state.userAccount?.status) === "nko";
@ -68,25 +73,14 @@ function TariffPage() {
}
const filteredTariffs = tariffs.filter((tariff) => {
if (tariff.privileges[0] === undefined) return false;
if (
(tariff.privileges[0].type === "day") === (unit === "time") &&
!tariff.isDeleted &&
!tariff.isCustom
) {
if (
((selectedItem === 0 && unit === "time") || unit !== "time") &&
tariff.privileges[0].serviceKey === "squiz" &&
tariff.privileges[0].privilegeId !== "squizHideBadge"
)
return true;
if (tariff.privileges[0] === undefined || tariff.isDeleted || tariff.isCustom) return false;
if (unit === "time") {
if (selectedItemTime === 0 && tariff.privileges[0].privilegeId === "quizUnlimTime") return true
if (selectedItemTime === 1 && tariff.privileges[0].privilegeId === "squizHideBadge") return true
}
if (
selectedItem === 1 &&
unit === "time" &&
tariff.privileges[0].privilegeId === "squizHideBadge"
) {
return true;
if (unit === "volume") {
if (selectedItemVolume === 0 && tariff.privileges[0].privilegeId === "quizCnt") return true
if (selectedItemVolume === 1 && tariff.privileges[0].privilegeId === "quizManual") return true
}
return false;
});
@ -206,15 +200,32 @@ function TariffPage() {
<>
{isMobile ? (
<Select
items={subPages}
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
items={subPagesTime}
selectedItem={selectedItemTime}
setSelectedItem={setSelectedItemTime}
/>
) : (
<Tabs
items={subPages}
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
items={subPagesTime}
selectedItem={selectedItemTime}
setSelectedItem={setSelectedItemTime}
/>
)}
</>
)}
{unit === "volume" && (
<>
{isMobile ? (
<Select
items={subPagesVolume}
selectedItem={selectedItemVolume}
setSelectedItem={setSelectedItemVolume}
/>
) : (
<Tabs
items={subPagesVolume}
selectedItem={selectedItemVolume}
setSelectedItem={setSelectedItemVolume}
/>
)}
</>
@ -247,6 +258,7 @@ function TariffPage() {
{/* <Slider items={createTariffElements(recentlyPurchased)} />*/}
{/* </>*/}
{/*)}*/}
<ModalRequestCreate open={isRequestCreate} onClose={() => setIsRequestCreate(false)}/>
</SectionWrapper>
);
}

@ -33,7 +33,6 @@ export const useAfterPay = () => {
//Проверяем можем ли мы оплатить корзину здесь и сейчас
const [, payCartError] = await payCart();
console.log("попытка оплаты не удалась")
if (payCartError) {
//Не получилось купить корзину. Ставим флаг, что сайт в состоянии ожидания пополнения счёта для оплаты
@ -54,7 +53,6 @@ export const useAfterPay = () => {
//Время ещё не вышло. У нас стоит флаг покупать корзину если время не вышло.
(async () => {
console.log("Время ещё не вышло. У нас стоит флаг покупать корзину если время не вышло.")
const [, payCartError] = await payCart();
if (!payCartError) {

@ -6,9 +6,5 @@ export default function PrivateRoute() {
const location = useLocation()
const user = useUserStore(state => state.user)
console.log("1 я рассуждаю кого выкинуть отсюда")
console.log(user)
console.log(location)
console.log("2 я рассуждаю кого выкинуть отсюда")
return user ? <Outlet /> : <Navigate to="/" replace />
}

@ -1138,6 +1138,13 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.25.0":
version "7.25.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb"
integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.15", "@babel/template@^7.24.0", "@babel/template@^7.3.3":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
@ -2203,6 +2210,15 @@
"@mui/utils" "^5.15.14"
prop-types "^15.8.1"
"@mui/private-theming@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.6.tgz#547671e7ae3f86b68d1289a0b90af04dfcc1c8c9"
integrity sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/utils" "^5.16.6"
prop-types "^15.8.1"
"@mui/styled-engine@^5.15.14":
version "5.15.14"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.14.tgz#168b154c4327fa4ccc1933a498331d53f61c0de2"
@ -2213,6 +2229,16 @@
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/styled-engine@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.6.tgz#60110c106dd482dfdb7e2aa94fd6490a0a3f8852"
integrity sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==
dependencies:
"@babel/runtime" "^7.23.9"
"@emotion/cache" "^11.11.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^5.15.15":
version "5.15.15"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.15.15.tgz#658771b200ce3c4a0f28e58169f02e5e718d1c53"
@ -2227,11 +2253,30 @@
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^5.16.5":
version "5.16.7"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.7.tgz#4583ca5bf3b38942e02c15a1e622ba869ac51393"
integrity sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/private-theming" "^5.16.6"
"@mui/styled-engine" "^5.16.6"
"@mui/types" "^7.2.15"
"@mui/utils" "^5.16.6"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/types@^7.2.14":
version "7.2.14"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.14.tgz#8a02ac129b70f3d82f2f9b76ded2c8d48e3fc8c9"
integrity sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==
"@mui/types@^7.2.15":
version "7.2.15"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.15.tgz#dadd232fe9a70be0d526630675dff3b110f30b53"
integrity sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==
"@mui/utils@^5.15.14":
version "5.15.14"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.15.14.tgz#e414d7efd5db00bfdc875273a40c0a89112ade3a"
@ -2242,6 +2287,31 @@
prop-types "^15.8.1"
react-is "^18.2.0"
"@mui/utils@^5.16.5", "@mui/utils@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.6.tgz#905875bbc58d3dcc24531c3314a6807aba22a711"
integrity sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/types" "^7.2.15"
"@types/prop-types" "^15.7.12"
clsx "^2.1.1"
prop-types "^15.8.1"
react-is "^18.3.1"
"@mui/x-date-pickers@^7.13.0":
version "7.13.0"
resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-7.13.0.tgz#1afe20dc7ee30c9c1f91c232f3c61f94d2b8427b"
integrity sha512-cmpAfkzOjUgL4I8WenU4elm1QJO8vWpGmIPCezT3Q9wFjGL1QApQhJ5gMZ+X4tM6Gha9AhIWNQX5eXHKbSoyFQ==
dependencies:
"@babel/runtime" "^7.25.0"
"@mui/system" "^5.16.5"
"@mui/utils" "^5.16.5"
"@types/react-transition-group" "^4.4.10"
clsx "^2.1.1"
prop-types "^15.8.1"
react-transition-group "^4.4.5"
"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
version "5.1.1-v1"
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129"
@ -2873,7 +2943,7 @@
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f"
integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==
"@types/prop-types@*", "@types/prop-types@^15.7.11":
"@types/prop-types@*", "@types/prop-types@^15.7.11", "@types/prop-types@^15.7.12":
version "15.7.12"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6"
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
@ -4449,6 +4519,11 @@ clsx@^2.0.0, clsx@^2.1.0:
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb"
integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==
clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@ -10334,6 +10409,11 @@ react-is@^18.0.0, react-is@^18.2.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-is@^18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
react-pdf@^7.1.2:
version "7.7.1"
resolved "https://registry.yarnpkg.com/react-pdf/-/react-pdf-7.7.1.tgz#8f5c4716a8ca65a0889825ef01e3a37956291334"