fix stepper css

This commit is contained in:
Nastya 2023-12-29 17:04:42 +03:00
commit 848e80a61f
21 changed files with 553 additions and 309 deletions

@ -1,11 +1,11 @@
import { Box } from "@mui/material";
// interface Props {
// color: string;
// }
interface Props {
color: string;
}
export default function ArrowLeft() {
export default function ArrowLeft({color = "#7E2AEA"}: Props) {
return (
<Box
@ -16,8 +16,8 @@ export default function ArrowLeft() {
}}
>
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.75 12H4.25" stroke="#7E2AEA" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M11 5.25L4.25 12L11 18.75" stroke="#7E2AEA" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M20.75 12H4.25" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M11 5.25L4.25 12L11 18.75" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</Box>

@ -32,7 +32,7 @@ export const Select = ({
placeholder = "",
colorMain = "#7E2AEA",
colorPlaceholder = "#9A9AAF",
color
color,
}: SelectProps) => {
const [activeItem, setActiveItem] = useState<number>(
empty ? -1 : activeItemIndex
@ -94,6 +94,7 @@ export const Select = ({
mt: "8px",
p: "4px",
borderRadius: "8px",
backgroundColor: theme.palette.background.default,
border: "1px solid #EEE4FC",
boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
},
@ -120,7 +121,7 @@ export const Select = ({
gap: "20px",
},
}}
IconComponent={(props) => <ArrowDown {...props } color={color}/>}
IconComponent={(props) => <ArrowDown {...props } />}
>
{items.map((item, index) => (
<MenuItem

@ -429,6 +429,8 @@ function QuizPreviewLayoutByType({
sx={{
width: "60%",
overflow: "hidden",
display: "flex",
justifyContent: "center"
}}
>
{backgroundBlock}

@ -41,7 +41,7 @@ export const Page = ({ currentQuestion }: PageProps) => {
</Box>
) : (
<YoutubeEmbedIframe
containerSX={{ width: "100%", height: "100%", maxHeight: "80vh", objectFit: "contain" }}
containerSX={{ width: "100%", height: "calc( 100vh - 270px)", maxHeight: "80vh", objectFit: "contain" }}
videoUrl={currentQuestion.content.video}
/>
)}

@ -73,15 +73,10 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
alignItems: "center",
gap: "20px",
marginTop: "20px",
flexDirection: "column",
width: isMobile ? "100%" : undefined
}}
>
<Typography sx={{
color: "#9A9AAF"
// color: theme.palette.grey2.main
}}>
{currentQuestion.content.ratingNegativeDescription}
</Typography>
<Box
sx={{
display: "inline-block",
@ -103,9 +98,17 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
emptyIcon={form?.icon("#9A9AAF")}
/>
</Box>
<Typography sx={{ color: "#9A9AAF" }}>
{currentQuestion.content.ratingPositiveDescription}
</Typography>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
gap: 2,
width: "100%"
}}
>
<Typography sx={{ color: "#9A9AAF" }}>{currentQuestion.content.ratingNegativeDescription}</Typography>
<Typography sx={{ color: "#9A9AAF" }}>{currentQuestion.content.ratingPositiveDescription}</Typography>
</Box>
</Box>
</Box>
);

@ -7,11 +7,13 @@ import { Dayjs } from "dayjs";
interface Props {
label?: string;
sx?: SxProps<Theme>;
sxIcon?: SxProps<Theme>;
sxDate?: SxProps<Theme>;
value?: Dayjs | null;
onChange?: (value: Dayjs | null) => void;
}
export default function LabeledDatePicker({ label, value, onChange, sx }: Props) {
export default function LabeledDatePicker({ label, value, onChange, sx, sxIcon, sxDate }: Props) {
const theme = useTheme();
const upLg = useMediaQuery(theme.breakpoints.up("md"));
@ -38,7 +40,7 @@ export default function LabeledDatePicker({ label, value, onChange, sx }: Props)
value={value}
onChange={onChange}
slots={{
openPickerIcon: () => <CalendarIcon />,
openPickerIcon: () => <CalendarIcon sx={sxIcon}/>,
}}
slotProps={{
openPickerButton: {
@ -47,6 +49,9 @@ export default function LabeledDatePicker({ label, value, onChange, sx }: Props)
},
"data-cy": "open-datepicker",
},
layout: {
sx: {backgroundColor: theme.palette.background.default,}
}
}}
sx={{
"& .MuiInputBase-root": {
@ -55,13 +60,14 @@ export default function LabeledDatePicker({ label, value, onChange, sx }: Props)
pr: "22px",
"& input": {
py: "11px",
pl: upLg ? "20px" : "13px",
pl: "20px",
lineHeight: "19px",
},
"& fieldset": {
borderColor: "#9A9AAF",
},
},
...sxDate
}}
/>
</Box>

@ -1,10 +1,12 @@
import { Box, IconButton } from "@mui/material";
import {Box, IconButton, ThemeProvider} from "@mui/material";
import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview";
import { useLayoutEffect, useRef } from "react";
import { Rnd } from "react-rnd";
import { useWindowSize } from "../../utils/hooks/useWindowSize";
import QuizPreviewLayout from "./QuizPreviewLayout";
import ResizeIcon from "@icons/ResizeIcon";
import {themesPublication} from "@utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
const DRAG_PARENT_MARGIN = 0;
const NAVBAR_HEIGHT = 0;
@ -20,6 +22,7 @@ interface RndPositionAndSize {
export default function QuizPreview() {
const isPreviewShown = useQuizPreviewStore((state) => state.isPreviewShown);
const rndParentRef = useRef<HTMLDivElement>(null);
const quiz = useCurrentQuiz();
const rndRef = useRef<Rnd | null>(null);
const rndPositionAndSizeRef = useRef<RndPositionAndSize>({
x: 0,
@ -51,66 +54,69 @@ export default function QuizPreview() {
);
return (
<Box
ref={rndParentRef}
data-cy="quiz-preview-container"
sx={{
position: "fixed",
top: NAVBAR_HEIGHT + DRAG_PARENT_MARGIN,
left: DRAG_PARENT_MARGIN,
bottom: DRAG_PARENT_BOTTOM_MARGIN,
right: DRAG_PARENT_MARGIN,
// backgroundColor: "rgba(0, 100, 0, 0.2)",
pointerEvents: "none",
zIndex: 100,
}}
>
{isPreviewShown && (
<Rnd
minHeight={20}
minWidth={20}
bounds="parent"
ref={rndRef}
dragHandleClassName="quiz-preview-draghandle"
default={{
x: rndPositionAndSizeRef.current.x,
y: rndPositionAndSizeRef.current.y,
width: rndPositionAndSizeRef.current.width,
height: rndPositionAndSizeRef.current.height,
}}
onResizeStop={(e, direction, ref, delta, position) => {
rndPositionAndSizeRef.current.x = position.x;
rndPositionAndSizeRef.current.y = position.y;
rndPositionAndSizeRef.current.width = ref.style.width;
rndPositionAndSizeRef.current.height = ref.style.height;
}}
onDragStop={(e, d) => {
rndPositionAndSizeRef.current.x = d.x;
rndPositionAndSizeRef.current.y = d.y;
}}
onDragStart={(e, d) => {
e.preventDefault();
}}
enableResizing={{
topLeft: isPreviewShown,
}}
resizeHandleComponent={{
topLeft: <ResizeIcon />,
}}
resizeHandleStyles={{
topLeft: {
top: "-1px",
left: "-1px",
},
}}
style={{
overflow: "hidden",
pointerEvents: "auto",
}}
>
<QuizPreviewLayout />
</Rnd>
)}
</Box>
<ThemeProvider theme={themesPublication?.[quiz?.config.theme]}>
<Box
ref={rndParentRef}
data-cy="quiz-preview-container"
sx={{
position: "fixed",
top: NAVBAR_HEIGHT + DRAG_PARENT_MARGIN,
left: DRAG_PARENT_MARGIN,
bottom: DRAG_PARENT_BOTTOM_MARGIN,
right: DRAG_PARENT_MARGIN,
// backgroundColor: "rgba(0, 100, 0, 0.2)",
pointerEvents: "none",
zIndex: 100,
}}
>
{isPreviewShown && (
<Rnd
minHeight={20}
minWidth={20}
bounds="parent"
ref={rndRef}
dragHandleClassName="quiz-preview-draghandle"
default={{
x: rndPositionAndSizeRef.current.x,
y: rndPositionAndSizeRef.current.y,
width: rndPositionAndSizeRef.current.width,
height: rndPositionAndSizeRef.current.height,
}}
onResizeStop={(e, direction, ref, delta, position) => {
rndPositionAndSizeRef.current.x = position.x;
rndPositionAndSizeRef.current.y = position.y;
rndPositionAndSizeRef.current.width = ref.style.width;
rndPositionAndSizeRef.current.height = ref.style.height;
}}
onDragStop={(e, d) => {
rndPositionAndSizeRef.current.x = d.x;
rndPositionAndSizeRef.current.y = d.y;
}}
onDragStart={(e, d) => {
e.preventDefault();
}}
enableResizing={{
topLeft: isPreviewShown,
}}
resizeHandleComponent={{
topLeft: <ResizeIcon />,
}}
resizeHandleStyles={{
topLeft: {
top: "-1px",
left: "-1px",
},
}}
style={{
overflow: "hidden",
pointerEvents: "auto",
}}
>
<QuizPreviewLayout />
</Rnd>
)}
</Box>
</ThemeProvider>
);
}

@ -17,7 +17,7 @@ import {
setCurrentQuestionIndex,
} from "@root/quizPreview";
import { AnyTypedQuizQuestion, UntypedQuizQuestion } from "model/questionTypes/shared";
import { useEffect } from "react";
import {useEffect, useRef, useState} from "react";
import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft";
import Date from "./QuizPreviewQuestionTypes/Date";
import Emoji from "./QuizPreviewQuestionTypes/Emoji";
@ -26,7 +26,7 @@ import Images from "./QuizPreviewQuestionTypes/Images";
import Number from "./QuizPreviewQuestionTypes/Number";
import Page from "./QuizPreviewQuestionTypes/Page";
import Rating from "./QuizPreviewQuestionTypes/Rating";
import Select from "./QuizPreviewQuestionTypes/Select";
import Select, {ArrowDownTheme} from "./QuizPreviewQuestionTypes/Select";
import Text from "./QuizPreviewQuestionTypes/Text";
import Variant from "./QuizPreviewQuestionTypes/Variant";
import Varimg from "./QuizPreviewQuestionTypes/Varimg";
@ -37,13 +37,14 @@ export default function QuizPreviewLayout() {
const theme = useTheme();
const questions = useQuestionsStore((state) => state.questions);
const currentQuizStep = useQuizPreviewStore((state) => state.currentQuestionIndex);
const [widthPreview, setWidthPreview] = useState(null)
const nonDeletedQuizQuestions = questions.filter((question) => !question.deleted && question.type !== "result" );
const maxCurrentQuizStep = nonDeletedQuizQuestions.length > 0 ? nonDeletedQuizQuestions.length - 1 : 0;
const currentProgress = Math.floor((currentQuizStep / maxCurrentQuizStep) * 100);
const PreviewWin = useRef(0);
const currentQuestion = nonDeletedQuizQuestions[currentQuizStep];
useEffect(
function resetCurrentQuizStep() {
if (currentQuizStep > maxCurrentQuizStep) {
@ -53,8 +54,22 @@ export default function QuizPreviewLayout() {
[currentQuizStep, maxCurrentQuizStep]
);
const observer = useRef(
new ResizeObserver((entries) => {
const { width } = entries[0].contentRect;
setWidthPreview(width)
})
);
useEffect(() => {
observer.current.observe(PreviewWin.current);
},
[PreviewWin, observer]);
console.log('current width state: ', widthPreview);
return (
<Paper
ref={PreviewWin}
className="quiz-preview-draghandle"
data-cy="quiz-preview-layout"
sx={{
@ -64,6 +79,7 @@ export default function QuizPreviewLayout() {
flexGrow: 1,
borderRadius: "12px",
pointerEvents: "auto",
backgroundColor: theme.palette.background.default
}}
>
<Box
@ -77,7 +93,7 @@ export default function QuizPreviewLayout() {
scrollbarWidth: "none",
}}
>
<QuestionPreviewComponent question={currentQuestion} />
<QuestionPreviewComponent question={currentQuestion} widthPreview={widthPreview} />
</Box>
<Box
sx={{
@ -98,8 +114,11 @@ export default function QuizPreviewLayout() {
height: "48px",
borderRadius: "8px",
"& .MuiOutlinedInput-notchedOutline": {
border: `1px solid ${theme.palette.brightPurple.main} !important`,
border: `1px solid ${theme.palette.primary.main} !important`,
},
"& .MuiSelect-icon": {
color: theme.palette.primary.main
}
}}
MenuProps={{
PaperProps: {
@ -109,6 +128,7 @@ export default function QuizPreviewLayout() {
borderRadius: "8px",
border: "1px solid #EEE4FC",
boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
backgroundColor: theme.palette.background.default,
},
},
MenuListProps: {
@ -119,21 +139,21 @@ export default function QuizPreviewLayout() {
gap: "8px",
"& .Mui-selected": {
backgroundColor: theme.palette.background.default,
color: theme.palette.brightPurple.main,
color: theme.palette.primary.main,
},
},
},
}}
inputProps={{
sx: {
color: theme.palette.brightPurple.main,
color: theme.palette.primary.main,
display: "flex",
alignItems: "center",
px: "9px",
gap: "20px",
},
}}
IconComponent={(props) => <ArrowDownIcon {...props} />}
IconComponent={ArrowDownTheme}
>
{Object.values(questions.filter(q=>q.type!=="result")).map(({ id, title }, index) => (
<MenuItem
@ -145,7 +165,7 @@ export default function QuizPreviewLayout() {
gap: "20px",
p: "4px",
borderRadius: "5px",
color: theme.palette.grey2.main,
color: "#9A9AAF",
}}
>
{`${index + 1}. ${title}`}
@ -196,7 +216,7 @@ export default function QuizPreviewLayout() {
disabled={currentQuizStep === 0}
sx={{ px: 1, minWidth: 0 }}
>
<ArrowLeft />
<ArrowLeft color={theme.palette.primary.main}/>
</Button>
<Button
variant="contained"
@ -212,32 +232,32 @@ export default function QuizPreviewLayout() {
);
}
function QuestionPreviewComponent({ question }: { question: AnyTypedQuizQuestion | UntypedQuizQuestion | undefined }) {
function QuestionPreviewComponent({ question, widthPreview }: { question: AnyTypedQuizQuestion | UntypedQuizQuestion | undefined, widthPreview?: number }) {
if (!question || question.type === null) return null;
switch (question.type) {
case "variant":
return <Variant question={question} />;
return <Variant question={question} widthPreview={widthPreview}/>;
case "images":
return <Images question={question} />;
return <Images question={question} widthPreview={widthPreview}/>;
case "varimg":
return <Varimg question={question} />;
return <Varimg question={question} widthPreview={widthPreview}/>;
case "emoji":
return <Emoji question={question} />;
return <Emoji question={question} widthPreview={widthPreview}/>;
case "text":
return <Text question={question} />;
return <Text question={question} widthPreview={widthPreview}/>;
case "select":
return <Select question={question} />;
return <Select question={question} widthPreview={widthPreview}/>;
case "date":
return <Date question={question} />;
return <Date question={question} widthPreview={widthPreview}/>;
case "number":
return <Number question={question} />;
return <Number question={question} widthPreview={widthPreview}/>;
case "file":
return <File question={question} />;
return <File question={question} widthPreview={widthPreview}/>;
case "page":
return <Page question={question} />;
return <Page question={question} widthPreview={widthPreview}/>;
case "rating":
return <Rating question={question} />;
return <Rating question={question} widthPreview={widthPreview}/>;
default:
notReachable(question);
}

@ -1,13 +1,18 @@
import { Box, Typography } from "@mui/material";
import {Box, Typography, useTheme} from "@mui/material";
import LabeledDatePicker from "@ui_kit/LabeledDatePicker";
import type { QuizQuestionDate } from "model/questionTypes/date";
import {modes} from "@utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
interface Props {
question: QuizQuestionDate;
}
export default function Date({ question }: Props) {
const theme = useTheme();
const mode = modes;
const quiz = useCurrentQuiz();
return (
<Box
sx={{
@ -17,7 +22,20 @@ export default function Date({ question }: Props) {
}}
>
<Typography variant="h6" data-cy="question-title">{question.title}</Typography>
<LabeledDatePicker />
<LabeledDatePicker sxIcon={{
"& path": {stroke: theme.palette.primary.main},
"& rect": {stroke: theme.palette.primary.main}
}}
sxDate={{
"& .MuiInputBase-root": {
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
borderRadius: "10px",
maxWidth: "250px",
pr: "22px",
}
}}
/>
</Box>
);
}

@ -44,7 +44,8 @@ export default function Emoji({ question }: Props) {
key={index}
sx={{
borderRadius: "12px",
border: `1px solid ${theme.palette.grey2.main}`,
border: `1px solid`,
borderColor: value === variant.answer ? theme.palette.primary.main : "#9A9AAF",
overflow: "hidden",
maxWidth: "317px",
width: "100%",
@ -66,17 +67,17 @@ export default function Emoji({ question }: Props) {
sx={{
margin: 0,
padding: "15px",
color: "#4D4D4D",
color: theme.palette.text.primary,
display: "flex",
gap: "10px",
background: "#f2f3f7"
background: theme.palette.background.default
}}
control={
<Radio
inputProps={{
"data-cy": "variant-radio",
}}
checkedIcon={<RadioCheck />} icon={<RadioIcon />}
checkedIcon={<RadioCheck color={theme.palette.primary.main}/>} icon={<RadioIcon />}
/>
}

@ -58,7 +58,7 @@ export default function File({ question }: Props) {
}}
/>
</Button>
{file && <Typography data-cy="chosen-file-name">Выбран файл: {file.name}</Typography>}
{file && <Typography data-cy="chosen-file-name">Вы загрузили: {file.name}</Typography>}
</Box>
);
}

@ -14,9 +14,10 @@ import type { QuizQuestionImages } from "model/questionTypes/images";
interface Props {
question: QuizQuestionImages;
widthPreview: number
}
export default function Images({ question }: Props) {
export default function Images({ question, widthPreview }: Props) {
const theme = useTheme();
const [selectedVariants, setSelectedVariants] = useState<number[]>([]);
@ -47,12 +48,13 @@ export default function Images({ question }: Props) {
gap: 1,
}}
>
<Typography variant="h6">{question.title}</Typography>
<Typography variant="h6" color={theme.palette.text.primary}>{question.title}</Typography>
<Box
sx={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))",
gap: 1,
gap: "15px",
maxWidth: "1050px"
}}
>
{question.content.variants
@ -70,8 +72,10 @@ export default function Images({ question }: Props) {
overflow: "hidden",
border: "1px solid",
borderColor: selectedVariants.includes(index)
? theme.palette.brightPurple.main
? theme.palette.primary.main
: "#E3E3E3",
maxWidth: "300px",
maxHeight: "340px"
}}
>
{variant.extendedText ? (

@ -1,9 +1,13 @@
import { useLayoutEffect, useState } from "react";
import { Box, Typography } from "@mui/material";
import {Box, Typography, useTheme} from "@mui/material";
import { CustomSlider } from "@ui_kit/CustomSlider";
import type { QuizQuestionNumber } from "model/questionTypes/number";
import CustomTextField from "@ui_kit/CustomTextField";
import {updateAnswer} from "@root/quizView";
import {modes} from "@utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
interface Props {
question: QuizQuestionNumber;
@ -11,7 +15,9 @@ interface Props {
export default function Number({ question }: Props) {
const [sliderValues, setSliderValues] = useState<number | number[]>(0);
const theme = useTheme();
const mode = modes;
const quiz = useCurrentQuiz();
const start = question.content.start;
const min = parseInt(question.content.range.split("—")[0]);
const max = parseInt(question.content.range.split("—")[1]);
@ -50,7 +56,66 @@ export default function Number({ question }: Props) {
defaultValue={start}
valueLabelDisplay={"on"}
step={question.content.step}
sx={{
color: theme.palette.primary.main,
"& .MuiSlider-valueLabel": {
background: theme.palette.primary.main,}
}}
/>
{!question.content.chooseRange && (
<Box sx={{mt: "30px", maxWidth: "80px",}}>
<CustomTextField
placeholder="0"
value={sliderValues}
sx={{
borderColor: theme.palette.text.primary,
"& .MuiInputBase-input": {
textAlign: "center",
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
},
}}
/>
</Box>
)}
{question.content.chooseRange && (
<Box
sx={{
mt: "30px",
display: "flex",
gap: "15px",
alignItems: "center",
"& .MuiFormControl-root": { width: "auto" },
}}
>
<CustomTextField
placeholder="0"
value={sliderValues[0]}
sx={{
maxWidth: "80px",
borderColor: theme.palette.text.primary,
"& .MuiInputBase-input": {
textAlign: "center",
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
},
}}
/>
<Typography color={theme.palette.text.primary}>до</Typography>
<CustomTextField
placeholder="0"
value={sliderValues[1]}
sx={{
maxWidth: "80px",
borderColor: theme.palette.text.primary,
"& .MuiInputBase-input": {
textAlign: "center",
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
},
}}
/>
</Box>
)}
</Box>
</Box>
);

@ -53,7 +53,7 @@ export default function Rating({ question }: Props) {
gap: 1,
}}
>
<Typography variant="h6" data-cy="question-title">{question.title}</Typography>
<Typography variant="h6" data-cy="question-title" color={theme.palette.text.primary} >{question.title}</Typography>
<Box
sx={{
display: "flex",
@ -67,7 +67,7 @@ export default function Rating({ question }: Props) {
data-rating={selectedRating}
sx={{
display: "flex",
gap: isMobile ? "10px" : "15px",
gap: "25px",
flexWrap: "wrap",
}}
>
@ -89,11 +89,7 @@ export default function Rating({ question }: Props) {
}}
>
<RatingIconComponent
color={
selectedRating > itemNumber
? theme.palette.brightPurple.main
: theme.palette.grey2.main
}
color={selectedRating > itemNumber ? theme.palette.primary.main : "#9A9AAF"}
/>
</Box>
))}

@ -19,7 +19,7 @@ interface Props {
export default function Text({ question }: Props) {
const theme = useTheme();
const [selectValue, setSelectValue] = useState<string>("");
const arrowDown = <ArrowDownIcon color = {"currentColor"}/>
function handleChange(event: SelectChangeEvent<string | null>) {
setSelectValue((event.target as HTMLInputElement).value);
}
@ -54,8 +54,11 @@ export default function Text({ question }: Props) {
height: "48px",
borderRadius: "8px",
"& .MuiOutlinedInput-notchedOutline": {
border: `1px solid ${theme.palette.brightPurple.main} !important`,
border: `1px solid ${theme.palette.primary.main} !important`,
},
"& .MuiSelect-icon": {
color: theme.palette.primary.main
}
}}
MenuProps={{
PaperProps: {
@ -64,6 +67,7 @@ export default function Text({ question }: Props) {
p: "4px",
borderRadius: "8px",
border: "1px solid #EEE4FC",
backgroundColor: theme.palette.background.default,
boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
},
},
@ -75,19 +79,20 @@ export default function Text({ question }: Props) {
gap: "8px",
"& .Mui-selected": {
backgroundColor: theme.palette.background.default,
color: theme.palette.brightPurple.main,
color: theme.palette.primary.main,
},
},
},
}}
inputProps={{
sx: {
color: theme.palette.brightPurple.main,
color: theme.palette.primary.main,
display: "flex",
alignItems: "center",
px: "9px",
gap: "20px",
"& + input": !selectValue && {
backgroundColor: theme.palette.background.default,
border: "none",
transform: "translateY(-50%)",
top: "50%",
@ -96,9 +101,10 @@ export default function Text({ question }: Props) {
color: "#333",
fontSize: "16px",
},
},
}}
IconComponent={(props) => <ArrowDownIcon {...props} />}
IconComponent={ArrowDownTheme}
>
{question.content.variants
.filter(({ answer }) => answer)
@ -113,7 +119,7 @@ export default function Text({ question }: Props) {
gap: "20px",
p: "4px",
borderRadius: "5px",
color: theme.palette.grey2.main,
color: "#9A9AAF",
}}
>
{variant.answer}
@ -124,3 +130,23 @@ export default function Text({ question }: Props) {
</Box>
);
}
export function ArrowDownTheme (props: any) {
return (
<Box
{...props}
sx={{
top: "25% !important",
height: "24px",
width: "24px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M19.5 9L12 16.5L4.5 9" stroke={"currentColor"} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Box>
)
}

@ -1,14 +1,14 @@
import { ChangeEvent, useState } from "react";
import {
Box,
FormControl,
FormControlLabel,
FormLabel,
Radio,
RadioGroup,
useRadioGroup,
Tooltip,
Typography,
Box,
FormControl,
FormControlLabel,
FormLabel,
Radio,
RadioGroup,
useRadioGroup,
Tooltip,
Typography, useTheme, Checkbox,
} from "@mui/material";
import InfoIcon from "@icons/InfoIcon";
@ -17,6 +17,9 @@ import type { QuizQuestionVariant } from "model/questionTypes/variant";
import CustomRadio from "@ui_kit/CustomRadio";
import RadioCheck from "@ui_kit/RadioCheck";
import RadioIcon from "@ui_kit/RadioIcon";
import {modes} from "@utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
import CheckboxIcon from "@icons/Checkbox";
interface Props {
question: QuizQuestionVariant;
@ -24,14 +27,16 @@ interface Props {
export default function Variant({ question }: Props) {
const [value, setValue] = useState<string | null>(null);
const theme = useTheme();
const mode = modes;
const quiz = useCurrentQuiz();
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setValue((event.target as HTMLInputElement).value);
};
return (
<FormControl fullWidth>
<FormLabel id="quiz-question-radio-group" data-cy="question-title" sx={{color: "#000000", marginBottom: "20px", fontSize: "24px", fontWeight: 500}}>
<FormLabel id="quiz-question-radio-group" data-cy="question-title" sx={{color: theme.palette.text.primary, marginBottom: "20px", fontSize: "24px", fontWeight: 500}}>
{question.title}
</FormLabel>
<RadioGroup
@ -52,24 +57,32 @@ export default function Variant({ question }: Props) {
data-cy="variant-answer"
labelPlacement="start"
sx={{borderRadius: "12px",
border: value === value ? "1px solid #7E2AEA" : "1px solid #9A9AAF",
border: value == variant.answer ? `1px solid ${theme.palette.primary.main}` : "1px solid #9A9AAF",
padding: "20px",
justifyContent: "space-between",
maxWidth: "685px",
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
width: "100%",
margin: 0
}}
control={
<Radio
inputProps={{
"data-cy": "variant-radio",
}}
checkedIcon={<RadioCheck />} icon={<RadioIcon />}
/>
control={question.content.multi ? (
<Checkbox
checkedIcon={<CheckboxIcon checked color={theme.palette.primary.main} />}
icon={<CheckboxIcon />}
/>
) : (
<Radio
inputProps={{
"data-cy": "variant-radio",
}}
checkedIcon={<RadioCheck color={theme.palette.primary.main}/>} icon={<RadioIcon />}
/>
)
}
label={
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<Typography>
<Typography color={theme.palette.text.primary}>
{variant.answer}
</Typography>
{variant.hints && (

@ -7,7 +7,7 @@ import {
Radio,
RadioGroup,
Tooltip,
Typography, useTheme,
Typography, useMediaQuery, useTheme,
} from "@mui/material";
import InfoIcon from "@icons/InfoIcon";
@ -16,14 +16,20 @@ import type { QuestionVariant } from "model/questionTypes/shared";
import type { QuizQuestionVarImg } from "model/questionTypes/varimg";
import RadioCheck from "@ui_kit/RadioCheck";
import RadioIcon from "@ui_kit/RadioIcon";
import {modes} from "@utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
interface Props {
question: QuizQuestionVarImg;
widthPreview: number;
}
export default function Varimg({ question }: Props) {
export default function Varimg({ question, widthPreview }: Props) {
const [selectedVariantIndex, setSelectedVariantIndex] = useState<number>(-1);
const theme = useTheme();
const mode = modes;
const quiz = useCurrentQuiz();
const isMobile = useMediaQuery(theme.breakpoints.down(650));
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setSelectedVariantIndex(
question.content.variants.findIndex(
@ -43,93 +49,113 @@ export default function Varimg({ question }: Props) {
gap: "40px",
}}
>
<FormControl sx={{maxWidth: "900px",
<FormControl sx={{
//maxWidth: "900px",
width: "100%", gap: "25px"}}>
<FormLabel
id="quiz-question-radio-group"
data-cy="question-title"
sx={{fontSize: "24px", fontWeight: 500}}
sx={{fontSize: "24px", fontWeight: 500, color: theme.palette.text.primary}}
>
{question.title}
</FormLabel>
<RadioGroup
aria-labelledby="quiz-question-radio-group"
value={currentVariant?.answer ?? ""}
onChange={handleChange}
sx={{gap: "20px"}}
>
{question.content.variants
.filter(({ answer }) => answer)
.map((variant, index) => (
<FormControlLabel
key={index}
value={variant.answer}
data-cy="variant-answer"
<Box sx={{
display: "flex",
alignItems: "center",
flexDirection: widthPreview < 650 ? "column-reverse" : undefined,
gap: "30px"
}}>
<RadioGroup
aria-labelledby="quiz-question-radio-group"
value={currentVariant?.answer ?? ""}
onChange={handleChange}
sx={{
margin: 0,
borderRadius: "5px",
padding: "15px",
color: "#4D4D4D",
border: `1px solid ${theme.palette.grey2.main}`,
gap: "20px",
display: "flex",
width: "100%",
}}
control={
<Radio
inputProps={{
"data-cy": "variant-radio",
>
{question.content.variants
.filter(({ answer }) => answer)
.map((variant, index) => (
<FormControlLabel
key={index}
value={variant.answer}
data-cy="variant-answer"
sx={{
margin: 0,
borderRadius: "5px",
padding: "15px",
color: theme.palette.text.primary,
border: `1px solid`,
borderColor: selectedVariantIndex == index
? theme.palette.primary.main
: "#E3E3E3",
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
/*display: "flex",*/
}}
control={
<Radio
inputProps={{
"data-cy": "variant-radio",
}}
checkedIcon={<RadioCheck color={theme.palette.primary.main}/>} icon={<RadioIcon />}
/>
}
label={
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<Typography>{variant.answer}</Typography>
{variant.hints && (
<Tooltip title={variant.hints} placement="right">
<Box>
<InfoIcon />
</Box>
</Tooltip>
)}
</Box>
}
/>
))}
</RadioGroup>
<Box
sx={{
border: "1px solid #E3E3E3",
maxWidth: "400px",
height: "400px",
display: "flex",
justifyContent: "center",
alignItems: "center",
borderRadius: "12px",
marginTop: widthPreview < 650 ? 0 : "50px",
overflow: "hidden",
}}
>
{currentVariant?.extendedText ? (
<img
src={currentVariant.extendedText}
data-cy="variant-image"
alt="question variant"
style={{
width: "100%",
height: "100%",
display: "block",
flexGrow: 1,
objectFit: "cover"
}}
checkedIcon={<RadioCheck />} icon={<RadioIcon />}
/>
}
label={
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<Typography>{variant.answer}</Typography>
{variant.hints && (
<Tooltip title={variant.hints} placement="right">
<Box>
<InfoIcon />
</Box>
</Tooltip>
)}
</Box>
}
/>
))}
</RadioGroup>
) : (
<Typography p={2}>
{selectedVariantIndex === -1
? widthPreview < 650 ? "Выберите вариант ниже" : "Выберите вариант"
: "Картинка отсутствует"}
</Typography>
)}
</Box>
</Box>
</FormControl>
<Box
sx={{
border: "1px solid #E3E3E3",
maxWidth: "400px",
height: "400px",
display: "flex",
justifyContent: "center",
alignItems: "center",
borderRadius: "12px",
marginTop: "50px",
overflow: "hidden",
}}
>
{currentVariant?.extendedText ? (
<img
src={currentVariant.extendedText}
data-cy="variant-image"
alt="question variant"
style={{
width: "100%",
display: "block",
objectFit: "scale-down",
flexGrow: 1,
}}
/>
) : (
<Typography p={2}>
{selectedVariantIndex === -1
? "Выберите вариант"
: "Картинка отсутствует"}
</Typography>
)}
</Box>
</Box>
);
}

@ -4,6 +4,7 @@ import YoutubeEmbedIframe from "./YoutubeEmbedIframe";
import { QuizStartpageAlignType, QuizStartpageType } from "@model/quizSettings";
import { notReachable } from "../../utils/notReachable";
import { useUADevice } from "../../utils/hooks/useUADevice";
import {useEffect, useRef, useState} from "react";
export default function QuizPreviewLayout() {
const theme = useTheme();
@ -36,7 +37,18 @@ export default function QuizPreviewLayout() {
) : null;
return (
<Paper className="quiz-preview-draghandle" sx={{ height: "100%" }}>
<Paper className="quiz-preview-draghandle"
sx={{
height: "100%",
background:
quiz.config.startpageType === "expanded"
? quiz.config.startpage.position === "left"
? "linear-gradient(90deg,#272626,transparent)"
: quiz.config.startpage.position === "center"
? "linear-gradient(180deg,transparent,#272626)"
: "linear-gradient(270deg,#272626,transparent)"
: theme.palette.background.default,
}}>
<QuizPreviewLayoutByType
quizHeaderBlock={
<>
@ -94,19 +106,19 @@ export default function QuizPreviewLayout() {
{quiz.config.info.clickable ? (
isMobileDevice ? (
<Link href={`tel:${quiz.config.info.phonenumber}`}>
<Typography sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }}>
<Typography sx={{ fontSize: "16px", color: theme.palette.primary.main }}>
{quiz.config.info.phonenumber}
</Typography>
</Link>
) : (
<ButtonBase onClick={handleCopyNumber}>
<Typography sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }}>
<Typography sx={{ fontSize: "16px", color: theme.palette.primary.main }}>
{quiz.config.info.phonenumber}
</Typography>
</ButtonBase>
)
) : (
<Typography sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }}>
<Typography sx={{ fontSize: "16px", color: theme.palette.primary.main }}>
{quiz.config.info.phonenumber}
</Typography>
)}
@ -138,6 +150,46 @@ function QuizPreviewLayoutByType({
const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(630));
function StartPageMobile() {
return(
<>
<Box
sx={{
width: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "flex-start",
p: "25px",
height: "80%"
}}
>
{quizHeaderBlock}
<Box
sx={{
height: "80%",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
width: "100%"
}}
>
{quizMainBlock}
</Box>
</Box>
<Box
sx={{
width: "100%",
overflow: "hidden",
}}
>
{backgroundBlock}
</Box>
</>
)
}
switch (startpageType) {
case null:
case "standard": {
@ -191,7 +243,7 @@ function QuizPreviewLayoutByType({
width: "40%",
position: "relative",
padding: "16px",
zIndex: 2,
zIndex: 3,
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
@ -208,7 +260,7 @@ function QuizPreviewLayoutByType({
top: 0,
height: "100%",
width: "100%",
zIndex: 1,
zIndex: -1,
}}
>
{backgroundBlock}
@ -230,7 +282,15 @@ function QuizPreviewLayoutByType({
}}
>
{quizHeaderBlock}
{backgroundBlock && <Box>{backgroundBlock}</Box>}
{backgroundBlock &&
<Box
sx={{
width: "60%",
overflow: "hidden",
display: "flex",
justifyContent: "center"
}}
>{backgroundBlock}</Box>}
{quizMainBlock}
</Box>
);

@ -1,9 +1,11 @@
import { Box, IconButton, useTheme, useMediaQuery } from "@mui/material";
import {Box, IconButton, useTheme, useMediaQuery, ThemeProvider} from "@mui/material";
import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview";
import { useLayoutEffect, useRef } from "react";
import {useEffect, useLayoutEffect, useRef, useState} from "react";
import { Rnd } from "react-rnd";
import QuizPreviewLayout from "./QuizPreviewLayout";
import ResizeIcon from "@icons/ResizeIcon";
import {themesPublication} from "@utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
const DRAG_PARENT_MARGIN = 0;
const NAVBAR_HEIGHT = 0;
@ -21,6 +23,7 @@ export const StartPagePreview = () => {
const rndParentRef = useRef<HTMLDivElement>(null);
const rndRef = useRef<Rnd | null>(null);
const theme = useTheme();
const quiz = useCurrentQuiz();
const isTablet = useMediaQuery(theme.breakpoints.down(630));
const rndPositionAndSizeRef = useRef<RndPositionAndSize>({
x: 0,
@ -52,66 +55,69 @@ export const StartPagePreview = () => {
);
return (
<Box
ref={rndParentRef}
sx={{
position: "fixed",
top: NAVBAR_HEIGHT + DRAG_PARENT_MARGIN,
left: DRAG_PARENT_MARGIN,
bottom: DRAG_PARENT_BOTTOM_MARGIN,
right: DRAG_PARENT_MARGIN,
pointerEvents: "none",
zIndex: 100,
}}
>
{isPreviewShown && (
<Rnd
minHeight={20}
minWidth={20}
bounds="parent"
ref={rndRef}
dragHandleClassName="quiz-preview-draghandle"
default={{
x: rndPositionAndSizeRef.current.x,
y: rndPositionAndSizeRef.current.y,
width: rndPositionAndSizeRef.current.width,
height: rndPositionAndSizeRef.current.height,
}}
onResizeStop={(e, direction, ref, delta, position) => {
rndPositionAndSizeRef.current.x = position.x;
rndPositionAndSizeRef.current.y = position.y;
rndPositionAndSizeRef.current.width = ref.style.width;
rndPositionAndSizeRef.current.height = ref.style.height;
}}
onDragStop={(e, d) => {
rndPositionAndSizeRef.current.x = d.x;
rndPositionAndSizeRef.current.y = d.y;
}}
onDragStart={(e, d) => {
e.preventDefault();
}}
enableResizing={{
topLeft: isPreviewShown,
}}
resizeHandleComponent={{
topLeft: <ResizeIcon />,
}}
resizeHandleStyles={{
topLeft: {
top: "-1px",
left: "-1px",
zIndex: 100,
},
}}
style={{
overflow: "hidden",
pointerEvents: "auto",
borderRadius: "5px",
}}
>
<QuizPreviewLayout />
</Rnd>
)}
</Box>
<ThemeProvider theme={themesPublication?.[quiz?.config.theme]}>
<Box
ref={rndParentRef}
sx={{
position: "fixed",
top: NAVBAR_HEIGHT + DRAG_PARENT_MARGIN,
left: DRAG_PARENT_MARGIN,
bottom: DRAG_PARENT_BOTTOM_MARGIN,
right: DRAG_PARENT_MARGIN,
pointerEvents: "none",
zIndex: 100,
}}
>
{isPreviewShown && (
<Rnd
minHeight={20}
minWidth={20}
bounds="parent"
ref={rndRef}
dragHandleClassName="quiz-preview-draghandle"
default={{
x: rndPositionAndSizeRef.current.x,
y: rndPositionAndSizeRef.current.y,
width: rndPositionAndSizeRef.current.width,
height: rndPositionAndSizeRef.current.height,
}}
onResizeStop={(e, direction, ref, delta, position) => {
rndPositionAndSizeRef.current.x = position.x;
rndPositionAndSizeRef.current.y = position.y;
rndPositionAndSizeRef.current.width = ref.style.width;
rndPositionAndSizeRef.current.height = ref.style.height;
}}
onDragStop={(e, d) => {
rndPositionAndSizeRef.current.x = d.x;
rndPositionAndSizeRef.current.y = d.y;
}}
onDragStart={(e, d) => {
e.preventDefault();
}}
enableResizing={{
topLeft: isPreviewShown,
}}
resizeHandleComponent={{
topLeft: <ResizeIcon />,
}}
resizeHandleStyles={{
topLeft: {
top: "-1px",
left: "-1px",
zIndex: 100,
},
}}
style={{
overflow: "hidden",
pointerEvents: "auto",
borderRadius: "5px",
}}
>
<QuizPreviewLayout />
</Rnd>
)}
</Box>
</ThemeProvider>
);
};

@ -35,12 +35,12 @@ export default function ProgressMobileStepper({
width: "100%",
flexGrow: 1,
padding: "8px 0",
"& .css-1ej0n1q-MuiLinearProgress-root-MuiMobileStepper-progress": {
"& .MuiLinearProgress-root": {
height: "10px",
background: "#ffffff",
width: "100%",
},
"& .css-1v0msyf-MuiLinearProgress-bar1": {
"& .MuiLinearProgress-bar": {
background: "#7e2aea",
},
}}

@ -14,10 +14,6 @@ const themePublic = createTheme({
padding: '13px 20px',
borderRadius: '8px',
boxShadow: "none",
// "&:hover": {
// backgroundColor: "#581CA7"
// }
},
},
{
@ -27,11 +23,6 @@ const themePublic = createTheme({
style: {
padding: '10px 20px',
borderRadius: '8px',
"&:hover": {
backgroundColor: "#581CA7",
border: '1px solid #581CA7',
}
},
},
],