при развращении с хаба - пытаемся купить тариф

This commit is contained in:
Nastya 2024-01-04 04:15:39 +03:00
commit 7a3503f4d1
8 changed files with 460 additions and 385 deletions

@ -23,7 +23,7 @@ import { ResultSettings } from "./pages/ResultPage/ResultSettings";
import MyQuizzesFull from "./pages/createQuize/MyQuizzesFull"; import MyQuizzesFull from "./pages/createQuize/MyQuizzesFull";
import Main from "./pages/main"; import Main from "./pages/main";
import EditPage from "./pages/startPage/EditPage"; import EditPage from "./pages/startPage/EditPage";
import Tariffs from "./pages/Tariffs/Tariffs"; import { Tariffs } from "./pages/Tariffs/Tariffs";
import { import {
clearAuthToken, clearAuthToken,
getMessageFromFetchError, getMessageFromFetchError,
@ -101,20 +101,27 @@ export function useUserAccountFetcher({
dayjs.locale("ru"); dayjs.locale("ru");
const routeslink = [ const routeslink = [
{ path: "/list", page: <MyQuizzesFull />, header: false, sidebar: false },
{ {
path: "/questions/:quizId", path: "/tariffs",
page: <QuestionsPage />, page: <Tariffs />,
header: true,
sidebar: false,
footer: false,
},
{
path: "/edit",
page: <EditPage />,
header: true, header: true,
sidebar: true, sidebar: true,
footer: true,
},
{
path: "/design",
page: <DesignPage />,
header: true,
sidebar: true,
footer: true,
}, },
{ path: "/contacts", page: <ContactFormPage />, header: true, sidebar: true },
{ path: "/result", page: <Result />, header: true, sidebar: true },
{ path: "/settings", page: <ResultSettings />, header: true, sidebar: true },
{ path: "/tariffs", page: <Tariffs />, header: true, sidebar: false },
{ path: "/edit", page: <EditPage />, header: true, sidebar: true },
{ path: "/view", page: <ViewPage />, header: false, sidebar: false },
{ path: "/design", page: <DesignPage />, header: true, sidebar: true },
] as const; ] as const;
export default function App() { export default function App() {
@ -190,13 +197,20 @@ export default function App() {
<Navigate to="/" replace state={{ redirectTo: "/restore" }} /> <Navigate to="/" replace state={{ redirectTo: "/restore" }} />
} }
/> />
<Route path="/list" element={<MyQuizzesFull />} />
<Route path={"/view"} element={<ViewPage />} />
<Route element={<PrivateRoute />}> <Route element={<PrivateRoute />}>
{routeslink.map((e, i) => ( {routeslink.map((e, i) => (
<Route <Route
key={i} key={i}
path={e.path} path={e.path}
element={ element={
<Main page={e.page} header={e.header} sidebar={e.sidebar} /> <Main
page={e.page}
header={e.header}
sidebar={e.sidebar}
footer={e.footer}
/>
} }
/> />
))} ))}

@ -25,19 +25,6 @@ import QuizPreview from "@ui_kit/QuizPreview/QuizPreview";
export const DesignPage = () => { export const DesignPage = () => {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { editQuizId } = useQuizStore(); 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 { showConfirmLeaveModal } = useUiTools();
const theme = useTheme(); const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
@ -82,13 +69,13 @@ export const DesignPage = () => {
); );
return ( return (
<> <>
<Header setMobileSidebar={setMobileSidebar} /> {/*<Header setMobileSidebar={setMobileSidebar} />*/}
<Box sx={{ display: "flex", flexDirection: isMobile ? "column" : "row" }}> <Box sx={{ display: "flex", flexDirection: isMobile ? "column" : "row" }}>
{isMobile ? ( {/*{isMobile ? (*/}
<SidebarMobile open={mobileSidebar} changePage={changePage} /> {/* <SidebarMobile open={mobileSidebar} changePage={changePage} />*/}
) : ( {/*) : (*/}
<Sidebar changePage={changePage} /> {/* <Sidebar changePage={changePage} />*/}
)} {/*)}*/}
<DesignFilling /> <DesignFilling />
{createPortal(<QuizPreview />, document.body)} {createPortal(<QuizPreview />, document.body)}
</Box> </Box>

@ -20,7 +20,7 @@ import { createTariffElements } from "./tariffsUtils/createTariffElements";
function TariffPage() { function TariffPage() {
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(1000)); const isTablet = useMediaQuery(theme.breakpoints.down(1000));
// const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const [tariffs, setTariffs] = useState(); const [tariffs, setTariffs] = useState();
@ -63,6 +63,11 @@ function TariffPage() {
if (user.cart.length > 0) { if (user.cart.length > 0) {
outCart(user.cart); outCart(user.cart);
} }
//Добавляем желаемый тариф в корзину
await makeRequest({
method: "PATCH",
url: `https://hub.pena.digital/customer/cart?id=${id}`,
});
//Если нам хватает денежек - покупаем тариф //Если нам хватает денежек - покупаем тариф
if (price <= user.wallet.cash) { if (price <= user.wallet.cash) {
try { try {
@ -78,10 +83,13 @@ function TariffPage() {
} else { } else {
//Деняк не хватило //Деняк не хватило
// history.pushState({}, null, "https://hub.pena.digital/wallet?action=squizpay"); // 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 - user.wallet) * 100}` 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); document.body.appendChild(link);
link.click(); // link.click();
} }
}; };
@ -104,7 +112,8 @@ function TariffPage() {
mb: "30px", mb: "30px",
display: "grid", display: "grid",
gap: "40px", gap: "40px",
gridTemplateColumns: `repeat(auto-fit, minmax(300px, ${isTablet ? "436px" : "360px" gridTemplateColumns: `repeat(auto-fit, minmax(300px, ${
isTablet ? "436px" : "360px"
}))`, }))`,
}} }}
> >
@ -150,13 +159,13 @@ function TariffPage() {
); );
} }
export default withErrorBoundary(TariffPage, { export const Tariffs = withErrorBoundary(TariffPage, {
fallback: ( fallback: (
<Typography mt="8px" textAlign="center"> <Typography mt="8px" textAlign="center">
Ошибка загрузки тарифов Ошибка загрузки тарифов
</Typography> </Typography>
), ),
onError: () => { }, onError: () => {},
}); });
const LoadingPage = () => ( const LoadingPage = () => (
@ -174,7 +183,7 @@ const LoadingPage = () => (
</Box> </Box>
); );
const inCart = () => { export const inCart = () => {
let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]"); let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]");
saveCart.forEach(async (id: string) => { saveCart.forEach(async (id: string) => {
try { try {

@ -15,6 +15,7 @@ import { useNavigate } from "react-router-dom";
import { resetEditConfig } from "@root/quizes/actions"; import { resetEditConfig } from "@root/quizes/actions";
import FirstQuiz from "./FirstQuiz"; import FirstQuiz from "./FirstQuiz";
import QuizCard from "./QuizCard"; import QuizCard from "./QuizCard";
import HeaderFull from "@ui_kit/Header/HeaderFull";
interface Props { interface Props {
outerContainerSx?: SxProps<Theme>; outerContainerSx?: SxProps<Theme>;
@ -32,6 +33,7 @@ export default function MyQuizzesFull({
return ( return (
<> <>
<HeaderFull />
{quizes.length === 0 ? ( {quizes.length === 0 ? (
<FirstQuiz /> <FirstQuiz />
) : ( ) : (

@ -1,4 +1,4 @@
import { useState, useRef } from "react"; import { useState, useRef, useLayoutEffect } from "react";
import ChartIcon from "@icons/ChartIcon"; import ChartIcon from "@icons/ChartIcon";
import LinkIcon from "@icons/LinkIcon"; import LinkIcon from "@icons/LinkIcon";
import PencilIcon from "@icons/PencilIcon"; import PencilIcon from "@icons/PencilIcon";
@ -15,6 +15,9 @@ import {
} from "@mui/material"; } from "@mui/material";
import { deleteQuiz, setEditQuizId } from "@root/quizes/actions"; import { deleteQuiz, setEditQuizId } from "@root/quizes/actions";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { inCart } from "../../pages/Tariffs/Tariffs";
import { makeRequest } from "@frontend/kitui";
import { enqueueSnackbar } from "notistack";
interface Props { interface Props {
quiz: Quiz; quiz: Quiz;
@ -42,6 +45,28 @@ export default function QuizCard({
const questionCount = useRef(quiz.questions_count.toString() || ""); const questionCount = useRef(quiz.questions_count.toString() || "");
useLayoutEffect(() => {
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 ( return (
<Box <Box
sx={{ sx={{

@ -1,40 +1,237 @@
import Header from "@ui_kit/Header/Header"; import { Header } from "../../src/pages/startPage/Header";
import Sidebar from "@ui_kit/Sidebar"; import Sidebar from "@ui_kit/Sidebar";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import { useTheme, useMediaQuery } from "@mui/material"; import { useTheme, useMediaQuery } from "@mui/material";
import HeaderFull from "@ui_kit/Header/HeaderFull"; import HeaderFull from "@ui_kit/Header/HeaderFull";
import { useEffect, useState } from "react";
import { SidebarMobile } from "./startPage/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";
interface Props { interface Props {
sidebar: boolean; sidebar: boolean;
header?: boolean; header?: boolean;
footer?: boolean;
page: JSX.Element; page: JSX.Element;
} }
export default function Main({ sidebar, header, page }: Props) { export default function Main({ sidebar, header, footer, page }: Props) {
const theme = useTheme(); const theme = useTheme();
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(600)); const isMobile = useMediaQuery(theme.breakpoints.down(600));
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<boolean>(false);
const [nextStep, setNextStep] = useState<number>(0);
const [openBranchingPage, setOpenBranchingPage] = useState<boolean>(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 ( return (
<> <>
{header ? <Header /> : <HeaderFull />} <Header setMobileSidebar={setMobileSidebar} />
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: isMobile ? "column" : "row",
}}
>
{sidebar ? (
<>
{isMobile ? (
<SidebarMobile open={mobileSidebar} changePage={changePage} />
) : (
<Sidebar changePage={changePage} />
)}
</>
) : (
<></>
)}
<Box
sx={{
width: "100%",
height: "calc(100vh - 80px)",
overflow: "hidden",
// padding: isMobile ? "15px" : "25px",
}} }}
> >
{sidebar ? <Sidebar /> : <></>}
<Box <Box
sx={{ sx={{
background: theme.palette.background.default, background: theme.palette.background.default,
width: "100%", width: "100%",
padding: isMobile ? "15px" : "25px", // padding: isMobile ? "15px" : "25px",
height: "calc(100vh - 80px)", // height: "calc(100vh - 80px)",
overflow: "auto", overflow: "auto",
boxSizing: "border-box", boxSizing: "border-box",
}} }}
> >
{page} {page}
</Box> </Box>
{footer && (
<Box
sx={{
width: "100%",
padding: isMobile ? "20px 16px" : "20px 20px",
display: "flex",
justifyContent: isMobile
? isMobileSm
? "center"
: "flex-end"
: "flex-start",
flexDirection: isMobile ? "row-reverse" : "-moz-initial",
alignItems: "center",
gap: "15px",
background: "#FFF",
borderTop: "#f2f3f7 2px solid",
}}
>
{isConditionMet &&
(isBranchingLogic ? (
<SmallSwitchQuestionListGraph
openBranchingPage={openBranchingPage}
setOpenBranchingPage={openBranchingPageHC}
/>
) : (
<PanelSwitchQuestionListGraph
openBranchingPage={openBranchingPage}
setOpenBranchingPage={openBranchingPageHC}
hideText
/>
))}
{/* Кнопка тестового просмотра */}
<ButtonTestPublication />
{/* Кнопка отозвать */}
<ButtonRecallQuiz />
{/* Ссылка */}
{quiz?.status === "start" &&
(!isLinkButton ? (
<Box
component={Link}
sx={{
whiteSpace: "nowrap",
textOverflow: "ellipsis",
overflow: "hidden",
display: isMobile ? "none" : "block",
color: "#7E2AEA",
fontSize: "14px",
}}
target="_blank"
to={"https://hbpn.link/" + quiz.qid}
>
https://hbpn.link/{quiz.qid}
</Box>
) : (
<Box
component={Link}
sx={{
cursor: "pointer",
minWidth: "34px",
height: "34px",
color: "#7E2AEA",
fontSize: "14px",
display: isMobile ? "none" : "flex",
justifyContent: "center",
alignItems: "Center",
background: "#EEE4FC",
borderRadius: "8px",
}}
target="_blank"
to={"https://hbpn.link/" + quiz.qid}
>
<LinkSimple />
</Box>
))}
{/* Маленькая кнопка ссылки */}
{isMobile && quiz?.status === "start" && (
<Box
component={Link}
sx={{
cursor: "pointer",
width: "34px",
height: "34px",
color: "#7E2AEA",
fontSize: "14px",
display: "flex",
justifyContent: "center",
alignItems: "Center",
background: "#EEE4FC",
borderRadius: "8px",
}}
target="_blank"
to={"https://hbpn.link/" + quiz.qid}
>
<LinkSimple />
</Box>
)}
</Box>
)}
</Box>
</Box> </Box>
</> </>
); );

@ -41,65 +41,22 @@ import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate"; import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate";
import { ConfirmLeaveModal } from "./ConfirmLeaveModal"; import { ConfirmLeaveModal } from "./ConfirmLeaveModal";
import { checkQuestionHint } from "@utils/checkQuestionHint"; 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() { export default function EditPage() {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { editQuizId } = useQuizStore(); const { editQuizId } = useQuizStore();
const { questions } = useQuestionsStore(); const { questions } = useQuestionsStore();
console.log(questions); 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 { whyCantCreatePublic, showConfirmLeaveModal } = useUiTools();
const theme = useTheme(); const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
const currentStep = useQuizStore((state) => state.currentStep); const currentStep = useQuizStore((state) => state.currentStep);
const isBranchingLogic = useMediaQuery(theme.breakpoints.down(1100)); const isBranchingLogic = useMediaQuery(theme.breakpoints.down(1100));
const isMobile = useMediaQuery(theme.breakpoints.down(660)); 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<boolean>(false);
const [nextStep, setNextStep] = useState<number>(0); const [nextStep, setNextStep] = useState<number>(0);
const quizConfig = quiz?.config; const quizConfig = quiz?.config;
const [openBranchingPage, setOpenBranchingPage] = useState<boolean>(false); const [openBranchingPage, setOpenBranchingPage] = useState<boolean>(false);
const openBranchingPageHC = () => {
if (!openBranchingPage) {
deleteTimeoutedQuestions(questions, quiz);
}
setOpenBranchingPage((old) => !old);
};
useEffect(() => { useEffect(() => {
if (editQuizId === null) navigate("/list"); if (editQuizId === null) navigate("/list");
}, [navigate, editQuizId]); }, [navigate, editQuizId]);
@ -144,33 +101,14 @@ export default function EditPage() {
const isConditionMet = const isConditionMet =
[1].includes(currentStep) && quizConfig.type !== "form"; [1].includes(currentStep) && quizConfig.type !== "form";
const changePage = (index: number) => {
if (currentStep === 2) {
setNextStep(index);
setShowConfirmLeaveModal(true);
return;
}
setCurrentStep(index);
};
return ( return (
<> <>
<Header setMobileSidebar={setMobileSidebar} />
<Box <Box
sx={{ sx={{
display: isMobile ? "block" : "flex", display: isMobile ? "block" : "flex",
position: "relative", position: "relative",
}} }}
> >
{isMobile ? (
<SidebarMobile open={mobileSidebar} changePage={changePage} />
) : (
<Sidebar changePage={changePage} />
)}
<Box <Box
sx={{ sx={{
background: theme.palette.background.default, background: theme.palette.background.default,
@ -207,103 +145,6 @@ export default function EditPage() {
</> </>
)} )}
</Box> </Box>
<Box
sx={{
width: "100%",
padding: isMobile ? "20px 16px" : "20px 20px",
display: "flex",
justifyContent: isMobile
? isMobileSm
? "center"
: "flex-end"
: "flex-start",
flexDirection: isMobile ? "row-reverse" : "-moz-initial",
alignItems: "center",
gap: "15px",
background: "#FFF",
borderTop: "#f2f3f7 2px solid",
}}
>
{isConditionMet &&
(isBranchingLogic ? (
<SmallSwitchQuestionListGraph
openBranchingPage={openBranchingPage}
setOpenBranchingPage={openBranchingPageHC}
/>
) : (
<PanelSwitchQuestionListGraph
openBranchingPage={openBranchingPage}
setOpenBranchingPage={openBranchingPageHC}
hideText
/>
))}
{/* Кнопка тестового просмотра */}
<ButtonTestPublication />
{/* Кнопка отозвать */}
<ButtonRecallQuiz />
{/* Ссылка */}
{quiz?.status === "start" &&
(!isLinkButton ? (
<Box
component={Link}
sx={{
whiteSpace: "nowrap",
textOverflow: "ellipsis",
overflow: "hidden",
display: isMobile ? "none" : "block",
color: "#7E2AEA",
fontSize: "14px",
}}
target="_blank"
to={"https://hbpn.link/" + quiz.qid}
>
https://hbpn.link/{quiz.qid}
</Box>
) : (
<Box
component={Link}
sx={{
cursor: "pointer",
minWidth: "34px",
height: "34px",
color: "#7E2AEA",
fontSize: "14px",
display: isMobile ? "none" : "flex",
justifyContent: "center",
alignItems: "Center",
background: "#EEE4FC",
borderRadius: "8px",
}}
target="_blank"
to={"https://hbpn.link/" + quiz.qid}
>
<LinkSimple />
</Box>
))}
{/* Маленькая кнопка ссылки */}
{isMobile && quiz?.status === "start" && (
<Box
component={Link}
sx={{
cursor: "pointer",
width: "34px",
height: "34px",
color: "#7E2AEA",
fontSize: "14px",
display: "flex",
justifyContent: "center",
alignItems: "Center",
background: "#EEE4FC",
borderRadius: "8px",
}}
target="_blank"
to={"https://hbpn.link/" + quiz.qid}
>
<LinkSimple />
</Box>
)}
</Box>
</Box> </Box>
</Box> </Box>

@ -80,12 +80,12 @@ export const Header = ({ setMobileSidebar }: HeaderProps) => {
</Link> </Link>
<FormControl fullWidth variant="standard"> <FormControl fullWidth variant="standard">
<TextField <TextField
value={quiz.name} // value={quiz.name}
onChange={(e) => // onChange={(e) =>
updateQuiz(quiz.id, (quiz) => { // updateQuiz(quiz.id, (quiz) => {
quiz.name = e.target.value; // quiz.name = e.target.value;
}) // })
} // }
fullWidth fullWidth
id="project-name" id="project-name"
placeholder="Название проекта окно" placeholder="Название проекта окно"