Merge branch 'theme-publication' into dev

This commit is contained in:
Nastya 2023-12-26 10:24:09 +03:00
commit 78ddb2e746
32 changed files with 652 additions and 142 deletions

@ -1,7 +1,12 @@
import { Box, useTheme } from "@mui/material"; import {Box, SxProps, Theme, useTheme} from "@mui/material";
interface Color{
export default function ArrowDownIcon(props: any) { color?: string
}
export default function ArrowDownIcon(
props: any,
{color = "#7E2AEA"}: Color
) {
const theme = useTheme(); const theme = useTheme();
return ( return (
@ -17,7 +22,7 @@ export default function ArrowDownIcon(props: any) {
}} }}
> >
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> <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={theme.palette.brightPurple.main} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" /> <path d="M19.5 9L12 16.5L4.5 9" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg> </svg>
</Box> </Box>
); );

@ -1,6 +1,9 @@
import { Box } from "@mui/material"; import {Box, SxProps, Theme} from "@mui/material";
export default function CalendarIcon() { interface Props {
sx?: SxProps<Theme>
}
export default function CalendarIcon({sx}:Props) {
return ( return (
<Box <Box
sx={{ sx={{
@ -20,6 +23,7 @@ export default function CalendarIcon() {
"&:active rect": { "&:active rect": {
stroke: "#FB5607", stroke: "#FB5607",
}, },
...sx
}} }}
> >
<svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">

@ -1,10 +1,11 @@
import { Box, useTheme } from "@mui/material"; import { Box, useTheme } from "@mui/material";
type CheckboxIconProps = { interface CheckboxIconProps {
checked?: boolean; checked?: boolean;
color?: string;
}; };
export const CheckboxIcon = ({ checked = false }: CheckboxIconProps) => { export default function CheckboxIcon ({ checked = false, color = "#7E2AEA", }: CheckboxIconProps) {
const theme = useTheme(); const theme = useTheme();
return ( return (
@ -17,9 +18,9 @@ export const CheckboxIcon = ({ checked = false }: CheckboxIconProps) => {
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
backgroundColor: checked backgroundColor: checked
? theme.palette.brightPurple.main ? color
: theme.palette.background.default, : "#F2F3F7",
border: `1px solid ${theme.palette.grey2.main}`, border: `1px solid #9A9AAF`,
}} }}
> >
{checked && ( {checked && (

@ -12,7 +12,7 @@ export const NameplateLogo: FC<SVGProps<SVGSVGElement>> = (props) => (
<circle cx="54.4046" cy="12.3947" r="2.1546" fill="#7E2AEA" /> <circle cx="54.4046" cy="12.3947" r="2.1546" fill="#7E2AEA" />
<path <path
d="M88.866 39.4685C88.2378 33.3607 85.3643 27.7037 80.8025 23.594C76.2408 19.4843 70.3156 17.2146 64.1757 17.2248C63.3039 17.2252 62.4328 17.2708 61.5658 17.3614C55.4608 18.0025 49.8093 20.8814 45.7015 25.443C41.5937 30.0046 39.3205 35.9256 39.3203 42.0642V42.0642V77.549H49.9658V62.468C54.128 65.3636 59.0787 66.9119 64.1491 66.9036C65.0208 66.9033 65.8919 66.8577 66.759 66.767C70.0031 66.426 73.1483 65.4494 76.0151 63.8929C78.8818 62.3364 81.4138 60.2305 83.4667 57.6955C85.5195 55.1604 87.0529 52.2458 87.9793 49.1181C88.9058 45.9904 89.2071 42.7109 88.866 39.4667V39.4685ZM75.1937 51.0011C74.0243 52.4537 72.5783 53.6599 70.9395 54.5498C69.3007 55.4397 67.5017 55.9956 65.6465 56.1854C65.149 56.2371 64.6492 56.2631 64.1491 56.2635C60.9296 56.2605 57.8068 55.1631 55.2932 53.1515C52.7796 51.1398 51.0245 48.3334 50.3161 45.1929C49.6077 42.0523 49.988 38.7642 51.3945 35.8683C52.8011 32.9723 55.1504 30.6406 58.0568 29.2558C60.9632 27.871 64.2541 27.5154 67.3892 28.2473C70.5244 28.9793 73.3176 30.7553 75.3103 33.284C77.303 35.8126 78.3769 38.9436 78.3558 42.1629C78.3346 45.3823 77.2196 48.4989 75.1937 51.0011Z" d="M88.866 39.4685C88.2378 33.3607 85.3643 27.7037 80.8025 23.594C76.2408 19.4843 70.3156 17.2146 64.1757 17.2248C63.3039 17.2252 62.4328 17.2708 61.5658 17.3614C55.4608 18.0025 49.8093 20.8814 45.7015 25.443C41.5937 30.0046 39.3205 35.9256 39.3203 42.0642V42.0642V77.549H49.9658V62.468C54.128 65.3636 59.0787 66.9119 64.1491 66.9036C65.0208 66.9033 65.8919 66.8577 66.759 66.767C70.0031 66.426 73.1483 65.4494 76.0151 63.8929C78.8818 62.3364 81.4138 60.2305 83.4667 57.6955C85.5195 55.1604 87.0529 52.2458 87.9793 49.1181C88.9058 45.9904 89.2071 42.7109 88.866 39.4667V39.4685ZM75.1937 51.0011C74.0243 52.4537 72.5783 53.6599 70.9395 54.5498C69.3007 55.4397 67.5017 55.9956 65.6465 56.1854C65.149 56.2371 64.6492 56.2631 64.1491 56.2635C60.9296 56.2605 57.8068 55.1631 55.2932 53.1515C52.7796 51.1398 51.0245 48.3334 50.3161 45.1929C49.6077 42.0523 49.988 38.7642 51.3945 35.8683C52.8011 32.9723 55.1504 30.6406 58.0568 29.2558C60.9632 27.871 64.2541 27.5154 67.3892 28.2473C70.5244 28.9793 73.3176 30.7553 75.3103 33.284C77.303 35.8126 78.3769 38.9436 78.3558 42.1629C78.3346 45.3823 77.2196 48.4989 75.1937 51.0011Z"
fill="#151515" fill={"currentColor" || "#151515"}
/> />
</svg> </svg>
); );

File diff suppressed because one or more lines are too long

@ -1,7 +1,10 @@
import { Box, useTheme } from "@mui/material"; import { Box, useTheme } from "@mui/material";
interface Props{
color?: string
}
export default function UploadIcon() { export default function UploadIcon({color= "#9A9AAF"}: Props) {
const theme = useTheme(); const theme = useTheme();
return ( return (
@ -15,9 +18,9 @@ export default function UploadIcon() {
}} }}
> >
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
<path d="M10.75 10.25L16 5L21.25 10.25" stroke={theme.palette.grey2.main} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /> <path d="M10.75 10.25L16 5L21.25 10.25" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
<path d="M16 19V5" stroke={theme.palette.grey2.main} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /> <path d="M16 19V5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
<path d="M27 19V26C27 26.2652 26.8946 26.5196 26.7071 26.7071C26.5196 26.8946 26.2652 27 26 27H6C5.73478 27 5.48043 26.8946 5.29289 26.7071C5.10536 26.5196 5 26.2652 5 26V19" stroke={theme.palette.grey2.main} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /> <path d="M27 19V26C27 26.2652 26.8946 26.5196 26.7071 26.7071C26.5196 26.8946 26.2652 27 26 27H6C5.73478 27 5.48043 26.8946 5.29289 26.7071C5.10536 26.5196 5 26.2652 5 26V19" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg> </svg>
</Box> </Box>
); );

@ -33,6 +33,7 @@ export interface QuizConfig {
startpageType: QuizStartpageType; startpageType: QuizStartpageType;
results: QuizResultsType; results: QuizResultsType;
haveRoot: string | null; haveRoot: string | null;
theme: "StandardTheme" | "StandardDarkTheme" | "PinkTheme" | "PinkDarkTheme" | "BlackWhiteTheme" | "OliveTheme" | "YellowTheme" | "GoldDarkTheme" | "PurpleTheme" | "BlueTheme" | "BlueDarkTheme";
resultInfo: { resultInfo: {
when: 'before' | 'after' | 'email', when: 'before' | 'after' | 'email',
share: true | false, share: true | false,
@ -95,6 +96,7 @@ export const defaultQuizConfig: QuizConfig = {
startpageType: null, startpageType: null,
results: null, results: null,
haveRoot: null, haveRoot: null,
theme: "StandardTheme",
resultInfo: { resultInfo: {
when: 'after', when: 'after',
share: false, share: false,

@ -14,7 +14,7 @@ import { getQuestionByContentId } from "@root/questions/actions";
import { updateDeleteId } from "@root/uiTools/actions"; import { updateDeleteId } from "@root/uiTools/actions";
import { useUiTools } from "@root/uiTools/store"; import { useUiTools } from "@root/uiTools/store";
import { CheckboxIcon } from "@icons/Checkbox"; import CheckboxIcon from "@icons/Checkbox";
type DeleteNodeModalProps = { type DeleteNodeModalProps = {
removeNode?: (id: string) => void; removeNode?: (id: string) => void;

@ -4,7 +4,7 @@ import {
MenuItem, MenuItem,
FormControl, FormControl,
Typography, Typography,
useTheme, useTheme, Theme,
} from "@mui/material"; } from "@mui/material";
import ArrowDown from "@icons/ArrowDownIcon"; import ArrowDown from "@icons/ArrowDownIcon";
@ -18,6 +18,9 @@ type SelectProps = {
onChange?: (item: string, num: number) => void; onChange?: (item: string, num: number) => void;
sx?: SxProps; sx?: SxProps;
placeholder?: string; placeholder?: string;
colorPlaceholder?: string;
colorMain?: string;
color?: string;
}; };
export const Select = ({ export const Select = ({
@ -27,6 +30,9 @@ export const Select = ({
onChange, onChange,
sx, sx,
placeholder = "", placeholder = "",
colorMain = "#7E2AEA",
colorPlaceholder = "#9A9AAF",
color
}: SelectProps) => { }: SelectProps) => {
const [activeItem, setActiveItem] = useState<number>( const [activeItem, setActiveItem] = useState<number>(
empty ? -1 : activeItemIndex empty ? -1 : activeItemIndex
@ -63,7 +69,7 @@ export const Select = ({
value ? ( value ? (
items[Number(value)] items[Number(value)]
) : ( ) : (
<Typography sx={{ color: theme.palette.grey2.main }}> <Typography sx={{ color: colorPlaceholder }}>
{placeholder} {placeholder}
</Typography> </Typography>
) )
@ -77,7 +83,7 @@ export const Select = ({
height: "48px", height: "48px",
borderRadius: "8px", borderRadius: "8px",
"& .MuiOutlinedInput-notchedOutline": { "& .MuiOutlinedInput-notchedOutline": {
border: `1px solid ${theme.palette.brightPurple.main} !important`, border: `1px solid ${colorMain} !important`,
height: "48px", height: "48px",
borderRadius: "10px", borderRadius: "10px",
}, },
@ -100,21 +106,21 @@ export const Select = ({
gap: "8px", gap: "8px",
"& .Mui-selected": { "& .Mui-selected": {
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.default,
color: theme.palette.brightPurple.main, color: colorMain,
}, },
}, },
}, },
}} }}
inputProps={{ inputProps={{
sx: { sx: {
color: theme.palette.brightPurple.main, color: colorMain,
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
px: "9px", px: "9px",
gap: "20px", gap: "20px",
}, },
}} }}
IconComponent={(props) => <ArrowDown {...props} />} IconComponent={(props) => <ArrowDown {...props } color={color}/>}
> >
{items.map((item, index) => ( {items.map((item, index) => (
<MenuItem <MenuItem
@ -126,7 +132,7 @@ export const Select = ({
gap: "20px", gap: "20px",
padding: "10px", padding: "10px",
borderRadius: "5px", borderRadius: "5px",
color: theme.palette.grey2.main, color: colorPlaceholder,
}} }}
> >
{item} {item}

@ -1,4 +1,4 @@
import { Box, Typography, Button, Paper, TextField, Link, InputAdornment } from "@mui/material"; import {Box, Typography, Button, Paper, TextField, Link, InputAdornment, useTheme} from "@mui/material";
import NameIcon from "@icons/ContactFormIcon/NameIcon"; import NameIcon from "@icons/ContactFormIcon/NameIcon";
import EmailIcon from "@icons/ContactFormIcon/EmailIcon"; import EmailIcon from "@icons/ContactFormIcon/EmailIcon";
import PhoneIcon from "@icons/ContactFormIcon/PhoneIcon"; import PhoneIcon from "@icons/ContactFormIcon/PhoneIcon";
@ -13,6 +13,7 @@ import { useQuestionsStore } from "@root/questions/store";
import { checkEmptyData } from "../ResultPage/cards/ResultCard"; import { checkEmptyData } from "../ResultPage/cards/ResultCard";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared"; import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
import {modes} from "../../utils/themes/Publication/themePublication";
import { enqueueSnackbar } from "notistack"; import { enqueueSnackbar } from "notistack";
type ContactFormProps = { type ContactFormProps = {
@ -37,8 +38,9 @@ export const ContactForm = ({
setShowResultForm, setShowResultForm,
}: ContactFormProps) => { }: ContactFormProps) => {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const mode = modes;
const { questions } = useQuestionsStore(); const { questions } = useQuestionsStore();
const theme = useTheme();
const [ready, setReady] = useState(false) const [ready, setReady] = useState(false)
const followNextForm = () => { const followNextForm = () => {
setShowContactForm(false); setShowContactForm(false);
@ -68,6 +70,7 @@ export const ContactForm = ({
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
backgroundColor: theme.palette.background.default,
height: "100vh" height: "100vh"
}} }}
> >
@ -82,7 +85,8 @@ export const ContactForm = ({
sx={{ sx={{
textAlign: "center", textAlign: "center",
m: "20px 0", m: "20px 0",
fontSize: "28px" fontSize: "28px",
color: theme.palette.text.primary
}} }}
> >
{quiz?.config.formContact.title || "Заполните форму, чтобы получить результаты теста"} {quiz?.config.formContact.title || "Заполните форму, чтобы получить результаты теста"}
@ -109,6 +113,7 @@ export const ContactForm = ({
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
flexDirection: "column", flexDirection: "column",
backgroundColor: theme.palette.background.default,
p: "30px" p: "30px"
}}> }}>
@ -146,13 +151,13 @@ export const ContactForm = ({
width: "450px", width: "450px",
}} }}
> >
<CustomCheckbox label="" handleChange={({ target }) => { setReady(target.checked) }} checked={ready} /> <CustomCheckbox label="" handleChange={({ target }) => { setReady(target.checked) }} checked={ready} colorIcon={theme.palette.primary.main}/>
<Typography> <Typography>
С С&ensp;
<Link> Положением об обработке персональных данных </Link> <Link> Положением об обработке персональных данных </Link>
и &ensp;и&ensp;
<Link> Политикой конфиденциальности </Link> <Link> Политикой конфиденциальности </Link>
ознакомлен &ensp;ознакомлен
</Typography> </Typography>
</Box> </Box>
@ -160,11 +165,14 @@ export const ContactForm = ({
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
mt: "20px" mt: "20px",
gap: "15px"
}} }}
> >
<NameplateLogo style={{ fontSize: "34px" }} /> <NameplateLogo style={{ fontSize: "34px", color: mode[quiz.config.theme] ? "#151515" : "#FFFFFF" }} />
<Typography sx={{ fontSize: "20px", color: "#4D4D4D", whiteSpace: "nowrap" }}>Сделано на PenaQuiz</Typography> <Typography sx={{ fontSize: "20px", color: mode[quiz.config.theme] ? "#4D4D4D" : "#F5F7FF", whiteSpace: "nowrap" }}>
Сделано на PenaQuiz
</Typography>
</Box> </Box>
</Paper> </Paper>
</Box > </Box >

@ -9,6 +9,8 @@ import type { AnyTypedQuizQuestion, QuizQuestionBase } from "../../model/questio
import { getQuestionByContentId } from "@root/questions/actions"; import { getQuestionByContentId } from "@root/questions/actions";
import { enqueueSnackbar } from "notistack"; import { enqueueSnackbar } from "notistack";
import { NameplateLogoFQ } from "@icons/NameplateLogoFQ"; import { NameplateLogoFQ } from "@icons/NameplateLogoFQ";
import {NameplateLogoFQDark} from "@icons/NameplateLogoFQDark";
import {modes} from "../../utils/themes/Publication/themePublication";
import { checkEmptyData } from "../ResultPage/cards/ResultCard"; import { checkEmptyData } from "../ResultPage/cards/ResultCard";
type FooterProps = { type FooterProps = {
@ -23,6 +25,7 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh
const [disableNextButton, setDisableNextButton] = useState<boolean>(false); const [disableNextButton, setDisableNextButton] = useState<boolean>(false);
const [stepNumber, setStepNumber] = useState(1); const [stepNumber, setStepNumber] = useState(1);
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const mode = modes;
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const questions = useQuestionsStore().questions as AnyTypedQuizQuestion[]; const questions = useQuestionsStore().questions as AnyTypedQuizQuestion[];
const theme = useTheme(); const theme = useTheme();
@ -233,7 +236,13 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh
gap: "10px", gap: "10px",
}} }}
> >
<NameplateLogoFQ style={{ fontSize: "34px", width: "200px", height: "auto" }} /> {mode[quiz.config.theme] ? (
<NameplateLogoFQ style={{ fontSize: "34px", width:"200px", height:"auto" }} />
):(
<NameplateLogoFQDark style={{ fontSize: "34px", width:"200px", height:"auto" }} />
)
}
{linear && {linear &&
<> <>
<Box <Box
@ -268,10 +277,41 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh
</Box> </Box>
</> </>
} }
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "10px",
marginRight: "auto",
// color: theme.palette.grey1.main,
}}
>
{/* <Typography>Шаг</Typography>
<Typography
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
fontWeight: "bold",
borderRadius: "50%",
width: "30px",
height: "30px",
color: "#FFF",
background: theme.palette.brightPurple.main,
}}
>
{stepNumber} */}
{/* </Typography> */}
{/* <Typography>Из</Typography>
<Typography sx={{ fontWeight: "bold" }}>
{questions.length}
</Typography> */}
</Box>
<Button <Button
disabled={disablePreviousButton} disabled={disablePreviousButton}
variant="contained" variant="contained"
sx={{ fontSize: "16px", padding: "10px 15px" }} sx={{ fontSize: "16px", padding: "10px 15px", "& :disabled": {color: `{hsl((theme.palette.primary.main) 30%)}`} }}
onClick={followPreviousStep} onClick={followPreviousStep}
> >
Назад Назад

@ -1,5 +1,5 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Box } from "@mui/material"; import {Box, useTheme} from "@mui/material";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { getQuestionByContentId } from "@root/questions/actions"; import { getQuestionByContentId } from "@root/questions/actions";
@ -61,11 +61,15 @@ export const Question = ({ questions }: QuestionProps) => {
if (!currentQuestion) return <>не смог отобразить вопрос</>; if (!currentQuestion) return <>не смог отобразить вопрос</>;
const QuestionComponent = QUESTIONS_MAP[currentQuestion.type as Exclude<QuestionType, "nonselected">]; const QuestionComponent =
QUESTIONS_MAP[currentQuestion.type as Exclude<QuestionType, "nonselected">];
const theme = useTheme();
return ( return (
<Box <Box
sx={{
backgroundColor: theme.palette.background.default
}}
height="100vh" height="100vh"
> >
{!showContactForm && !showResultForm && ( {!showContactForm && !showResultForm && (

@ -7,6 +7,7 @@ import { useQuestionsStore } from "@root/questions/store";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared"; import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
import YoutubeEmbedIframe from "../../ui_kit/StartPagePreview/YoutubeEmbedIframe.tsx" import YoutubeEmbedIframe from "../../ui_kit/StartPagePreview/YoutubeEmbedIframe.tsx"
import { NameplateLogo } from "@icons/NameplateLogo"; import { NameplateLogo } from "@icons/NameplateLogo";
import {modes} from "../../utils/themes/Publication/themePublication";
type ResultFormProps = { type ResultFormProps = {
currentQuestion: AnyTypedQuizQuestion; currentQuestion: AnyTypedQuizQuestion;
@ -23,6 +24,7 @@ export const ResultForm = ({
}: ResultFormProps) => { }: ResultFormProps) => {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const mode = modes;
const { questions } = useQuestionsStore(); const { questions } = useQuestionsStore();
const resultQuestion = questions.find( const resultQuestion = questions.find(
(question) => (question) =>
@ -126,7 +128,7 @@ export const ResultForm = ({
}} }}
> >
<NameplateLogo style={{ fontSize: "34px" }} /> <NameplateLogo style={{ fontSize: "34px" }} />
<Typography sx={{ fontSize: "20px", color: "#4D4D4D", whiteSpace: "nowrap" }}>Сделано на PenaQuiz</Typography> <Typography sx={{ fontSize: "20px", color: mode[quiz.config.theme] ? "#4D4D4D" : "#F5F7FF", whiteSpace: "nowrap" }}>Сделано на PenaQuiz</Typography>
</Box> </Box>
</Box> </Box>

@ -5,6 +5,7 @@ import { QuizStartpageAlignType, QuizStartpageType } from "@model/quizSettings";
import { notReachable } from "../../utils/notReachable"; import { notReachable } from "../../utils/notReachable";
import { useUADevice } from "../../utils/hooks/useUADevice"; import { useUADevice } from "../../utils/hooks/useUADevice";
import { NameplateLogo } from "@icons/NameplateLogo"; import { NameplateLogo } from "@icons/NameplateLogo";
import {modes} from "../../utils/themes/Publication/themePublication";
interface Props { interface Props {
setVisualStartPage: (a: boolean) => void; setVisualStartPage: (a: boolean) => void;
@ -13,6 +14,7 @@ interface Props {
export const StartPageViewPublication = ({ setVisualStartPage }: Props) => { export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
const theme = useTheme(); const theme = useTheme();
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const mode = modes;
const { isMobileDevice } = useUADevice(); const { isMobileDevice } = useUADevice();
if (!quiz) return null; if (!quiz) return null;
@ -85,6 +87,7 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
? "linear-gradient(180deg,transparent,#272626)" ? "linear-gradient(180deg,transparent,#272626)"
: "linear-gradient(270deg,#272626,transparent)" : "linear-gradient(270deg,#272626,transparent)"
: "", : "",
backgroundColor: theme.palette.background.default,
color: quiz.config.startpageType === "expanded" ? "white" : "black", color: quiz.config.startpageType === "expanded" ? "white" : "black",
}} }}
@ -114,7 +117,7 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
<Typography sx={{ fontSize: "14px" }}>{quiz.config.info.orgname}</Typography> <Typography sx={{ fontSize: "14px" }}>{quiz.config.info.orgname}</Typography>
</Box> </Box>
<Link mb="16px" href={quiz.config.info.site}> <Link mb="16px" href={quiz.config.info.site}>
<Typography sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }}> <Typography sx={{ fontSize: "16px", color: theme.palette.primary.main }}>
{quiz.config.info.site} {quiz.config.info.site}
</Typography> </Typography>
</Link> </Link>
@ -149,6 +152,7 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
overflowWrap: "break-word", overflowWrap: "break-word",
width: "100%", width: "100%",
textAlign: quiz.config.startpageType === "centered" ? "center" : "-moz-initial", textAlign: quiz.config.startpageType === "centered" ? "center" : "-moz-initial",
color: theme.palette.text.primary
}} }}
> >
{quiz.name} {quiz.name}
@ -186,19 +190,19 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
{quiz.config.info.clickable ? ( {quiz.config.info.clickable ? (
isMobileDevice ? ( isMobileDevice ? (
<Link href={`tel:${quiz.config.info.phonenumber}`}> <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} {quiz.config.info.phonenumber}
</Typography> </Typography>
</Link> </Link>
) : ( ) : (
<ButtonBase onClick={handleCopyNumber}> <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} {quiz.config.info.phonenumber}
</Typography> </Typography>
</ButtonBase> </ButtonBase>
) )
) : ( ) : (
<Typography sx={{ fontSize: "16px", color: theme.palette.brightPurple.main }}> <Typography sx={{ fontSize: "16px", color: theme.palette.primary.main }}>
{quiz.config.info.phonenumber} {quiz.config.info.phonenumber}
</Typography> </Typography>
)} )}
@ -211,10 +215,11 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
gap: "15px"
}} }}
> >
<NameplateLogo style={{ fontSize: "34px" }} /> <NameplateLogo style={{ fontSize: "34px", color: mode[quiz.config.theme] ? "#151515" : "#FFFFFF" }} />
<Typography sx={{ fontSize: "20px", color: "#4D4D4D", whiteSpace: "nowrap" }}> <Typography sx={{ fontSize: "20px", color: mode[quiz.config.theme] ? "#4D4D4D" : "#F5F7FF", whiteSpace: "nowrap", }}>
Сделано на PenaQuiz Сделано на PenaQuiz
</Typography> </Typography>
</Box> </Box>

@ -1,5 +1,5 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Box } from "@mui/material"; import {Box, Button, ThemeProvider, useTheme} from "@mui/material";
import { StartPageViewPublication } from "./StartPageViewPublication"; import { StartPageViewPublication } from "./StartPageViewPublication";
import { Question } from "./Question"; import { Question } from "./Question";
@ -7,7 +7,7 @@ import { useQuestions } from "@root/questions/hooks";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import useSWR from "swr"; import useSWR from "swr";
import { quizApi } from "@api/quiz"; import { quizApi } from "@api/quiz";
import { setQuizes } from "@root/quizes/actions"; import { setQuizes, updateQuiz } from "@root/quizes/actions";
import { isAxiosError } from "axios"; import { isAxiosError } from "axios";
import { devlog } from "@frontend/kitui"; import { devlog } from "@frontend/kitui";
import { useQuizStore } from "@root/quizes/store"; import { useQuizStore } from "@root/quizes/store";
@ -17,13 +17,15 @@ import { enqueueSnackbar } from "notistack";
import { useQuestionsStore } from "@root/questions/store"; import { useQuestionsStore } from "@root/questions/store";
import { setQuestions } from "@root/questions/actions"; import { setQuestions } from "@root/questions/actions";
import { questionApi } from "@api/question"; import { questionApi } from "@api/question";
import { ApologyPage } from "./ApologyPage"; import { ApologyPage } from "./ApologyPage"
import {themesPublication} from "../../utils/themes/Publication/themePublication";
export const ViewPage = () => { export const ViewPage = () => {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { editQuizId } = useQuizStore(); const { editQuizId } = useQuizStore();
const { questions } = useQuestionsStore(); const { questions } = useQuestionsStore();
const theme = useTheme();
useEffect(() => { useEffect(() => {
const getData = async () => { const getData = async () => {
const quizes = await quizApi.getList(); const quizes = await quizApi.getList();
@ -55,12 +57,50 @@ export const ViewPage = () => {
if (visualStartPage === undefined) return <></>; if (visualStartPage === undefined) return <></>;
if (questions.length === 0 || (questions.length === 1 && questions[0].type === "result")) return <ApologyPage message="Нет созданных вопросов"/> if (questions.length === 0 || (questions.length === 1 && questions[0].type === "result")) return <ApologyPage message="Нет созданных вопросов"/>
return ( return (
<Box> <ThemeProvider theme={themesPublication?.[quiz?.config.theme]}>
{!visualStartPage ? ( <Box sx={{backgroundColor: theme.palette.background.default}}>
<StartPageViewPublication setVisualStartPage={setVisualStartPage} /> {!visualStartPage ? (
) : ( <StartPageViewPublication setVisualStartPage={setVisualStartPage} />
<Question questions={filteredQuestions} /> ) : (
)} <Question questions={filteredQuestions} />
</Box> )}
<Box>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "StandardTheme"
})}>Standard</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "PinkTheme"
})}>Pink</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "BlackWhiteTheme"
})}>BlackWhite</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "OliveTheme"
})}>Olive</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "YellowTheme"
})}>Yellow</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "PurpleTheme"
})}>Purple</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "BlueTheme"
})}>Blue</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "StandardDarkTheme"
})}>StandardDark</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "PinkDarkTheme"
})}>PinkDark</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "GoldDarkTheme"
})}>GoldDark</Button>
<Button onClick={() => updateQuiz(quiz.id, (quiz) => {
quiz.config.theme = "BlueDarkTheme"
})}>BlueDark</Button>
</Box>
</Box>
</ThemeProvider>
); );
}; };

