Merge branch 'staging'
This commit is contained in:
commit
a461c8dc3d
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
1.0.2 Страничка результатов способна показать историю и правильность ответов для балловго квиза
|
||||||
|
1.0.1 Отображение для баллового квиза на страничке результатов списка
|
||||||
|
1.0.0 Добавлены фичи "мультиответ", "перенос строки в своём ответе", "свой ответ", "плейсхолдер своего ответа"
|
@ -3,9 +3,13 @@ include:
|
|||||||
file: "/templates/docker/build-template.gitlab-ci.yml"
|
file: "/templates/docker/build-template.gitlab-ci.yml"
|
||||||
- project: "devops/pena-continuous-integration"
|
- project: "devops/pena-continuous-integration"
|
||||||
file: "/templates/docker/deploy-template.gitlab-ci.yml"
|
file: "/templates/docker/deploy-template.gitlab-ci.yml"
|
||||||
|
- project: "devops/pena-continuous-integration"
|
||||||
|
file: "/templates/docker/service-discovery.gitlab-ci.yml"
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- deploy
|
- deploy
|
||||||
|
- service-discovery
|
||||||
|
|
||||||
build-app:
|
build-app:
|
||||||
tags:
|
tags:
|
||||||
- frontbuild
|
- frontbuild
|
||||||
@ -30,3 +34,6 @@ deploy-to-prod:
|
|||||||
tags:
|
tags:
|
||||||
- front
|
- front
|
||||||
- prod
|
- prod
|
||||||
|
|
||||||
|
service-discovery:
|
||||||
|
extends: .sd_artefacts_template
|
||||||
|
@ -3,6 +3,9 @@ services:
|
|||||||
respondent:
|
respondent:
|
||||||
container_name: respondent
|
container_name: respondent
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
com.pena.domains: s.hbpn.link
|
||||||
|
com.pena.front_headers: "Access-Control-Allow-Origin $$http_origin always"
|
||||||
image: $CI_REGISTRY_IMAGE/staging:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID
|
image: $CI_REGISTRY_IMAGE/staging:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID
|
||||||
hostname: respondent
|
hostname: respondent
|
||||||
tty: true
|
tty: true
|
||||||
|
@ -20,9 +20,13 @@ import { ApologyPage } from "./ViewPublicationPage/ApologyPage";
|
|||||||
import ViewPublicationPage from "./ViewPublicationPage/ViewPublicationPage";
|
import ViewPublicationPage from "./ViewPublicationPage/ViewPublicationPage";
|
||||||
import { HelmetProvider } from "react-helmet-async";
|
import { HelmetProvider } from "react-helmet-async";
|
||||||
|
|
||||||
|
import "moment/dist/locale/ru";
|
||||||
moment.locale("ru");
|
moment.locale("ru");
|
||||||
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
|
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
|
||||||
|
|
||||||
|
console.log(localeText);
|
||||||
|
console.log(moment);
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
quizSettings?: QuizSettings;
|
quizSettings?: QuizSettings;
|
||||||
quizId: string;
|
quizId: string;
|
||||||
|
@ -32,8 +32,6 @@ type Props = {
|
|||||||
};
|
};
|
||||||
//Костыль для особого квиза. Для него не нужно показывать email адрес
|
//Костыль для особого квиза. Для него не нужно показывать email адрес
|
||||||
const isDisableEmail = window.location.pathname.includes("/377c7570-1bee-4320-ac1e-d731b6223ce8");
|
const isDisableEmail = window.location.pathname.includes("/377c7570-1bee-4320-ac1e-d731b6223ce8");
|
||||||
console.log("isDisableEmail");
|
|
||||||
console.log(isDisableEmail);
|
|
||||||
|
|
||||||
export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
|
export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -120,8 +118,6 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
|
|||||||
async function handleShowResultsClick() {
|
async function handleShowResultsClick() {
|
||||||
const FC = settings.cfg.formContact.fields;
|
const FC = settings.cfg.formContact.fields;
|
||||||
|
|
||||||
console.log("некорректная");
|
|
||||||
console.log(!isDisableEmail && FC["email"].used !== EMAIL_REGEXP.test(email));
|
|
||||||
if (!isDisableEmail && FC["email"].used !== EMAIL_REGEXP.test(email)) {
|
if (!isDisableEmail && FC["email"].used !== EMAIL_REGEXP.test(email)) {
|
||||||
return enqueueSnackbar("введена некорректная почта");
|
return enqueueSnackbar("введена некорректная почта");
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,6 @@ export const Inputs = ({
|
|||||||
const { settings } = useQuizSettings();
|
const { settings } = useQuizSettings();
|
||||||
const FC = settings.cfg.formContact.fields;
|
const FC = settings.cfg.formContact.fields;
|
||||||
|
|
||||||
console.log("crutch.disableEmail");
|
|
||||||
console.log(crutch.disableEmail);
|
|
||||||
|
|
||||||
if (!FC) return null;
|
if (!FC) return null;
|
||||||
const Name = (
|
const Name = (
|
||||||
<CustomInput
|
<CustomInput
|
||||||
|
@ -43,7 +43,10 @@ export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
|
|||||||
<Typography sx={{ color: theme.palette.text.primary }}>
|
<Typography sx={{ color: theme.palette.text.primary }}>
|
||||||
Вопрос {stepNumber} из {questionsAmount}
|
Вопрос {stepNumber} из {questionsAmount}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Stepper activeStep={stepNumber} steps={questionsAmount} />
|
<Stepper
|
||||||
|
activeStep={stepNumber}
|
||||||
|
steps={questionsAmount}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{prevButton}
|
{prevButton}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
import { Box, Button, Link, Typography, useTheme } from "@mui/material";
|
import { Box, Button, Link, Typography, useTheme } from "@mui/material";
|
||||||
|
|
||||||
import { useQuizViewStore } from "@/stores/quizView";
|
import { useQuizViewStore } from "@/stores/quizView";
|
||||||
@ -76,6 +76,16 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const choiceImgUrlQuestion = useMemo(() => {
|
||||||
|
if (
|
||||||
|
resultQuestion.content.editedUrlImagesList !== undefined &&
|
||||||
|
resultQuestion.content.editedUrlImagesList !== null
|
||||||
|
) {
|
||||||
|
return resultQuestion.content.editedUrlImagesList[isMobile ? "mobile" : isTablet ? "tablet" : "desktop"];
|
||||||
|
} else {
|
||||||
|
return resultQuestion.content.back;
|
||||||
|
}
|
||||||
|
}, [resultQuestion]);
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -166,7 +176,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{resultQuestion?.content.useImage && resultQuestion.content.back && (
|
{resultQuestion?.content.useImage && choiceImgUrlQuestion && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@ -176,7 +186,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
alt="resultImage"
|
alt="resultImage"
|
||||||
src={resultQuestion.content.back}
|
src={choiceImgUrlQuestion}
|
||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: spec ? "auto" : isMobile ? "236px" : "306px",
|
height: spec ? "auto" : isMobile ? "236px" : "306px",
|
||||||
|
@ -20,8 +20,9 @@ import NextButton from "./tools/NextButton";
|
|||||||
import PrevButton from "./tools/PrevButton";
|
import PrevButton from "./tools/PrevButton";
|
||||||
|
|
||||||
export default function ViewPublicationPage() {
|
export default function ViewPublicationPage() {
|
||||||
const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizSettings();
|
const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle, questions } = useQuizSettings();
|
||||||
const answers = useQuizViewStore((state) => state.answers);
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
|
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
||||||
let currentQuizStep = useQuizViewStore((state) => state.currentQuizStep);
|
let currentQuizStep = useQuizViewStore((state) => state.currentQuizStep);
|
||||||
const {
|
const {
|
||||||
currentQuestion,
|
currentQuestion,
|
||||||
@ -99,7 +100,7 @@ export default function ViewPublicationPage() {
|
|||||||
|
|
||||||
if (preview) return;
|
if (preview) return;
|
||||||
|
|
||||||
sendQuestionAnswer(quizId, currentQuestion, currentAnswer)?.catch((e) => {
|
sendQuestionAnswer(quizId, currentQuestion, currentAnswer, ownVariants)?.catch((e) => {
|
||||||
enqueueSnackbar("Ошибка при отправке ответа");
|
enqueueSnackbar("Ошибка при отправке ответа");
|
||||||
console.error("Error sending answer", e);
|
console.error("Error sending answer", e);
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
import { useQuizViewStore } from "@/stores/quizView";
|
||||||
|
import { useQuizSettings } from "@contexts/QuizDataContext";
|
||||||
|
import CalendarIcon from "@icons/CalendarIcon";
|
||||||
|
import type { QuizQuestionDate } from "@model/questionTypes/date";
|
||||||
|
import { Box, Typography, useTheme } from "@mui/material";
|
||||||
|
import { DatePicker } from "@mui/x-date-pickers";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
import type { Moment } from "moment";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
type DateProps = {
|
||||||
|
currentQuestion: QuizQuestionDate;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ({ currentQuestion }: DateProps) => {
|
||||||
|
const { settings } = useQuizSettings();
|
||||||
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
|
const { updateAnswer } = useQuizViewStore((state) => state);
|
||||||
|
const theme = useTheme();
|
||||||
|
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string;
|
||||||
|
const currentAnswer = moment(answer) || moment();
|
||||||
|
|
||||||
|
const onDateChange = async (date: Moment | null) => {
|
||||||
|
if (!date) return;
|
||||||
|
|
||||||
|
updateAnswer(currentQuestion.id, date, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DatePicker
|
||||||
|
format="DD/MM/YYYY"
|
||||||
|
slots={{
|
||||||
|
openPickerIcon: () => (
|
||||||
|
<CalendarIcon
|
||||||
|
sx={{
|
||||||
|
"& path": { stroke: theme.palette.primary.main },
|
||||||
|
"& rect": { stroke: theme.palette.primary.main },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
value={currentAnswer}
|
||||||
|
onChange={onDateChange}
|
||||||
|
slotProps={{
|
||||||
|
openPickerButton: { sx: { p: 0 }, "data-cy": "open-datepicker" },
|
||||||
|
layout: {
|
||||||
|
sx: { backgroundColor: theme.palette.background.default },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
"& .MuiInputBase-root": {
|
||||||
|
backgroundColor: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#F2F3F7"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
borderRadius: "10px",
|
||||||
|
maxWidth: "250px",
|
||||||
|
pr: "30px",
|
||||||
|
"& input": { py: "11px", pl: "20px", lineHeight: "19px" },
|
||||||
|
"& fieldset": { borderColor: "#9A9AAF" },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
100
lib/components/ViewPublicationPage/questions/Date/DateRange.tsx
Normal file
100
lib/components/ViewPublicationPage/questions/Date/DateRange.tsx
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { useQuizSettings } from "@/contexts/QuizDataContext";
|
||||||
|
import { useQuizViewStore } from "@/stores/quizView";
|
||||||
|
import type { QuizQuestionDate } from "@model/questionTypes/date";
|
||||||
|
import { DateCalendar } from "@mui/x-date-pickers";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
import type { Moment } from "moment";
|
||||||
|
import moment from "moment";
|
||||||
|
import { Box, Paper, TextField, useTheme } from "@mui/material";
|
||||||
|
import { useRootContainerSize } from "@/contexts/RootContainerWidthContext";
|
||||||
|
|
||||||
|
type DateProps = {
|
||||||
|
currentQuestion: QuizQuestionDate;
|
||||||
|
};
|
||||||
|
console.log(moment.locale());
|
||||||
|
export default ({ currentQuestion }: DateProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMobile = useRootContainerSize() < 690;
|
||||||
|
const { settings } = useQuizSettings();
|
||||||
|
const { updateAnswer } = useQuizViewStore((state) => state);
|
||||||
|
|
||||||
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
|
const answer = (answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string) || ["0", "0"];
|
||||||
|
|
||||||
|
const currentFrom = Number(answer[0]) ? moment(Number(answer[0])) : moment().utc();
|
||||||
|
const currentTo = Number(answer[1]) ? moment(Number(answer[1])) : moment().utc();
|
||||||
|
|
||||||
|
const onDateChange = async (date: Moment | null, index: number) => {
|
||||||
|
if (!date) return;
|
||||||
|
let newAnswer = [...answer];
|
||||||
|
newAnswer[index] = (moment(date).unix() * 1000).toString();
|
||||||
|
|
||||||
|
updateAnswer(currentQuestion.id, newAnswer, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
sx={{
|
||||||
|
backgroundColor: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#F2F3F7"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
width: isMobile ? "min-content" : "auto",
|
||||||
|
display: "inline-flex",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
marginTop: "20px",
|
||||||
|
p: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
<span style={{ marginLeft: "25px", color: theme.palette.text.primary }}>От</span>
|
||||||
|
<DateCalendar
|
||||||
|
sx={{
|
||||||
|
"& .MuiInputBase-root": {
|
||||||
|
backgroundColor: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#F2F3F7"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
borderRadius: "10px",
|
||||||
|
maxWidth: "250px",
|
||||||
|
pr: "30px",
|
||||||
|
"& input": { py: "11px", pl: "20px", lineHeight: "19px" },
|
||||||
|
"& fieldset": { borderColor: "#9A9AAF" },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={currentFrom}
|
||||||
|
onChange={(data) => onDateChange(data, 0)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<span style={{ marginLeft: "25px", color: theme.palette.text.primary }}>До</span>
|
||||||
|
<DateCalendar
|
||||||
|
sx={{
|
||||||
|
"& .MuiInputBase-root": {
|
||||||
|
backgroundColor: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#F2F3F7"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
borderRadius: "10px",
|
||||||
|
maxWidth: "250px",
|
||||||
|
pr: "30px",
|
||||||
|
"& input": { py: "11px", pl: "20px", lineHeight: "19px" },
|
||||||
|
"& fieldset": { borderColor: "#9A9AAF" },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={currentTo}
|
||||||
|
onChange={(data) => onDateChange(data, 1)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
@ -1,30 +1,14 @@
|
|||||||
import { useQuizViewStore } from "@/stores/quizView";
|
|
||||||
import { useQuizSettings } from "@contexts/QuizDataContext";
|
|
||||||
import CalendarIcon from "@icons/CalendarIcon";
|
|
||||||
import type { QuizQuestionDate } from "@model/questionTypes/date";
|
import type { QuizQuestionDate } from "@model/questionTypes/date";
|
||||||
|
import DateRange from "./DateRange";
|
||||||
|
import DatePicker from "./DatePicker";
|
||||||
import { Box, Typography, useTheme } from "@mui/material";
|
import { Box, Typography, useTheme } from "@mui/material";
|
||||||
import { DatePicker } from "@mui/x-date-pickers";
|
|
||||||
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
|
||||||
import type { Moment } from "moment";
|
|
||||||
import moment from "moment";
|
|
||||||
|
|
||||||
type DateProps = {
|
type DateProps = {
|
||||||
currentQuestion: QuizQuestionDate;
|
currentQuestion: QuizQuestionDate;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Date = ({ currentQuestion }: DateProps) => {
|
export const Date = ({ currentQuestion }: DateProps) => {
|
||||||
const { settings } = useQuizSettings();
|
|
||||||
const answers = useQuizViewStore((state) => state.answers);
|
|
||||||
const { updateAnswer } = useQuizViewStore((state) => state);
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string;
|
|
||||||
const currentAnswer = moment(answer) || moment();
|
|
||||||
|
|
||||||
const onDateChange = async (date: Moment | null) => {
|
|
||||||
if (!date) return;
|
|
||||||
|
|
||||||
updateAnswer(currentQuestion.id, date, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
@ -35,52 +19,11 @@ export const Date = ({ currentQuestion }: DateProps) => {
|
|||||||
>
|
>
|
||||||
{currentQuestion.title}
|
{currentQuestion.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box
|
{currentQuestion.content.isRange ? (
|
||||||
sx={{
|
<DateRange currentQuestion={currentQuestion} />
|
||||||
display: "flex",
|
) : (
|
||||||
flexDirection: "column",
|
<DatePicker currentQuestion={currentQuestion} />
|
||||||
width: "100%",
|
)}
|
||||||
marginTop: "20px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<DatePicker
|
|
||||||
format="DD/MM/YYYY"
|
|
||||||
slots={{
|
|
||||||
openPickerIcon: () => (
|
|
||||||
<CalendarIcon
|
|
||||||
sx={{
|
|
||||||
"& path": { stroke: theme.palette.primary.main },
|
|
||||||
"& rect": { stroke: theme.palette.primary.main },
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
value={currentAnswer}
|
|
||||||
onChange={onDateChange}
|
|
||||||
slotProps={{
|
|
||||||
openPickerButton: { sx: { p: 0 }, "data-cy": "open-datepicker" },
|
|
||||||
layout: {
|
|
||||||
sx: { backgroundColor: theme.palette.background.default },
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
"& .MuiInputBase-root": {
|
|
||||||
backgroundColor: settings.cfg.design
|
|
||||||
? quizThemes[settings.cfg.theme].isLight
|
|
||||||
? "#F2F3F7"
|
|
||||||
: "rgba(154,154,175, 0.2)"
|
|
||||||
: quizThemes[settings.cfg.theme].isLight
|
|
||||||
? "white"
|
|
||||||
: theme.palette.background.default,
|
|
||||||
borderRadius: "10px",
|
|
||||||
maxWidth: "250px",
|
|
||||||
pr: "30px",
|
|
||||||
"& input": { py: "11px", pl: "20px", lineHeight: "19px" },
|
|
||||||
"& fieldset": { borderColor: "#9A9AAF" },
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
import type { QuestionVariant } from "@/model/questionTypes/shared";
|
import type { QuestionVariant } from "@/model/questionTypes/shared";
|
||||||
import { useQuizSettings } from "@contexts/QuizDataContext";
|
import { useQuizSettings } from "@contexts/QuizDataContext";
|
||||||
import { Box, FormControl, FormControlLabel, Radio, Typography, useTheme } from "@mui/material";
|
import {
|
||||||
|
Box,
|
||||||
|
Checkbox,
|
||||||
|
FormControl,
|
||||||
|
FormControlLabel,
|
||||||
|
Input,
|
||||||
|
Radio,
|
||||||
|
TextareaAutosize,
|
||||||
|
Typography,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
import { useQuizViewStore } from "@stores/quizView";
|
import { useQuizViewStore } from "@stores/quizView";
|
||||||
import RadioCheck from "@ui_kit/RadioCheck";
|
import RadioCheck from "@ui_kit/RadioCheck";
|
||||||
import RadioIcon from "@ui_kit/RadioIcon";
|
import RadioIcon from "@ui_kit/RadioIcon";
|
||||||
@ -14,18 +24,111 @@ type EmojiVariantProps = {
|
|||||||
questionId: string;
|
questionId: string;
|
||||||
variant: QuestionVariant;
|
variant: QuestionVariant;
|
||||||
index: number;
|
index: number;
|
||||||
|
isMulti: boolean;
|
||||||
|
own: boolean;
|
||||||
|
questionLargeCheck: boolean;
|
||||||
|
ownPlaceholder: string;
|
||||||
|
answer: string | string[] | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmojiVariant = ({ variant, index, questionId }: EmojiVariantProps) => {
|
interface OwnInputProps {
|
||||||
|
questionId: string;
|
||||||
|
variant: QuestionVariant;
|
||||||
|
largeCheck: boolean;
|
||||||
|
ownPlaceholder: string;
|
||||||
|
}
|
||||||
|
const OwnInput = ({ questionId, variant, largeCheck, ownPlaceholder }: OwnInputProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
||||||
|
const { updateOwnVariant } = useQuizViewStore((state) => state);
|
||||||
|
|
||||||
|
const ownAnswer = ownVariants[ownVariants.findIndex((v) => v.id === variant.id)]?.variant.answer || "";
|
||||||
|
|
||||||
|
return largeCheck ? (
|
||||||
|
<Box sx={{ overflow: "auto" }}>
|
||||||
|
<TextareaAutosize
|
||||||
|
placeholder={ownPlaceholder || "|"}
|
||||||
|
style={{
|
||||||
|
resize: "none",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: "16px",
|
||||||
|
color: ownAnswer.length === 0 ? theme.palette.ownPlaceholder.main : theme.palette.text.primary,
|
||||||
|
letterSpacing: "-0.4px",
|
||||||
|
wordSpacing: "-3px",
|
||||||
|
outline: "0px none",
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
border: "none",
|
||||||
|
//@ts-ignore
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::placeholder": {
|
||||||
|
color: theme.palette.ownPlaceholder.main,
|
||||||
|
opacity: 0.65,
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
|
overflow: "auto",
|
||||||
|
}}
|
||||||
|
value={ownAnswer}
|
||||||
|
onClick={(e: React.MouseEvent<HTMLTextAreaElement>) => e.stopPropagation()}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
updateOwnVariant(variant.id, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Input
|
||||||
|
placeholder={ownPlaceholder || "|"}
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: "18px",
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
value={ownAnswer}
|
||||||
|
disableUnderline
|
||||||
|
onClick={(e: React.MouseEvent<HTMLElement>) => e.stopPropagation()}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
updateOwnVariant(variant.id, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EmojiVariant = ({
|
||||||
|
answer,
|
||||||
|
variant,
|
||||||
|
index,
|
||||||
|
questionId,
|
||||||
|
isMulti,
|
||||||
|
own,
|
||||||
|
questionLargeCheck,
|
||||||
|
ownPlaceholder,
|
||||||
|
}: EmojiVariantProps) => {
|
||||||
const { settings } = useQuizSettings();
|
const { settings } = useQuizSettings();
|
||||||
const answers = useQuizViewStore((state) => state.answers);
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state);
|
const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { answer } = answers.find((answer) => answer.questionId === questionId) ?? {};
|
|
||||||
|
|
||||||
const onVariantClick = async (event: MouseEvent<HTMLDivElement>) => {
|
const onVariantClick = async (event: MouseEvent<HTMLDivElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
const variantId = variant.id;
|
||||||
|
if (isMulti) {
|
||||||
|
const currentAnswer = typeof answer !== "string" ? answer || [] : [];
|
||||||
|
|
||||||
|
return updateAnswer(
|
||||||
|
questionId,
|
||||||
|
currentAnswer.includes(variantId)
|
||||||
|
? currentAnswer?.filter((item) => item !== variantId)
|
||||||
|
: [...currentAnswer, variantId],
|
||||||
|
variant.points || 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
updateAnswer(questionId, variant.id, variant.points || 0);
|
updateAnswer(questionId, variant.id, variant.points || 0);
|
||||||
|
|
||||||
if (answer === variant.id) {
|
if (answer === variant.id) {
|
||||||
@ -39,7 +142,7 @@ export const EmojiVariant = ({ variant, index, questionId }: EmojiVariantProps)
|
|||||||
sx={{
|
sx={{
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
border: `1px solid`,
|
border: `1px solid`,
|
||||||
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
borderColor: answer?.includes(variant.id) ? theme.palette.primary.main : "#9A9AAF",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
maxWidth: "317px",
|
maxWidth: "317px",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@ -74,6 +177,17 @@ export const EmojiVariant = ({ variant, index, questionId }: EmojiVariantProps)
|
|||||||
{variant.extendedText && <Typography fontSize="100px">{variant.extendedText}</Typography>}
|
{variant.extendedText && <Typography fontSize="100px">{variant.extendedText}</Typography>}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
{own && (
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
fontSize: "14px",
|
||||||
|
pl: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Введите свой ответ
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
key={variant.id}
|
key={variant.id}
|
||||||
sx={{
|
sx={{
|
||||||
@ -85,6 +199,7 @@ export const EmojiVariant = ({ variant, index, questionId }: EmojiVariantProps)
|
|||||||
alignItems: variant.answer.length <= 60 ? "center" : "flex-start",
|
alignItems: variant.answer.length <= 60 ? "center" : "flex-start",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
height: "80px",
|
height: "80px",
|
||||||
|
overflow: "auto",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
"& .MuiFormControlLabel-label": {
|
"& .MuiFormControlLabel-label": {
|
||||||
wordBreak: "break-word",
|
wordBreak: "break-word",
|
||||||
@ -92,8 +207,9 @@ export const EmojiVariant = ({ variant, index, questionId }: EmojiVariantProps)
|
|||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
"&::-webkit-scrollbar": { width: "4px" },
|
"&::-webkit-scrollbar": { width: "4px" },
|
||||||
"&::-webkit-scrollbar-thumb": {
|
"&::-webkit-scrollbar-thumb": {
|
||||||
backgroundColor: "#b8babf",
|
backgroundColor: theme.palette.primary.main,
|
||||||
},
|
},
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
},
|
},
|
||||||
"& .MuiFormControlLabel-label.Mui-disabled": {
|
"& .MuiFormControlLabel-label.Mui-disabled": {
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
@ -101,16 +217,34 @@ export const EmojiVariant = ({ variant, index, questionId }: EmojiVariantProps)
|
|||||||
}}
|
}}
|
||||||
value={index}
|
value={index}
|
||||||
control={
|
control={
|
||||||
<Radio
|
isMulti ? (
|
||||||
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
<Checkbox
|
||||||
icon={<RadioIcon />}
|
checked={!!answer?.includes(variant.id)}
|
||||||
sx={{ position: "absolute", top: "-162px", right: "12px" }}
|
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
||||||
/>
|
icon={<RadioIcon />}
|
||||||
|
sx={{ position: "absolute", top: "-162px", right: "12px" }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Radio
|
||||||
|
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
||||||
|
icon={<RadioIcon />}
|
||||||
|
sx={{ position: "absolute", top: "-162px", right: "12px" }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
label={
|
label={
|
||||||
<Box sx={{ display: "flex", gap: "10px" }}>
|
own ? (
|
||||||
<Typography sx={{ wordBreak: "break-word", lineHeight: "normal" }}>{variant.answer}</Typography>
|
<OwnInput
|
||||||
</Box>
|
questionId={questionId}
|
||||||
|
variant={variant}
|
||||||
|
largeCheck={questionLargeCheck}
|
||||||
|
ownPlaceholder={ownPlaceholder || "|"}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Box sx={{ display: "flex", gap: "10px" }}>
|
||||||
|
<Typography sx={{ wordBreak: "break-word", lineHeight: "normal" }}>{variant.answer}</Typography>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -3,6 +3,7 @@ import { Box, RadioGroup, Typography, useTheme } from "@mui/material";
|
|||||||
import { useQuizViewStore } from "@stores/quizView";
|
import { useQuizViewStore } from "@stores/quizView";
|
||||||
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
|
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
|
||||||
import { EmojiVariant } from "./EmojiVariant";
|
import { EmojiVariant } from "./EmojiVariant";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
polyfillCountryFlagEmojis();
|
polyfillCountryFlagEmojis();
|
||||||
|
|
||||||
@ -16,6 +17,8 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
||||||
|
|
||||||
|
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
@ -44,14 +47,24 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", width: "100%", gap: "42px", flexWrap: "wrap" }}>
|
<Box sx={{ display: "flex", width: "100%", gap: "42px", flexWrap: "wrap" }}>
|
||||||
{currentQuestion.content.variants.map((variant, index) => (
|
{currentQuestion.content.variants
|
||||||
<EmojiVariant
|
.filter((v) => {
|
||||||
key={variant.id}
|
if (!v.isOwn) return true;
|
||||||
questionId={currentQuestion.id}
|
return v.isOwn && currentQuestion.content.own;
|
||||||
variant={variant}
|
})
|
||||||
index={index}
|
.map((variant, index) => (
|
||||||
/>
|
<EmojiVariant
|
||||||
))}
|
key={variant.id}
|
||||||
|
questionId={currentQuestion.id}
|
||||||
|
variant={variant}
|
||||||
|
index={index}
|
||||||
|
isMulti={Boolean(currentQuestion.content.multi)}
|
||||||
|
own={Boolean(variant.isOwn)}
|
||||||
|
questionLargeCheck={true}
|
||||||
|
answer={answer}
|
||||||
|
ownPlaceholder={currentQuestion.content?.ownPlaceholder || ""}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -61,7 +61,10 @@ export const UploadedFile = ({ currentQuestion, setIsSending }: UploadedFileProp
|
|||||||
>
|
>
|
||||||
{answer?.split("|")[0]}
|
{answer?.split("|")[0]}
|
||||||
</Typography>
|
</Typography>
|
||||||
<IconButton sx={{ p: 0 }} onClick={deleteFile}>
|
<IconButton
|
||||||
|
sx={{ p: 0 }}
|
||||||
|
onClick={deleteFile}
|
||||||
|
>
|
||||||
<CloseBold />
|
<CloseBold />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,42 +1,147 @@
|
|||||||
import type { QuestionVariant } from "@/model/questionTypes/shared";
|
import { CheckboxIcon } from "@/assets/icons/Checkbox";
|
||||||
|
import type { QuestionVariant, QuestionVariantWithEditedImages } from "@/model/questionTypes/shared";
|
||||||
import { useQuizSettings } from "@contexts/QuizDataContext";
|
import { useQuizSettings } from "@contexts/QuizDataContext";
|
||||||
import { Box, FormControlLabel, Radio, useTheme } from "@mui/material";
|
import { Box, Checkbox, FormControlLabel, Input, Radio, TextareaAutosize, Typography, useTheme } from "@mui/material";
|
||||||
import { useQuizViewStore } from "@stores/quizView";
|
import { useQuizViewStore } from "@stores/quizView";
|
||||||
import RadioCheck from "@ui_kit/RadioCheck";
|
import RadioCheck from "@ui_kit/RadioCheck";
|
||||||
import RadioIcon from "@ui_kit/RadioIcon";
|
import RadioIcon from "@ui_kit/RadioIcon";
|
||||||
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
import type { MouseEvent } from "react";
|
import { useMemo, type MouseEvent } from "react";
|
||||||
|
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
||||||
|
|
||||||
type ImagesProps = {
|
type ImagesProps = {
|
||||||
questionId: string;
|
questionId: string;
|
||||||
variant: QuestionVariant;
|
variant: QuestionVariantWithEditedImages;
|
||||||
index: number;
|
index: number;
|
||||||
|
answer: string | string[] | undefined;
|
||||||
|
isMulti: boolean;
|
||||||
|
own: boolean;
|
||||||
|
questionLargeCheck: boolean;
|
||||||
|
ownPlaceholder: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ImageVariant = ({ questionId, variant, index }: ImagesProps) => {
|
interface OwnInputProps {
|
||||||
|
questionId: string;
|
||||||
|
variant: QuestionVariant;
|
||||||
|
largeCheck: boolean;
|
||||||
|
ownPlaceholder: string;
|
||||||
|
}
|
||||||
|
const OwnInput = ({ questionId, variant, largeCheck, ownPlaceholder }: OwnInputProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
||||||
|
const { updateOwnVariant } = useQuizViewStore((state) => state);
|
||||||
|
|
||||||
|
const ownAnswer = ownVariants[ownVariants.findIndex((v) => v.id === variant.id)]?.variant.answer || "";
|
||||||
|
|
||||||
|
return largeCheck ? (
|
||||||
|
<Box sx={{ overflow: "auto" }}>
|
||||||
|
<TextareaAutosize
|
||||||
|
placeholder={ownPlaceholder || "|"}
|
||||||
|
style={{
|
||||||
|
resize: "none",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: "16px",
|
||||||
|
color: ownAnswer.length === 0 ? theme.palette.ownPlaceholder.main : theme.palette.text.primary,
|
||||||
|
letterSpacing: "-0.4px",
|
||||||
|
wordSpacing: "-3px",
|
||||||
|
outline: "0px none",
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
border: "none",
|
||||||
|
//@ts-ignore
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::placeholder": {
|
||||||
|
color: theme.palette.ownPlaceholder.main,
|
||||||
|
opacity: 0.65,
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
|
}}
|
||||||
|
value={ownAnswer}
|
||||||
|
onClick={(e: React.MouseEvent<HTMLTextAreaElement>) => e.stopPropagation()}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
updateOwnVariant(variant.id, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Input
|
||||||
|
placeholder={ownPlaceholder || "|"}
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: "18px",
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
value={ownAnswer}
|
||||||
|
disableUnderline
|
||||||
|
onClick={(e: React.MouseEvent<HTMLElement>) => e.stopPropagation()}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
updateOwnVariant(variant.id, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ImageVariant = ({
|
||||||
|
questionId,
|
||||||
|
answer,
|
||||||
|
isMulti,
|
||||||
|
variant,
|
||||||
|
index,
|
||||||
|
own,
|
||||||
|
questionLargeCheck,
|
||||||
|
ownPlaceholder,
|
||||||
|
}: ImagesProps) => {
|
||||||
const { settings } = useQuizSettings();
|
const { settings } = useQuizSettings();
|
||||||
const answers = useQuizViewStore((state) => state.answers);
|
|
||||||
const { deleteAnswer, updateAnswer } = useQuizViewStore((state) => state);
|
const { deleteAnswer, updateAnswer } = useQuizViewStore((state) => state);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const answer = answers.find((answer) => answer.questionId === questionId)?.answer;
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
|
const isMobile = useRootContainerSize() < 450;
|
||||||
|
const isTablet = useRootContainerSize() < 850;
|
||||||
|
|
||||||
const onVariantClick = async (event: MouseEvent<HTMLDivElement>) => {
|
const onVariantClick = async (event: MouseEvent<HTMLDivElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
updateAnswer(questionId, variant.id, variant.points || 0);
|
const variantId = variant.id;
|
||||||
|
if (isMulti) {
|
||||||
|
const currentAnswer = typeof answer !== "string" ? answer || [] : [];
|
||||||
|
|
||||||
if (answer === variant.id) {
|
return updateAnswer(
|
||||||
|
questionId,
|
||||||
|
currentAnswer.includes(variantId)
|
||||||
|
? currentAnswer?.filter((item) => item !== variantId)
|
||||||
|
: [...currentAnswer, variantId],
|
||||||
|
variant.points || 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAnswer(questionId, variantId, variant.points || 0);
|
||||||
|
|
||||||
|
if (answer === variantId) {
|
||||||
deleteAnswer(questionId);
|
deleteAnswer(questionId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const choiceImgUrl = useMemo(() => {
|
||||||
|
if (variant.editedUrlImagesList !== undefined && variant.editedUrlImagesList !== null) {
|
||||||
|
return variant.editedUrlImagesList[isMobile ? "mobile" : isTablet ? "tablet" : "desktop"];
|
||||||
|
} else {
|
||||||
|
return variant.extendedText;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
position: "relative",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
border: `1px solid`,
|
border: `1px solid`,
|
||||||
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
borderColor: !!answer?.includes(variant.id) ? theme.palette.primary.main : "#9A9AAF",
|
||||||
"&:hover": { borderColor: theme.palette.primary.main },
|
"&:hover": { borderColor: theme.palette.primary.main },
|
||||||
background:
|
background:
|
||||||
settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
|
settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
|
||||||
@ -51,7 +156,7 @@ export const ImageVariant = ({ questionId, variant, index }: ImagesProps) => {
|
|||||||
<Box sx={{ width: "100%", height: "300px" }}>
|
<Box sx={{ width: "100%", height: "300px" }}>
|
||||||
{variant.extendedText && (
|
{variant.extendedText && (
|
||||||
<img
|
<img
|
||||||
src={variant.extendedText}
|
src={choiceImgUrl}
|
||||||
alt=""
|
alt=""
|
||||||
style={{
|
style={{
|
||||||
display: "block",
|
display: "block",
|
||||||
@ -64,6 +169,17 @@ export const ImageVariant = ({ questionId, variant, index }: ImagesProps) => {
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
{own && (
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
fontSize: "14px",
|
||||||
|
pl: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Введите свой ответ
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
key={variant.id}
|
key={variant.id}
|
||||||
sx={{
|
sx={{
|
||||||
@ -80,29 +196,57 @@ export const ImageVariant = ({ questionId, variant, index }: ImagesProps) => {
|
|||||||
"& .MuiFormControlLabel-label": {
|
"& .MuiFormControlLabel-label": {
|
||||||
wordBreak: "break-word",
|
wordBreak: "break-word",
|
||||||
height: variant.answer.length <= 60 ? undefined : "60px",
|
height: variant.answer.length <= 60 ? undefined : "60px",
|
||||||
overflow: "auto",
|
|
||||||
lineHeight: "normal",
|
lineHeight: "normal",
|
||||||
|
overflow: "auto",
|
||||||
|
maxHeight: "100%",
|
||||||
|
width: "100%",
|
||||||
"&::-webkit-scrollbar": {
|
"&::-webkit-scrollbar": {
|
||||||
width: "4px",
|
width: "4px",
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-thumb": {
|
"&::-webkit-scrollbar-thumb": {
|
||||||
backgroundColor: "#b8babf",
|
backgroundColor: theme.palette.primary.main,
|
||||||
},
|
},
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
value={index}
|
value={index}
|
||||||
control={
|
control={
|
||||||
<Radio
|
isMulti ? (
|
||||||
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
<Checkbox
|
||||||
icon={<RadioIcon />}
|
id="cock"
|
||||||
sx={{
|
checked={!!answer?.includes(variant.id)}
|
||||||
position: "absolute",
|
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
||||||
top: "-297px",
|
icon={<RadioIcon />}
|
||||||
right: 0,
|
sx={{
|
||||||
}}
|
position: "absolute",
|
||||||
/>
|
top: "-297px",
|
||||||
|
right: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Radio
|
||||||
|
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
||||||
|
icon={<RadioIcon />}
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "-297px",
|
||||||
|
right: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
own ? (
|
||||||
|
<OwnInput
|
||||||
|
questionId={questionId}
|
||||||
|
variant={variant}
|
||||||
|
largeCheck={questionLargeCheck}
|
||||||
|
ownPlaceholder={ownPlaceholder || "|"}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
variant.answer
|
||||||
|
)
|
||||||
}
|
}
|
||||||
label={variant.answer}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
||||||
import type { QuizQuestionImages } from "@model/questionTypes/images";
|
import type { QuizQuestionImages } from "@model/questionTypes/images";
|
||||||
import { Box, RadioGroup, Typography, useTheme } from "@mui/material";
|
import { Box, RadioGroup, Typography, useTheme } from "@mui/material";
|
||||||
import { useQuizViewStore } from "@stores/quizView";
|
import { createQuizViewStore, useQuizViewStore } from "@stores/quizView";
|
||||||
import { ImageVariant } from "./ImageVariant";
|
import { ImageVariant } from "./ImageVariant";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
type ImagesProps = {
|
type ImagesProps = {
|
||||||
currentQuestion: QuizQuestionImages;
|
currentQuestion: QuizQuestionImages;
|
||||||
@ -15,6 +16,8 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
|
|||||||
const isTablet = useRootContainerSize() < 1000;
|
const isTablet = useRootContainerSize() < 1000;
|
||||||
const isMobile = useRootContainerSize() < 500;
|
const isMobile = useRootContainerSize() < 500;
|
||||||
|
|
||||||
|
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
@ -25,7 +28,7 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
|
|||||||
{currentQuestion.title}
|
{currentQuestion.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
name={currentQuestion.id}
|
name={currentQuestion.id.toString()}
|
||||||
value={currentQuestion.content.variants.findIndex(({ id }) => answer === id)}
|
value={currentQuestion.content.variants.findIndex(({ id }) => answer === id)}
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -43,14 +46,24 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currentQuestion.content.variants.map((variant, index) => (
|
{currentQuestion.content.variants
|
||||||
<ImageVariant
|
.filter((v) => {
|
||||||
key={variant.id}
|
if (!v.isOwn) return true;
|
||||||
questionId={currentQuestion.id}
|
return v.isOwn && currentQuestion.content.own;
|
||||||
variant={variant}
|
})
|
||||||
index={index}
|
.map((variant, index) => (
|
||||||
/>
|
<ImageVariant
|
||||||
))}
|
key={variant.id}
|
||||||
|
questionId={currentQuestion.id}
|
||||||
|
variant={variant}
|
||||||
|
index={index}
|
||||||
|
answer={answer}
|
||||||
|
isMulti={Boolean(currentQuestion.content.multi)}
|
||||||
|
own={Boolean(variant.isOwn)}
|
||||||
|
questionLargeCheck={true}
|
||||||
|
ownPlaceholder={currentQuestion.content?.ownPlaceholder || ""}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -8,7 +8,7 @@ import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
|||||||
|
|
||||||
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
|
||||||
import type { ChangeEvent } from "react";
|
import { useMemo, type ChangeEvent } from "react";
|
||||||
import type { QuizQuestionText } from "@model/questionTypes/text";
|
import type { QuizQuestionText } from "@model/questionTypes/text";
|
||||||
|
|
||||||
interface TextNormalProps {
|
interface TextNormalProps {
|
||||||
@ -21,12 +21,22 @@ export const TextNormal = ({ currentQuestion, answer }: TextNormalProps) => {
|
|||||||
const { settings } = useQuizSettings();
|
const { settings } = useQuizSettings();
|
||||||
const { updateAnswer } = useQuizViewStore((state) => state);
|
const { updateAnswer } = useQuizViewStore((state) => state);
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
|
const isTablet = useRootContainerSize() < 850;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const onInputChange = async ({ target }: ChangeEvent<HTMLInputElement>) => {
|
const onInputChange = async ({ target }: ChangeEvent<HTMLInputElement>) => {
|
||||||
updateAnswer(currentQuestion.id, target.value, 0);
|
updateAnswer(currentQuestion.id, target.value, 0);
|
||||||
};
|
};
|
||||||
|
const choiceImgUrlQuestion = useMemo(() => {
|
||||||
|
if (
|
||||||
|
currentQuestion.content.editedUrlImagesList !== undefined &&
|
||||||
|
currentQuestion.content.editedUrlImagesList !== null
|
||||||
|
) {
|
||||||
|
return currentQuestion.content.editedUrlImagesList[isMobile ? "mobile" : isTablet ? "tablet" : "desktop"];
|
||||||
|
} else {
|
||||||
|
return currentQuestion.content.back;
|
||||||
|
}
|
||||||
|
}, [currentQuestion]);
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
@ -61,7 +71,7 @@ export const TextNormal = ({ currentQuestion, answer }: TextNormalProps) => {
|
|||||||
"&:focus-visible": { borderColor: theme.palette.primary.main },
|
"&:focus-visible": { borderColor: theme.palette.primary.main },
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
{choiceImgUrlQuestion && choiceImgUrlQuestion !== " " && choiceImgUrlQuestion !== null && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
maxWidth: "400px",
|
maxWidth: "400px",
|
||||||
@ -72,7 +82,7 @@ export const TextNormal = ({ currentQuestion, answer }: TextNormalProps) => {
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
key={currentQuestion.id}
|
key={currentQuestion.id}
|
||||||
src={currentQuestion.content.back}
|
src={choiceImgUrlQuestion}
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
import { useQuizSettings } from "@contexts/QuizDataContext";
|
import { useQuizSettings } from "@contexts/QuizDataContext";
|
||||||
import { CheckboxIcon } from "@icons/Checkbox";
|
import { CheckboxIcon } from "@icons/Checkbox";
|
||||||
import type { QuestionVariant } from "@model/questionTypes/shared";
|
import type { QuestionVariant } from "@model/questionTypes/shared";
|
||||||
import { Checkbox, FormControlLabel, TextField as MuiTextField, Radio, TextFieldProps, useTheme } from "@mui/material";
|
import {
|
||||||
|
Checkbox,
|
||||||
|
FormControlLabel,
|
||||||
|
Input,
|
||||||
|
TextField as MuiTextField,
|
||||||
|
Radio,
|
||||||
|
TextFieldProps,
|
||||||
|
TextareaAutosize,
|
||||||
|
Typography,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
import { useQuizViewStore } from "@stores/quizView";
|
import { useQuizViewStore } from "@stores/quizView";
|
||||||
import RadioCheck from "@ui_kit/RadioCheck";
|
import RadioCheck from "@ui_kit/RadioCheck";
|
||||||
import RadioIcon from "@ui_kit/RadioIcon";
|
import RadioIcon from "@ui_kit/RadioIcon";
|
||||||
@ -10,6 +20,70 @@ import type { FC, MouseEvent } from "react";
|
|||||||
|
|
||||||
const TextField = MuiTextField as unknown as FC<TextFieldProps>;
|
const TextField = MuiTextField as unknown as FC<TextFieldProps>;
|
||||||
|
|
||||||
|
interface OwnInputProps {
|
||||||
|
questionId: string;
|
||||||
|
variant: QuestionVariant;
|
||||||
|
largeCheck: boolean;
|
||||||
|
ownPlaceholder: string;
|
||||||
|
}
|
||||||
|
const OwnInput = ({ questionId, variant, largeCheck, ownPlaceholder }: OwnInputProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
||||||
|
const { updateOwnVariant } = useQuizViewStore((state) => state);
|
||||||
|
|
||||||
|
const ownAnswer = ownVariants[ownVariants.findIndex((v) => v.id === variant.id)]?.variant.answer || "";
|
||||||
|
|
||||||
|
return largeCheck ? (
|
||||||
|
<TextareaAutosize
|
||||||
|
placeholder={ownPlaceholder || "|"}
|
||||||
|
style={{
|
||||||
|
resize: "none",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: "16px",
|
||||||
|
color: ownAnswer.length === 0 ? theme.palette.ownPlaceholder.main : theme.palette.text.primary,
|
||||||
|
letterSpacing: "-0.4px",
|
||||||
|
wordSpacing: "-3px",
|
||||||
|
outline: "0px none",
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
border: "none",
|
||||||
|
//@ts-ignore
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::placeholder": {
|
||||||
|
color: theme.palette.ownPlaceholder.main,
|
||||||
|
opacity: "0.65!important",
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
|
}}
|
||||||
|
value={ownAnswer}
|
||||||
|
onClick={(e: React.MouseEvent<HTMLTextAreaElement>) => e.stopPropagation()}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
updateOwnVariant(variant.id, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Input
|
||||||
|
placeholder={ownPlaceholder || "|"}
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: "18px",
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
value={ownAnswer}
|
||||||
|
disableUnderline
|
||||||
|
onClick={(e: React.MouseEvent<HTMLElement>) => e.stopPropagation()}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
updateOwnVariant(variant.id, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const VariantItem = ({
|
export const VariantItem = ({
|
||||||
questionId,
|
questionId,
|
||||||
isMulti,
|
isMulti,
|
||||||
@ -17,13 +91,17 @@ export const VariantItem = ({
|
|||||||
answer,
|
answer,
|
||||||
index,
|
index,
|
||||||
own = false,
|
own = false,
|
||||||
|
questionLargeCheck,
|
||||||
|
ownPlaceholder,
|
||||||
}: {
|
}: {
|
||||||
isMulti: boolean;
|
isMulti: boolean;
|
||||||
questionId: string;
|
questionId: string;
|
||||||
variant: QuestionVariant;
|
variant: QuestionVariant;
|
||||||
answer: string | string[] | undefined;
|
answer: string | string[] | undefined;
|
||||||
index: number;
|
index: number;
|
||||||
own?: boolean;
|
own: boolean;
|
||||||
|
questionLargeCheck: boolean;
|
||||||
|
ownPlaceholder: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { settings } = useQuizSettings();
|
const { settings } = useQuizSettings();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -57,7 +135,9 @@ export const VariantItem = ({
|
|||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
key={variant.id}
|
key={variant.id}
|
||||||
sx={{
|
sx={{
|
||||||
|
position: "relative",
|
||||||
margin: "0",
|
margin: "0",
|
||||||
|
mt: own ? "10px" : "0",
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
padding: "15px",
|
padding: "15px",
|
||||||
@ -78,12 +158,15 @@ export const VariantItem = ({
|
|||||||
"&:hover": { borderColor: theme.palette.primary.main },
|
"&:hover": { borderColor: theme.palette.primary.main },
|
||||||
"&.MuiFormControl-root": { width: "100%" },
|
"&.MuiFormControl-root": { width: "100%" },
|
||||||
"& .MuiFormControlLabel-label": {
|
"& .MuiFormControlLabel-label": {
|
||||||
|
width: "100%",
|
||||||
|
maxHeight: "100%",
|
||||||
wordBreak: "break-word",
|
wordBreak: "break-word",
|
||||||
height: variant.answer.length <= 60 ? undefined : "60px",
|
height: variant.answer.length <= 60 ? undefined : "60px",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
lineHeight: "normal",
|
lineHeight: "normal",
|
||||||
"&::-webkit-scrollbar": { width: "4px" },
|
"&::-webkit-scrollbar": { width: "4px" },
|
||||||
"&::-webkit-scrollbar-thumb": { backgroundColor: "#b8babf" },
|
"&::-webkit-scrollbar-thumb": { backgroundColor: theme.palette.primary.main },
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
},
|
},
|
||||||
"& .MuiFormControlLabel-label.Mui-disabled": {
|
"& .MuiFormControlLabel-label.Mui-disabled": {
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
@ -93,15 +176,10 @@ export const VariantItem = ({
|
|||||||
labelPlacement="start"
|
labelPlacement="start"
|
||||||
control={
|
control={
|
||||||
isMulti ? (
|
isMulti ? (
|
||||||
<Checkbox
|
<Radio
|
||||||
checked={!!answer?.includes(variant.id)}
|
checked={!!answer?.includes(variant.id)}
|
||||||
checkedIcon={
|
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
||||||
<CheckboxIcon
|
icon={<RadioIcon />}
|
||||||
checked
|
|
||||||
color={theme.palette.primary.main}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
icon={<CheckboxIcon />}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Radio
|
<Radio
|
||||||
@ -110,7 +188,30 @@ export const VariantItem = ({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
label={own ? <TextField label="Другое..." /> : variant.answer}
|
label={
|
||||||
|
own ? (
|
||||||
|
<>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
fontSize: "14px",
|
||||||
|
position: "absolute",
|
||||||
|
top: "-23px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Введите свой ответ
|
||||||
|
</Typography>
|
||||||
|
<OwnInput
|
||||||
|
questionId={questionId}
|
||||||
|
variant={variant}
|
||||||
|
largeCheck={questionLargeCheck}
|
||||||
|
ownPlaceholder={ownPlaceholder || "|"}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
variant.answer
|
||||||
|
)
|
||||||
|
}
|
||||||
onClick={sendVariant}
|
onClick={sendVariant}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Box, FormGroup, RadioGroup, Typography, useTheme } from "@mui/material";
|
import { Box, FormGroup, RadioGroup, Typography, useTheme } from "@mui/material";
|
||||||
import { useEffect } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
|
|
||||||
import { VariantItem } from "./VariantItem";
|
import { VariantItem } from "./VariantItem";
|
||||||
|
|
||||||
@ -16,6 +16,7 @@ type VariantProps = {
|
|||||||
export const Variant = ({ currentQuestion }: VariantProps) => {
|
export const Variant = ({ currentQuestion }: VariantProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
|
const isTablet = useRootContainerSize() < 850;
|
||||||
const answers = useQuizViewStore((state) => state.answers);
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
||||||
const updateOwnVariant = useQuizViewStore((state) => state.updateOwnVariant);
|
const updateOwnVariant = useQuizViewStore((state) => state.updateOwnVariant);
|
||||||
@ -32,6 +33,16 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const choiceImgUrlQuestion = useMemo(() => {
|
||||||
|
if (
|
||||||
|
currentQuestion.content.editedUrlImagesList !== undefined &&
|
||||||
|
currentQuestion.content.editedUrlImagesList !== null
|
||||||
|
) {
|
||||||
|
return currentQuestion.content.editedUrlImagesList[isMobile ? "mobile" : isTablet ? "tablet" : "desktop"];
|
||||||
|
} else {
|
||||||
|
return currentQuestion.content.back;
|
||||||
|
}
|
||||||
|
}, [currentQuestion]);
|
||||||
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -73,33 +84,31 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
|
|||||||
gap: "20px",
|
gap: "20px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currentQuestion.content.variants.map((variant, index) => (
|
{currentQuestion.content.variants
|
||||||
<VariantItem
|
.filter((v) => {
|
||||||
key={variant.id}
|
if (!v.isOwn) return true;
|
||||||
questionId={currentQuestion.id}
|
return v.isOwn && currentQuestion.content.own;
|
||||||
isMulti={currentQuestion.content.multi}
|
})
|
||||||
variant={variant}
|
.map((variant, index) => (
|
||||||
answer={answer}
|
<VariantItem
|
||||||
index={index}
|
key={variant.id}
|
||||||
/>
|
questionId={currentQuestion.id}
|
||||||
))}
|
isMulti={currentQuestion.content.multi}
|
||||||
{currentQuestion.content.own && ownVariant && (
|
variant={variant}
|
||||||
<VariantItem
|
answer={answer}
|
||||||
own
|
index={index}
|
||||||
questionId={currentQuestion.id}
|
own={Boolean(variant.isOwn)}
|
||||||
isMulti={currentQuestion.content.multi}
|
questionLargeCheck={currentQuestion.content.largeCheck}
|
||||||
variant={ownVariant.variant}
|
ownPlaceholder={currentQuestion.content?.ownPlaceholder || ""}
|
||||||
answer={answer}
|
/>
|
||||||
index={currentQuestion.content.variants.length + 2}
|
))}
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Group>
|
</Group>
|
||||||
{currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
{choiceImgUrlQuestion && choiceImgUrlQuestion !== " " && choiceImgUrlQuestion !== null && (
|
||||||
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px" }}>
|
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px" }}>
|
||||||
<img
|
<img
|
||||||
key={currentQuestion.id}
|
key={currentQuestion.id}
|
||||||
src={currentQuestion.content.back}
|
src={choiceImgUrlQuestion}
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
@ -1,28 +1,115 @@
|
|||||||
import type { QuestionVariant } from "@/model/questionTypes/shared";
|
import type { QuestionVariant, QuestionVariantWithEditedImages } from "@/model/questionTypes/shared";
|
||||||
import { useQuizSettings } from "@contexts/QuizDataContext";
|
import { useQuizSettings } from "@contexts/QuizDataContext";
|
||||||
import { FormControlLabel, Radio, useTheme } from "@mui/material";
|
import {
|
||||||
|
FormControlLabel,
|
||||||
|
TextareaAutosize,
|
||||||
|
Radio,
|
||||||
|
useTheme,
|
||||||
|
Box,
|
||||||
|
Input,
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
Typography,
|
||||||
|
} from "@mui/material";
|
||||||
import { useQuizViewStore } from "@stores/quizView";
|
import { useQuizViewStore } from "@stores/quizView";
|
||||||
import RadioCheck from "@ui_kit/RadioCheck";
|
import RadioCheck from "@ui_kit/RadioCheck";
|
||||||
import RadioIcon from "@ui_kit/RadioIcon";
|
import RadioIcon from "@ui_kit/RadioIcon";
|
||||||
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
import type { MouseEvent } from "react";
|
import { type MouseEvent } from "react";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
|
||||||
type VarimgVariantProps = {
|
type VarimgVariantProps = {
|
||||||
questionId: string;
|
questionId: string;
|
||||||
variant: QuestionVariant;
|
variant: QuestionVariantWithEditedImages;
|
||||||
index: number;
|
index: number;
|
||||||
isSending: boolean;
|
isSending: boolean;
|
||||||
setIsSending: (isSending: boolean) => void;
|
setIsSending: (isSending: boolean) => void;
|
||||||
|
questionLargeCheck: boolean;
|
||||||
|
isMulti: boolean;
|
||||||
|
answer: string | string[] | undefined;
|
||||||
|
ownPlaceholder: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VarimgVariant = ({ questionId, variant, index, isSending, setIsSending }: VarimgVariantProps) => {
|
interface OwnInputProps {
|
||||||
const { settings } = useQuizSettings();
|
questionId: string;
|
||||||
const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state);
|
variant: QuestionVariant;
|
||||||
const answers = useQuizViewStore((state) => state.answers);
|
largeCheck: boolean;
|
||||||
|
ownPlaceholder: string;
|
||||||
|
}
|
||||||
|
const OwnInput = ({ questionId, variant, largeCheck, ownPlaceholder }: OwnInputProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
||||||
|
const { updateOwnVariant } = useQuizViewStore((state) => state);
|
||||||
|
|
||||||
|
const ownAnswer = ownVariants[ownVariants.findIndex((v) => v.id === variant.id)]?.variant.answer || "";
|
||||||
|
|
||||||
|
return largeCheck ? (
|
||||||
|
<TextareaAutosize
|
||||||
|
placeholder={ownPlaceholder || "|"}
|
||||||
|
style={{
|
||||||
|
resize: "none",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: "16px",
|
||||||
|
color: ownAnswer.length === 0 ? theme.palette.ownPlaceholder.main : theme.palette.text.primary,
|
||||||
|
letterSpacing: "-0.4px",
|
||||||
|
wordSpacing: "-3px",
|
||||||
|
outline: "0px none",
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
border: "none",
|
||||||
|
//@ts-ignore
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::placeholder": {
|
||||||
|
color: theme.palette.ownPlaceholder.main,
|
||||||
|
opacity: "0.65",
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
|
maxHeight: "44px",
|
||||||
|
overflow: "auto",
|
||||||
|
}}
|
||||||
|
value={ownAnswer}
|
||||||
|
onClick={(e: React.MouseEvent<HTMLTextAreaElement>) => e.stopPropagation()}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
updateOwnVariant(variant.id, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Input
|
||||||
|
placeholder={ownPlaceholder || "|"}
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
width: "100%",
|
||||||
|
fontSize: "18px",
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
value={ownAnswer}
|
||||||
|
disableUnderline
|
||||||
|
onClick={(e: React.MouseEvent<HTMLElement>) => e.stopPropagation()}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
updateOwnVariant(variant.id, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const VarimgVariant = ({
|
||||||
|
questionId,
|
||||||
|
variant,
|
||||||
|
index,
|
||||||
|
isSending,
|
||||||
|
setIsSending,
|
||||||
|
questionLargeCheck,
|
||||||
|
ownPlaceholder,
|
||||||
|
answer,
|
||||||
|
}: VarimgVariantProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const { answer } = answers.find((answer) => answer.questionId === questionId) ?? {};
|
const { settings } = useQuizSettings();
|
||||||
|
const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state);
|
||||||
|
|
||||||
const sendVariant = async (event: MouseEvent<HTMLLabelElement>) => {
|
const sendVariant = async (event: MouseEvent<HTMLLabelElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -34,50 +121,145 @@ export const VarimgVariant = ({ questionId, variant, index, isSending, setIsSend
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
if (variant?.isOwn) {
|
||||||
<FormControlLabel
|
return (
|
||||||
key={variant.id}
|
<Box>
|
||||||
disabled={isSending}
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
marginBottom: "15px",
|
color: theme.palette.text.primary,
|
||||||
borderRadius: "12px",
|
fontSize: "14px",
|
||||||
padding: "20px",
|
pl: "15px",
|
||||||
color: theme.palette.text.primary,
|
}}
|
||||||
backgroundColor: settings.cfg.design
|
>
|
||||||
? quizThemes[settings.cfg.theme].isLight
|
Введите свой ответ
|
||||||
? "#FFFFFF"
|
</Typography>
|
||||||
: "rgba(255,255,255, 0.3)"
|
|
||||||
: quizThemes[settings.cfg.theme].isLight
|
<FormControlLabel
|
||||||
? "white"
|
key={variant.id}
|
||||||
: theme.palette.background.default,
|
disabled={isSending}
|
||||||
border: `1px solid`,
|
sx={{
|
||||||
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
marginBottom: "15px",
|
||||||
display: "flex",
|
borderRadius: "12px",
|
||||||
margin: 0,
|
padding: "20px",
|
||||||
justifyContent: "space-between",
|
color: theme.palette.text.primary,
|
||||||
"&:hover": { borderColor: theme.palette.primary.main },
|
backgroundColor: settings.cfg.design
|
||||||
"& .MuiFormControlLabel-label": {
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
wordBreak: "break-word",
|
? "#FFFFFF"
|
||||||
height: variant.answer.length <= 60 ? undefined : "60px",
|
: "rgba(255,255,255, 0.3)"
|
||||||
overflow: "auto",
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
lineHeight: "normal",
|
? "white"
|
||||||
"&::-webkit-scrollbar": { width: "4px" },
|
: theme.palette.background.default,
|
||||||
"&::-webkit-scrollbar-thumb": { backgroundColor: "#b8babf" },
|
border: `1px solid`,
|
||||||
},
|
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
||||||
"& .MuiFormControlLabel-label.Mui-disabled": {
|
display: "flex",
|
||||||
color: theme.palette.text.primary,
|
margin: 0,
|
||||||
},
|
justifyContent: "space-between",
|
||||||
}}
|
"&:hover": { borderColor: theme.palette.primary.main },
|
||||||
labelPlacement="start"
|
"& .MuiFormControlLabel-label": {
|
||||||
value={index}
|
wordBreak: "break-word",
|
||||||
onClick={sendVariant}
|
height: variant.answer.length <= 60 ? undefined : "60px",
|
||||||
label={variant.answer}
|
overflow: "auto",
|
||||||
control={
|
lineHeight: "normal",
|
||||||
<Radio
|
width: "100%",
|
||||||
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
"&::-webkit-scrollbar": {
|
||||||
icon={<RadioIcon />}
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
"& .MuiFormControlLabel-label.Mui-disabled": {
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
labelPlacement="start"
|
||||||
|
value={index}
|
||||||
|
onClick={sendVariant}
|
||||||
|
label={
|
||||||
|
variant?.isOwn ? (
|
||||||
|
<OwnInput
|
||||||
|
questionId={questionId}
|
||||||
|
variant={variant}
|
||||||
|
largeCheck={questionLargeCheck}
|
||||||
|
ownPlaceholder={ownPlaceholder || "|"}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
variant.answer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
control={
|
||||||
|
<Radio
|
||||||
|
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
||||||
|
icon={<RadioIcon />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
}
|
</Box>
|
||||||
/>
|
);
|
||||||
);
|
} else {
|
||||||
|
return (
|
||||||
|
<FormControlLabel
|
||||||
|
key={variant.id}
|
||||||
|
disabled={isSending}
|
||||||
|
sx={{
|
||||||
|
marginBottom: "15px",
|
||||||
|
borderRadius: "12px",
|
||||||
|
padding: "20px",
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
backgroundColor: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#FFFFFF"
|
||||||
|
: "rgba(255,255,255, 0.3)"
|
||||||
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
border: `1px solid`,
|
||||||
|
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
||||||
|
display: "flex",
|
||||||
|
margin: 0,
|
||||||
|
justifyContent: "space-between",
|
||||||
|
"&:hover": { borderColor: theme.palette.primary.main },
|
||||||
|
"& .MuiFormControlLabel-label": {
|
||||||
|
wordBreak: "break-word",
|
||||||
|
height: variant.answer.length <= 60 ? undefined : "60px",
|
||||||
|
overflow: "auto",
|
||||||
|
lineHeight: "normal",
|
||||||
|
width: "100%",
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
scrollbarColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
"& .MuiFormControlLabel-label.Mui-disabled": {
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
labelPlacement="start"
|
||||||
|
value={index}
|
||||||
|
onClick={sendVariant}
|
||||||
|
label={
|
||||||
|
variant?.isOwn ? (
|
||||||
|
<OwnInput
|
||||||
|
questionId={questionId}
|
||||||
|
variant={variant}
|
||||||
|
largeCheck={questionLargeCheck}
|
||||||
|
ownPlaceholder={ownPlaceholder || "|"}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
variant.answer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
control={
|
||||||
|
<Radio
|
||||||
|
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
||||||
|
icon={<RadioIcon />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { Box, RadioGroup, Typography, useTheme } from "@mui/material";
|
import { Box, RadioGroup, Typography, useTheme } from "@mui/material";
|
||||||
|
|
||||||
import { VarimgVariant } from "./VarimgVariant";
|
import { VarimgVariant } from "./VarimgVariant";
|
||||||
@ -9,6 +9,7 @@ import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
|||||||
import BlankImage from "@icons/BlankImage";
|
import BlankImage from "@icons/BlankImage";
|
||||||
|
|
||||||
import type { QuizQuestionVarImg } from "@model/questionTypes/varimg";
|
import type { QuizQuestionVarImg } from "@model/questionTypes/varimg";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
type VarimgProps = {
|
type VarimgProps = {
|
||||||
currentQuestion: QuizQuestionVarImg;
|
currentQuestion: QuizQuestionVarImg;
|
||||||
@ -17,13 +18,46 @@ type VarimgProps = {
|
|||||||
export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
const answers = useQuizViewStore((state) => state.answers);
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
|
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
||||||
|
const updateOwnVariant = useQuizViewStore((state) => state.updateOwnVariant);
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
|
const isTablet = useRootContainerSize() < 850;
|
||||||
|
|
||||||
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
||||||
|
const ownVariant = ownVariants.find((variant) => variant.id === currentQuestion.id);
|
||||||
const variant = currentQuestion.content.variants.find(({ id }) => answer === id);
|
const variant = currentQuestion.content.variants.find(({ id }) => answer === id);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ownVariant) {
|
||||||
|
updateOwnVariant(currentQuestion.id, "");
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const choiceImgUrlAnswer = useMemo(() => {
|
||||||
|
if (variant !== undefined) {
|
||||||
|
if (variant.editedUrlImagesList !== undefined && variant.editedUrlImagesList !== null) {
|
||||||
|
return variant.editedUrlImagesList[isMobile ? "mobile" : isTablet ? "tablet" : "desktop"];
|
||||||
|
} else {
|
||||||
|
return variant.extendedText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [variant]);
|
||||||
|
|
||||||
|
const choiceImgUrlQuestion = useMemo(() => {
|
||||||
|
if (
|
||||||
|
currentQuestion.content.editedUrlImagesList !== undefined &&
|
||||||
|
currentQuestion.content.editedUrlImagesList !== null
|
||||||
|
) {
|
||||||
|
return currentQuestion.content.editedUrlImagesList[isMobile ? "mobile" : isTablet ? "tablet" : "desktop"];
|
||||||
|
} else {
|
||||||
|
return currentQuestion.content.back;
|
||||||
|
}
|
||||||
|
}, [variant]);
|
||||||
|
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
@ -64,16 +98,25 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
|||||||
"&:active": { color: theme.palette.text.primary },
|
"&:active": { color: theme.palette.text.primary },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currentQuestion.content.variants.map((variant, index) => (
|
{currentQuestion.content.variants
|
||||||
<VarimgVariant
|
.filter((v) => {
|
||||||
key={variant.id}
|
if (!v.isOwn) return true;
|
||||||
questionId={currentQuestion.id}
|
return v.isOwn && currentQuestion.content.own;
|
||||||
variant={variant}
|
})
|
||||||
isSending={isSending}
|
.map((variant, index) => (
|
||||||
setIsSending={setIsSending}
|
<VarimgVariant
|
||||||
index={index}
|
key={variant.id}
|
||||||
/>
|
questionId={currentQuestion.id}
|
||||||
))}
|
variant={variant}
|
||||||
|
isSending={isSending}
|
||||||
|
setIsSending={setIsSending}
|
||||||
|
index={index}
|
||||||
|
questionLargeCheck={currentQuestion.content.largeCheck}
|
||||||
|
ownPlaceholder={currentQuestion.content?.ownPlaceholder || ""}
|
||||||
|
isMulti={Boolean(currentQuestion.content?.multi)}
|
||||||
|
answer={answer}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
<Box
|
<Box
|
||||||
@ -93,21 +136,19 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{answer ? (
|
{answer ? (
|
||||||
variant?.extendedText ? (
|
choiceImgUrlAnswer ? (
|
||||||
<img
|
<img
|
||||||
key={variant.extendedText}
|
key={choiceImgUrlAnswer}
|
||||||
src={variant.extendedText}
|
src={choiceImgUrlAnswer}
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<BlankImage />
|
<BlankImage />
|
||||||
)
|
)
|
||||||
) : currentQuestion.content.back !== " " &&
|
) : choiceImgUrlQuestion !== " " && choiceImgUrlQuestion !== null && choiceImgUrlQuestion.length > 0 ? (
|
||||||
currentQuestion.content.back !== null &&
|
|
||||||
currentQuestion.content.back.length > 0 ? (
|
|
||||||
<img
|
<img
|
||||||
src={currentQuestion.content.back}
|
src={choiceImgUrlQuestion}
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
@ -17,5 +17,6 @@ export interface QuizQuestionDate extends QuizQuestionBase {
|
|||||||
back: string | null;
|
back: string | null;
|
||||||
originalBack: string | null;
|
originalBack: string | null;
|
||||||
autofill: boolean;
|
autofill: boolean;
|
||||||
|
isRange?: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,5 +20,7 @@ export interface QuizQuestionEmoji extends QuizQuestionBase {
|
|||||||
back: string | null;
|
back: string | null;
|
||||||
originalBack: string | null;
|
originalBack: string | null;
|
||||||
autofill: boolean;
|
autofill: boolean;
|
||||||
|
ownPlaceholder?: string;
|
||||||
|
isLargeCheck?: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { QuestionHint, QuestionVariant, QuizQuestionBase, QuestionBranchingRule } from "./shared";
|
import type { QuestionHint, QuestionVariantWithEditedImages, QuizQuestionBase, QuestionBranchingRule } from "./shared";
|
||||||
|
|
||||||
export interface QuizQuestionImages extends QuizQuestionBase {
|
export interface QuizQuestionImages extends QuizQuestionBase {
|
||||||
type: "images";
|
type: "images";
|
||||||
@ -21,12 +21,14 @@ export interface QuizQuestionImages extends QuizQuestionBase {
|
|||||||
/** Чекбокс "Необязательный вопрос" */
|
/** Чекбокс "Необязательный вопрос" */
|
||||||
required: boolean;
|
required: boolean;
|
||||||
/** Варианты (картинки) */
|
/** Варианты (картинки) */
|
||||||
variants: QuestionVariant[];
|
variants: QuestionVariantWithEditedImages[];
|
||||||
hint: QuestionHint;
|
hint: QuestionHint;
|
||||||
rule: QuestionBranchingRule;
|
rule: QuestionBranchingRule;
|
||||||
back: string | null;
|
back: string | null;
|
||||||
originalBack: string | null;
|
originalBack: string | null;
|
||||||
autofill: boolean;
|
autofill: boolean;
|
||||||
largeCheck: boolean;
|
largeCheck: boolean;
|
||||||
|
ownPlaceholder?: string;
|
||||||
|
isLargeCheck?: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { QuizQuestionBase, QuestionBranchingRule, QuestionHint } from "./shared";
|
import type { QuizQuestionBase, QuestionBranchingRule, QuestionHint, EditedUrlImagesList } from "./shared";
|
||||||
|
|
||||||
interface ResultQuestionBranchingRule extends QuestionBranchingRule {
|
interface ResultQuestionBranchingRule extends QuestionBranchingRule {
|
||||||
minScore?: number;
|
minScore?: number;
|
||||||
@ -15,6 +15,7 @@ export interface QuizQuestionResult extends QuizQuestionBase {
|
|||||||
price: [number] | [number, number];
|
price: [number] | [number, number];
|
||||||
useImage: boolean;
|
useImage: boolean;
|
||||||
rule: ResultQuestionBranchingRule;
|
rule: ResultQuestionBranchingRule;
|
||||||
|
editedUrlImagesList?: EditedUrlImagesList | null;
|
||||||
hint: QuestionHint;
|
hint: QuestionHint;
|
||||||
autofill: boolean;
|
autofill: boolean;
|
||||||
usage: boolean;
|
usage: boolean;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { type } from "os";
|
||||||
import type { QuizQuestionDate } from "./date";
|
import type { QuizQuestionDate } from "./date";
|
||||||
import type { QuizQuestionEmoji } from "./emoji";
|
import type { QuizQuestionEmoji } from "./emoji";
|
||||||
import type { QuizQuestionFile } from "./file";
|
import type { QuizQuestionFile } from "./file";
|
||||||
@ -20,6 +21,9 @@ export interface QuestionBranchingRuleMain {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type EditedImagesScreens = "desktop" | "tablet" | "mobile" | "small";
|
||||||
|
export type EditedUrlImagesList = Record<EditedImagesScreens, string>;
|
||||||
|
|
||||||
export interface QuestionBranchingRule {
|
export interface QuestionBranchingRule {
|
||||||
children: string[];
|
children: string[];
|
||||||
//список условий
|
//список условий
|
||||||
@ -43,10 +47,15 @@ export type QuestionVariant = {
|
|||||||
hints: string;
|
hints: string;
|
||||||
/** Дополнительное поле для текста, emoji, ссылки на картинку */
|
/** Дополнительное поле для текста, emoji, ссылки на картинку */
|
||||||
extendedText: string;
|
extendedText: string;
|
||||||
|
isOwn?: boolean;
|
||||||
|
isMulti?: boolean;
|
||||||
/** Оригинал изображения (до кропа) */
|
/** Оригинал изображения (до кропа) */
|
||||||
originalImageUrl: string;
|
originalImageUrl: string;
|
||||||
points?: number;
|
points?: number;
|
||||||
};
|
};
|
||||||
|
export interface QuestionVariantWithEditedImages extends QuestionVariant {
|
||||||
|
editedUrlImagesList?: EditedUrlImagesList | null;
|
||||||
|
}
|
||||||
|
|
||||||
export type QuestionType =
|
export type QuestionType =
|
||||||
| "variant"
|
| "variant"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { QuizQuestionBase, QuestionHint, QuestionBranchingRule } from "./shared";
|
import type { QuizQuestionBase, QuestionHint, QuestionBranchingRule, EditedUrlImagesList } from "./shared";
|
||||||
|
|
||||||
export interface QuizQuestionText extends QuizQuestionBase {
|
export interface QuizQuestionText extends QuizQuestionBase {
|
||||||
type: "text";
|
type: "text";
|
||||||
@ -14,6 +14,7 @@ export interface QuizQuestionText extends QuizQuestionBase {
|
|||||||
/** Чекбокс "Автозаполнение адреса" */
|
/** Чекбокс "Автозаполнение адреса" */
|
||||||
autofill: boolean;
|
autofill: boolean;
|
||||||
answerType: "single" | "multi" | "numberOnly";
|
answerType: "single" | "multi" | "numberOnly";
|
||||||
|
editedUrlImagesList?: EditedUrlImagesList | null;
|
||||||
hint: QuestionHint;
|
hint: QuestionHint;
|
||||||
rule: QuestionBranchingRule;
|
rule: QuestionBranchingRule;
|
||||||
back: string | null;
|
back: string | null;
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
import type { QuizQuestionBase, QuestionVariant, QuestionHint, QuestionBranchingRule } from "./shared";
|
import type {
|
||||||
|
QuizQuestionBase,
|
||||||
|
QuestionVariant,
|
||||||
|
QuestionHint,
|
||||||
|
QuestionBranchingRule,
|
||||||
|
EditedUrlImagesList,
|
||||||
|
} from "./shared";
|
||||||
|
|
||||||
export interface QuizQuestionVariant extends QuizQuestionBase {
|
export interface QuizQuestionVariant extends QuizQuestionBase {
|
||||||
type: "variant";
|
type: "variant";
|
||||||
@ -14,6 +20,7 @@ export interface QuizQuestionVariant extends QuizQuestionBase {
|
|||||||
innerNameCheck: boolean;
|
innerNameCheck: boolean;
|
||||||
/** Чекбокс "Необязательный вопрос" */
|
/** Чекбокс "Необязательный вопрос" */
|
||||||
required: boolean;
|
required: boolean;
|
||||||
|
editedUrlImagesList?: EditedUrlImagesList | null;
|
||||||
/** Поле "Внутреннее название вопроса" */
|
/** Поле "Внутреннее название вопроса" */
|
||||||
innerName: string;
|
innerName: string;
|
||||||
/** Варианты ответов */
|
/** Варианты ответов */
|
||||||
@ -23,5 +30,6 @@ export interface QuizQuestionVariant extends QuizQuestionBase {
|
|||||||
back: string | null;
|
back: string | null;
|
||||||
originalBack: string | null;
|
originalBack: string | null;
|
||||||
autofill: boolean;
|
autofill: boolean;
|
||||||
|
ownPlaceholder?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
import type { QuestionHint, QuestionVariant, QuizQuestionBase, QuestionBranchingRule } from "./shared";
|
import type {
|
||||||
|
QuestionHint,
|
||||||
|
QuestionVariantWithEditedImages,
|
||||||
|
EditedUrlImagesList,
|
||||||
|
QuizQuestionBase,
|
||||||
|
QuestionBranchingRule,
|
||||||
|
} from "./shared";
|
||||||
|
|
||||||
export interface QuizQuestionVarImg extends QuizQuestionBase {
|
export interface QuizQuestionVarImg extends QuizQuestionBase {
|
||||||
type: "varimg";
|
type: "varimg";
|
||||||
@ -12,7 +18,8 @@ export interface QuizQuestionVarImg extends QuizQuestionBase {
|
|||||||
innerName: string;
|
innerName: string;
|
||||||
/** Чекбокс "Необязательный вопрос" */
|
/** Чекбокс "Необязательный вопрос" */
|
||||||
required: boolean;
|
required: boolean;
|
||||||
variants: QuestionVariant[];
|
variants: QuestionVariantWithEditedImages[];
|
||||||
|
editedUrlImagesList?: EditedUrlImagesList | null;
|
||||||
hint: QuestionHint;
|
hint: QuestionHint;
|
||||||
rule: QuestionBranchingRule;
|
rule: QuestionBranchingRule;
|
||||||
back: string | null;
|
back: string | null;
|
||||||
@ -20,5 +27,8 @@ export interface QuizQuestionVarImg extends QuizQuestionBase {
|
|||||||
autofill: boolean;
|
autofill: boolean;
|
||||||
largeCheck: boolean;
|
largeCheck: boolean;
|
||||||
replText: string;
|
replText: string;
|
||||||
|
/** Чекбокс "Можно несколько" */
|
||||||
|
multi?: boolean;
|
||||||
|
ownPlaceholder?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export type QuestionAnswer = {
|
|||||||
answer: Answer;
|
answer: Answer;
|
||||||
};
|
};
|
||||||
|
|
||||||
type OwnVariant = {
|
export type OwnVariant = {
|
||||||
id: string;
|
id: string;
|
||||||
variant: QuestionVariant;
|
variant: QuestionVariant;
|
||||||
};
|
};
|
||||||
@ -99,7 +99,7 @@ export const createQuizViewStore = () =>
|
|||||||
state.ownVariants.push({
|
state.ownVariants.push({
|
||||||
id,
|
id,
|
||||||
variant: {
|
variant: {
|
||||||
id: nanoid(),
|
id: id,
|
||||||
answer,
|
answer,
|
||||||
extendedText: "",
|
extendedText: "",
|
||||||
hints: "",
|
hints: "",
|
||||||
|
@ -33,6 +33,8 @@ export function useQuestionFlowControl() {
|
|||||||
//Изменение стейта (переменной currentQuestionId) ведёт к пересчёту что же за объект сейчас используется. Мы каждый раз просто ищем в списке
|
//Изменение стейта (переменной currentQuestionId) ведёт к пересчёту что же за объект сейчас используется. Мы каждый раз просто ищем в списке
|
||||||
const currentQuestion = sortedQuestions.find((question) => question.id === currentQuestionId) ?? sortedQuestions[0];
|
const currentQuestion = sortedQuestions.find((question) => question.id === currentQuestionId) ?? sortedQuestions[0];
|
||||||
|
|
||||||
|
// console.log(currentQuestion)
|
||||||
|
|
||||||
//Индекс текущего вопроса только если квиз линейный
|
//Индекс текущего вопроса только если квиз линейный
|
||||||
const linearQuestionIndex = //: number | null
|
const linearQuestionIndex = //: number | null
|
||||||
currentQuestion && sortedQuestions.every(({ content }) => content.rule.parentId !== "root") // null when branching enabled
|
currentQuestion && sortedQuestions.every(({ content }) => content.rule.parentId !== "root") // null when branching enabled
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { sendAnswer } from "@/api/quizRelase";
|
import { sendAnswer } from "@/api/quizRelase";
|
||||||
import { RealTypedQuizQuestion } from "@/model/questionTypes/shared";
|
import { RealTypedQuizQuestion } from "@/model/questionTypes/shared";
|
||||||
import { QuestionAnswer } from "@/stores/quizView";
|
import { OwnVariant, QuestionAnswer, createQuizViewStore } from "@/stores/quizView";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { notReachable } from "./notReachable";
|
import { notReachable } from "./notReachable";
|
||||||
|
|
||||||
export function sendQuestionAnswer(
|
export function sendQuestionAnswer(
|
||||||
quizId: string,
|
quizId: string,
|
||||||
question: RealTypedQuizQuestion,
|
question: RealTypedQuizQuestion,
|
||||||
questionAnswer: QuestionAnswer | undefined
|
questionAnswer: QuestionAnswer | undefined,
|
||||||
|
ownVariants: OwnVariant[]
|
||||||
) {
|
) {
|
||||||
if (!questionAnswer) {
|
if (!questionAnswer) {
|
||||||
return sendAnswer({
|
return sendAnswer({
|
||||||
@ -18,15 +19,67 @@ export function sendQuestionAnswer(
|
|||||||
}
|
}
|
||||||
switch (question.type) {
|
switch (question.type) {
|
||||||
case "date": {
|
case "date": {
|
||||||
if (!moment.isMoment(questionAnswer.answer)) throw new Error("Cannot send answer in date question");
|
let answer = "";
|
||||||
|
|
||||||
|
if (question.content.isRange) {
|
||||||
|
if (!Array.isArray(questionAnswer.answer)) throw new Error("Cannot send answer in range question");
|
||||||
|
|
||||||
|
let from = Number(questionAnswer.answer[0]);
|
||||||
|
let to = Number(questionAnswer.answer[1]);
|
||||||
|
|
||||||
|
if (
|
||||||
|
from !== 0 &&
|
||||||
|
to !== 0 &&
|
||||||
|
from !== Math.min(Number(questionAnswer.answer[0]), Number(questionAnswer.answer[1]))
|
||||||
|
) {
|
||||||
|
from = Math.min(Number(questionAnswer.answer[0]), Number(questionAnswer.answer[1]));
|
||||||
|
to = Math.max(Number(questionAnswer.answer[0]), Number(questionAnswer.answer[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
answer = `${!from ? "_" : moment(from).format("YYYY.MM.DD")} - ${!to ? "_" : moment(to).format("YYYY.MM.DD")}`;
|
||||||
|
} else {
|
||||||
|
if (!moment.isMoment(questionAnswer.answer)) throw new Error("Cannot send answer in date question");
|
||||||
|
|
||||||
|
answer = moment(questionAnswer.answer).format("YYYY.MM.DD");
|
||||||
|
}
|
||||||
return sendAnswer({
|
return sendAnswer({
|
||||||
questionId: question.id,
|
questionId: question.id,
|
||||||
body: moment(questionAnswer.answer).format("YYYY.MM.DD"),
|
body: answer,
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case "emoji": {
|
case "emoji": {
|
||||||
|
if (question.content.multi) {
|
||||||
|
const answer = questionAnswer.answer;
|
||||||
|
const ownVariant = Array.isArray(answer)
|
||||||
|
? ownVariants[ownVariants.findIndex((variant) => answer.some((a: string) => a === variant.id))]?.variant || ""
|
||||||
|
: ownVariants[ownVariants.findIndex((variant) => variant.id === questionAnswer.answer)]?.variant || "";
|
||||||
|
|
||||||
|
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
||||||
|
|
||||||
|
//Оставляем только выбранные варианты
|
||||||
|
const selectedVariants = question.content.variants.filter((v) => answer.includes(v.id));
|
||||||
|
|
||||||
|
let answerString = ``;
|
||||||
|
selectedVariants.forEach((e) => {
|
||||||
|
if (e.isOwn) {
|
||||||
|
if (question.content.own && selectedVariants.some((v) => v.isOwn)) {
|
||||||
|
answerString += `\`${e.extendedText} ${ownVariant?.answer ?? ""}\`,`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
answerString += `\`${e.extendedText} ${e.answer ?? ""}\`,`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
answerString = answerString.slice(0, -1);
|
||||||
|
|
||||||
|
return sendAnswer({
|
||||||
|
questionId: question.id,
|
||||||
|
body: answerString,
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const variant = question.content.variants.find((v) => v.id === questionAnswer.answer);
|
const variant = question.content.variants.find((v) => v.id === questionAnswer.answer);
|
||||||
if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`);
|
if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`);
|
||||||
|
|
||||||
@ -40,7 +93,40 @@ export function sendQuestionAnswer(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case "images": {
|
case "images": {
|
||||||
|
if (question.content.multi) {
|
||||||
|
const answer = questionAnswer.answer;
|
||||||
|
const ownAnswer = Array.isArray(answer)
|
||||||
|
? ownVariants[ownVariants.findIndex((variant) => answer.some((a: string) => a === variant.id))]?.variant
|
||||||
|
?.answer || ""
|
||||||
|
: ownVariants[ownVariants.findIndex((variant) => variant.id === questionAnswer.answer)]?.variant?.answer ||
|
||||||
|
"";
|
||||||
|
|
||||||
|
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
||||||
|
|
||||||
|
//Оставляем только выбранные варианты
|
||||||
|
const selectedVariants = question.content.variants.filter((v) => answer.includes(v.id));
|
||||||
|
|
||||||
|
let answerString = ``;
|
||||||
|
selectedVariants.forEach((e) => {
|
||||||
|
if (!e.isOwn || (e.isOwn && question.content.own)) {
|
||||||
|
const body = {
|
||||||
|
Image: e.extendedText,
|
||||||
|
Description: e.isOwn ? ownAnswer : e.answer,
|
||||||
|
};
|
||||||
|
answerString += `\`${JSON.stringify(body)}\`,`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
answerString = answerString.slice(0, -1);
|
||||||
|
|
||||||
|
return sendAnswer({
|
||||||
|
questionId: question.id,
|
||||||
|
body: answerString,
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const variant = question.content.variants.find((v) => v.id === questionAnswer.answer);
|
const variant = question.content.variants.find((v) => v.id === questionAnswer.answer);
|
||||||
|
|
||||||
if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`);
|
if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`);
|
||||||
const body = {
|
const body = {
|
||||||
Image: variant.extendedText,
|
Image: variant.extendedText,
|
||||||
@ -99,13 +185,30 @@ export function sendQuestionAnswer(
|
|||||||
case "variant": {
|
case "variant": {
|
||||||
if (question.content.multi) {
|
if (question.content.multi) {
|
||||||
const answer = questionAnswer.answer;
|
const answer = questionAnswer.answer;
|
||||||
if (!Array.isArray(answer)) throw new Error("Cannot send answer in select question");
|
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
||||||
|
|
||||||
|
const ownAnswer = Array.isArray(answer)
|
||||||
|
? ownVariants[ownVariants.findIndex((variant) => answer.some((a: string) => a === variant.id))]?.variant
|
||||||
|
?.answer || ""
|
||||||
|
: ownVariants[ownVariants.findIndex((variant) => variant.id === questionAnswer.answer)]?.variant?.answer ||
|
||||||
|
"";
|
||||||
|
|
||||||
|
//Оставляем только выбранные варианты
|
||||||
const selectedVariants = question.content.variants.filter((v) => answer.includes(v.id));
|
const selectedVariants = question.content.variants.filter((v) => answer.includes(v.id));
|
||||||
|
|
||||||
|
let answerString = ``;
|
||||||
|
selectedVariants.forEach((e) => {
|
||||||
|
if (!e.isOwn) answerString += `\`${e.answer}\`,`;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (question.content.own && selectedVariants.some((v) => v.isOwn)) {
|
||||||
|
answerString += `\`${ownAnswer}\`,`;
|
||||||
|
}
|
||||||
|
answerString = answerString.slice(0, -1);
|
||||||
|
|
||||||
return sendAnswer({
|
return sendAnswer({
|
||||||
questionId: question.id,
|
questionId: question.id,
|
||||||
body: selectedVariants.map((v) => v.answer).join(", "),
|
body: answerString,
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -121,16 +224,19 @@ export function sendQuestionAnswer(
|
|||||||
}
|
}
|
||||||
case "varimg": {
|
case "varimg": {
|
||||||
const variant = question.content.variants.find((v) => v.id === questionAnswer.answer);
|
const variant = question.content.variants.find((v) => v.id === questionAnswer.answer);
|
||||||
|
const ownAnswer =
|
||||||
|
ownVariants[ownVariants.findIndex((variant) => variant.id === questionAnswer.answer)]?.variant?.answer || "";
|
||||||
|
|
||||||
if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`);
|
if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`);
|
||||||
const body = {
|
const body = {
|
||||||
Image: variant.extendedText,
|
Image: variant.extendedText,
|
||||||
Description: variant.answer,
|
Description: question.content.own ? ownAnswer : variant.answer,
|
||||||
};
|
};
|
||||||
if (!body) throw new Error(`Body of answer in question ${question.id} is undefined`);
|
if (!body) throw new Error(`Body of answer in question ${question.id} is undefined`);
|
||||||
|
|
||||||
return sendAnswer({
|
return sendAnswer({
|
||||||
questionId: question.id,
|
questionId: question.id,
|
||||||
body: JSON.stringify(body),
|
body: `\`${JSON.stringify(body)}\``,
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,9 @@ const darkTheme = createTheme({
|
|||||||
navbarbg: {
|
navbarbg: {
|
||||||
main: "#333647",
|
main: "#333647",
|
||||||
},
|
},
|
||||||
|
ownPlaceholder: {
|
||||||
|
main: "(51, 54, 71, 0.65)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -46,6 +46,9 @@ const lightTheme = createTheme({
|
|||||||
orange: {
|
orange: {
|
||||||
main: "#FB5607",
|
main: "#FB5607",
|
||||||
},
|
},
|
||||||
|
ownPlaceholder: {
|
||||||
|
main: "1,1,1,0.65",
|
||||||
|
},
|
||||||
navbarbg: {
|
navbarbg: {
|
||||||
main: "#FFFFFF",
|
main: "#FFFFFF",
|
||||||
},
|
},
|
||||||
|
2
lib/utils/themes/mui.d.ts
vendored
2
lib/utils/themes/mui.d.ts
vendored
@ -12,6 +12,7 @@ declare module "@mui/material/styles" {
|
|||||||
grey4: Palette["primary"];
|
grey4: Palette["primary"];
|
||||||
orange: Palette["primary"];
|
orange: Palette["primary"];
|
||||||
navbarbg: Palette["primary"];
|
navbarbg: Palette["primary"];
|
||||||
|
ownPlaceholder: Palette["primary"];
|
||||||
}
|
}
|
||||||
interface PaletteOptions {
|
interface PaletteOptions {
|
||||||
lightPurple?: PaletteOptions["primary"];
|
lightPurple?: PaletteOptions["primary"];
|
||||||
@ -24,6 +25,7 @@ declare module "@mui/material/styles" {
|
|||||||
grey4?: PaletteOptions["primary"];
|
grey4?: PaletteOptions["primary"];
|
||||||
orange?: PaletteOptions["primary"];
|
orange?: PaletteOptions["primary"];
|
||||||
navbarbg?: PaletteOptions["primary"];
|
navbarbg?: PaletteOptions["primary"];
|
||||||
|
ownPlaceholder?: PaletteOptions["primary"];
|
||||||
}
|
}
|
||||||
interface TypographyVariants {
|
interface TypographyVariants {
|
||||||
infographic: React.CSSProperties;
|
infographic: React.CSSProperties;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@frontend/squzanswerer",
|
"name": "@frontend/squzanswerer",
|
||||||
"version": "1.0.55",
|
"version": "1.0.56",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist-package/index.js",
|
"main": "./dist-package/index.js",
|
||||||
"module": "./dist-package/index.js",
|
"module": "./dist-package/index.js",
|
||||||
|
Loading…
Reference in New Issue
Block a user