Merge branch 'input-limit' into support-sse-logic
This commit is contained in:
commit
d5ad04cf3a
@ -430,23 +430,23 @@ const PseudoButton = () => {
|
|||||||
if (!quiz) return null;
|
if (!quiz) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextField
|
<CustomTextField
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
quiz.config.formContact.button = target.value;
|
quiz.config.formContact.button = target.value;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
maxLength={23}
|
||||||
value={quiz.config.formContact.button}
|
value={quiz.config.formContact.button}
|
||||||
sx={{
|
sx={{
|
||||||
heigth: "44px",
|
heigth: "44px",
|
||||||
width: "190px",
|
width: "190px",
|
||||||
"& .MuiInputBase-root": {
|
backgroundColor: "#7E2AEA",
|
||||||
backgroundColor: "#7E2AEA",
|
borderRadius: "8px",
|
||||||
borderRadius: "8px",
|
color: "white",
|
||||||
color: "white",
|
padding: 0,
|
||||||
},
|
|
||||||
"& .MuiInputBase-input": {
|
"& .MuiInputBase-input": {
|
||||||
padding: "10px 20px",
|
padding: "10px 10px",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
},
|
},
|
||||||
"& .MuiInputBase-input::placeholder": {
|
"& .MuiInputBase-input::placeholder": {
|
||||||
@ -454,9 +454,7 @@ const PseudoButton = () => {
|
|||||||
opacity: "1",
|
opacity: "1",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
placeholder="Название кнопки"
|
placeholder={quiz.config.formContact.button || "Название кнопки"}
|
||||||
>
|
/>
|
||||||
{quiz.config.formContact.button || "Название кнопки"}
|
|
||||||
</TextField>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -60,6 +60,7 @@ export default function NewFieldParent({
|
|||||||
value={quiz.config.formContact.fields[defaultValue].text}
|
value={quiz.config.formContact.fields[defaultValue].text}
|
||||||
placeholder={placeholderHelp}
|
placeholder={placeholderHelp}
|
||||||
text={""}
|
text={""}
|
||||||
|
maxLength={20}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ display: "flex", flexDirection: "column", gap: "15px" }}>
|
<Box sx={{ display: "flex", flexDirection: "column", gap: "15px" }}>
|
||||||
@ -74,6 +75,7 @@ export default function NewFieldParent({
|
|||||||
value={quiz.config.formContact.fields[defaultValue].innerText}
|
value={quiz.config.formContact.fields[defaultValue].innerText}
|
||||||
placeholder={placeholderField}
|
placeholder={placeholderField}
|
||||||
text={""}
|
text={""}
|
||||||
|
maxLength={20}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
@ -28,11 +28,18 @@ const ButtonsThemeDark = [
|
|||||||
["Розовый", "PinkDarkTheme", "#D34085", "#FFFFFF"],
|
["Розовый", "PinkDarkTheme", "#D34085", "#FFFFFF"],
|
||||||
["Бирюзовый", "BlueDarkTheme", "#07A0C3", "#FFFFFF"],
|
["Бирюзовый", "BlueDarkTheme", "#07A0C3", "#FFFFFF"],
|
||||||
];
|
];
|
||||||
export const DesignFilling = (mobileSidebar: boolean) => {
|
|
||||||
|
interface Props {
|
||||||
|
mobileSidebar: boolean;
|
||||||
|
heightSidebar: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DesignFilling = ({ mobileSidebar, heightSidebar }: Props) => {
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(830));
|
const isMobile = useMediaQuery(theme.breakpoints.down(830));
|
||||||
|
const heightBar = heightSidebar + 51 + 88 + 36;
|
||||||
|
console.log(mobileSidebar, "111");
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -40,7 +47,7 @@ export const DesignFilling = (mobileSidebar: boolean) => {
|
|||||||
padding: "25px",
|
padding: "25px",
|
||||||
height: isMobile
|
height: isMobile
|
||||||
? mobileSidebar
|
? mobileSidebar
|
||||||
? "calc(100vh - 271px)"
|
? `calc(100vh - ${heightBar}px)`
|
||||||
: "calc(100vh - 127px)"
|
: "calc(100vh - 127px)"
|
||||||
: "calc(100vh - 80px)",
|
: "calc(100vh - 80px)",
|
||||||
}}
|
}}
|
||||||
|
@ -22,7 +22,12 @@ import { DesignFilling } from "./DesignFilling";
|
|||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
import QuizPreview from "@ui_kit/QuizPreview/QuizPreview";
|
import QuizPreview from "@ui_kit/QuizPreview/QuizPreview";
|
||||||
|
|
||||||
export const DesignPage = () => {
|
interface Props {
|
||||||
|
heightSidebar: number;
|
||||||
|
mobileSidebar: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DesignPage = ({ heightSidebar, mobileSidebar }: Props) => {
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
const { editQuizId } = useQuizStore();
|
const { editQuizId } = useQuizStore();
|
||||||
const { showConfirmLeaveModal } = useUiTools();
|
const { showConfirmLeaveModal } = useUiTools();
|
||||||
@ -30,7 +35,6 @@ export const DesignPage = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const currentStep = useQuizStore((state) => state.currentStep);
|
const currentStep = useQuizStore((state) => state.currentStep);
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(660));
|
const isMobile = useMediaQuery(theme.breakpoints.down(660));
|
||||||
const [mobileSidebar, setMobileSidebar] = useState<boolean>(false);
|
|
||||||
const [nextStep, setNextStep] = useState<number>(0);
|
const [nextStep, setNextStep] = useState<number>(0);
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
@ -69,7 +73,10 @@ export const DesignPage = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ display: "flex", flexDirection: isMobile ? "column" : "row" }}>
|
<Box sx={{ display: "flex", flexDirection: isMobile ? "column" : "row" }}>
|
||||||
<DesignFilling mobileSidebar={mobileSidebar} />
|
<DesignFilling
|
||||||
|
mobileSidebar={mobileSidebar}
|
||||||
|
heightSidebar={heightSidebar}
|
||||||
|
/>
|
||||||
{createPortal(<QuizPreview />, document.body)}
|
{createPortal(<QuizPreview />, document.body)}
|
||||||
</Box>
|
</Box>
|
||||||
<ConfirmLeaveModal
|
<ConfirmLeaveModal
|
||||||
|
@ -47,7 +47,7 @@ export const AnswerItem = ({
|
|||||||
const isTablet = useMediaQuery(theme.breakpoints.down(790));
|
const isTablet = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
||||||
|
const [inputValue, setInputValue] = useState("");
|
||||||
const setQuestionVariantAnswer = useDebouncedCallback((value) => {
|
const setQuestionVariantAnswer = useDebouncedCallback((value) => {
|
||||||
setQuestionVariantField(questionId, variant.id, "answer", value);
|
setQuestionVariantField(questionId, variant.id, "answer", value);
|
||||||
}, 200);
|
}, 200);
|
||||||
@ -77,13 +77,17 @@ export const AnswerItem = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
defaultValue={variant.answer}
|
value={variant.answer}
|
||||||
fullWidth
|
fullWidth
|
||||||
focused={false}
|
focused={false}
|
||||||
placeholder={"Добавьте ответ"}
|
placeholder={"Добавьте ответ"}
|
||||||
multiline={largeCheck}
|
multiline={largeCheck}
|
||||||
onChange={({ target }: ChangeEvent<HTMLInputElement>) => {
|
onChange={({ target }: ChangeEvent<HTMLInputElement>) => {
|
||||||
setQuestionVariantAnswer(target.value || " ");
|
if (target.value.length <= 1000) {
|
||||||
|
const inputValue = target.value;
|
||||||
|
setInputValue(inputValue);
|
||||||
|
}
|
||||||
|
setQuestionVariantAnswer(inputValue || " ");
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => {
|
onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => {
|
||||||
if (disableKeyDown) {
|
if (disableKeyDown) {
|
||||||
|
@ -205,8 +205,7 @@ export default function ButtonsOptionsAndPict({
|
|||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
> */}
|
> */}
|
||||||
{question.type !== "text"
|
{question.type !== "text" && (
|
||||||
&&
|
|
||||||
<MiniButtonSetting
|
<MiniButtonSetting
|
||||||
onMouseEnter={() => setButtonHover("branching")}
|
onMouseEnter={() => setButtonHover("branching")}
|
||||||
onMouseLeave={() => setButtonHover("")}
|
onMouseLeave={() => setButtonHover("")}
|
||||||
@ -229,7 +228,9 @@ export default function ButtonsOptionsAndPict({
|
|||||||
: theme.palette.grey3.main,
|
: theme.palette.grey3.main,
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
color:
|
color:
|
||||||
switchState === "branching" ? theme.palette.grey3.main : null,
|
switchState === "branching"
|
||||||
|
? theme.palette.grey3.main
|
||||||
|
: null,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -244,7 +245,7 @@ export default function ButtonsOptionsAndPict({
|
|||||||
/>
|
/>
|
||||||
{isIconMobile ? null : "Ветвление"}
|
{isIconMobile ? null : "Ветвление"}
|
||||||
</MiniButtonSetting>
|
</MiniButtonSetting>
|
||||||
}
|
)}
|
||||||
{/* </Tooltip> */}
|
{/* </Tooltip> */}
|
||||||
<MiniButtonSetting
|
<MiniButtonSetting
|
||||||
onMouseEnter={() => setButtonHover("image")}
|
onMouseEnter={() => setButtonHover("image")}
|
||||||
|
@ -99,6 +99,7 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Выберите вариант"}
|
placeholder={"Выберите вариант"}
|
||||||
text={question.content.default}
|
text={question.content.default}
|
||||||
|
maxLength={60}
|
||||||
onChange={({ target }) => debounceAnswer(target.value)}
|
onChange={({ target }) => debounceAnswer(target.value)}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -51,7 +51,7 @@ export default function Emoji({
|
|||||||
<AnswerDraggableList
|
<AnswerDraggableList
|
||||||
question={question}
|
question={question}
|
||||||
additionalContent={(variant) => (
|
additionalContent={(variant) => (
|
||||||
<>Оооооо, тестовая публикация получа
|
<>
|
||||||
{!isTablet && (
|
{!isTablet && (
|
||||||
<Box sx={{ cursor: "pointer" }}>
|
<Box sx={{ cursor: "pointer" }}>
|
||||||
<Box
|
<Box
|
||||||
|
@ -41,6 +41,7 @@ export default function OptionsAndPicture({
|
|||||||
setOpenBranchingPage,
|
setOpenBranchingPage,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [switchState, setSwitchState] = useState("setting");
|
const [switchState, setSwitchState] = useState("setting");
|
||||||
|
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
|
||||||
const [selectedVariantId, setSelectedVariantId] = useState<string | null>(
|
const [selectedVariantId, setSelectedVariantId] = useState<string | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
@ -66,6 +67,8 @@ export default function OptionsAndPicture({
|
|||||||
const handleImageUpload = async (file: File) => {
|
const handleImageUpload = async (file: File) => {
|
||||||
if (!selectedVariantId) return;
|
if (!selectedVariantId) return;
|
||||||
|
|
||||||
|
setPictureUploading(true);
|
||||||
|
|
||||||
const url = await uploadQuestionImage(
|
const url = await uploadQuestionImage(
|
||||||
question.id,
|
question.id,
|
||||||
quizQid,
|
quizQid,
|
||||||
@ -84,6 +87,8 @@ export default function OptionsAndPicture({
|
|||||||
);
|
);
|
||||||
closeImageUploadModal();
|
closeImageUploadModal();
|
||||||
openCropModal(file, url);
|
openCropModal(file, url);
|
||||||
|
|
||||||
|
setPictureUploading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleCropModalSaveClick(imageBlob: Blob) {
|
function handleCropModalSaveClick(imageBlob: Blob) {
|
||||||
@ -111,6 +116,7 @@ export default function OptionsAndPicture({
|
|||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<AddOrEditImageButton
|
<AddOrEditImageButton
|
||||||
imageSrc={variant.extendedText}
|
imageSrc={variant.extendedText}
|
||||||
|
uploading={pictureUploding}
|
||||||
onImageClick={() => {
|
onImageClick={() => {
|
||||||
setSelectedVariantId(variant.id);
|
setSelectedVariantId(variant.id);
|
||||||
if (variant.extendedText) {
|
if (variant.extendedText) {
|
||||||
@ -136,6 +142,7 @@ export default function OptionsAndPicture({
|
|||||||
{isMobile && (
|
{isMobile && (
|
||||||
<AddOrEditImageButton
|
<AddOrEditImageButton
|
||||||
imageSrc={variant.extendedText}
|
imageSrc={variant.extendedText}
|
||||||
|
uploading={pictureUploding}
|
||||||
onImageClick={() => {
|
onImageClick={() => {
|
||||||
setSelectedVariantId(variant.id);
|
setSelectedVariantId(variant.id);
|
||||||
if (variant.extendedText) {
|
if (variant.extendedText) {
|
||||||
|
@ -24,7 +24,7 @@ export default function SettingOptionsAndPict({
|
|||||||
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
|
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(680));
|
const isMobile = useMediaQuery(theme.breakpoints.down(680));
|
||||||
|
|
||||||
console.log("question.content.replText ", question.content.replText)
|
console.log("question.content.replText ", question.content.replText);
|
||||||
const setReplText = useDebouncedCallback((replText) => {
|
const setReplText = useDebouncedCallback((replText) => {
|
||||||
updateQuestion(question.id, (question) => {
|
updateQuestion(question.id, (question) => {
|
||||||
if (question.type !== "varimg") return;
|
if (question.type !== "varimg") return;
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import {
|
||||||
|
Box,
|
||||||
|
Link,
|
||||||
|
Typography,
|
||||||
|
Skeleton,
|
||||||
|
useMediaQuery,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
import {
|
import {
|
||||||
addQuestionVariant,
|
addQuestionVariant,
|
||||||
uploadQuestionImage,
|
uploadQuestionImage,
|
||||||
@ -30,6 +37,7 @@ export default function OptionsPicture({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const onClickAddAnAnswer = useAddAnswer();
|
const onClickAddAnAnswer = useAddAnswer();
|
||||||
const quizQid = useCurrentQuiz()?.qid;
|
const quizQid = useCurrentQuiz()?.qid;
|
||||||
|
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
|
||||||
const [selectedVariantId, setSelectedVariantId] = useState<string | null>(
|
const [selectedVariantId, setSelectedVariantId] = useState<string | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
@ -53,6 +61,8 @@ export default function OptionsPicture({
|
|||||||
const handleImageUpload = async (file: File) => {
|
const handleImageUpload = async (file: File) => {
|
||||||
if (!selectedVariantId) return;
|
if (!selectedVariantId) return;
|
||||||
|
|
||||||
|
setPictureUploading(true);
|
||||||
|
|
||||||
const url = await uploadQuestionImage(
|
const url = await uploadQuestionImage(
|
||||||
question.id,
|
question.id,
|
||||||
quizQid,
|
quizQid,
|
||||||
@ -69,8 +79,11 @@ export default function OptionsPicture({
|
|||||||
variant.originalImageUrl = url;
|
variant.originalImageUrl = url;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
closeImageUploadModal();
|
closeImageUploadModal();
|
||||||
openCropModal(file, url);
|
openCropModal(file, url);
|
||||||
|
|
||||||
|
setPictureUploading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleCropModalSaveClick(imageBlob: Blob) {
|
function handleCropModalSaveClick(imageBlob: Blob) {
|
||||||
@ -98,6 +111,7 @@ export default function OptionsPicture({
|
|||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<AddOrEditImageButton
|
<AddOrEditImageButton
|
||||||
imageSrc={variant.extendedText}
|
imageSrc={variant.extendedText}
|
||||||
|
uploading={pictureUploding}
|
||||||
onImageClick={() => {
|
onImageClick={() => {
|
||||||
setSelectedVariantId(variant.id);
|
setSelectedVariantId(variant.id);
|
||||||
if (variant.extendedText) {
|
if (variant.extendedText) {
|
||||||
@ -123,6 +137,7 @@ export default function OptionsPicture({
|
|||||||
{isMobile && (
|
{isMobile && (
|
||||||
<AddOrEditImageButton
|
<AddOrEditImageButton
|
||||||
imageSrc={variant.extendedText}
|
imageSrc={variant.extendedText}
|
||||||
|
uploading={pictureUploding}
|
||||||
onImageClick={() => {
|
onImageClick={() => {
|
||||||
setSelectedVariantId(variant.id);
|
setSelectedVariantId(variant.id);
|
||||||
if (variant.extendedText) {
|
if (variant.extendedText) {
|
||||||
|
@ -66,7 +66,7 @@ export default function QuestionsPage({
|
|||||||
margin: "60px 0 40px 0",
|
margin: "60px 0 40px 0",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant={"h5"}>
|
<Typography variant={"h5"} sx={{ wordBreak: "break-word" }}>
|
||||||
{quiz.name ? quiz.name : "Заголовок quiz"}
|
{quiz.name ? quiz.name : "Заголовок quiz"}
|
||||||
</Typography>
|
</Typography>
|
||||||
{!openBranchingPage && (
|
{!openBranchingPage && (
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
import { useState } from "react";
|
||||||
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
|
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
|
||||||
import { Box, ButtonBase, Typography, useTheme } from "@mui/material";
|
import { Box, Skeleton, Typography, useTheme } from "@mui/material";
|
||||||
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
|
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
|
||||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||||
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
|
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
|
||||||
@ -12,6 +13,7 @@ type UploadImageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function UploadImage({ question }: UploadImageProps) {
|
export default function UploadImage({ question }: UploadImageProps) {
|
||||||
|
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
|
|
||||||
@ -29,29 +31,51 @@ export default function UploadImage({ question }: UploadImageProps) {
|
|||||||
>
|
>
|
||||||
Загрузить изображение
|
Загрузить изображение
|
||||||
</Typography>
|
</Typography>
|
||||||
<DropZone
|
{pictureUploding ? (
|
||||||
text={"5 MB максимум"}
|
<Skeleton variant="rounded" sx={{ height: "120px", width: "300px" }} />
|
||||||
|
) : (
|
||||||
|
<DropZone
|
||||||
|
text={"5 MB максимум"}
|
||||||
heightImg={"110px"}
|
heightImg={"110px"}
|
||||||
sx={{ maxWidth: "300px", width: "100%" }}
|
sx={{ maxWidth: "300px", width: "100%" }}
|
||||||
imageUrl={question.content.back}
|
imageUrl={question.content.back}
|
||||||
originalImageUrl={question.content.originalBack}
|
originalImageUrl={question.content.originalBack}
|
||||||
onImageUploadClick={(file) => {
|
onImageUploadClick={async (file) => {
|
||||||
uploadQuestionImage(question.id, quiz.qid, file, (question, url) => {
|
setPictureUploading(true);
|
||||||
question.content.back = url;
|
|
||||||
question.content.originalBack = url;
|
await uploadQuestionImage(
|
||||||
});
|
question.id,
|
||||||
}}
|
quiz.qid,
|
||||||
onDeleteClick={() => {
|
file,
|
||||||
updateQuestion(question.id, (question) => {
|
(question, url) => {
|
||||||
question.content.back = null;
|
question.content.back = url;
|
||||||
});
|
question.content.originalBack = url;
|
||||||
}}
|
},
|
||||||
onImageSaveClick={(file) => {
|
);
|
||||||
uploadQuestionImage(question.id, quiz.qid, file, (question, url) => {
|
|
||||||
question.content.back = url;
|
setPictureUploading(false);
|
||||||
});
|
}}
|
||||||
}}
|
onDeleteClick={() => {
|
||||||
/>
|
updateQuestion(question.id, (question) => {
|
||||||
|
question.content.back = null;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onImageSaveClick={async (file) => {
|
||||||
|
setPictureUploading(true);
|
||||||
|
|
||||||
|
await uploadQuestionImage(
|
||||||
|
question.id,
|
||||||
|
quiz.qid,
|
||||||
|
file,
|
||||||
|
(question, url) => {
|
||||||
|
question.content.back = url;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
setPictureUploading(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,7 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
const [expand, setExpand] = useState(true);
|
const [expand, setExpand] = useState(true);
|
||||||
const [resultCardSettings, setResultCardSettings] = useState(false);
|
const [resultCardSettings, setResultCardSettings] = useState(false);
|
||||||
const [buttonPlus, setButtonPlus] = useState(true);
|
const [buttonPlus, setButtonPlus] = useState(true);
|
||||||
|
const [inputValue, setInputValue] = useState("");
|
||||||
const question = getQuestionByContentId(resultData.content.rule.parentId);
|
const question = getQuestionByContentId(resultData.content.rule.parentId);
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
|
|
||||||
@ -328,12 +329,16 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
<TextField
|
<TextField
|
||||||
id="heading-description"
|
id="heading-description"
|
||||||
value={resultData.content.text}
|
value={resultData.content.text}
|
||||||
onChange={({ target }: { target: HTMLInputElement }) =>
|
onChange={({ target }: { target: HTMLInputElement }) => {
|
||||||
|
if (target.value.length <= 3000) {
|
||||||
|
const inputValue = target.value;
|
||||||
|
setInputValue(inputValue);
|
||||||
|
}
|
||||||
updateQuestion(
|
updateQuestion(
|
||||||
resultData.id,
|
resultData.id,
|
||||||
(question) => (question.content.text = target.value),
|
(question) => (question.content.text = inputValue),
|
||||||
)
|
);
|
||||||
}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="Описание"
|
placeholder="Описание"
|
||||||
multiline
|
multiline
|
||||||
|
@ -258,7 +258,7 @@ function TariffPage() {
|
|||||||
component="h2"
|
component="h2"
|
||||||
mb="20px"
|
mb="20px"
|
||||||
>
|
>
|
||||||
Вы подтверждаете платёж в сумму {openModal.price}
|
Вы подтверждаете платёж в сумму {openModal.price} ₽
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button variant="contained" onClick={() => tryBuy(openModal)}>
|
<Button variant="contained" onClick={() => tryBuy(openModal)}>
|
||||||
купить
|
купить
|
||||||
|
@ -95,8 +95,9 @@ export default function Main({ sidebar, header, footer, Page }: Props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const [widthMain, setWidthMain] = useState(null);
|
const [widthMain, setWidthMain] = useState(null);
|
||||||
|
const [heightSidebar, setHeightSidebar] = useState(null);
|
||||||
const mainBlock = useRef(0);
|
const mainBlock = useRef(0);
|
||||||
|
const heightHeader = heightSidebar + 51 + 36;
|
||||||
const observer = useRef(
|
const observer = useRef(
|
||||||
new ResizeObserver((entries) => {
|
new ResizeObserver((entries) => {
|
||||||
const { width } = entries[0].contentRect;
|
const { width } = entries[0].contentRect;
|
||||||
@ -121,7 +122,11 @@ export default function Main({ sidebar, header, footer, Page }: Props) {
|
|||||||
{sidebar ? (
|
{sidebar ? (
|
||||||
<>
|
<>
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
<SidebarMobile open={mobileSidebar} changePage={changePage} />
|
<SidebarMobile
|
||||||
|
open={mobileSidebar}
|
||||||
|
changePage={changePage}
|
||||||
|
setHeightSitebar={setHeightSidebar}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Sidebar changePage={changePage} />
|
<Sidebar changePage={changePage} />
|
||||||
)}
|
)}
|
||||||
@ -134,7 +139,7 @@ export default function Main({ sidebar, header, footer, Page }: Props) {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
height: isMobile
|
height: isMobile
|
||||||
? mobileSidebar
|
? mobileSidebar
|
||||||
? "calc(100vh - 195px)"
|
? `calc(100vh - ${heightHeader}px)`
|
||||||
: "calc(100vh - 51px)"
|
: "calc(100vh - 51px)"
|
||||||
: "calc(100vh - 80px)",
|
: "calc(100vh - 80px)",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -157,6 +162,7 @@ export default function Main({ sidebar, header, footer, Page }: Props) {
|
|||||||
setOpenBranchingPage={openBranchingPageHC}
|
setOpenBranchingPage={openBranchingPageHC}
|
||||||
widthMain={widthMain}
|
widthMain={widthMain}
|
||||||
mobileSidebar={mobileSidebar}
|
mobileSidebar={mobileSidebar}
|
||||||
|
heightSidebar={heightSidebar}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
@ -47,12 +47,14 @@ interface Props {
|
|||||||
setOpenBranchingPage: (a: boolean) => void;
|
setOpenBranchingPage: (a: boolean) => void;
|
||||||
widthMain: number;
|
widthMain: number;
|
||||||
mobileSidebar: boolean;
|
mobileSidebar: boolean;
|
||||||
|
heightSidebar: number;
|
||||||
}
|
}
|
||||||
export default function EditPage({
|
export default function EditPage({
|
||||||
openBranchingPage,
|
openBranchingPage,
|
||||||
setOpenBranchingPage,
|
setOpenBranchingPage,
|
||||||
widthMain,
|
widthMain,
|
||||||
mobileSidebar,
|
mobileSidebar,
|
||||||
|
heightSidebar,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
const { editQuizId } = useQuizStore();
|
const { editQuizId } = useQuizStore();
|
||||||
@ -67,6 +69,7 @@ export default function EditPage({
|
|||||||
const quizConfig = quiz?.config;
|
const quizConfig = quiz?.config;
|
||||||
// const [openBranchingPage, setOpenBranchingPage] = useState<boolean>(false);
|
// const [openBranchingPage, setOpenBranchingPage] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const heightBar = heightSidebar + 51 + 88 + 23;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (editQuizId === null) navigate("/list");
|
if (editQuizId === null) navigate("/list");
|
||||||
}, [navigate, editQuizId]);
|
}, [navigate, editQuizId]);
|
||||||
@ -133,7 +136,7 @@ export default function EditPage({
|
|||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
height: isMobile
|
height: isMobile
|
||||||
? mobileSidebar
|
? mobileSidebar
|
||||||
? `calc(100vh - 269px)`
|
? `calc(100vh - ${heightBar}px)`
|
||||||
: `calc(100vh - 125px)`
|
: `calc(100vh - 125px)`
|
||||||
: isConditionMet
|
: isConditionMet
|
||||||
? isBranchingLogic
|
? isBranchingLogic
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
|
Skeleton,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
@ -72,6 +73,9 @@ export default function StartPageSettings() {
|
|||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
const [formState, setFormState] = useState<"design" | "content">("design");
|
const [formState, setFormState] = useState<"design" | "content">("design");
|
||||||
const [mobileVersion, setMobileVersion] = useState(false);
|
const [mobileVersion, setMobileVersion] = useState(false);
|
||||||
|
const [faviconUploding, setFaviconUploading] = useState<boolean>(false);
|
||||||
|
const [backgroundUploding, setBackgroundUploading] = useState<boolean>(false);
|
||||||
|
const [logoUploding, setLogoUploading] = useState<boolean>(false);
|
||||||
|
|
||||||
if (!quiz) return null;
|
if (!quiz) return null;
|
||||||
|
|
||||||
@ -81,14 +85,20 @@ export default function StartPageSettings() {
|
|||||||
|
|
||||||
const designType = quiz?.config?.startpageType;
|
const designType = quiz?.config?.startpageType;
|
||||||
|
|
||||||
const favIconDropZoneElement = (
|
const favIconDropZoneElement = faviconUploding ? (
|
||||||
|
<Skeleton sx={{ width: "48px", height: "48px", transform: "none" }} />
|
||||||
|
) : (
|
||||||
<FaviconDropZone
|
<FaviconDropZone
|
||||||
imageUrl={quiz.config.startpage.favIcon}
|
imageUrl={quiz.config.startpage.favIcon}
|
||||||
onImageUploadClick={async (file) => {
|
onImageUploadClick={async (file) => {
|
||||||
|
setFaviconUploading(true);
|
||||||
const resizedImage = await resizeFavIcon(file);
|
const resizedImage = await resizeFavIcon(file);
|
||||||
uploadQuizImage(quiz.id, resizedImage, (quiz, url) => {
|
|
||||||
|
await uploadQuizImage(quiz.id, resizedImage, (quiz, url) => {
|
||||||
quiz.config.startpage.favIcon = url;
|
quiz.config.startpage.favIcon = url;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setFaviconUploading(false);
|
||||||
}}
|
}}
|
||||||
onDeleteClick={() => {
|
onDeleteClick={() => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
@ -327,30 +337,47 @@ export default function StartPageSettings() {
|
|||||||
>
|
>
|
||||||
Изображение
|
Изображение
|
||||||
</Typography>
|
</Typography>
|
||||||
<DropZone
|
{backgroundUploding ? (
|
||||||
value={"5 MB максимум"}
|
<Skeleton
|
||||||
sx={{ maxWidth: "300px" }}
|
sx={{
|
||||||
imageUrl={quiz.config.startpage.background.desktop}
|
width: "300px",
|
||||||
originalImageUrl={
|
height: "120px",
|
||||||
quiz.config.startpage.background.originalDesktop
|
transform: "none",
|
||||||
}
|
}}
|
||||||
onImageUploadClick={(file) => {
|
/>
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
) : (
|
||||||
quiz.config.startpage.background.desktop = url;
|
<DropZone
|
||||||
quiz.config.startpage.background.originalDesktop = url;
|
text={"5 MB максимум"}
|
||||||
});
|
sx={{ maxWidth: "300px" }}
|
||||||
}}
|
imageUrl={quiz.config.startpage.background.desktop}
|
||||||
onImageSaveClick={(file) => {
|
originalImageUrl={
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
quiz.config.startpage.background.originalDesktop
|
||||||
quiz.config.startpage.background.desktop = url;
|
}
|
||||||
});
|
onImageUploadClick={async (file) => {
|
||||||
}}
|
setBackgroundUploading(true);
|
||||||
onDeleteClick={() => {
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
quiz.config.startpage.background.desktop = url;
|
||||||
quiz.config.startpage.background.desktop = null;
|
quiz.config.startpage.background.originalDesktop =
|
||||||
});
|
url;
|
||||||
}}
|
});
|
||||||
/>
|
|
||||||
|
setBackgroundUploading(false);
|
||||||
|
}}
|
||||||
|
onImageSaveClick={async (file) => {
|
||||||
|
setBackgroundUploading(true);
|
||||||
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
|
quiz.config.startpage.background.desktop = url;
|
||||||
|
});
|
||||||
|
|
||||||
|
setBackgroundUploading(false);
|
||||||
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
|
quiz.config.startpage.background.desktop = null;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<ModalSizeImage />
|
<ModalSizeImage />
|
||||||
@ -383,47 +410,68 @@ export default function StartPageSettings() {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<ButtonBase
|
{backgroundUploding ? (
|
||||||
component="label"
|
<Skeleton
|
||||||
sx={{
|
|
||||||
justifyContent: "center",
|
|
||||||
height: "48px",
|
|
||||||
width: "48px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
my: "20px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
onChange={(event) => {
|
|
||||||
const file = event.target.files?.[0];
|
|
||||||
if (file) {
|
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
|
||||||
quiz.config.startpage.background.video = url;
|
|
||||||
});
|
|
||||||
// setVideo(URL.createObjectURL(file));
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
hidden
|
|
||||||
accept=".mp4"
|
|
||||||
multiple
|
|
||||||
type="file"
|
|
||||||
/>
|
|
||||||
<UploadBox
|
|
||||||
icon={<UploadIcon />}
|
|
||||||
sx={{
|
sx={{
|
||||||
height: "48px",
|
|
||||||
width: "48px",
|
width: "48px",
|
||||||
|
height: "48px",
|
||||||
|
transform: "none",
|
||||||
|
margin: "20px 0",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ButtonBase>
|
) : (
|
||||||
{quiz.config.startpage.background.video ? (
|
<>
|
||||||
<video
|
<ButtonBase
|
||||||
src={quiz.config.startpage.background.video}
|
component="label"
|
||||||
width="400"
|
sx={{
|
||||||
controls
|
justifyContent: "center",
|
||||||
/>
|
height: "48px",
|
||||||
) : null}
|
width: "48px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
my: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
onChange={async (event) => {
|
||||||
|
setBackgroundUploading(true);
|
||||||
|
const file = event.target.files?.[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
await uploadQuizImage(
|
||||||
|
quiz.id,
|
||||||
|
file,
|
||||||
|
(quiz, url) => {
|
||||||
|
quiz.config.startpage.background.video = url;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
// setVideo(URL.createObjectURL(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
setBackgroundUploading(false);
|
||||||
|
}}
|
||||||
|
hidden
|
||||||
|
accept=".mp4"
|
||||||
|
multiple
|
||||||
|
type="file"
|
||||||
|
/>
|
||||||
|
<UploadBox
|
||||||
|
icon={<UploadIcon />}
|
||||||
|
sx={{
|
||||||
|
height: "48px",
|
||||||
|
width: "48px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ButtonBase>
|
||||||
|
{quiz.config.startpage.background.video && (
|
||||||
|
<video
|
||||||
|
src={quiz.config.startpage.background.video}
|
||||||
|
width="400"
|
||||||
|
controls
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{designType !== "centered" && (
|
{designType !== "centered" && (
|
||||||
@ -497,28 +545,44 @@ export default function StartPageSettings() {
|
|||||||
>
|
>
|
||||||
Логотип
|
Логотип
|
||||||
</Typography>
|
</Typography>
|
||||||
<DropZone
|
{logoUploding ? (
|
||||||
value={"5 MB максимум"}
|
<Skeleton
|
||||||
sx={{ maxWidth: "300px" }}
|
sx={{
|
||||||
imageUrl={quiz.config.startpage.logo}
|
width: "300px",
|
||||||
originalImageUrl={quiz.config.startpage.originalLogo}
|
height: "120px",
|
||||||
onImageUploadClick={(file) => {
|
transform: "none",
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
}}
|
||||||
quiz.config.startpage.logo = url;
|
/>
|
||||||
quiz.config.startpage.originalLogo = url;
|
) : (
|
||||||
});
|
<DropZone
|
||||||
}}
|
text={"5 MB максимум"}
|
||||||
onImageSaveClick={(file) => {
|
sx={{ maxWidth: "300px" }}
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
imageUrl={quiz.config.startpage.logo}
|
||||||
quiz.config.startpage.logo = url;
|
originalImageUrl={quiz.config.startpage.originalLogo}
|
||||||
});
|
onImageUploadClick={async (file) => {
|
||||||
}}
|
setLogoUploading(true);
|
||||||
onDeleteClick={() => {
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
quiz.config.startpage.logo = url;
|
||||||
quiz.config.startpage.logo = null;
|
quiz.config.startpage.originalLogo = url;
|
||||||
});
|
});
|
||||||
}}
|
|
||||||
/>
|
setLogoUploading(false);
|
||||||
|
}}
|
||||||
|
onImageSaveClick={async (file) => {
|
||||||
|
setLogoUploading(true);
|
||||||
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
|
quiz.config.startpage.logo = url;
|
||||||
|
});
|
||||||
|
|
||||||
|
setLogoUploading(false);
|
||||||
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
|
quiz.config.startpage.logo = null;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Typography
|
<Typography
|
||||||
@ -564,28 +628,44 @@ export default function StartPageSettings() {
|
|||||||
>
|
>
|
||||||
Логотип
|
Логотип
|
||||||
</Typography>
|
</Typography>
|
||||||
<DropZone
|
{logoUploding ? (
|
||||||
value={"5 MB максимум"}
|
<Skeleton
|
||||||
sx={{ maxWidth: "300px" }}
|
sx={{
|
||||||
imageUrl={quiz.config.startpage.logo}
|
width: "300px",
|
||||||
originalImageUrl={quiz.config.startpage.originalLogo}
|
height: "120px",
|
||||||
onImageUploadClick={(file) => {
|
transform: "none",
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
}}
|
||||||
quiz.config.startpage.logo = url;
|
/>
|
||||||
quiz.config.startpage.originalLogo = url;
|
) : (
|
||||||
});
|
<DropZone
|
||||||
}}
|
text={"5 MB максимум"}
|
||||||
onImageSaveClick={(file) => {
|
sx={{ maxWidth: "300px" }}
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
imageUrl={quiz.config.startpage.logo}
|
||||||
quiz.config.startpage.logo = url;
|
originalImageUrl={quiz.config.startpage.originalLogo}
|
||||||
});
|
onImageUploadClick={async (file) => {
|
||||||
}}
|
setLogoUploading(true);
|
||||||
onDeleteClick={() => {
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
quiz.config.startpage.logo = url;
|
||||||
quiz.config.startpage.logo = null;
|
quiz.config.startpage.originalLogo = url;
|
||||||
});
|
});
|
||||||
}}
|
|
||||||
/>
|
setLogoUploading(false);
|
||||||
|
}}
|
||||||
|
onImageSaveClick={async (file) => {
|
||||||
|
setLogoUploading(true);
|
||||||
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
|
quiz.config.startpage.logo = url;
|
||||||
|
});
|
||||||
|
|
||||||
|
setLogoUploading(false);
|
||||||
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
|
quiz.config.startpage.logo = null;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Typography
|
<Typography
|
||||||
@ -621,7 +701,7 @@ export default function StartPageSettings() {
|
|||||||
quiz.name = e.target.value;
|
quiz.name = e.target.value;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
maxLength={40}
|
maxLength={200}
|
||||||
/>
|
/>
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
import { Box, Button, Skeleton, useTheme, useMediaQuery } from "@mui/material";
|
||||||
import Plus from "@icons/questionsPage/plus";
|
import Plus from "@icons/questionsPage/plus";
|
||||||
import { Box, Button, SxProps, Theme } from "@mui/material";
|
|
||||||
import Image from "../assets/icons/questionsPage/image";
|
import Image from "../assets/icons/questionsPage/image";
|
||||||
|
|
||||||
|
import type { SxProps, Theme } from "@mui/material";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
sx?: SxProps<Theme>;
|
sx?: SxProps<Theme>;
|
||||||
imageSrc?: string;
|
imageSrc?: string;
|
||||||
onImageClick?: () => void;
|
onImageClick?: () => void;
|
||||||
onPlusClick?: () => void;
|
onPlusClick?: () => void;
|
||||||
|
uploading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AddOrEditImageButton({
|
export default function AddOrEditImageButton({
|
||||||
@ -14,59 +17,76 @@ export default function AddOrEditImageButton({
|
|||||||
onPlusClick,
|
onPlusClick,
|
||||||
sx,
|
sx,
|
||||||
imageSrc,
|
imageSrc,
|
||||||
|
uploading = false,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<>
|
||||||
sx={{
|
{uploading ? (
|
||||||
display: "flex",
|
<Skeleton
|
||||||
height: "40px",
|
variant="rounded"
|
||||||
minWidth: "60px",
|
sx={{
|
||||||
width: "60px",
|
height: "40px",
|
||||||
borderRadius: "3px",
|
width: isMobile ? "auto" : "80px",
|
||||||
overflow: "hidden",
|
margin: isMobile ? "8px" : "0 10px 0 8px",
|
||||||
...sx,
|
}}
|
||||||
}}
|
/>
|
||||||
>
|
) : (
|
||||||
<Button
|
<Box
|
||||||
onClick={onImageClick}
|
sx={{
|
||||||
sx={{
|
display: "flex",
|
||||||
p: 0,
|
height: "40px",
|
||||||
minWidth: "40px",
|
minWidth: "60px",
|
||||||
flexGrow: 1,
|
width: "60px",
|
||||||
backgroundColor: "#EEE4FC",
|
borderRadius: "3px",
|
||||||
}}
|
overflow: "hidden",
|
||||||
>
|
...sx,
|
||||||
{imageSrc ? (
|
}}
|
||||||
<img
|
>
|
||||||
src={imageSrc}
|
<Button
|
||||||
alt=""
|
onClick={onImageClick}
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
objectFit: "scale-down",
|
|
||||||
display: "block",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Image
|
|
||||||
sx={{
|
sx={{
|
||||||
height: "100%",
|
p: 0,
|
||||||
width: "100%",
|
minWidth: "40px",
|
||||||
|
flexGrow: 1,
|
||||||
|
backgroundColor: "#EEE4FC",
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
)}
|
{imageSrc ? (
|
||||||
</Button>
|
<img
|
||||||
<Button
|
src={imageSrc}
|
||||||
onClick={onPlusClick}
|
alt=""
|
||||||
data-cy="add-image-button"
|
style={{
|
||||||
sx={{
|
width: "100%",
|
||||||
p: 0,
|
height: "100%",
|
||||||
minWidth: "20px",
|
objectFit: "scale-down",
|
||||||
width: "20px",
|
display: "block",
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
<Plus />
|
) : (
|
||||||
</Button>
|
<Image
|
||||||
</Box>
|
sx={{
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={onPlusClick}
|
||||||
|
data-cy="add-image-button"
|
||||||
|
sx={{
|
||||||
|
p: 0,
|
||||||
|
minWidth: "20px",
|
||||||
|
width: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Plus />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FC } from "react";
|
import { useState, FC } from "react";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
@ -25,6 +25,7 @@ interface Iprops {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
|
export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
|
||||||
|
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
|
||||||
const quizQid = useCurrentQuiz()?.qid;
|
const quizQid = useCurrentQuiz()?.qid;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const {
|
const {
|
||||||
@ -38,6 +39,8 @@ export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
|
|||||||
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] =
|
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] =
|
||||||
useDisclosure();
|
useDisclosure();
|
||||||
async function handleImageUpload(file: File) {
|
async function handleImageUpload(file: File) {
|
||||||
|
setPictureUploading(true);
|
||||||
|
|
||||||
const url = await uploadQuestionImage(
|
const url = await uploadQuestionImage(
|
||||||
resultData.id,
|
resultData.id,
|
||||||
quizQid,
|
quizQid,
|
||||||
@ -49,6 +52,8 @@ export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
|
|||||||
);
|
);
|
||||||
closeImageUploadModal();
|
closeImageUploadModal();
|
||||||
openCropModal(file, url);
|
openCropModal(file, url);
|
||||||
|
|
||||||
|
setPictureUploading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCropModalSaveClick(imageBlob: Blob) {
|
function handleCropModalSaveClick(imageBlob: Blob) {
|
||||||
@ -142,6 +147,7 @@ export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
|
|||||||
>
|
>
|
||||||
<AddOrEditImageButton
|
<AddOrEditImageButton
|
||||||
imageSrc={resultData.content.back}
|
imageSrc={resultData.content.back}
|
||||||
|
uploading={pictureUploding}
|
||||||
onImageClick={() => {
|
onImageClick={() => {
|
||||||
if (resultData.content.back) {
|
if (resultData.content.back) {
|
||||||
return openCropModal(
|
return openCropModal(
|
||||||
|
@ -32,6 +32,7 @@ import { clearUserData } from "@root/user";
|
|||||||
interface Iprops {
|
interface Iprops {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
changePage: (step: number) => void;
|
changePage: (step: number) => void;
|
||||||
|
setHeightSitebar: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const quizSetupSteps = [
|
const quizSetupSteps = [
|
||||||
@ -46,12 +47,29 @@ const quizSetupSteps = [
|
|||||||
{ sidebarIcon: <Question style={{ color: "#974BFA", fontSize: "24px" }} /> },
|
{ sidebarIcon: <Question style={{ color: "#974BFA", fontSize: "24px" }} /> },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const SidebarMobile: FC<Iprops> = ({ open, changePage }) => {
|
export const SidebarMobile: FC<Iprops> = ({
|
||||||
|
open,
|
||||||
|
changePage,
|
||||||
|
setHeightSitebar,
|
||||||
|
}) => {
|
||||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||||
const [inputOpen, setInputOpen] = useState<boolean>(false);
|
const [inputOpen, setInputOpen] = useState<boolean>(false);
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
const heightSidebar = useRef(null);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const observer = useRef(
|
||||||
|
new ResizeObserver((entries) => {
|
||||||
|
const { height } = entries[0].contentRect;
|
||||||
|
setHeightSitebar(height);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
observer.current.observe(heightSidebar.current);
|
||||||
|
}, [heightSidebar, observer]);
|
||||||
|
|
||||||
const handleClick = (event) => {
|
const handleClick = (event) => {
|
||||||
setAnchorEl(anchorEl ? null : event.currentTarget);
|
setAnchorEl(anchorEl ? null : event.currentTarget);
|
||||||
};
|
};
|
||||||
@ -80,6 +98,7 @@ export const SidebarMobile: FC<Iprops> = ({ open, changePage }) => {
|
|||||||
const id = openPopper ? "simple-popper" : undefined;
|
const id = openPopper ? "simple-popper" : undefined;
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
ref={heightSidebar}
|
||||||
sx={{
|
sx={{
|
||||||
display: open ? "block" : "none",
|
display: open ? "block" : "none",
|
||||||
minHeight: "134px",
|
minHeight: "134px",
|
||||||
@ -148,7 +167,9 @@ export const SidebarMobile: FC<Iprops> = ({ open, changePage }) => {
|
|||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
) : (
|
) : (
|
||||||
<Typography color={"white"}>{quiz.name}</Typography>
|
<Typography color={"white"} sx={{ wordBreak: "break-word" }}>
|
||||||
|
{quiz.name}
|
||||||
|
</Typography>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<IconButton onClick={() => setInputOpen(true)}>
|
<IconButton onClick={() => setInputOpen(true)}>
|
||||||
|
Loading…
Reference in New Issue
Block a user