@ -1,17 +1,22 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import { DatePicker } from "@mui/x-date-pickers"; import { DatePicker } from "@mui/x-date-pickers";
import { Box, Typography } from "@mui/material"; import {Box, Typography, useTheme} from "@mui/material";
import { useQuizViewStore, updateAnswer } from "@root/quizView"; import { useQuizViewStore, updateAnswer } from "@root/quizView";
import type { QuizQuestionDate } from "../../../model/questionTypes/date"; import type { QuizQuestionDate } from "../../../model/questionTypes/date";
import CalendarIcon from "@icons/CalendarIcon"; import CalendarIcon from "@icons/CalendarIcon";
import {modes} from "../../../utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
type DateProps = { type DateProps = {
currentQuestion: QuizQuestionDate; currentQuestion: QuizQuestionDate;
}; };
export const Date = ({ currentQuestion }: DateProps) => { export const Date = ({ currentQuestion }: DateProps) => {
const theme = useTheme();
const mode = modes;
const quiz = useCurrentQuiz();
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const answer = answers.find( const answer = answers.find(
({ questionId }) => questionId === currentQuestion.content.id ({ questionId }) => questionId === currentQuestion.content.id
@ -20,7 +25,7 @@ export const Date = ({ currentQuestion }: DateProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -31,7 +36,10 @@ export const Date = ({ currentQuestion }: DateProps) => {
> >
<DatePicker <DatePicker
slots={{ slots={{
openPickerIcon: () => <CalendarIcon />, openPickerIcon: () => <CalendarIcon sx={{
"& path": {stroke: theme.palette.primary.main},
"& rect": {stroke: theme.palette.primary.main}
}} />,
}} }}
value={dayjs( value={dayjs(
answer answer
@ -61,10 +69,14 @@ export const Date = ({ currentQuestion }: DateProps) => {
}, },
"data-cy": "open-datepicker", "data-cy": "open-datepicker",
}, },
layout: {
sx: {backgroundColor: theme.palette.background.default,}
}
}} }}
sx={{ sx={{
"& .MuiInputBase-root": { "& .MuiInputBase-root": {
backgroundColor: "#F2F3F7", backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
borderRadius: "10px", borderRadius: "10px",
maxWidth: "250px", maxWidth: "250px",
pr: "22px", pr: "22px",
@ -77,6 +89,7 @@ export const Date = ({ currentQuestion }: DateProps) => {
borderColor: "#9A9AAF", borderColor: "#9A9AAF",
}, },
}, },
}} }}
/> />
</Box> </Box>

@ -29,7 +29,7 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<RadioGroup <RadioGroup
name={currentQuestion.id} name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex( value={currentQuestion.content.variants.findIndex(
@ -55,7 +55,8 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
key={variant.id} key={variant.id}
sx={{ sx={{
borderRadius: "12px", borderRadius: "12px",
border: `1px solid ${theme.palette.grey2.main}`, border: `1px solid`,
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
overflow: "hidden", overflow: "hidden",
maxWidth: "317px", maxWidth: "317px",
width: "100%", width: "100%",
@ -89,7 +90,7 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
sx={{ sx={{
margin: 0, margin: 0,
padding: "15px", padding: "15px",
color: "#4D4D4D", color: theme.palette.text.primary,
display: "flex", display: "flex",
gap: "10px", gap: "10px",
}} }}
@ -107,7 +108,7 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
} }
}} }}
control={ control={
<Radio checkedIcon={<RadioCheck />} icon={<RadioIcon />} /> <Radio checkedIcon={<RadioCheck color={theme.palette.primary.main}/>} icon={<RadioIcon />} />
} }
label={ label={
<Box sx={{ display: "flex", gap: "10px" }}> <Box sx={{ display: "flex", gap: "10px" }}>

@ -56,7 +56,7 @@ export const File = ({ currentQuestion }: FileProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -68,11 +68,11 @@ export const File = ({ currentQuestion }: FileProps) => {
> >
{answer?.split("|")[0] && ( {answer?.split("|")[0] && (
<Box sx={{ display: "flex", alignItems: "center", gap: "15px" }}> <Box sx={{ display: "flex", alignItems: "center", gap: "15px" }}>
<Typography>Вы загрузили:</Typography> <Typography color={theme.palette.text.primary}>Вы загрузили:</Typography>
<Box <Box
sx={{ sx={{
padding: "5px 5px 5px 16px", padding: "5px 5px 5px 16px",
backgroundColor: theme.palette.brightPurple.main, backgroundColor: theme.palette.primary.main,
borderRadius: "8px", borderRadius: "8px",
color: "#FFFFFF", color: "#FFFFFF",
display: "flex", display: "flex",
@ -115,7 +115,8 @@ export const File = ({ currentQuestion }: FileProps) => {
alignItems: "center", alignItems: "center",
padding: "33px 44px 33px 55px", padding: "33px 44px 33px 55px",
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.default,
border: `1px solid ${theme.palette.grey2.main}`, border: `1px solid #9A9AAF`,
// border: `1px solid ${theme.palette.grey2.main}`,
borderRadius: "8px", borderRadius: "8px",
}} }}
> >
@ -123,7 +124,8 @@ export const File = ({ currentQuestion }: FileProps) => {
<Box> <Box>
<Typography <Typography
sx={{ sx={{
color: theme.palette.grey2.main, color: "#9A9AAF",
// color: theme.palette.grey2.main,
fontWeight: 500, fontWeight: 500,
}} }}
> >
@ -134,7 +136,8 @@ export const File = ({ currentQuestion }: FileProps) => {
</Typography> </Typography>
<Typography <Typography
sx={{ sx={{
color: theme.palette.grey2.main, color: "#9A9AAF",
// color: theme.palette.grey2.main,
fontSize: "16px", fontSize: "16px",
lineHeight: "19px", lineHeight: "19px",
}} }}

@ -30,7 +30,7 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<RadioGroup <RadioGroup
name={currentQuestion.id} name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex( value={currentQuestion.content.variants.findIndex(
@ -62,7 +62,8 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
sx={{ sx={{
cursor: "pointer", cursor: "pointer",
borderRadius: "5px", borderRadius: "5px",
border: `1px solid ${theme.palette.grey2.main}`, border: `1px solid`,
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
}} }}
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
@ -98,12 +99,12 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
sx={{ sx={{
display: "block", display: "block",
textAlign: "center", textAlign: "center",
color: theme.palette.grey2.main, color: theme.palette.text.primary,
marginTop: "10px", marginTop: "10px",
}} }}
value={index} value={index}
control={ control={
<Radio checkedIcon={<RadioCheck />} icon={<RadioIcon />} /> <Radio checkedIcon={<RadioCheck color={theme.palette.primary.main}/>} icon={<RadioIcon />} />
} }
label={variant.answer} label={variant.answer}
/> />

@ -1,5 +1,5 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Box, Typography } from "@mui/material"; import { Box, Typography, Slider, useTheme } from "@mui/material";
import { useDebouncedCallback } from "use-debounce"; import { useDebouncedCallback } from "use-debounce";
import CustomTextField from "@ui_kit/CustomTextField"; import CustomTextField from "@ui_kit/CustomTextField";
@ -8,6 +8,8 @@ import { CustomSlider } from "@ui_kit/CustomSlider";
import { useQuizViewStore, updateAnswer } from "@root/quizView"; import { useQuizViewStore, updateAnswer } from "@root/quizView";
import type { QuizQuestionNumber } from "../../../model/questionTypes/number"; import type { QuizQuestionNumber } from "../../../model/questionTypes/number";
import {modes} from "../../../utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
type NumberProps = { type NumberProps = {
currentQuestion: QuizQuestionNumber; currentQuestion: QuizQuestionNumber;
@ -16,6 +18,9 @@ type NumberProps = {
export const Number = ({ currentQuestion }: NumberProps) => { export const Number = ({ currentQuestion }: NumberProps) => {
const [minRange, setMinRange] = useState<string>("0"); const [minRange, setMinRange] = useState<string>("0");
const [maxRange, setMaxRange] = useState<string>("100000000000"); const [maxRange, setMaxRange] = useState<string>("100000000000");
const theme = useTheme();
const mode = modes;
const quiz = useCurrentQuiz();
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const updateMinRangeDebounced = useDebouncedCallback( const updateMinRangeDebounced = useDebouncedCallback(
(value, crowded = false) => { (value, crowded = false) => {
@ -59,7 +64,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -92,34 +97,38 @@ export const Number = ({ currentQuestion }: NumberProps) => {
setMaxRange(String(range[1])); setMaxRange(String(range[1]));
} }
}} }}
sx={{
color: theme.palette.primary.main,
"& .MuiSlider-valueLabel": {
background: theme.palette.primary.main,}
}}
/> />
{!currentQuestion.content.chooseRange && ( {!currentQuestion.content.chooseRange && (
<Box <CustomTextField
sx={{ placeholder="0"
display: "flex", value={answer}
gap: "15px", onChange={({ target }) => {
alignItems: "center", updateAnswer(
"& .MuiFormControl-root": { width: "auto" }, currentQuestion.content.id,
window.Number(target.value) > max
? String(max)
: window.Number(target.value) < min
? String(min)
: target.value
);
}} }}
> sx={{
<CustomTextField maxWidth: "80px",
placeholder="0" borderColor: theme.palette.text.primary,
value={answer} "& .MuiInputBase-input": {
onChange={({ target }) => { textAlign: "center",
updateAnswer( backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
currentQuestion.content.id, },
window.Number(target.value) > max }}
? String(max) />
: window.Number(target.value) < min
? String(min)
: target.value
);
}}
sx={{ maxWidth: "80px", textAlign: "center" }}
/>
</Box>
)} )}
{currentQuestion.content.chooseRange && ( {currentQuestion.content.chooseRange && (
<Box <Box
sx={{ sx={{
@ -143,9 +152,16 @@ export const Number = ({ currentQuestion }: NumberProps) => {
updateMinRangeDebounced(`${target.value}${maxRange}`); updateMinRangeDebounced(`${target.value}${maxRange}`);
}} }}
sx={{ maxWidth: "80px", textAlign: "center" }} sx={{
maxWidth: "80px",
borderColor: theme.palette.text.primary,
"& .MuiInputBase-input": {
textAlign: "center",
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
},
}}
/> />
<Typography>до</Typography> <Typography color={theme.palette.text.primary}>до</Typography>
<CustomTextField <CustomTextField
placeholder="0" placeholder="0"
value={maxRange} value={maxRange}
@ -160,7 +176,14 @@ export const Number = ({ currentQuestion }: NumberProps) => {
updateMaxRangeDebounced(`${minRange}${target.value}`); updateMaxRangeDebounced(`${minRange}${target.value}`);
}} }}
sx={{ maxWidth: "80px", textAlign: "center" }} sx={{
maxWidth: "80px",
borderColor: theme.palette.text.primary,
"& .MuiInputBase-input": {
textAlign: "center",
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
},
}}
/> />
</Box> </Box>
)} )}

@ -1,4 +1,4 @@
import { Box, Typography } from "@mui/material"; import {Box, Typography, useTheme} from "@mui/material";
import { useQuizViewStore, updateAnswer } from "@root/quizView"; import { useQuizViewStore, updateAnswer } from "@root/quizView";
@ -12,15 +12,12 @@ type PageProps = {
export const Page = ({ currentQuestion }: PageProps) => { export const Page = ({ currentQuestion }: PageProps) => {
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.content.id) ?? {}; const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.content.id) ?? {};
const theme = useTheme();
console.log(currentQuestion);
return ( return (
<Box> <Box>
<Typography variant="h5" sx={{ paddingBottom: "25px" }}> <Typography variant="h5" sx={{ paddingBottom: "25px", color: theme.palette.text.primary }}>{currentQuestion.title}</Typography>
{currentQuestion.title} <Typography color={theme.palette.text.primary}>{currentQuestion.content.text}</Typography>
</Typography>
<Typography>{currentQuestion.content.text}</Typography>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",

@ -65,7 +65,7 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box <Box
sx={{ sx={{
display: "inline-flex", display: "inline-flex",
@ -74,7 +74,10 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
marginTop: "20px", marginTop: "20px",
}} }}
> >
<Typography sx={{ color: theme.palette.grey2.main }}> <Typography sx={{
color: "#9A9AAF"
// color: theme.palette.grey2.main
}}>
{currentQuestion.content.ratingNegativeDescription} {currentQuestion.content.ratingNegativeDescription}
</Typography> </Typography>
<Box <Box
@ -90,11 +93,11 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
} }
sx={{ height: "50px", gap: "15px" }} sx={{ height: "50px", gap: "15px" }}
max={currentQuestion.content.steps} max={currentQuestion.content.steps}
icon={form?.icon(theme.palette.brightPurple.main)} icon={form?.icon(theme.palette.primary.main)}
emptyIcon={form?.icon(theme.palette.grey2.main)} emptyIcon={form?.icon("#9A9AAF")}
/> />
</Box> </Box>
<Typography sx={{ color: theme.palette.grey2.main }}> <Typography sx={{ color: "#9A9AAF" }}>
{currentQuestion.content.ratingPositiveDescription} {currentQuestion.content.ratingPositiveDescription}
</Typography> </Typography>
</Box> </Box>

@ -1,4 +1,4 @@
import { Box, Typography } from "@mui/material"; import {Box, Typography, useTheme} from "@mui/material";
import { Select as SelectComponent } from "../../../pages/Questions/Select"; import { Select as SelectComponent } from "../../../pages/Questions/Select";
@ -12,6 +12,7 @@ type SelectProps = {
export const Select = ({ currentQuestion }: SelectProps) => { export const Select = ({ currentQuestion }: SelectProps) => {
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const theme = useTheme();
const { answer } = const { answer } =
answers.find( answers.find(
({ questionId }) => questionId === currentQuestion.content.id ({ questionId }) => questionId === currentQuestion.content.id
@ -19,7 +20,7 @@ export const Select = ({ currentQuestion }: SelectProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -32,6 +33,8 @@ export const Select = ({ currentQuestion }: SelectProps) => {
placeholder={currentQuestion.content.default} placeholder={currentQuestion.content.default}
activeItemIndex={answer ? Number(answer) : -1} activeItemIndex={answer ? Number(answer) : -1}
items={currentQuestion.content.variants.map(({ answer }) => answer)} items={currentQuestion.content.variants.map(({ answer }) => answer)}
colorMain={theme.palette.primary.main}
color={theme.palette.primary.main}
onChange={(_, value) => { onChange={(_, value) => {
if (value < 0) { if (value < 0) {
deleteAnswer(currentQuestion.content.id); deleteAnswer(currentQuestion.content.id);

@ -1,4 +1,4 @@
import { Box, Typography } from "@mui/material"; import {Box, Typography, useTheme} from "@mui/material";
import CustomTextField from "@ui_kit/CustomTextField"; import CustomTextField from "@ui_kit/CustomTextField";
@ -13,10 +13,10 @@ type TextProps = {
export const Text = ({ currentQuestion }: TextProps) => { export const Text = ({ currentQuestion }: TextProps) => {
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.content.id) ?? {}; const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.content.id) ?? {};
const theme = useTheme();
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -29,6 +29,11 @@ export const Text = ({ currentQuestion }: TextProps) => {
placeholder={currentQuestion.content.placeholder} placeholder={currentQuestion.content.placeholder}
value={answer || ""} value={answer || ""}
onChange={({ target }) => updateAnswer(currentQuestion.content.id, target.value)} onChange={({ target }) => updateAnswer(currentQuestion.content.id, target.value)}
sx={{
"&:focus-visible": {
borderColor: theme.palette.primary.main
}
}}
/> />
</Box> </Box>
</Box> </Box>

@ -21,10 +21,12 @@ import {
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 { CheckboxIcon } from "@icons/Checkbox"; import CheckboxIcon from "@icons/Checkbox";
import {modes} from "../../../utils/themes/Publication/themePublication";
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant"; import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
import type { QuestionVariant } from "../../../model/questionTypes/shared"; import type { QuestionVariant } from "../../../model/questionTypes/shared";
import {useCurrentQuiz} from "@root/quizes/hooks";
type VariantProps = { type VariantProps = {
stepNumber: number; stepNumber: number;
@ -40,6 +42,7 @@ type VariantItemProps = {
}; };
export const Variant = ({ currentQuestion }: VariantProps) => { export const Variant = ({ currentQuestion }: VariantProps) => {
const theme = useTheme()
const { answers, ownVariants } = useQuizViewStore(); const { answers, ownVariants } = useQuizViewStore();
const { answer } = const { answer } =
answers.find( answers.find(
@ -59,7 +62,7 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box sx={{ display: "flex" }}> <Box sx={{ display: "flex" }}>
<Group <Group
name={currentQuestion.id} name={currentQuestion.id}
@ -126,15 +129,19 @@ const VariantItem = ({
own = false, own = false,
}: VariantItemProps) => { }: VariantItemProps) => {
const theme = useTheme(); const theme = useTheme();
const mode = modes
const quiz = useCurrentQuiz();
return ( return (
<FormControlLabel <FormControlLabel
key={variant.id} key={variant.id}
sx={{ sx={{
margin: "0", margin: "0",
borderRadius: "12px", borderRadius: "12px",
color: theme.palette.text.primary,
padding: "15px", padding: "15px",
border: `1px solid ${theme.palette.grey2.main}`, border: `1px solid`,
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
display: "flex", display: "flex",
maxWidth: "685px", maxWidth: "685px",
justifyContent: "space-between", justifyContent: "space-between",
@ -150,11 +157,11 @@ const VariantItem = ({
currentQuestion.content.multi ? ( currentQuestion.content.multi ? (
<Checkbox <Checkbox
checked={!!answer?.includes(variant.id)} checked={!!answer?.includes(variant.id)}
checkedIcon={<CheckboxIcon checked />} checkedIcon={<CheckboxIcon checked color={theme.palette.primary.main} />}
icon={<CheckboxIcon />} icon={<CheckboxIcon />}
/> />
) : ( ) : (
<Radio checkedIcon={<RadioCheck />} icon={<RadioIcon />} /> <Radio checkedIcon={<RadioCheck color={theme.palette.primary.main}/>} icon={<RadioIcon />} />
) )
} }
label={own ? <TextField label="Другое..." /> : variant.answer} label={own ? <TextField label="Другое..." /> : variant.answer}

@ -15,6 +15,8 @@ import RadioCheck from "@ui_kit/RadioCheck";
import RadioIcon from "@ui_kit/RadioIcon"; import RadioIcon from "@ui_kit/RadioIcon";
import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg"; import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
import {modes} from "../../../utils/themes/Publication/themePublication";
import {useCurrentQuiz} from "@root/quizes/hooks";
type VarimgProps = { type VarimgProps = {
currentQuestion: QuizQuestionVarImg; currentQuestion: QuizQuestionVarImg;
@ -22,6 +24,8 @@ type VarimgProps = {
export const Varimg = ({ currentQuestion }: VarimgProps) => { export const Varimg = ({ currentQuestion }: VarimgProps) => {
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const mode = modes;
const quiz = useCurrentQuiz();
const theme = useTheme(); const theme = useTheme();
const { answer } = const { answer } =
answers.find( answers.find(
@ -33,7 +37,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box sx={{ display: "flex", marginTop: "20px" }}> <Box sx={{ display: "flex", marginTop: "20px" }}>
<RadioGroup <RadioGroup
name={currentQuestion.id} name={currentQuestion.id}
@ -56,8 +60,10 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
marginBottom: "15px", marginBottom: "15px",
borderRadius: "5px", borderRadius: "5px",
padding: "15px", padding: "15px",
color: "#4D4D4D", color: theme.palette.text.primary,
border: `1px solid ${theme.palette.grey2.main}`, backgroundColor: mode[quiz.config.theme] ? "white" : theme.palette.background.default,
border: `1px solid`,
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
display: "flex", display: "flex",
}} }}
value={index} value={index}
@ -74,7 +80,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
} }
}} }}
control={ control={
<Radio checkedIcon={<RadioCheck />} icon={<RadioIcon />} /> <Radio checkedIcon={<RadioCheck color={theme.palette.primary.main}/>} icon={<RadioIcon />} />
} }
label={variant.answer} label={variant.answer}
/> />

@ -54,6 +54,7 @@ export default function EditPage() {
const { editQuizId } = useQuizStore(); const { editQuizId } = useQuizStore();
const { questions } = useQuestionsStore(); const { questions } = useQuestionsStore();
console.log(quiz)
useEffect(() => { useEffect(() => {
const getData = async () => { const getData = async () => {
const quizes = await quizApi.getList(); const quizes = await quizApi.getList();

@ -1,7 +1,7 @@
import { FormControlLabel, Checkbox, useTheme, Box, useMediaQuery } from "@mui/material"; import { FormControlLabel, Checkbox, useTheme, Box, useMediaQuery } from "@mui/material";
import React from "react"; import React from "react";
import { CheckboxIcon } from "@icons/Checkbox"; import CheckboxIcon from "@icons/Checkbox";
import type { SxProps } from "@mui/material"; import type { SxProps } from "@mui/material";
@ -11,9 +11,10 @@ interface Props {
checked?: boolean; checked?: boolean;
sx?: SxProps; sx?: SxProps;
dataCy?: string; dataCy?: string;
colorIcon?: string;
} }
export default function CustomCheckbox({ label, handleChange, checked, sx, dataCy }: Props) { export default function CustomCheckbox({ label, handleChange, checked, sx, dataCy, colorIcon }: Props) {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
@ -24,7 +25,7 @@ export default function CustomCheckbox({ label, handleChange, checked, sx, dataC
sx={{ padding: "0px 13px 1px 11px" }} sx={{ padding: "0px 13px 1px 11px" }}
disableRipple disableRipple
icon={<CheckboxIcon />} icon={<CheckboxIcon />}
checkedIcon={<CheckboxIcon checked />} checkedIcon={<CheckboxIcon checked color={colorIcon} />}
onChange={handleChange} onChange={handleChange}
checked={checked} checked={checked}
data-cy={dataCy} data-cy={dataCy}
@ -32,7 +33,7 @@ export default function CustomCheckbox({ label, handleChange, checked, sx, dataC
} }
label={label} label={label}
sx={{ sx={{
color: theme.palette.grey2.main, color: "#9A9AAF",
height: "26px", height: "26px",
...sx, ...sx,
}} }}

@ -1,4 +1,4 @@
import { Slider, useTheme } from "@mui/material"; import {Slider, SxProps, Theme, useTheme} from "@mui/material";
type CustomSliderProps = { type CustomSliderProps = {
defaultValue?: number; defaultValue?: number;
@ -6,6 +6,7 @@ type CustomSliderProps = {
min?: number; min?: number;
max?: number; max?: number;
step?: number; step?: number;
sx?: SxProps<Theme>
onChange?: (_: Event, value: number | number[]) => void; onChange?: (_: Event, value: number | number[]) => void;
onChangeCommitted?: (_: React.SyntheticEvent | Event, value: number | number[]) => void; onChangeCommitted?: (_: React.SyntheticEvent | Event, value: number | number[]) => void;
}; };
@ -18,6 +19,7 @@ export const CustomSlider = ({
step, step,
onChange, onChange,
onChangeCommitted, onChangeCommitted,
sx,
}: CustomSliderProps) => { }: CustomSliderProps) => {
// const handleChange = ({ type }: Event, newValue: number | number[]) => { // const handleChange = ({ type }: Event, newValue: number | number[]) => {
// // Для корректной работы слайдера в FireFox // // Для корректной работы слайдера в FireFox
@ -40,11 +42,11 @@ export const CustomSlider = ({
onMouseDown={(e) => e.stopPropagation()} onMouseDown={(e) => e.stopPropagation()}
data-cy="slider" data-cy="slider"
sx={{ sx={{
color: theme.palette.brightPurple.main, color: "#7E2AEA",
padding: "0", padding: "0",
marginTop: "75px", marginTop: "75px",
"& .MuiSlider-valueLabel": { "& .MuiSlider-valueLabel": {
background: theme.palette.brightPurple.main, background: "#7E2AEA",
borderRadius: "8px", borderRadius: "8px",
minWidth: "60px", minWidth: "60px",
width: "auto", width: "auto",
@ -71,6 +73,7 @@ export const CustomSlider = ({
"& .MuiSlider-track": { "& .MuiSlider-track": {
height: "12px", height: "12px",
}, },
...sx
}} }}
/> />
); );

@ -1,7 +1,10 @@
import { Box, useTheme } from "@mui/material"; import { Box, useTheme } from "@mui/material";
interface Props {
color?: string
}
export default function RadioCheck() { export default function RadioCheck( {color = "#7E2AEA"} : Props) {
const theme = useTheme(); const theme = useTheme();
return ( return (
@ -16,7 +19,7 @@ export default function RadioCheck() {
}} }}
> >
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="25" height="25" rx="12.5" fill="#7E2AEA" stroke="#7E2AEA"/> <rect x="0.5" y="0.5" width="25" height="25" rx="12.5" fill={color} stroke={color}/>
<rect x="8" y="8" width="10" height="10" rx="5" fill="white"/> <rect x="8" y="8" width="10" height="10" rx="5" fill="white"/>
</svg> </svg>
</Box> </Box>

@ -0,0 +1,43 @@
import { createTheme } from "@mui/material";
import theme from "../generic";
const themePublic = createTheme({
...theme,
components: {
MuiButton: {
variants: [
{
props: {
variant: 'contained'
},
style: {
padding: '13px 20px',
borderRadius: '8px',
boxShadow: "none",
// "&:hover": {
// backgroundColor: "#581CA7"
// }
},
},
{
props: {
variant: 'outlined'
},
style: {
padding: '10px 20px',
borderRadius: '8px',
"&:hover": {
backgroundColor: "#581CA7",
border: '1px solid #581CA7',
}
},
},
],
},
},
},
)
export default themePublic;

@ -0,0 +1,253 @@
import { createTheme } from "@mui/material";
import themePublic from "./genericPublication";
import theme from "../generic";
const StandardTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#7E2AEA",
},
secondary: {
main: "#252734"
},
text: {
primary: "#333647",
secondary: "#7E2AEA",
},
background: {
default: "#FFFFFF",
},
}
})
const StandardDarkTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#7E2AEA",
},
secondary: {
main: "#252734"
},
text: {
primary: "#FFFFFF",
secondary: "#7E2AEA",
},
background: {
default: "#333647",
},
}
})
const PinkTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#D34085",
},
secondary: {
main: "#252734"
},
text: {
primary: "#333647",
secondary: "#D34085",
},
background: {
default: "#FFF9FC",
},
}
})
const PinkDarkTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#D34085",
},
secondary: {
main: "#252734"
},
text: {
primary: "#FFFFFF",
secondary: "#D34085",
},
background: {
default: "#333647",
},
}
})
const BlackWhiteTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#4E4D51",
},
secondary: {
main: "#252734"
},
text: {
primary: "#333647",
secondary: "#FFF9FC",
},
background: {
default: "#FFFFFF",
},
}
})
const OliveTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#758E4F",
},
secondary: {
main: "#252734"
},
text: {
primary: "#333647",
secondary: "#758E4F",
},
background: {
default: "#F9FBF1",
},
}
})
const PurpleTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#7E2AEA",
},
secondary: {
main: "#252734"
},
text: {
primary: "#333647",
secondary: "#7E2AEA",
},
background: {
default: "#FBF8FF",
},
}
})
const YellowTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#F2B133",
},
secondary: {
main: "#252734"
},
text: {
primary: "#333647",
secondary: "#F2B133",
},
background: {
default: "#FFFCF6",
},
}
})
const GoldDarkTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#E6AA37",
},
secondary: {
main: "#FFFCF6",
},
text: {
primary: "#FFFFFF",
secondary: "#F2B133",
},
background: {
default: "#333647",
},
}
})
const BlueTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#4964ED",
},
secondary: {
main: "#252734"
},
text: {
primary: "#333647",
secondary: "#4964ED",
},
background: {
default: "#F5F7FF",
},
}
})
const BlueDarkTheme = createTheme({
...themePublic,
palette: {
primary: {
main: "#07A0C3",
},
secondary: {
main: "#252734"
},
text: {
primary: "#FFFFFF",
secondary: "#07A0C3",
},
background: {
default: "#333647",
},
}
})
export const modes = {
StandardTheme: true,
StandardDarkTheme: false,
PinkTheme: true,
PinkDarkTheme: false,
BlackWhiteTheme: true,
OliveTheme: true,
YellowTheme: true,
GoldDarkTheme: false,
PurpleTheme: true,
BlueTheme: true,
BlueDarkTheme: false
}
export const themesPublication = {
StandardTheme,
StandardDarkTheme,
PinkTheme,
PinkDarkTheme,
BlackWhiteTheme,
OliveTheme,
YellowTheme,
GoldDarkTheme,
PurpleTheme,
BlueTheme,
BlueDarkTheme,
}