diff --git a/src/App.tsx b/src/App.tsx
index 35ccd8d3..0702b85f 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -23,6 +23,7 @@ import { ResultSettings } from "./pages/ResultPage/ResultSettings";
import MyQuizzesFull from "./pages/createQuize/MyQuizzesFull";
import Main from "./pages/main";
import EditPage from "./pages/startPage/EditPage";
+import { Tariffs } from "./pages/Tariffs/Tariffs";
import {
clearAuthToken,
getMessageFromFetchError,
@@ -100,16 +101,20 @@ export function useUserAccountFetcher({
dayjs.locale("ru");
const routeslink = [
- { path: "/list", page: , header: false, sidebar: false },
{
- path: "/questions/:quizId",
- page: ,
+ path: "/edit",
+ page: EditPage,
header: true,
sidebar: true,
+ footer: true,
+ },
+ {
+ path: "/design",
+ page: DesignPage,
+ header: true,
+ sidebar: true,
+ footer: true,
},
- { path: "/contacts", page: , header: true, sidebar: true },
- { path: "/result", page: , header: true, sidebar: true },
- { path: "/settings", page: , header: true, sidebar: true },
] as const;
export default function App() {
@@ -185,21 +190,24 @@ export default function App() {
}
/>
+ } />
+ } />
+ } />
}>
{routeslink.map((e, i) => (
+
}
/>
))}
-
- } />
- } />
- } />
- } />
>
diff --git a/src/assets/icons/BackButtonIcon.tsx b/src/assets/icons/BackButtonIcon.tsx
index 883173e9..daed12e3 100644
--- a/src/assets/icons/BackButtonIcon.tsx
+++ b/src/assets/icons/BackButtonIcon.tsx
@@ -9,9 +9,9 @@ export const BackButtonIcon = () => (
);
diff --git a/src/assets/icons/NumberIcon.tsx b/src/assets/icons/NumberIcon.tsx
new file mode 100644
index 00000000..0402e39e
--- /dev/null
+++ b/src/assets/icons/NumberIcon.tsx
@@ -0,0 +1,208 @@
+import { Box, SxProps, Theme } from "@mui/material";
+import { ReactElement } from "react";
+
+interface Props {
+ number: number;
+ color: string;
+ backgroundColor?: string;
+ sx?: SxProps;
+}
+
+export default function NumberIcon({
+ number,
+ backgroundColor = "rgb(0 0 0 / 0)",
+ color,
+ sx,
+}: Props) {
+ number = number % 100;
+
+ const firstDigit = Math.floor(number / 10);
+ const secondDigit = number % 10;
+
+ const firstDigitTranslateX = 6;
+ const secondDigitTranslateX = number < 10 ? 9 : number < 20 ? 11 : 12;
+
+ const firstDigitElement = digitSvgs[firstDigit](firstDigitTranslateX);
+ const secondDigitElement = digitSvgs[secondDigit](secondDigitTranslateX);
+
+ return (
+
+
+
+ );
+}
+
+const circleSvg = (
+
+);
+
+const digitSvgs: Record ReactElement> = {
+ 0: (translateX: number) => (
+
+ ),
+ 1: (translateX: number) => (
+
+ ),
+ 2: (translateX: number) => (
+
+ ),
+ 3: (translateX: number) => (
+
+ ),
+ 4: (translateX: number) => (
+ <>
+
+
+ >
+ ),
+ 5: (translateX: number) => (
+
+ ),
+ 6: (translateX: number) => (
+ <>
+
+
+ >
+ ),
+ 7: (translateX: number) => (
+
+ ),
+ 8: (translateX: number) => (
+ <>
+
+
+ >
+ ),
+ 9: (translateX: number) => (
+ <>
+
+
+ >
+ ),
+};
diff --git a/src/model/privilege.ts b/src/model/privilege.ts
new file mode 100644
index 00000000..2df7f763
--- /dev/null
+++ b/src/model/privilege.ts
@@ -0,0 +1,5 @@
+import { Privilege, PrivilegeWithAmount } from "@frontend/kitui";
+
+export type ServiceKeyToPrivilegesMap = Record;
+
+export type PrivilegeWithoutPrice = Omit;
diff --git a/src/model/tariff.ts b/src/model/tariff.ts
new file mode 100644
index 00000000..39ebab6b
--- /dev/null
+++ b/src/model/tariff.ts
@@ -0,0 +1,6 @@
+import { Tariff } from "@frontend/kitui";
+
+export interface GetTariffsResponse {
+ totalPages: number;
+ tariffs: Tariff[];
+}
diff --git a/src/pages/DesignPage/DesignFilling.tsx b/src/pages/DesignPage/DesignFilling.tsx
index 6fde9e35..bd3ec613 100644
--- a/src/pages/DesignPage/DesignFilling.tsx
+++ b/src/pages/DesignPage/DesignFilling.tsx
@@ -138,20 +138,6 @@ export const DesignFilling = () => {
))}
-
-
-
-
-
);
};
diff --git a/src/pages/DesignPage/DesignPage.tsx b/src/pages/DesignPage/DesignPage.tsx
index d35b5c51..94a2c716 100644
--- a/src/pages/DesignPage/DesignPage.tsx
+++ b/src/pages/DesignPage/DesignPage.tsx
@@ -6,7 +6,7 @@ import { useQuizStore } from "@root/quizes/store";
import Sidebar from "@ui_kit/Sidebar";
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
-import { SidebarMobile } from "../startPage/Sidebar/SidebarMobile";
+import { SidebarMobile } from "../../ui_kit/Sidebar/SidebarMobile";
import { cleanQuestions, setQuestions } from "@root/questions/actions";
import {
updateModalInfoWhyCantCreate,
@@ -17,7 +17,7 @@ import { questionApi } from "@api/question";
import { useUiTools } from "@root/uiTools/store";
import { ConfirmLeaveModal } from "../startPage/ConfirmLeaveModal";
-import { Header } from "../startPage/Header";
+import { Header } from "@ui_kit/Header/Header";
import { DesignFilling } from "./DesignFilling";
import { createPortal } from "react-dom";
import QuizPreview from "@ui_kit/QuizPreview/QuizPreview";
@@ -25,19 +25,6 @@ import QuizPreview from "@ui_kit/QuizPreview/QuizPreview";
export const DesignPage = () => {
const quiz = useCurrentQuiz();
const { editQuizId } = useQuizStore();
-
- useEffect(() => {
- const getData = async () => {
- const quizes = await quizApi.getList();
- setQuizes(quizes);
- if (editQuizId) {
- const questions = await questionApi.getList({ quiz_id: editQuizId });
- setQuestions(questions);
- }
- };
- getData();
- }, []);
-
const { showConfirmLeaveModal } = useUiTools();
const theme = useTheme();
const navigate = useNavigate();
@@ -82,13 +69,7 @@ export const DesignPage = () => {
);
return (
<>
-
- {isMobile ? (
-
- ) : (
-
- )}
{createPortal(, document.body)}
diff --git a/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx b/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx
index a62ff46f..6b6fc883 100644
--- a/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx
+++ b/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx
@@ -108,38 +108,38 @@ export const AnswerItem = ({
),
endAdornment: (
-
-
-
-
-
- setQuestionVariantAnswer(e.target.value || " ")
- }
- onKeyDown={(
- event: KeyboardEvent,
- ) => event.stopPropagation()}
- />
-
+ {/**/}
+ {/* */}
+ {/**/}
+ {/**/}
+ {/* */}
+ {/* setQuestionVariantAnswer(e.target.value || " ")*/}
+ {/* }*/}
+ {/* onKeyDown={(*/}
+ {/* event: KeyboardEvent,*/}
+ {/* ) => event.stopPropagation()}*/}
+ {/* />*/}
+ {/**/}
diff --git a/src/pages/Questions/DataOptions/settingData.tsx b/src/pages/Questions/DataOptions/settingData.tsx
index 8115e2e2..39a4fd7d 100644
--- a/src/pages/Questions/DataOptions/settingData.tsx
+++ b/src/pages/Questions/DataOptions/settingData.tsx
@@ -75,7 +75,7 @@ export default function SettingsData({ question }: SettingsDataProps) {
*/}
*/}
setTitle(target.value)}
sx={{
width: "100%",
@@ -365,8 +365,6 @@ const IconAndrom = (questionType: QuestionType | null) => {
);
default:
- return (
-
- );
+ return null;
}
};
diff --git a/src/pages/Questions/OwnTextField/settingTextField.tsx b/src/pages/Questions/OwnTextField/settingTextField.tsx
index 4534d176..bfd92290 100644
--- a/src/pages/Questions/OwnTextField/settingTextField.tsx
+++ b/src/pages/Questions/OwnTextField/settingTextField.tsx
@@ -126,7 +126,7 @@ export default function SettingTextField({ question }: SettingTextFieldProps) {
*/}
(false);
+
+ const openedModal = () => {
+ updateDesireToOpenABranchingModal(question.content.id);
+ };
+
const SSHC = (data: string) => {
setSwitchState(data);
};
@@ -59,12 +86,105 @@ export default function PageOptions({ disableInput, question }: Props) {
-
-
+
+
+ {/*
+
+ */}
+ copyQuestion(question.id, question.quizId)}
+ >
+
+
+ {
+ if (question.type === null) {
+ deleteQuestion(question.id);
+ }
+ if (question.content.rule.parentId.length !== 0) {
+ setOpenDelete(true);
+ } else {
+ deleteQuestionWithTimeout(question.id, () =>
+ DeleteFunction(questions, question, quiz),
+ );
+ }
+ }}
+ data-cy="delete-question"
+ >
+
+
+ setOpenDelete(false)}>
+
+
+ Вы удаляете вопрос, участвующий в ветвлении. Все его потомки
+ потеряют данные ветвления. Вы уверены, что хотите удалить
+ вопрос?
+
+
+
+
+
+
+
+
+
+
+ {/**/}
+ {/**/}
>
);
}
diff --git a/src/pages/Questions/QuestionsPage.tsx b/src/pages/Questions/QuestionsPage.tsx
index e08a5fa2..df8d2a24 100755
--- a/src/pages/Questions/QuestionsPage.tsx
+++ b/src/pages/Questions/QuestionsPage.tsx
@@ -62,19 +62,21 @@ export default function QuestionsPage({
{quiz.name ? quiz.name : "Заголовок quiz"}
-
+ {!openBranchingPage && (
+
+ )}
- Настройки вопроса
+
+ Настройки вопросов
+
{/* = ({
const theme = useTheme();
const dropZone = useRef(null);
const [ready, setReady] = useState(false);
-
+ const isMobile = useMediaQuery(theme.breakpoints.down(600));
const handleDragEnter = (event: DragEvent) => {
event.preventDefault();
setReady(true);
@@ -65,7 +66,7 @@ export const UploadImageModal: React.FC = ({
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
- maxWidth: "690px",
+ maxWidth: isMobile ? "300px" : "690px",
bgcolor: "background.paper",
borderRadius: "12px",
boxShadow: 24,
@@ -106,13 +107,14 @@ export const UploadImageModal: React.FC = ({
ref={dropZone}
sx={{
width: "580px",
- padding: "33px 10px 33px 55px",
+ padding: isMobile ? "33px" : "33px 10px 33px 55px",
display: "flex",
alignItems: "center",
backgroundColor: theme.palette.background.default,
border: `1px solid ${ready ? "red" : theme.palette.grey2.main}`,
borderRadius: "8px",
gap: "55px",
+ flexDirection: isMobile ? "column" : undefined,
}}
onDragEnter={handleDragEnter} // Применяем обработчик onDragEnter напрямую
>
diff --git a/src/pages/Questions/answerOptions/responseSettings.tsx b/src/pages/Questions/answerOptions/responseSettings.tsx
index 27b77271..51546395 100644
--- a/src/pages/Questions/answerOptions/responseSettings.tsx
+++ b/src/pages/Questions/answerOptions/responseSettings.tsx
@@ -98,7 +98,7 @@ export default function ResponseSettings({ question }: Props) {
{
+ const get = async () => {
+ const user = await makeRequest({
+ method: "GET",
+ url: "https://squiz.pena.digital/customer/account",
+ });
+ const tariffs = await makeRequest({
+ method: "GET",
+ url: "https://squiz.pena.digital/strator/tariff?page=1&limit=100",
+ });
+ const discounts = await makeRequest({
+ method: "GET",
+ url: "https://squiz.pena.digital/price/discounts",
+ });
+ setUser(user);
+ setTariffs(tariffs);
+ setDiscounts(discounts.Discounts);
+ };
+ get();
+ }, []);
+
+ if (!user || !tariffs || !discounts) return ;
+
+ console.log("user ", user);
+ console.log("tariffs ", tariffs);
+ console.log("discounts ", discounts);
+
+ 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: `https://hub.pena.digital/customer/cart?id=${id}`,
+ });
+ //Если нам хватает денежек - покупаем тариф
+ if (price <= user.wallet.cash) {
+ try {
+ await makeRequest({
+ method: "POST",
+ url: "https://suiz.pena.digital/customer/cart/pay",
+ });
+ } catch (e) {
+ enqueueSnackbar("Произошла ошибка. Попробуйте позже");
+ }
+ //Развращаем товары в корзину
+ inCart();
+ } else {
+ //Деняк не хватило
+ // history.pushState({}, null, "https://hub.pena.digital/wallet?action=squizpay");
+
+ var link = document.createElement("a");
+ link.href = `https://hub.pena.digital/payment?action=squizpay&dif=${
+ (price - Number(user.wallet.cash)) * 100
+ }`;
+ document.body.appendChild(link);
+ // link.click();
+ }
+ };
+
+ const purchasesAmount = user?.wallet.purchasesAmount ?? 0;
+ const isUserNko = user?.status === "nko";
+ const filteredTariffs = tariffs.tariffs.filter((tariff) => {
+ return (
+ tariff.privileges[0].serviceKey === "squiz" &&
+ !tariff.isDeleted &&
+ !tariff.isCustom
+ );
+ });
+
+ return (
+ <>
+
+
+ {createTariffElements(
+ filteredTariffs,
+ true,
+ user,
+ discounts,
+ openModalHC,
+ )}
+
+ 0}
+ onClose={() => setOpenModal({})}
+ >
+
+
+ Вы подтверждаете платёж в сумму {openModal.price} ₽
+
+
+
+
+ >
+ );
+}
+
+export const Tariffs = withErrorBoundary(TariffPage, {
+ fallback: (
+
+ Ошибка загрузки тарифов
+
+ ),
+ onError: () => {},
+});
+
+const LoadingPage = () => (
+
+
+ {"Подождите, пожалуйста, идёт загрузка :)"}
+
+
+);
+
+export const inCart = () => {
+ let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]");
+ saveCart.forEach(async (id: string) => {
+ try {
+ await makeRequest({
+ method: "PATCH",
+ url: `https://hub.pena.digital/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);
+ }
+ });
+};
+const outCart = (cart: string[]) => {
+ //Сделаем муторно и подольше, зато при прерывании сессии данные потеряются минимально
+ cart.forEach(async (id: string) => {
+ try {
+ await makeRequest({
+ method: "DELETE",
+ url: `https://suiz.pena.digital/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("Я не смог удалить из корзины тариф :(");
+ }
+ });
+};
diff --git a/src/pages/Tariffs/tariffsUtils/FreeTariffCard.tsx b/src/pages/Tariffs/tariffsUtils/FreeTariffCard.tsx
new file mode 100644
index 00000000..a5aaab30
--- /dev/null
+++ b/src/pages/Tariffs/tariffsUtils/FreeTariffCard.tsx
@@ -0,0 +1,33 @@
+import Typography from "@mui/material/Typography";
+import TariffCard from "./TariffCard";
+import NumberIcon from "@icons/NumberIcon";
+import { useTheme } from "@mui/material";
+
+export default function FreeTariffCard() {
+ const theme = useTheme();
+
+ return (
+ }
+ discount={""}
+ headerText="бесплатно"
+ text="Первые 14 дней после регистрации, вы можете пользоваться полным функционалом сервиса совершенно бесплатно"
+ price={
+
+ 0 руб.
+
+ }
+ sx={{
+ backgroundColor: "#7e2aea",
+ color: "white",
+ }}
+ buttonProps={{
+ text: "Выбрать",
+ sx: {
+ color: "white",
+ borderColor: "white",
+ },
+ }}
+ />
+ );
+}
diff --git a/src/pages/Tariffs/tariffsUtils/TariffCard.tsx b/src/pages/Tariffs/tariffsUtils/TariffCard.tsx
new file mode 100644
index 00000000..ae5a21cc
--- /dev/null
+++ b/src/pages/Tariffs/tariffsUtils/TariffCard.tsx
@@ -0,0 +1,145 @@
+import {
+ Box,
+ Typography,
+ Tooltip,
+ SxProps,
+ Theme,
+ Button,
+ Badge,
+} from "@mui/material";
+import { MouseEventHandler, ReactNode } from "react";
+
+interface Props {
+ icon: ReactNode;
+ headerText: string;
+ discount?: string;
+ text: string | string[];
+ sx?: SxProps;
+ buttonProps?: {
+ sx?: SxProps;
+ onClick?: MouseEventHandler;
+ text?: string;
+ };
+ price?: ReactNode;
+}
+
+export default function TariffCard({
+ icon,
+ headerText,
+ text,
+ sx,
+ price,
+ buttonProps,
+ discount,
+}: Props) {
+ text = Array.isArray(text) ? text : [text];
+
+ return (
+
+
+ {icon}
+ {price && (
+
+ {price}
+
+ )}
+
+ {discount && discount !== "0%" && (
+
+ -{discount}
+
+ )}
+
+ {headerText}} placement="top">
+
+ {headerText}
+
+
+ (
+ {line}
+ ))}
+ placement="top"
+ >
+
+ {text.map((line, index) => (
+
+ {line}
+
+ ))}
+
+
+ {buttonProps && (
+
+ )}
+
+ );
+}
diff --git a/src/pages/Tariffs/tariffsUtils/calcCart.ts b/src/pages/Tariffs/tariffsUtils/calcCart.ts
new file mode 100644
index 00000000..b2a3f74f
--- /dev/null
+++ b/src/pages/Tariffs/tariffsUtils/calcCart.ts
@@ -0,0 +1,250 @@
+import {
+ CartData,
+ Discount,
+ PrivilegeCartData,
+ Tariff,
+ TariffCartData,
+ findPrivilegeDiscount,
+ findDiscountFactor,
+ applyLoyaltyDiscount,
+} from "@frontend/kitui";
+
+function applyPrivilegeDiscounts(cartData: CartData, discounts: Discount[]) {
+ cartData.services.forEach((service) => {
+ const privMap = new Map();
+ service.tariffs.forEach((tariff) =>
+ tariff.privileges.forEach((p) => {
+ privMap.set(
+ p.privilegeId,
+ p.amount + (privMap.get(p.privilegeId) || 0),
+ );
+ }),
+ );
+
+ service.tariffs.forEach((tariff) => {
+ tariff.privileges.forEach((privilege) => {
+ const privilegeDiscount = findPrivilegeDiscount(
+ privilege.privilegeId,
+ privMap.get(privilege.privilegeId) || 0,
+ discounts,
+ );
+ if (!privilegeDiscount) return;
+
+ const discountAmount =
+ privilege.price * (1 - findDiscountFactor(privilegeDiscount));
+ privilege.price -= discountAmount;
+ cartData.allAppliedDiscounts.push(privilegeDiscount);
+ privilege.appliedPrivilegeDiscount = privilegeDiscount;
+
+ tariff.price -= discountAmount;
+ service.price -= discountAmount;
+ cartData.priceAfterDiscounts -= discountAmount;
+ });
+ });
+ });
+}
+function findServiceDiscount(
+ serviceKey: string,
+ currentPrice: number,
+ discounts: Discount[],
+): Discount | null {
+ const applicableDiscounts = discounts.filter((discount) => {
+ return (
+ discount.Layer === 2 &&
+ discount.Condition.Group === serviceKey &&
+ currentPrice >= Number(discount.Condition.PriceFrom)
+ );
+ });
+
+ if (!applicableDiscounts.length) return null;
+
+ const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
+ return Number(current.Condition.PriceFrom) >
+ Number(prev.Condition.PriceFrom)
+ ? current
+ : prev;
+ });
+
+ return maxValueDiscount;
+}
+
+function findCartDiscount(
+ cartPurchasesAmount: number,
+ discounts: Discount[],
+): Discount | null {
+ const applicableDiscounts = discounts.filter((discount) => {
+ return (
+ discount.Layer === 3 &&
+ cartPurchasesAmount >= Number(discount.Condition.CartPurchasesAmount)
+ );
+ });
+ console.log("FCD", applicableDiscounts);
+
+ if (!applicableDiscounts.length) return null;
+
+ const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
+ return Number(current.Condition.CartPurchasesAmount) >
+ Number(prev.Condition.CartPurchasesAmount)
+ ? current
+ : prev;
+ });
+
+ return maxValueDiscount;
+}
+
+function applyCartDiscount(cartData: CartData, discounts: Discount[]) {
+ const cartDiscount = findCartDiscount(
+ cartData.priceAfterDiscounts,
+ discounts,
+ );
+ if (!cartDiscount) return;
+
+ cartData.priceAfterDiscounts *= findDiscountFactor(cartDiscount);
+ cartData.allAppliedDiscounts.push(cartDiscount);
+ cartData.appliedCartPurchasesDiscount = cartDiscount;
+}
+
+function applyServiceDiscounts(cartData: CartData, discounts: Discount[]) {
+ const privMap = new Map();
+ cartData.services.forEach((service) => {
+ service.tariffs.forEach((tariff) =>
+ tariff.privileges.forEach((p) => {
+ privMap.set(p.serviceKey, p.price + (privMap.get(p.serviceKey) || 0));
+ }),
+ );
+ });
+
+ cartData.services.forEach((service) => {
+ service.tariffs.map((tariff) => {
+ tariff.privileges.forEach((privilege) => {
+ const privilegeDiscount = findServiceDiscount(
+ privilege.serviceKey,
+ privMap.get(privilege.serviceKey),
+ discounts,
+ );
+ if (!privilegeDiscount) return;
+
+ const discountAmount =
+ privilege.price * (1 - findDiscountFactor(privilegeDiscount));
+ privilege.price -= discountAmount;
+ cartData.allAppliedDiscounts.push(privilegeDiscount);
+ service.appliedServiceDiscount = privilegeDiscount;
+
+ tariff.price -= discountAmount;
+ service.price -= discountAmount;
+ cartData.priceAfterDiscounts -= discountAmount;
+ });
+ });
+ });
+}
+
+export function calcCart(
+ tariffs: Tariff[],
+ discounts: Discount[],
+ purchasesAmount: number,
+ isUserNko?: boolean,
+): CartData {
+ const cartData: CartData = {
+ services: [],
+ priceBeforeDiscounts: 0,
+ priceAfterDiscounts: 0,
+ itemCount: 0,
+ appliedCartPurchasesDiscount: null,
+ appliedLoyaltyDiscount: null,
+ allAppliedDiscounts: [],
+ };
+
+ tariffs.forEach((tariff) => {
+ if (tariff.price !== undefined && tariff.privileges.length !== 1)
+ throw new Error("Price is defined for tariff with several");
+
+ let serviceData = cartData.services.find(
+ (service) => service.serviceKey === "custom" && tariff.isCustom,
+ );
+ if (!serviceData && !tariff.isCustom)
+ serviceData = cartData.services.find(
+ (service) => service.serviceKey === tariff.privileges[0].serviceKey,
+ );
+
+ if (!serviceData) {
+ serviceData = {
+ serviceKey: tariff.isCustom
+ ? "custom"
+ : tariff.privileges[0].serviceKey,
+ tariffs: [],
+ price: 0,
+ appliedServiceDiscount: null,
+ };
+ cartData.services.push(serviceData);
+ }
+
+ const tariffCartData: TariffCartData = {
+ price: tariff.price ?? 0,
+ isCustom: tariff.isCustom,
+ privileges: [],
+ id: tariff._id,
+ name: tariff.name,
+ };
+ serviceData.tariffs.push(tariffCartData);
+
+ tariff.privileges.forEach((privilege) => {
+ let privilegePrice = privilege.amount * privilege.price;
+ if (!tariff.price) tariffCartData.price += privilegePrice;
+ else privilegePrice = tariff.price;
+
+ const privilegeCartData: PrivilegeCartData = {
+ serviceKey: privilege.serviceKey,
+ privilegeId: privilege.privilegeId,
+ description: privilege.description,
+ price: privilegePrice,
+ amount: privilege.amount,
+ appliedPrivilegeDiscount: null,
+ };
+
+ tariffCartData.privileges.push(privilegeCartData);
+ cartData.priceAfterDiscounts += privilegePrice;
+ cartData.itemCount++;
+ });
+
+ cartData.priceBeforeDiscounts += tariffCartData.price;
+ serviceData.price += tariffCartData.price;
+ });
+
+ const nkoDiscount = findNkoDiscount(discounts);
+ if (isUserNko && nkoDiscount) {
+ applyNkoDiscount(cartData, nkoDiscount);
+ } else {
+ applyPrivilegeDiscounts(cartData, discounts);
+ applyServiceDiscounts(cartData, discounts);
+ applyCartDiscount(cartData, discounts);
+ applyLoyaltyDiscount(cartData, discounts, purchasesAmount);
+ }
+
+ cartData.allAppliedDiscounts = Array.from(
+ new Set(cartData.allAppliedDiscounts),
+ );
+
+ return cartData;
+}
+
+function applyNkoDiscount(cartData: CartData, discount: Discount) {
+ cartData.priceAfterDiscounts *= discount.Target.Factor;
+ cartData.allAppliedDiscounts.push(discount);
+}
+
+export function findNkoDiscount(discounts: Discount[]): Discount | null {
+ const applicableDiscounts = discounts.filter(
+ (discount) => discount.Condition.UserType === "nko",
+ );
+
+ if (!applicableDiscounts.length) return null;
+
+ const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
+ return current.Condition.CartPurchasesAmount >
+ prev.Condition.CartPurchasesAmount
+ ? current
+ : prev;
+ });
+
+ return maxValueDiscount;
+}
diff --git a/src/pages/Tariffs/tariffsUtils/calcTariffPrices.ts b/src/pages/Tariffs/tariffsUtils/calcTariffPrices.ts
new file mode 100644
index 00000000..42dd1d6b
--- /dev/null
+++ b/src/pages/Tariffs/tariffsUtils/calcTariffPrices.ts
@@ -0,0 +1,54 @@
+import { Discount, Tariff, findDiscountFactor } from "@frontend/kitui";
+import { calcCart } from "./calcCart";
+
+export function calcIndividualTariffPrices(
+ tariff: Tariff,
+ discounts: Discount[],
+ purchasesAmount: number,
+ currentTariffs: Tariff[],
+ isUserNko?: boolean,
+): {
+ priceBeforeDiscounts: number;
+ priceAfterDiscounts: number;
+} {
+ const priceBeforeDiscounts =
+ tariff.price ||
+ tariff.privileges.reduce(
+ (sum, privilege) => sum + privilege.amount * privilege.price,
+ 0,
+ );
+ let priceAfterDiscounts = 0;
+
+ const cart = calcCart(
+ [...currentTariffs, tariff],
+ discounts,
+ purchasesAmount,
+ isUserNko,
+ );
+ if (cart.allAppliedDiscounts[0]?.Target.Overhelm)
+ return {
+ priceBeforeDiscounts: priceBeforeDiscounts,
+ priceAfterDiscounts:
+ priceBeforeDiscounts * cart.allAppliedDiscounts[0].Target.Factor,
+ };
+ cart.services.forEach((s) => {
+ if (s.serviceKey === tariff.privileges[0].serviceKey) {
+ let processed = false;
+ s.tariffs.forEach((t) => {
+ if (t.id === tariff._id && !processed) {
+ processed = true;
+ t.privileges.forEach((p) => (priceAfterDiscounts += p.price));
+ }
+ });
+ priceAfterDiscounts *= findDiscountFactor(s.appliedServiceDiscount);
+ }
+ });
+ priceAfterDiscounts *= findDiscountFactor(cart.appliedLoyaltyDiscount);
+ priceAfterDiscounts *= findDiscountFactor(cart.appliedCartPurchasesDiscount);
+
+ // cart.allAppliedDiscounts.forEach((discount) => {
+ // priceAfterDiscounts *= findDiscountFactor(discount)
+ // })
+ //priceAfterDiscounts = cart.priceAfterDiscounts
+ return { priceBeforeDiscounts, priceAfterDiscounts };
+}
diff --git a/src/pages/Tariffs/tariffsUtils/createTariffElements.tsx b/src/pages/Tariffs/tariffsUtils/createTariffElements.tsx
new file mode 100644
index 00000000..f552bb85
--- /dev/null
+++ b/src/pages/Tariffs/tariffsUtils/createTariffElements.tsx
@@ -0,0 +1,77 @@
+import { Tariff } from "@frontend/kitui";
+import TariffCard from "./TariffCard";
+import NumberIcon from "@icons/NumberIcon";
+import { calcIndividualTariffPrices } from "./calcTariffPrices";
+import { currencyFormatter } from "./currencyFormatter";
+import FreeTariffCard from "./FreeTariffCard";
+import { Typography, useTheme } from "@mui/material";
+
+export const createTariffElements = (
+ filteredTariffs: Tariff[],
+ addFreeTariff = false,
+ user: any,
+ discounts: any,
+ onclick: any,
+) => {
+ const theme = useTheme();
+ const tariffElements = filteredTariffs
+ .filter((tariff) => tariff.privileges.length > 0)
+ .map((tariff, index) => {
+ const { priceBeforeDiscounts, priceAfterDiscounts } =
+ calcIndividualTariffPrices(
+ tariff,
+ discounts,
+ user.purchasesAmount,
+ [],
+ user.isUserNko,
+ );
+
+ return (
+
+ }
+ buttonProps={{
+ text: "Выбрать",
+ onClick: () =>
+ onclick({ id: tariff._id, price: priceBeforeDiscounts / 100 }),
+ }}
+ headerText={tariff.name}
+ text={tariff.privileges.map((p) => `${p.name} - ${p.amount}`)}
+ price={
+ <>
+ {priceBeforeDiscounts !== priceAfterDiscounts && (
+
+ {currencyFormatter.format(priceBeforeDiscounts / 100)}
+
+ )}
+
+ {currencyFormatter.format(priceAfterDiscounts / 100)}
+
+ >
+ }
+ />
+ );
+ });
+
+ if (addFreeTariff) {
+ if (tariffElements.length < 6)
+ tariffElements.push();
+ else tariffElements.splice(5, 0, );
+ }
+
+ return tariffElements;
+};
diff --git a/src/pages/Tariffs/tariffsUtils/currencyFormatter.ts b/src/pages/Tariffs/tariffsUtils/currencyFormatter.ts
new file mode 100644
index 00000000..5924c6bd
--- /dev/null
+++ b/src/pages/Tariffs/tariffsUtils/currencyFormatter.ts
@@ -0,0 +1,6 @@
+export const currencyFormatter = new Intl.NumberFormat("ru", {
+ currency: "RUB",
+ style: "currency",
+ compactDisplay: "short",
+ minimumFractionDigits: 0,
+});
diff --git a/src/pages/createQuize/MyQuizzesFull.tsx b/src/pages/createQuize/MyQuizzesFull.tsx
index b0f15fe1..16a8895d 100644
--- a/src/pages/createQuize/MyQuizzesFull.tsx
+++ b/src/pages/createQuize/MyQuizzesFull.tsx
@@ -15,6 +15,7 @@ import { useNavigate } from "react-router-dom";
import { resetEditConfig } from "@root/quizes/actions";
import FirstQuiz from "./FirstQuiz";
import QuizCard from "./QuizCard";
+import HeaderFull from "@ui_kit/Header/HeaderFull";
interface Props {
outerContainerSx?: SxProps;
@@ -32,10 +33,14 @@ export default function MyQuizzesFull({
return (
<>
+
{quizes.length === 0 ? (
) : (
-
+
{
+ const pay = async () => {
+ try {
+ await makeRequest({
+ method: "POST",
+ url: "https://suiz.pena.digital/customer/cart/pay",
+ });
+ inCart();
+ } catch (e) {
+ enqueueSnackbar(
+ "Попробуйте снова купить тариф после зачисления средств",
+ );
+ }
+ };
+ const params = new URLSearchParams(window.location.search);
+ const fromSquiz = params.get("action");
+ if (fromSquiz === "fromhub") {
+ window.history.replaceState(null, '', "/list")
+ pay();
+ }
+ }, []);
+
return (
diff --git a/src/pages/main.tsx b/src/pages/main.tsx
index 311a6e8f..dc944572 100755
--- a/src/pages/main.tsx
+++ b/src/pages/main.tsx
@@ -1,39 +1,255 @@
-import Header from "@ui_kit/Header/Header";
+import { Header } from "@ui_kit/Header/Header";
import Sidebar from "@ui_kit/Sidebar";
import Box from "@mui/material/Box";
-import { useTheme, useMediaQuery } from "@mui/material";
+import { useTheme, useMediaQuery, IconButton } from "@mui/material";
import HeaderFull from "@ui_kit/Header/HeaderFull";
+import { useEffect, useState } from "react";
+import { SidebarMobile } from "../ui_kit/Sidebar/SidebarMobile";
+import { setShowConfirmLeaveModal } from "@root/uiTools/actions";
+import { setCurrentStep, setQuizes } from "@root/quizes/actions";
+import { useQuizStore } from "@root/quizes/store";
+import { SmallSwitchQuestionListGraph } from "@ui_kit/Toolbars/SmallSwitchQuestionListGraph";
+import { PanelSwitchQuestionListGraph } from "@ui_kit/Toolbars/PanelSwitchQuestionListGraph";
+import { ButtonTestPublication } from "@ui_kit/Toolbars/ButtonTestPublication";
+import { ButtonRecallQuiz } from "@ui_kit/Toolbars/ButtonRecallQuiz";
+import { Link } from "react-router-dom";
+import { LinkSimple } from "@icons/LinkSimple";
+import { useCurrentQuiz } from "@root/quizes/hooks";
+import { deleteTimeoutedQuestions } from "@utils/deleteTimeoutedQuestions";
+import { useQuestionsStore } from "@root/questions/store";
+import { quizApi } from "@api/quiz";
+import { questionApi } from "@api/question";
+import { createResult, setQuestions } from "@root/questions/actions";
+import { toggleQuizPreview } from "@root/quizPreview";
+import VisibilityIcon from "@mui/icons-material/Visibility";
interface Props {
sidebar: boolean;
header?: boolean;
- page: JSX.Element;
+ footer?: boolean;
+ Page?: React.Component;
}
-export default function Main({ sidebar, header, page }: Props) {
+export default function Main({ sidebar, header, footer, Page }: Props) {
const theme = useTheme();
- const isMobile = useMediaQuery(theme.breakpoints.down(600));
+ const quiz = useCurrentQuiz();
+ const quizConfig = quiz?.config;
+ const { questions } = useQuestionsStore();
+ const { editQuizId } = useQuizStore();
+ const currentStep = useQuizStore((state) => state.currentStep);
+
+ useEffect(() => {
+ const getData = async () => {
+ const quizes = await quizApi.getList();
+ setQuizes(quizes);
+
+ if (editQuizId) {
+ const questions = await questionApi.getList({ quiz_id: editQuizId });
+
+ setQuestions(questions);
+ //Всегда должен существовать хоть 1 резулт - "line"
+ if (
+ !questions?.find(
+ (q) =>
+ (q.type === "result" && q.content.includes(':"line"')) ||
+ q.content.includes(":'line'"),
+ )
+ ) {
+ createResult(quiz?.backendId, "line");
+ console.log("Я не нашёл линейный резулт и собираюсь создать новый");
+ }
+ }
+ };
+ getData();
+ }, []);
+
+ const isMobile = useMediaQuery(theme.breakpoints.down(650));
+ const isMobileSm = useMediaQuery(theme.breakpoints.down(370));
+ const isBranchingLogic = useMediaQuery(theme.breakpoints.down(1100));
+ const isLinkButton = useMediaQuery(theme.breakpoints.down(708));
+ const [mobileSidebar, setMobileSidebar] = useState(false);
+ const [nextStep, setNextStep] = useState(0);
+ const [openBranchingPage, setOpenBranchingPage] = useState(false);
+
+ const openBranchingPageHC = () => {
+ if (!openBranchingPage) {
+ deleteTimeoutedQuestions(questions, quiz);
+ }
+ setOpenBranchingPage((old) => !old);
+ };
+
+ if (!quizConfig) return <>>;
+
+ const isConditionMet =
+ [1].includes(currentStep) && quizConfig.type !== "form";
+
+ const changePage = (index: number) => {
+ if (currentStep === 2) {
+ setNextStep(index);
+ setShowConfirmLeaveModal(true);
+
+ return;
+ }
+
+ setCurrentStep(index);
+ };
return (
<>
- {header ? : }
+
- {sidebar ? : <>>}
+ {sidebar ? (
+ <>
+ {isMobile ? (
+
+ ) : (
+
+ )}
+ >
+ ) : (
+ <>>
+ )}
- {page}
+
+
+
+
+ {footer && (
+
+ {isConditionMet &&
+ (isBranchingLogic ? (
+
+ ) : (
+
+ ))}
+ {/* Кнопка тестового просмотра */}
+
+ {/* Кнопка отозвать */}
+
+ {/* Ссылка */}
+ {quiz?.status === "start" &&
+ (!isLinkButton ? (
+
+ https://hbpn.link/{quiz.qid}
+
+ ) : (
+
+
+
+ ))}
+ {/* Маленькая кнопка ссылки */}
+ {isMobile && quiz?.status === "start" && (
+
+
+
+ )}
+
+
+
+
+
+
+ )}
>
diff --git a/src/pages/startPage/EditPage.tsx b/src/pages/startPage/EditPage.tsx
index ff8649ca..cb50dd5f 100755
--- a/src/pages/startPage/EditPage.tsx
+++ b/src/pages/startPage/EditPage.tsx
@@ -20,7 +20,7 @@ import SwitchStepPages from "@ui_kit/switchStepPages";
import { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { useDebouncedCallback } from "use-debounce";
-import { SidebarMobile } from "./Sidebar/SidebarMobile";
+import { SidebarMobile } from "../../ui_kit/Sidebar/SidebarMobile";
import {
cleanQuestions,
createResult,
@@ -32,7 +32,7 @@ import {
setShowConfirmLeaveModal,
updateSomeWorkBackend,
} from "@root/uiTools/actions";
-import { Header } from "./Header";
+import { Header } from "@ui_kit/Header/Header";
import { useQuestionsStore } from "@root/questions/store";
import { questionApi } from "@api/question";
import { useUiTools } from "@root/uiTools/store";
@@ -41,64 +41,28 @@ import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate";
import { ConfirmLeaveModal } from "./ConfirmLeaveModal";
import { checkQuestionHint } from "@utils/checkQuestionHint";
-import { deleteTimeoutedQuestions } from "@utils/deleteTimeoutedQuestions";
-import { toggleQuizPreview } from "@root/quizPreview";
-import { LinkSimple } from "@icons/LinkSimple";
-import { SmallSwitchQuestionListGraph } from "@ui_kit/Toolbars/SmallSwitchQuestionListGraph";
-import { PanelSwitchQuestionListGraph } from "@ui_kit/Toolbars/PanelSwitchQuestionListGraph";
-import { ButtonTestPublication } from "@ui_kit/Toolbars/ButtonTestPublication";
-import { ButtonRecallQuiz } from "@ui_kit/Toolbars/ButtonRecallQuiz";
-export default function EditPage() {
+interface Props {
+ openBranchingPage: boolean;
+ setOpenBranchingPage: (a: boolean) => void;
+}
+export default function EditPage({
+ openBranchingPage,
+ setOpenBranchingPage,
+}: Props) {
const quiz = useCurrentQuiz();
const { editQuizId } = useQuizStore();
const { questions } = useQuestionsStore();
console.log(questions);
-
- useEffect(() => {
- const getData = async () => {
- const quizes = await quizApi.getList();
- setQuizes(quizes);
-
- if (editQuizId) {
- const questions = await questionApi.getList({ quiz_id: editQuizId });
-
- setQuestions(questions);
- //Всегда должен существовать хоть 1 резулт - "line"
- if (
- !questions?.find(
- (q) =>
- (q.type === "result" && q.content.includes(':"line"')) ||
- q.content.includes(":'line'"),
- )
- ) {
- createResult(quiz?.backendId, "line");
- console.log("Я не нашёл линейный резулт и собираюсь создать новый");
- }
- }
- };
- getData();
- }, []);
-
const { whyCantCreatePublic, showConfirmLeaveModal } = useUiTools();
const theme = useTheme();
const navigate = useNavigate();
const currentStep = useQuizStore((state) => state.currentStep);
const isBranchingLogic = useMediaQuery(theme.breakpoints.down(1100));
const isMobile = useMediaQuery(theme.breakpoints.down(660));
- const isLinkButton = useMediaQuery(theme.breakpoints.down(708));
- const isMobileSm = useMediaQuery(theme.breakpoints.down(370));
- const [mobileSidebar, setMobileSidebar] = useState(false);
const [nextStep, setNextStep] = useState(0);
const quizConfig = quiz?.config;
- const [openBranchingPage, setOpenBranchingPage] = useState(false);
-
- const openBranchingPageHC = () => {
- if (!openBranchingPage) {
- deleteTimeoutedQuestions(questions, quiz);
- }
- setOpenBranchingPage((old) => !old);
- };
+ // const [openBranchingPage, setOpenBranchingPage] = useState(false);
useEffect(() => {
if (editQuizId === null) navigate("/list");
@@ -144,33 +108,14 @@ export default function EditPage() {
const isConditionMet =
[1].includes(currentStep) && quizConfig.type !== "form";
- const changePage = (index: number) => {
- if (currentStep === 2) {
- setNextStep(index);
- setShowConfirmLeaveModal(true);
-
- return;
- }
-
- setCurrentStep(index);
- };
-
return (
<>
-
-
- {isMobile ? (
-
- ) : (
-
- )}
-
)}
-
-
- {isConditionMet &&
- (isBranchingLogic ? (
-
- ) : (
-
- ))}
- {/* Кнопка тестового просмотра */}
-
- {/* Кнопка отозвать */}
-
- {/* Ссылка */}
- {quiz?.status === "start" &&
- (!isLinkButton ? (
-
- https://hbpn.link/{quiz.qid}
-
- ) : (
-
-
-
- ))}
- {/* Маленькая кнопка ссылки */}
- {isMobile && quiz?.status === "start" && (
-
-
-
- )}
-
diff --git a/src/pages/startPage/Header.tsx b/src/pages/startPage/Header.tsx
deleted file mode 100644
index 4789ba97..00000000
--- a/src/pages/startPage/Header.tsx
+++ /dev/null
@@ -1,178 +0,0 @@
-import { LogoutButton } from "@ui_kit/LogoutButton";
-import BackArrowIcon from "@icons/BackArrowIcon";
-import { Burger } from "@icons/Burger";
-
-import {
- Box,
- Container,
- FormControl,
- IconButton,
- TextField,
- useMediaQuery,
- useTheme,
-} from "@mui/material";
-import { updateQuiz } from "@root/quizes/actions";
-import { useCurrentQuiz } from "@root/quizes/hooks";
-import CustomAvatar from "@ui_kit/Header/Avatar";
-import NavMenuItem from "@ui_kit/Header/NavMenuItem";
-
-import { enqueueSnackbar } from "notistack";
-import { useState } from "react";
-import { Link, useNavigate } from "react-router-dom";
-
-import Logotip from "../Landing/images/icons/QuizLogo";
-import { clearUserData } from "@root/user";
-import { clearAuthToken } from "@frontend/kitui";
-import { logout } from "@api/auth";
-
-type HeaderProps = {
- setMobileSidebar: (callback: (visible: boolean) => boolean) => void;
-};
-
-export const Header = ({ setMobileSidebar }: HeaderProps) => {
- const quiz = useCurrentQuiz();
- const theme = useTheme();
- const navigate = useNavigate();
- const isTablet = useMediaQuery(theme.breakpoints.down(1000));
- const isMobile = useMediaQuery(theme.breakpoints.down(660));
-
- async function handleLogoutClick() {
- const [, logoutError] = await logout();
-
- if (logoutError) {
- return enqueueSnackbar(logoutError);
- }
-
- clearAuthToken();
- clearUserData();
- navigate("/");
- }
-
- return (
-
-
- {isMobile ? : }
-
-
-
-
-
-
-
-
-
- updateQuiz(quiz.id, (quiz) => {
- quiz.name = e.target.value;
- })
- }
- fullWidth
- id="project-name"
- placeholder="Название проекта окно"
- sx={{
- width: "270px",
- "& .MuiInputBase-root": {
- height: "34px",
- borderRadius: "8px",
- p: 0,
- },
- }}
- inputProps={{
- sx: {
- height: "20px",
- borderRadius: "8px",
- fontSize: "16px",
- lineHeight: "20px",
- p: "7px",
- color: "black",
- "&::placeholder": {
- opacity: 1,
- },
- },
- }}
- />
-
-
- {isTablet ? (
-
- {isMobile ? (
- setMobileSidebar((visible: boolean) => !visible)}
- style={{ fontSize: "30px", color: "white", cursor: "pointer" }}
- />
- ) : (
-
- {/* */}
-
- )}
-
- ) : (
- <>
-
- {/* */}
- {/*
-
-
- */}
-
-
- {/* */}
-
-
- >
- )}
-
- );
-};
diff --git a/src/ui_kit/Header/Header.tsx b/src/ui_kit/Header/Header.tsx
old mode 100755
new mode 100644
index 8a891dd5..6e692666
--- a/src/ui_kit/Header/Header.tsx
+++ b/src/ui_kit/Header/Header.tsx
@@ -1,8 +1,9 @@
+import { LogoutButton } from "@ui_kit/LogoutButton";
import BackArrowIcon from "@icons/BackArrowIcon";
-import EyeIcon from "@icons/EyeIcon";
+import { Burger } from "@icons/Burger";
+
import {
Box,
- Button,
Container,
FormControl,
IconButton,
@@ -10,15 +11,43 @@ import {
useMediaQuery,
useTheme,
} from "@mui/material";
-import { decrementCurrentStep } from "@root/quizes/actions";
-import PenaLogo from "../PenaLogo";
-import CustomAvatar from "./Avatar";
-import NavMenuItem from "./NavMenuItem";
-import { Link } from "react-router-dom";
+import { updateQuiz } from "@root/quizes/actions";
+import { useCurrentQuiz } from "@root/quizes/hooks";
+import CustomAvatar from "@ui_kit/Header/Avatar";
+import NavMenuItem from "@ui_kit/Header/NavMenuItem";
-export default function Header() {
+import { enqueueSnackbar } from "notistack";
+import { useState } from "react";
+import { Link, useNavigate } from "react-router-dom";
+
+import Logotip from "../../pages/Landing/images/icons/QuizLogo";
+import { clearUserData } from "@root/user";
+import { clearAuthToken } from "@frontend/kitui";
+import { logout } from "@api/auth";
+import { ToTariffsButton } from "@ui_kit/Toolbars/ToTariffsButton";
+
+type HeaderProps = {
+ setMobileSidebar: (callback: (visible: boolean) => boolean) => void;
+};
+
+export const Header = ({ setMobileSidebar }: HeaderProps) => {
+ const quiz = useCurrentQuiz();
const theme = useTheme();
+ const navigate = useNavigate();
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
+ const isMobile = useMediaQuery(theme.breakpoints.down(650));
+
+ async function handleLogoutClick() {
+ const [, logoutError] = await logout();
+
+ if (logoutError) {
+ return enqueueSnackbar(logoutError);
+ }
+
+ clearAuthToken();
+ clearUserData();
+ navigate("/");
+ }
return (
-
-
+
+ {isMobile ? (
+
+ ) : (
+
+ )}
-
-
-
+
+
+
+
+
+ updateQuiz(quiz.id, (quiz) => {
+ quiz.name = e.target.value;
+ })
+ }
fullWidth
id="project-name"
- placeholder="Название проекта окно"
+ placeholder="Название проекта"
sx={{
width: "270px",
"& .MuiInputBase-root": {
@@ -77,36 +118,32 @@ export default function Header() {
/>
-
- {isTablet ? null : (
- <>
-
- {/* */}
- {/*
-
-
- */}
-
-
- {/* */}
-
- >
- )}
+
+ {isMobile ? (
+ setMobileSidebar((visible: boolean) => !visible)}
+ style={{ fontSize: "30px", color: "white", cursor: "pointer" }}
+ />
+ ) : (
+ <>
+
+
+
+
+ >
+ )}
+
);
-}
+};
diff --git a/src/ui_kit/Header/HeaderFull.tsx b/src/ui_kit/Header/HeaderFull.tsx
index 6f81d324..e2074429 100644
--- a/src/ui_kit/Header/HeaderFull.tsx
+++ b/src/ui_kit/Header/HeaderFull.tsx
@@ -17,6 +17,7 @@ import { Link, useNavigate } from "react-router-dom";
import { enqueueSnackbar } from "notistack";
import { clearUserData } from "@root/user";
import { LogoutButton } from "@ui_kit/LogoutButton";
+import { ToTariffsButton } from "@ui_kit/Toolbars/ToTariffsButton";
export default function HeaderFull() {
const theme = useTheme();
@@ -47,18 +48,12 @@ export default function HeaderFull() {
height: "80px",
alignItems: "center",
gap: isTablet ? "20px" : "60px",
- flexDirection: isMobile ? "row-reverse" : "row",
+ flexDirection: "row",
justifyContent: isMobile ? "space-between" : "center",
bgcolor: "white",
borderBottom: "1px solid #E3E3E3",
}}
>
- {isTablet && (
- setMobileSidebar(!mobileSidebar)}
- style={{ fontSize: "30px", color: "#000000", cursor: "pointer" }}
- />
- )}
@@ -69,57 +64,17 @@ export default function HeaderFull() {
gap: "30px",
overflow: "hidden",
}}
- >
- {/*
-
-
-
-
-
- */}
-
+ >
)}
-
- {/* {!isTablet && (
- <>
-
-
-
-
-
- Мой баланс
-
-
- 00.00 руб.
-
-
- >
- )} */}
- {!isMobile && (
- <>
- {/* */}
-
- >
- )}
+
+
+
);
}
diff --git a/src/ui_kit/Header/NavMenuItem.tsx b/src/ui_kit/Header/NavMenuItem.tsx
index fe4dd953..d602c3c8 100755
--- a/src/ui_kit/Header/NavMenuItem.tsx
+++ b/src/ui_kit/Header/NavMenuItem.tsx
@@ -17,6 +17,7 @@ export default function NavMenuItem({
return (
+ я есть навбар меню итем
+ я подписан как навбар коллапсед
= ({
padding: "20px",
borderRadius: "8px",
width: isMobile ? "343px" : "620px",
+ height: isMobile ? "80vh" : undefined,
+ display: isMobile ? "flex" : undefined,
+ flexDirection: isMobile ? "column" : undefined,
+ justifyContent: isMobile ? "space-evenly" : undefined,
}}
>
= ({
sx={[
styleSlider,
{
- width: isMobile ? "350px" : "250px",
+ width: isMobile ? undefined : "250px",
},
]}
value={scale * 100}
@@ -278,7 +282,7 @@ export const CropModal: FC = ({
sx={[
styleSlider,
{
- width: isMobile ? "350px" : "250px",
+ width: isMobile ? undefined : "250px",
},
]}
value={darken}
@@ -295,6 +299,7 @@ export const CropModal: FC = ({
width: "100%",
display: "flex",
gap: "10px",
+ flexWrap: isMobile ? "wrap" : undefined,
}}
>