run prettier on whole project

This commit is contained in:
nflnkr 2024-05-31 19:41:18 +03:00
parent 0baf300f4e
commit 6c2e44ca66
142 changed files with 4210 additions and 5034 deletions

@ -1,19 +1,12 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
],
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended"],
ignorePatterns: ["dist", ".eslintrc.cjs"],
parser: "@typescript-eslint/parser",
plugins: ["react-refresh"],
rules: {
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-interface": "off",
@ -26,10 +19,7 @@ module.exports = {
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{ "vars": "all", "args": "none" }
],
"@typescript-eslint/no-unused-vars": ["warn", { vars: "all", args: "none" }],
"@typescript-eslint/restrict-template-expressions": "off",
"no-debugger": "off",
"no-empty-function": "off",

@ -1,11 +1,17 @@
## Правила
- Запрещено использовать vh/vw css-юниты и их производные
## Виджет
### Сборка
```bash
yarn build:widget
```
### Использование
```html
<script type="module">
import widget from "https://hbpn.link/export/pub.js";
@ -13,35 +19,50 @@ yarn build:widget
widget.create({
selector: "widget-container",
quizId: "...",
})
});
</script>
```
## Npm-пакет
### Перед использованием и публикацией
```bash
npm config set //penahub.gitlab.yandexcloud.net/api/v4/packages/npm/:_authToken=INSTANCE_TOKEN
npm config set //penahub.gitlab.yandexcloud.net/api/v4/projects/43/packages/npm/:_authToken=PROJECT_TOKEN
```
### Публикация
1. Инкрементировать версию в package.json
2.
```bash
yarn publish
```
3. Нажать enter при запросе версии
### Установка
Добавить в корень проекта файл .yarnrc с содержимым
```
"@frontend:registry" "https://penahub.gitlab.yandexcloud.net/api/v4/packages/npm/"
```
```bash
yarn add @frontend/squzanswerer
```
Peer dependencies:
```bash
yarn add @emoji-mart/data @emoji-mart/react @emotion/react @emotion/styled @mui/icons-material @mui/material @mui/x-date-pickers axios emoji-mart immer moment nanoid notistack react-dom react-error-boundary react-router-dom react swr use-debounce zustand
```
### Использование
```ts
import { QuizView } from "@frontend/squzanswerer";

@ -2,7 +2,7 @@ import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
baseUrl: "http://localhost:3000",
viewportWidth: 1440,
viewportHeight: 900,
supportFile: false,

@ -5,4 +5,3 @@ services:
image: $CI_REGISTRY_IMAGE/main:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID
hostname: respondent
tty: true

@ -5,4 +5,3 @@ services:
image: $CI_REGISTRY_IMAGE/staging:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID
hostname: respondent
tty: true

@ -1,6 +1,6 @@
import { GetQuizDataResponse, parseQuizData } from "@model/api/getQuizData";
import axios from "axios";
import MobileDetect from 'mobile-detect';
import MobileDetect from "mobile-detect";
import device from "current-device";
import type { AxiosError } from "axios";
@ -10,16 +10,25 @@ import * as Bowser from "bowser";
import { domain } from "../utils/defineDomain";
let SESSIONS = "";
const md = new MobileDetect(window.navigator.userAgent);
const userAgent = navigator.userAgent;
//операционная система
let OSDevice: string | undefined;
if (userAgent.toLowerCase().includes("linux")) { OSDevice = "Linux"; }
if (userAgent.toLowerCase().includes("windows")) { OSDevice = "Windows"; }
if (/iPad|iPhone|iPod/.test(userAgent)) { OSDevice = "IOS"; }
if (userAgent.toLowerCase().includes("macintosh")) { OSDevice = "Mac OS"; }
if (OSDevice === undefined) { OSDevice = userAgent; }
if (userAgent.toLowerCase().includes("linux")) {
OSDevice = "Linux";
}
if (userAgent.toLowerCase().includes("windows")) {
OSDevice = "Windows";
}
if (/iPad|iPhone|iPod/.test(userAgent)) {
OSDevice = "IOS";
}
if (userAgent.toLowerCase().includes("macintosh")) {
OSDevice = "Mac OS";
}
if (OSDevice === undefined) {
OSDevice = userAgent;
}
//браузер
let browserUser: string;
@ -31,12 +40,16 @@ if (Bowser.name === "Chrome") {
browserUser = "Safari";
} else if (Bowser.name === "Yandex Browser") {
browserUser = "Yandex Browser";
} else { browserUser = userAgent; }
} else {
browserUser = userAgent;
}
const DeviceType = device.type;
let Device = md.mobile();
if (Device === null) { Device = userAgent; }
if (Device === null) {
Device = userAgent;
}
type PublicationMakeRequestParams = {
url: string;
@ -50,10 +63,10 @@ export const publicationMakeRequest = ({ url, body }: PublicationMakeRequestPara
headers: {
"X-Sessionkey": SESSIONS,
"Content-Type": "multipart/form-data",
"DeviceType": DeviceType,
"Device": Device,
"OS": OSDevice,
"Browser": browserUser
DeviceType: DeviceType,
Device: Device,
OS: OSDevice,
Browser: browserUser,
},
method: "POST",
});
@ -65,17 +78,15 @@ export async function getData(quizId: string): Promise<{
error?: AxiosError;
}> {
try {
const { data, headers } = await axios<GetQuizDataResponse>(
domain + `/answer/settings`,
{
const { data, headers } = await axios<GetQuizDataResponse>(domain + `/answer/settings`, {
method: "POST",
headers: {
"X-Sessionkey": SESSIONS,
"Content-Type": "application/json",
"DeviceType": DeviceType,
"Device": Device,
"OS": OSDevice,
"Browser": userAgent
DeviceType: DeviceType,
Device: Device,
OS: OSDevice,
Browser: userAgent,
},
data: {
quiz_id: quizId,
@ -83,8 +94,7 @@ export async function getData(quizId: string): Promise<{
page: 0,
need_config: true,
},
}
);
});
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
if (typeof sessions[quizId] === "number") {
@ -119,7 +129,11 @@ export async function getQuizData(quizId: string) {
const quizSettings = replaceSpacesToEmptyLines(parseQuizData(quizDataResponse));
const res = JSON.parse(JSON.stringify({ data: quizSettings }).replaceAll(/\\" \\"/g, '""').replaceAll(/" "/g, '""')).data as QuizSettings;
const res = JSON.parse(
JSON.stringify({ data: quizSettings })
.replaceAll(/\\" \\"/g, '""')
.replaceAll(/" "/g, '""')
).data as QuizSettings;
res.recentlyCompleted = response.isRecentlyCompleted;
return res;
}

@ -1,12 +1,9 @@
import { Box, SxProps, Theme, useTheme } from "@mui/material";
interface Color {
color?: string
color?: string;
}
export default function ArrowDownIcon(
props: any,
{color = "#7E2AEA"}: Color
) {
export default function ArrowDownIcon(props: any, { color = "#7E2AEA" }: Color) {
const theme = useTheme();
return (
@ -22,7 +19,13 @@ export default function ArrowDownIcon(
}}
>
<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" />
<path
d="M19.5 9L12 16.5L4.5 9"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</Box>
);

@ -1,10 +1,26 @@
export default function BlankImage() {
return (
<svg width="100%" height="100%" viewBox="0 -70 800 535" fill="none" display="block" preserveAspectRatio="xMidYMax meet" xmlns="http://www.w3.org/2000/svg">
<path fill="#F0F0F0" d="M555 47a47.003 47.003 0 0 1 29.014-43.422 46.999 46.999 0 0 1 61.408 61.408 46.997 46.997 0 0 1-76.656 15.248A47 47 0 0 1 555 47Z" />
<path fill="#F3F3F3" d="M641.874 240.665c7.74-7.74 20.263-7.82 28.102-.181L1051 611.837 779.035 883.805 383.869 498.67l258.005-258.005Z" />
<path fill="#EDEDED" d="M183.393 61.546c7.692-7.037 19.499-6.985 27.129.12l677.42 630.746-690.929 382.738L-397 592.531 183.393 61.546Z" />
<svg
width="100%"
height="100%"
viewBox="0 -70 800 535"
fill="none"
display="block"
preserveAspectRatio="xMidYMax meet"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="#F0F0F0"
d="M555 47a47.003 47.003 0 0 1 29.014-43.422 46.999 46.999 0 0 1 61.408 61.408 46.997 46.997 0 0 1-76.656 15.248A47 47 0 0 1 555 47Z"
/>
<path
fill="#F3F3F3"
d="M641.874 240.665c7.74-7.74 20.263-7.82 28.102-.181L1051 611.837 779.035 883.805 383.869 498.67l258.005-258.005Z"
/>
<path
fill="#EDEDED"
d="M183.393 61.546c7.692-7.037 19.499-6.985 27.129.12l677.42 630.746-690.929 382.738L-397 592.531 183.393 61.546Z"
/>
</svg>
);
}

@ -22,7 +22,7 @@ export default function CalendarIcon({ sx }: Props) {
"&:active rect": {
stroke: "#FB5607",
},
...sx
...sx,
}}
>
<svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">

@ -5,7 +5,7 @@ type CheckboxIconProps = {
color?: string;
};
export const CheckboxIcon = ({ checked = false, color = "#7E2AEA", }: CheckboxIconProps) => {
export const CheckboxIcon = ({ checked = false, color = "#7E2AEA" }: CheckboxIconProps) => {
const theme = useTheme();
return (
@ -17,26 +17,13 @@ export const CheckboxIcon = ({ checked = false, color = "#7E2AEA", }: CheckboxIc
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: checked
? color
: "#F2F3F7",
backgroundColor: checked ? color : "#F2F3F7",
border: `1px solid #9A9AAF`,
}}
>
{checked && (
<svg
xmlns="http://www.w3.org/2000/svg"
width="15"
height="15"
viewBox="0 0 25 18"
fill="none"
>
<path
d="M2 9L10 16.5L22.5 1.5"
stroke="#ffffff"
strokeWidth="4"
strokeLinecap="round"
/>
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 25 18" fill="none">
<path d="M2 9L10 16.5L22.5 1.5" stroke="#ffffff" strokeWidth="4" strokeLinecap="round" />
</svg>
)}
</Box>

@ -8,13 +8,7 @@ export default function CloseBold({ width }: Props) {
const theme = useTheme();
return (
<svg
width="35"
height="33"
viewBox="0 0 35 33"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg width="35" height="33" viewBox="0 0 35 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Close">
<g id="Rectangle 57" opacity="0.3" filter="url(#filter0_d_4080_12482)">
<rect x="6" y="4" width="24" height="24" rx="12" fill="#9A9AAF" />
@ -55,30 +49,13 @@ export default function CloseBold({ width }: Props) {
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/>
<feMorphology
radius="1"
operator="dilate"
in="SourceAlpha"
result="effect1_dropShadow_4080_12482"
/>
<feMorphology radius="1" operator="dilate" in="SourceAlpha" result="effect1_dropShadow_4080_12482" />
<feOffset dy="2" />
<feGaussianBlur stdDeviation="2.5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.416562 0 0 0 0 0.452406 0 0 0 0 0.775 0 0 0 0.18 0"
/>
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_4080_12482"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_4080_12482"
result="shape"
/>
<feColorMatrix type="matrix" values="0 0 0 0 0.416562 0 0 0 0 0.452406 0 0 0 0 0.775 0 0 0 0.18 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4080_12482" />
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4080_12482" result="shape" />
</filter>
</defs>
</svg>

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
backgroundColor: string
backgroundColor: string;
}
export default function AddressIcon({ color, backgroundColor }: Props) {
@ -19,13 +19,7 @@ export default function AddressIcon({ color, backgroundColor }: Props) {
borderTopLeftRadius: "12px",
}}
>
<svg
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M7.5 7.96875C8.53553 7.96875 9.375 7.12928 9.375 6.09375C9.375 5.05822 8.53553 4.21875 7.5 4.21875C6.46447 4.21875 5.625 5.05822 5.625 6.09375C5.625 7.12928 6.46447 7.96875 7.5 7.96875Z"
stroke={color}

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
backgroundColor: string
backgroundColor: string;
}
export default function EmailIcon({ color, backgroundColor }: Props) {
@ -21,9 +21,14 @@ export default function EmailIcon({ color, backgroundColor }: Props) {
>
<svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="3" width="15" height="12" rx="3" stroke="#9A9AAF" strokeWidth="1.5" />
<path d="M4 6.75L7.3 9.225C8.01111 9.75833 8.98889 9.75833 9.7 9.225L13 6.75" stroke="#9A9AAF" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
<path
d="M4 6.75L7.3 9.225C8.01111 9.75833 8.98889 9.75833 9.7 9.225L13 6.75"
stroke="#9A9AAF"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</Box>
);
}

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
backgroundColor: string
backgroundColor: string;
}
export default function NameIcon({ color, backgroundColor }: Props) {
@ -20,8 +20,19 @@ export default function NameIcon({ color, backgroundColor }: Props) {
}}
>
<svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="2.97143" cy="2.97143" r="2.97143" transform="matrix(-1 0 0 1 11.4688 2.5)" stroke="#9A9AAF" strokeWidth="1.5"/>
<path d="M3.29688 12.8526C3.29688 12.2135 3.69865 11.6433 4.30054 11.4284V11.4284C7.01416 10.4592 9.97959 10.4592 12.6932 11.4284V11.4284C13.2951 11.6433 13.6969 12.2135 13.6969 12.8526V13.8298C13.6969 14.7119 12.9156 15.3895 12.0424 15.2648L11.7512 15.2232C9.59262 14.9148 7.40113 14.9148 5.24252 15.2232L4.95137 15.2648C4.07814 15.3895 3.29688 14.7119 3.29688 13.8298V12.8526Z" stroke="#9A9AAF" strokeWidth="1.5"/>
<circle
cx="2.97143"
cy="2.97143"
r="2.97143"
transform="matrix(-1 0 0 1 11.4688 2.5)"
stroke="#9A9AAF"
strokeWidth="1.5"
/>
<path
d="M3.29688 12.8526C3.29688 12.2135 3.69865 11.6433 4.30054 11.4284V11.4284C7.01416 10.4592 9.97959 10.4592 12.6932 11.4284V11.4284C13.2951 11.6433 13.6969 12.2135 13.6969 12.8526V13.8298C13.6969 14.7119 12.9156 15.3895 12.0424 15.2648L11.7512 15.2232C9.59262 14.9148 7.40113 14.9148 5.24252 15.2232L4.95137 15.2648C4.07814 15.3895 3.29688 14.7119 3.29688 13.8298V12.8526Z"
stroke="#9A9AAF"
strokeWidth="1.5"
/>
</svg>
</Box>
);

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
backgroundColor: string
backgroundColor: string;
}
export default function PhoneIcon({ color, backgroundColor }: Props) {
@ -20,7 +20,11 @@ export default function PhoneIcon({ color, backgroundColor }: Props) {
}}
>
<svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.6893 15.0369C12.2537 16.4725 8.57727 15.1236 5.47772 12.024C2.37818 8.9245 1.02926 5.24806 2.46484 3.81247L3.41006 2.86725C4.06259 2.21472 5.13781 2.23197 5.81163 2.90578L7.27569 4.36984C7.9495 5.04365 7.96675 6.11888 7.31421 6.77141L7.11119 6.97443C6.75888 7.32675 6.72441 7.8951 7.05178 8.29181C7.36754 8.67446 7.70796 9.0556 8.07707 9.4247C8.44617 9.7938 8.82731 10.1342 9.20996 10.45C9.60666 10.7774 10.175 10.7429 10.5273 10.3906L10.7304 10.1875C11.3829 9.53501 12.4581 9.55226 13.1319 10.2261L14.596 11.6901C15.2698 12.364 15.287 13.4392 14.6345 14.0917L13.6893 15.0369Z" stroke="#9A9AAF" strokeWidth="1.5"/>
<path
d="M13.6893 15.0369C12.2537 16.4725 8.57727 15.1236 5.47772 12.024C2.37818 8.9245 1.02926 5.24806 2.46484 3.81247L3.41006 2.86725C4.06259 2.21472 5.13781 2.23197 5.81163 2.90578L7.27569 4.36984C7.9495 5.04365 7.96675 6.11888 7.31421 6.77141L7.11119 6.97443C6.75888 7.32675 6.72441 7.8951 7.05178 8.29181C7.36754 8.67446 7.70796 9.0556 8.07707 9.4247C8.44617 9.7938 8.82731 10.1342 9.20996 10.45C9.60666 10.7774 10.175 10.7429 10.5273 10.3906L10.7304 10.1875C11.3829 9.53501 12.4581 9.55226 13.1319 10.2261L14.596 11.6901C15.2698 12.364 15.287 13.4392 14.6345 14.0917L13.6893 15.0369Z"
stroke="#9A9AAF"
strokeWidth="1.5"
/>
</svg>
</Box>
);

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
backgroundColor: string
backgroundColor: string;
}
export default function TextIcon({ color, backgroundColor }: Props) {
@ -19,19 +19,8 @@ export default function TextIcon({ color, backgroundColor }: Props) {
borderTopLeftRadius: "12px",
}}
>
<svg
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.67188 1.60156L8.67188 13.3838"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
/>
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.67188 1.60156L8.67188 13.3838" stroke={color} strokeLinecap="round" strokeLinejoin="round" />
<path
d="M10.6016 4.21875H13.7768C13.8534 4.21875 13.9268 4.26814 13.9809 4.35604C14.035 4.44395 14.0655 4.56318 14.0655 4.6875V10.3125C14.0655 10.4368 14.035 10.556 13.9809 10.644C13.9268 10.7319 13.8534 10.7812 13.7768 10.7812H10.6016"
stroke={color}
@ -44,30 +33,10 @@ export default function TextIcon({ color, backgroundColor }: Props) {
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M3.98438 6.5625H5.625"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M7.85156 1.60156H9.49219"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M7.85156 13.3828H9.49219"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M4.80469 6.5625V8.67188"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path d="M3.98438 6.5625H5.625" stroke={color} strokeLinecap="round" strokeLinejoin="round" />
<path d="M7.85156 1.60156H9.49219" stroke={color} strokeLinecap="round" strokeLinejoin="round" />
<path d="M7.85156 13.3828H9.49219" stroke={color} strokeLinecap="round" strokeLinejoin="round" />
<path d="M4.80469 6.5625V8.67188" stroke={color} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Box>
);

@ -6,23 +6,13 @@ type InfoProps = {
sx?: SxProps;
onClick?: () => void;
className?: string;
color?: string
color?: string;
};
export default function Info({ width = 20, height = 20, sx, onClick, className, color = "#7e2aea" }: InfoProps) {
return (
<IconButton
sx={sx}
className={className}
onClick={onClick}
>
<svg
width={width}
height={height}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<IconButton sx={sx} className={className} onClick={onClick}>
<svg width={width} height={height} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M10 19C14.9706 19 19 14.9706 19 10C19 5.02944 14.9706 1 10 1C5.02944 1 1 5.02944 1 10C1 14.9706 5.02944 19 10 19Z"
stroke={color}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,7 +1,7 @@
import { Box, useTheme } from "@mui/material";
interface Props {
color?: string
color?: string;
}
export default function UploadIcon({ color = "#9A9AAF" }: Props) {
@ -18,9 +18,21 @@ export default function UploadIcon({color= "#9A9AAF"}: Props) {
}}
>
<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={color} 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={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={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={color}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</Box>
);

@ -16,24 +16,9 @@ export default function FlagIcon({ color, width = 30 }: Props) {
justifyContent: "center",
}}
>
<svg
width={width}
height={width}
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5 27V6"
stroke={color}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M5 21.0016C13 15.0016 19 27.0016 27 21.0016V6.00158C19 12.0016 13 0.00158215 5 6.00158"
fill={color}
/>
<svg width={width} height={width} viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 27V6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
<path d="M5 21.0016C13 15.0016 19 27.0016 27 21.0016V6.00158C19 12.0016 13 0.00158215 5 6.00158" fill={color} />
<path
d="M5 21.0016C13 15.0016 19 27.0016 27 21.0016V6.00158C19 12.0016 13 0.00158203 5 6.00158"
stroke={color}

@ -5,7 +5,7 @@ interface Props {
width?: number;
}
export default function HashtagIcon({ color, width = 30, }: Props) {
export default function HashtagIcon({ color, width = 30 }: Props) {
return (
<Box
sx={{
@ -16,13 +16,7 @@ export default function HashtagIcon({ color, width = 30, }: Props) {
justifyContent: "center",
}}
>
<svg
width={width}
height={width}
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg width={width} height={width} viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M3 11.3333H29M3 20.6667H29M13.6364 2L8.90909 30M23.0909 2L18.3636 30"
stroke={color}

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
width: number
width: number;
}
export default function HeartIcon({ color, width }: Props) {
@ -16,13 +16,7 @@ export default function HeartIcon({ color, width }: Props) {
justifyContent: "center",
}}
>
<svg
width={width}
height={width}
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg width={width} height={width} viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M16 27C16 27 3.5 20 3.5 11.5C3.5 9.99737 4.02062 8.54114 4.97328 7.37908C5.92593 6.21703 7.25178 5.42093 8.72525 5.12624C10.1987 4.83154 11.7288 5.05646 13.0551 5.76272C14.3814 6.46898 15.4221 7.61296 16 9.00001C16.5779 7.61296 17.6186 6.46898 18.9449 5.76272C20.2712 5.05646 21.8013 4.83154 23.2748 5.12624C24.7482 5.42093 26.0741 6.21703 27.0267 7.37908C27.9794 8.54114 28.5 9.99737 28.5 11.5C28.5 20 16 27 16 27Z"
fill={color}

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
width: number
width: number;
}
export default function LightbulbIcon({ color, width }: Props) {
@ -16,20 +16,8 @@ export default function LightbulbIcon({ color , width }: Props) {
justifyContent: "center",
}}
>
<svg
width={width}
height={width}
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 29H21"
stroke={color}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<svg width={width} height={width} viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 29H21" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
<path
d="M9.83761 20.8739C8.6471 19.9482 7.68288 18.7637 7.01801 17.4102C6.35313 16.0566 6.00504 14.5694 6.00011 13.0614C5.97511 7.6364 10.3376 3.1239 15.7626 2.9989C17.8622 2.94913 19.9242 3.56166 21.6561 4.74961C23.388 5.93756 24.7019 7.64064 25.4115 9.6173C26.1211 11.594 26.1904 13.7439 25.6094 15.7621C25.0285 17.7803 23.827 19.5644 22.1751 20.8614C21.8102 21.1435 21.5146 21.5052 21.311 21.919C21.1073 22.3328 21.001 22.7877 21.0001 23.2489V23.9989C21.0001 24.2641 20.8948 24.5185 20.7072 24.706C20.5197 24.8935 20.2653 24.9989 20.0001 24.9989H12.0001C11.7349 24.9989 11.4805 24.8935 11.293 24.706C11.1055 24.5185 11.0001 24.2641 11.0001 23.9989V23.2489C10.997 22.7912 10.8909 22.34 10.6896 21.9289C10.4884 21.5177 10.1972 21.1572 9.83761 20.8739V20.8739Z"
stroke={color}

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
width: number
width: number;
}
export default function LikeIcon({ color, width }: Props) {
@ -16,13 +16,7 @@ export default function LikeIcon({ color, width }: Props) {
justifyContent: "center",
}}
>
<svg
width={width}
height={width}
viewBox="0 0 40 40"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg width={width} height={width} viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M8 17H14V30H8C7.73478 30 7.48043 29.8946 7.29289 29.7071C7.10536 29.5196 7 29.2652 7 29V18C7 17.7348 7.10536 17.4804 7.29289 17.2929C7.48043 17.1054 7.73478 17 8 17V17Z"
stroke={color}

@ -2,7 +2,7 @@ import { Box } from "@mui/material";
interface Props {
color: string;
width: number
width: number;
}
export default function TropfyIcon({ color, width }: Props) {
@ -16,13 +16,7 @@ export default function TropfyIcon({ color, width }: Props) {
justifyContent: "center",
}}
>
<svg
width={width}
height={width}
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg width={width} height={width} viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M7 7V13.8875C7 18.85 10.975 22.9625 15.9375 23C17.1246 23.0082 18.3017 22.7815 19.4008 22.3329C20.5 21.8843 21.4995 21.2227 22.3419 20.3862C23.1843 19.5496 23.8528 18.5547 24.309 17.4586C24.7652 16.3626 25 15.1872 25 14V7C25 6.73478 24.8946 6.48043 24.7071 6.29289C24.5196 6.10536 24.2652 6 24 6H8C7.73478 6 7.48043 6.10536 7.29289 6.29289C7.10536 6.48043 7 6.73478 7 7Z"
fill={color}
@ -31,20 +25,8 @@ export default function TropfyIcon({ color, width }: Props) {
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M12 28H20"
stroke={color}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M16 23V28"
stroke={color}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path d="M12 28H20" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
<path d="M16 23V28" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
<path
d="M24.7754 16H26.0004C27.0613 16 28.0787 15.5786 28.8288 14.8284C29.579 14.0783 30.0004 13.0609 30.0004 12V10C30.0004 9.73478 29.895 9.48043 29.7075 9.29289C29.52 9.10536 29.2656 9 29.0004 9H25.0004"
stroke={color}

@ -1,20 +1,9 @@
import {
startTransition,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react";
import { startTransition, useEffect, useLayoutEffect, useRef, useState } from "react";
import { ErrorBoundary } from "react-error-boundary";
import useSWR from "swr";
import { SnackbarProvider } from "notistack";
import moment from "moment";
import {
Box,
ScopedCssBaseline,
CssBaseline,
ThemeProvider,
} from "@mui/material";
import { Box, ScopedCssBaseline, CssBaseline, ThemeProvider } from "@mui/material";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
import { ruRU } from "@mui/x-date-pickers/locales";
@ -38,8 +27,7 @@ import lightTheme from "@utils/themes/light";
import type { QuizSettings } from "@model/settingsData";
moment.locale("ru");
const localeText =
ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
type Props = {
quizSettings?: QuizSettings;
@ -59,9 +47,7 @@ function QuizAnswererInner({
disableGlobalCss = false,
}: Props) {
const [quizViewStore] = useState(createQuizViewStore);
const [rootContainerWidth, setRootContainerWidth] = useState<number>(
() => window.innerWidth
);
const [rootContainerWidth, setRootContainerWidth] = useState<number>(() => window.innerWidth);
const rootContainerRef = useRef<HTMLDivElement>(null);
const { data, error, isLoading } = useSWR(
quizSettings ? null : ["quizData", quizId],
@ -73,12 +59,8 @@ function QuizAnswererInner({
refreshInterval: 0,
}
);
const vkMetrics = useVkMetricsGoals(
quizSettings?.settings.cfg.vkMetricsNumber
);
const yandexMetrics = useYandexMetricsGoals(
quizSettings?.settings.cfg.yandexMetricsNumber
);
const vkMetrics = useVkMetricsGoals(quizSettings?.settings.cfg.vkMetricsNumber);
const yandexMetrics = useYandexMetricsGoals(quizSettings?.settings.cfg.yandexMetricsNumber);
useEffect(() => {
setTimeout(() => {
@ -88,15 +70,13 @@ function QuizAnswererInner({
}, []);
useLayoutEffect(() => {
if (rootContainerRef.current)
setRootContainerWidth(rootContainerRef.current.clientWidth);
if (rootContainerRef.current) setRootContainerWidth(rootContainerRef.current.clientWidth);
}, []);
useEffect(() => {
const handleWindowResize = () => {
startTransition(() => {
if (rootContainerRef.current)
setRootContainerWidth(rootContainerRef.current.clientWidth);
if (rootContainerRef.current) setRootContainerWidth(rootContainerRef.current.clientWidth);
});
};
window.addEventListener("resize", handleWindowResize);
@ -112,8 +92,7 @@ function QuizAnswererInner({
quizSettings ??= data;
if (!quizSettings) throw new Error("Quiz data is null");
if (quizSettings.questions.length === 0)
return <ApologyPage error={new Error("No questions found")} />;
if (quizSettings.questions.length === 0) return <ApologyPage error={new Error("No questions found")} />;
if (!quizId) return <ApologyPage error={new Error("No quiz id")} />;
const quizContainer = (
@ -126,10 +105,7 @@ function QuizAnswererInner({
position: "relative",
}}
>
<ErrorBoundary
FallbackComponent={ApologyPage}
onError={handleComponentError}
>
<ErrorBoundary FallbackComponent={ApologyPage} onError={handleComponentError}>
<ViewPublicationPage />
</ErrorBoundary>
</Box>
@ -138,9 +114,7 @@ function QuizAnswererInner({
return (
<QuizViewContext.Provider value={quizViewStore}>
<RootContainerWidthContext.Provider value={rootContainerWidth}>
<QuizDataContext.Provider
value={{ ...quizSettings, quizId, preview, changeFaviconAndTitle }}
>
<QuizDataContext.Provider value={{ ...quizSettings, quizId, preview, changeFaviconAndTitle }}>
{disableGlobalCss ? (
<ScopedCssBaseline
sx={{
@ -162,16 +136,9 @@ function QuizAnswererInner({
export default function QuizAnswerer(props: Props) {
return (
<LocalizationProvider
dateAdapter={AdapterMoment}
adapterLocale="ru"
localeText={localeText}
>
<LocalizationProvider dateAdapter={AdapterMoment} adapterLocale="ru" localeText={localeText}>
<ThemeProvider theme={lightTheme}>
<SnackbarProvider
preventDuplicate={true}
style={{ backgroundColor: lightTheme.palette.brightPurple.main }}
>
<SnackbarProvider preventDuplicate={true} style={{ backgroundColor: lightTheme.palette.brightPurple.main }}>
<QuizAnswererInner {...props} />
</SnackbarProvider>
</ThemeProvider>

@ -27,7 +27,9 @@ export const ApologyPage = ({ error }: Props) => {
textAlign: "center",
color: "text.primary",
}}
>{message}</Typography>
>
{message}
</Typography>
</Box>
);
};

@ -21,10 +21,7 @@ import { DESIGN_LIST } from "@utils/designList";
import { NameplateLogo } from "@icons/NameplateLogo";
import type {
FormContactFieldData,
FormContactFieldName,
} from "@model/settingsData";
import type { FormContactFieldData, FormContactFieldName } from "@model/settingsData";
import type { QuizQuestionResult } from "@model/questionTypes/result";
import type { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
@ -70,15 +67,9 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
? currentQuestion
: questions.find((question): question is QuizQuestionResult => {
if (settings?.cfg.haveRoot) {
return (
question.type === "result" &&
question.content.rule.parentId === currentQuestion.content.id
);
return question.type === "result" && question.content.rule.parentId === currentQuestion.content.id;
} else {
return (
question.type === "result" &&
question.content.rule.parentId === "line"
);
return question.type === "result" && question.content.rule.parentId === "line";
}
});
@ -103,10 +94,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
});
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
localStorage.setItem(
"sessions",
JSON.stringify({ ...sessions, [quizId]: new Date().getTime() })
);
localStorage.setItem("sessions", JSON.stringify({ ...sessions, [quizId]: new Date().getTime() }));
} catch (e) {
enqueueSnackbar("ответ не был засчитан");
}
@ -116,9 +104,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
const FCcopy: Record<FormContactFieldName, FormContactFieldData> =
settings.cfg.formContact.fields || settings.cfg.formContact;
const filteredFC: Partial<
Record<FormContactFieldName, FormContactFieldData>
> = {};
const filteredFC: Partial<Record<FormContactFieldName, FormContactFieldData>> = {};
for (const i in FCcopy) {
const field = FCcopy[i as keyof typeof FCcopy];
if (field.used) {
@ -133,13 +119,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
}
if (fireOnce.current) {
if (
name.length === 0 &&
email.length === 0 &&
phone.length === 0 &&
text.length === 0 &&
adress.length === 0
)
if (name.length === 0 && email.length === 0 && phone.length === 0 && text.length === 0 && adress.length === 0)
return enqueueSnackbar("Пожалуйста, заполните поля");
//почта валидна, хоть одно поле заполнено
@ -211,7 +191,8 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
settings.cfg.design && !isMobile
? quizThemes[settings.cfg.theme].isLight
? `url(${DESIGN_LIST[settings.cfg.theme]})`
: `linear-gradient(90deg, rgba(39, 38, 38, 0.95) 7.66%, rgba(42, 42, 46, 0.85) 42.12%, rgba(51, 54, 71, 0.4) 100%), url(${DESIGN_LIST[settings.cfg.theme]
: `linear-gradient(90deg, rgba(39, 38, 38, 0.95) 7.66%, rgba(42, 42, 46, 0.85) 42.12%, rgba(51, 54, 71, 0.4) 100%), url(${
DESIGN_LIST[settings.cfg.theme]
})`
: null,
}}
@ -224,14 +205,12 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
minHeight: "100%",
display: "flex",
flexDirection: isMobile ? "column" : "row",
background:
settings.cfg.design && !isMobile
? undefined
: theme.palette.background.default,
background: settings.cfg.design && !isMobile ? undefined : theme.palette.background.default,
}}
>
<ContactTextBlock settings={settings} />
<Box sx={{
<Box
sx={{
flexGrow: isMobile ? 1 : 0,
display: "flex",
alignItems: "center",
@ -239,7 +218,8 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
flexDirection: "column",
backgroundColor: theme.palette.background.default,
height: "auto",
}}>
}}
>
<Box
sx={{
display: "flex",
@ -255,7 +235,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
display: "flex",
flexDirection: "column",
mt: isMobile ? "10px" : "20px",
mb: "20px"
mb: "20px",
}}
>
<Inputs
@ -286,21 +266,19 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
colorIcon={theme.palette.primary.main}
sx={{ marginRight: "0" }}
/>
<Typography sx={{
<Typography
sx={{
color: theme.palette.text.primary,
lineHeight: "18.96px"
}} fontSize={"16px"}>
lineHeight: "18.96px",
}}
fontSize={"16px"}
>
С&ensp;
<Link href={"https://shub.pena.digital/ppdd"}
target="_blank">
Положением об обработке персональных
данных{" "}
<Link href={"https://shub.pena.digital/ppdd"} target="_blank">
Положением об обработке персональных данных{" "}
</Link>
&ensp;и&ensp;
<Link
href={"https://shub.pena.digital/docs/privacy"}
target="_blank"
>
<Link href={"https://shub.pena.digital/docs/privacy"} target="_blank">
{" "}
Политикой конфиденциальности{" "}
</Link>
@ -321,7 +299,6 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
border: "1px solid #9A9AAF",
color: "#9A9AAF",
},
}}
>
{settings.cfg.formContact?.button || "Получить результаты"}
@ -331,7 +308,8 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
<Box
component={Link}
target={"_blank"}
href={`https://${window.location.hostname.includes("s") ? "s" : ""
href={`https://${
window.location.hostname.includes("s") ? "s" : ""
}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
sx={{
display: "flex",
@ -346,9 +324,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
<NameplateLogo
style={{
fontSize: "20px",
color: quizThemes[settings.cfg.theme].isLight
? "#151515"
: "#FFFFFF",
color: quizThemes[settings.cfg.theme].isLight ? "#151515" : "#FFFFFF",
}}
/>
</Box>

@ -5,7 +5,7 @@ import {FC} from "react";
type ContactTextBlockProps = {
settings: QuizSettingsConfig;
}
};
export const ContactTextBlock: FC<ContactTextBlockProps> = ({ settings }) => {
const theme = useTheme();
@ -21,7 +21,7 @@ export const ContactTextBlock: FC<ContactTextBlockProps> = ({settings}) => {
justifyContent: "center",
borderRight: isMobile ? undefined : "1px solid #9A9AAF80",
margin: isMobile ? 0 : "40px 0",
padding: isMobile ? "0" : "0 40px"
padding: isMobile ? "0" : "0 40px",
}}
>
<Box
@ -45,8 +45,7 @@ export const ContactTextBlock: FC<ContactTextBlockProps> = ({settings}) => {
wordBreak: "break-word",
}}
>
{settings.cfg.formContact.title ||
"Заполните форму, чтобы получить результаты теста"}
{settings.cfg.formContact.title || "Заполните форму, чтобы получить результаты теста"}
</Typography>
{settings.cfg.formContact.desc && (
<Typography
@ -62,5 +61,5 @@ export const ContactTextBlock: FC<ContactTextBlockProps> = ({settings}) => {
)}
</Box>
</Box>
)
}
);
};

@ -5,11 +5,11 @@ import {Value} from "react-phone-number-input";
type CountrySelectorProps = {
setMask: Dispatch<SetStateAction<string>>;
}
};
export const CountrySelector: FC<CountrySelectorProps> = ({ setMask }) => {
const theme = useTheme();
const [country, setCountry] = useState('RU');
const [country, setCountry] = useState("RU");
const handleChange = (e: SelectChangeEvent<Value>) => {
setCountry(e.target.value);
@ -25,7 +25,7 @@ export const CountrySelector: FC<CountrySelectorProps> = ({setMask}) => {
PaperProps: {
style: {
backgroundColor: theme.palette.background.default,
borderRadius: '12px',
borderRadius: "12px",
scrollbarWidth: "none",
},
},
@ -36,7 +36,7 @@ export const CountrySelector: FC<CountrySelectorProps> = ({setMask}) => {
"& .MuiSelect-select": {
paddingLeft: "5px",
paddingRight: "5px",
color: 'gray',
color: "gray",
fontSize: "12px",
border: "none",
},
@ -58,10 +58,8 @@ export const CountrySelector: FC<CountrySelectorProps> = ({setMask}) => {
}}
>
{Object.keys(phoneMasksByCountry).map((countryCode) => {
return <MenuItem
value={countryCode}>{phoneMasksByCountry[countryCode][0]}</MenuItem>
return <MenuItem value={countryCode}>{phoneMasksByCountry[countryCode][0]}</MenuItem>;
})}
</Select>
);
};

@ -1,19 +1,10 @@
import {
Box,
InputAdornment,
TextField as MuiTextField,
TextFieldProps,
Typography,
useTheme
} from "@mui/material";
import { Box, InputAdornment, TextField as MuiTextField, TextFieldProps, Typography, useTheme } from "@mui/material";
import { useRootContainerSize } from "@contexts/RootContainerWidthContext.ts";
import { useQuizData } from "@contexts/QuizDataContext.ts";
import { useIMask } from "react-imask";
import { quizThemes } from "@utils/themes/Publication/themePublication.ts";
import { FC, useState } from "react";
import {
CountrySelector
} from "@/components/ViewPublicationPage/ContactForm/CustomInput/CountrySelector/CountrySelector.tsx";
import { CountrySelector } from "@/components/ViewPublicationPage/ContactForm/CustomInput/CountrySelector/CountrySelector.tsx";
import { phoneMasksByCountry } from "@utils/phoneMasksByCountry.tsx";
type InputProps = {
@ -22,17 +13,16 @@ type InputProps = {
Icon: FC<{ color: string; backgroundColor: string }>;
onChange: TextFieldProps["onChange"];
id: string;
isPhone?:boolean
isPhone?: boolean;
};
const TextField = MuiTextField as unknown as FC<TextFieldProps>;
export const CustomInput = ({ title, desc, Icon, onChange, isPhone }: InputProps) => {
const theme = useTheme();
const isMobile = useRootContainerSize() < 600;
const { settings } = useQuizData();
const [mask, setMask] = useState(phoneMasksByCountry['RU'][1]);
const [mask, setMask] = useState(phoneMasksByCountry["RU"][1]);
const { ref } = useIMask({ mask });
return (
<Box m="10px 0">
@ -67,25 +57,14 @@ export const CustomInput = ({ title, desc, Icon, onChange ,isPhone}: InputProps)
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Icon
color="gray"
backgroundColor={
quizThemes[settings.cfg.theme].isLight
? "#F2F3F7"
: "#F2F3F71A"
}
/>
<Icon color="gray" backgroundColor={quizThemes[settings.cfg.theme].isLight ? "#F2F3F7" : "#F2F3F71A"} />
</InputAdornment>
),
endAdornment: (
<InputAdornment position="end">
{isPhone && (
<CountrySelector setMask={setMask} />)}
</InputAdornment>
<InputAdornment position="end">{isPhone && <CountrySelector setMask={setMask} />}</InputAdornment>
),
}}
/>
</Box>
);
};

@ -4,9 +4,7 @@ import EmailIcon from "@icons/ContactFormIcon/EmailIcon.tsx";
import TextIcon from "@icons/ContactFormIcon/TextIcon.tsx";
import AddressIcon from "@icons/ContactFormIcon/AddressIcon.tsx";
import { Dispatch, SetStateAction } from "react";
import {
CustomInput
} from "@/components/ViewPublicationPage/ContactForm/CustomInput/CustomInput.tsx";
import { CustomInput } from "@/components/ViewPublicationPage/ContactForm/CustomInput/CustomInput.tsx";
import PhoneIcon from "@icons/ContactFormIcon/PhoneIcon.tsx";
type InputsProps = {

@ -14,9 +14,7 @@ type FooterProps = {
export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
const theme = useTheme();
const { questions, settings } = useQuizData();
const questionsAmount = questions.filter(
({ type }) => type !== "result"
).length;
const questionsAmount = questions.filter(({ type }) => type !== "result").length;
return (
<Box
@ -26,9 +24,7 @@ export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
borderTop: `1px solid #9A9AAF80`,
height: "75px",
display: "flex",
background: settings.cfg.design
? "rgba(154,154,175, 0.2)"
: "transparent",
background: settings.cfg.design ? "rgba(154,154,175, 0.2)" : "transparent",
}}
>
<Box

@ -48,9 +48,7 @@ export const Question = ({
height: "100%",
backgroundPosition: "center",
backgroundSize: "cover",
backgroundImage: settings.cfg.design
? `url(${DESIGN_LIST[settings.cfg.theme]})`
: null,
backgroundImage: settings.cfg.design ? `url(${DESIGN_LIST[settings.cfg.theme]})` : null,
}}
>
<Box
@ -125,23 +123,13 @@ export const Question = ({
</Box>
</Box>
{questionSelect}
<Footer
stepNumber={currentQuestionStepNumber}
prevButton={prevButton}
nextButton={nextButton}
/>
<Footer stepNumber={currentQuestionStepNumber} prevButton={prevButton} nextButton={nextButton} />
</Box>
</Box>
);
};
function QuestionByType({
question,
stepNumber,
}: {
question: RealTypedQuizQuestion;
stepNumber: number | null;
}) {
function QuestionByType({ question, stepNumber }: { question: RealTypedQuizQuestion; stepNumber: number | null }) {
switch (question.type) {
case "variant":
return <Variant currentQuestion={question} />;

@ -2,7 +2,6 @@ import { useQuizData } from "@/contexts/QuizDataContext";
import { AnyTypedQuizQuestion } from "@/model/questionTypes/shared";
import { Box, FormControl, MenuItem, Select as MuiSelect, useTheme } from "@mui/material";
interface Props {
selectedQuestion: AnyTypedQuizQuestion;
setQuestion: (questionIdF: string) => void;
@ -15,11 +14,13 @@ export default function QuestionSelect({ selectedQuestion, setQuestion }: Props)
if (!preview) return null;
return (
<Box sx={{
<Box
sx={{
p: "20px",
display: "flex",
justifyContent: "center",
}}>
}}
>
<FormControl
fullWidth
size="small"
@ -27,7 +28,6 @@ export default function QuestionSelect({ selectedQuestion, setQuestion }: Props)
maxWidth: "500px",
minWidth: "200px",
height: "48px",
}}
className="cancel"
>
@ -85,8 +85,9 @@ export default function QuestionSelect({ selectedQuestion, setQuestion }: Props)
},
}}
>
{questions.filter((q) => q.type !== "result").map(
(question, index) => (
{questions
.filter((q) => q.type !== "result")
.map((question, index) => (
<MenuItem
key={question.id}
value={question.id}
@ -103,8 +104,7 @@ export default function QuestionSelect({ selectedQuestion, setQuestion }: Props)
>
{`${index + 1}. ${question.title}`}
</MenuItem>
),
)}
))}
</MuiSelect>
</FormControl>
</Box>

@ -26,9 +26,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
const isMobile = useRootContainerSize() < 650;
const isTablet = useRootContainerSize() < 1000;
const { settings, show_badge, quizId } = useQuizData();
const setCurrentQuizStep = useQuizViewStore(
(state) => state.setCurrentQuizStep
);
const setCurrentQuizStep = useQuizViewStore((state) => state.setCurrentQuizStep);
const spec = settings.cfg.spec;
const vkMetrics = useVkMetricsGoals(settings.cfg.vkMetricsNumber);
const yandexMetrics = useYandexMetricsGoals(settings.cfg.yandexMetricsNumber);
@ -51,10 +49,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
backgroundColor: theme.palette.background.default,
backgroundPosition: "center",
backgroundSize: "cover",
backgroundImage:
settings.cfg.design && !isMobile
? `url(${DESIGN_LIST[settings.cfg.theme]})`
: null,
backgroundImage: settings.cfg.design && !isMobile ? `url(${DESIGN_LIST[settings.cfg.theme]})` : null,
position: "relative",
}}
>
@ -121,8 +116,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
maxWidth: "700px",
}}
>
{!resultQuestion?.content.useImage &&
resultQuestion.content.video && (
{!resultQuestion?.content.useImage && resultQuestion.content.video && (
<YoutubeEmbedIframe
videoUrl={resultQuestion.content.video}
containerSX={{
@ -132,8 +126,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
}}
/>
)}
{resultQuestion?.content.useImage &&
resultQuestion.content.back && (
{resultQuestion?.content.useImage && resultQuestion.content.back && (
<Box
sx={{
width: "100%",
@ -154,8 +147,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
/>
</Box>
)}
{resultQuestion.description !== "" &&
resultQuestion.description !== " " && (
{resultQuestion.description !== "" && resultQuestion.description !== " " && (
<Typography
sx={{
fontSize: "27px",
@ -182,8 +174,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
{resultQuestion.title}
</Typography>
{resultQuestion.content.text !== "" &&
resultQuestion.content.text !== " " && (
{resultQuestion.content.text !== "" && resultQuestion.content.text !== " " && (
<Typography
sx={{
fontSize: "17px",
@ -220,9 +211,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
<NameplateLogo
style={{
fontSize: "23px",
color: quizThemes[settings.cfg.theme].isLight
? "#000000"
: "#F5F7FF",
color: quizThemes[settings.cfg.theme].isLight ? "#000000" : "#F5F7FF",
}}
/>
</Box>
@ -240,8 +229,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
bottom: 0,
}}
>
{settings.cfg.resultInfo.showResultForm === "before" &&
!settings.cfg.score && (
{settings.cfg.resultInfo.showResultForm === "before" && !settings.cfg.score && (
<Button
onClick={() => setCurrentQuizStep("contactform")}
variant="contained"
@ -254,18 +242,18 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
{resultQuestion.content.hint.text || "Узнать подробнее"}
</Button>
)}
{settings.cfg.resultInfo.showResultForm === "after" &&
resultQuestion.content.redirect && (
{settings.cfg.resultInfo.showResultForm === "after" && resultQuestion.content.redirect && (
<Button
onClick={() => {
vkMetrics.resultLink();
yandexMetrics.resultLink();
setTimeout(() => {
location.href =
(resultQuestion.content.redirect.includes("https")
location.href = (
resultQuestion.content.redirect.includes("https")
? resultQuestion.content.redirect
: `https://${resultQuestion.content.redirect}`).replace(/\s+/g, "");
}, 1000)
: `https://${resultQuestion.content.redirect}`
).replace(/\s+/g, "");
}, 1000);
}}
variant="contained"
sx={{

@ -3,10 +3,7 @@ import { StartPageMobile } from "./StartPageMobile";
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
import type {
QuizStartpageAlignType,
QuizStartpageType,
} from "@model/settingsData";
import type { QuizStartpageAlignType, QuizStartpageType } from "@model/settingsData";
type QuizPreviewLayoutByTypeProps = {
quizHeaderBlock: JSX.Element;

@ -6,10 +6,7 @@ import {useQuizData} from "@contexts/QuizDataContext";
import { notReachable } from "@utils/notReachable";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import type {
QuizStartpageAlignType,
QuizStartpageType,
} from "@model/settingsData";
import type { QuizStartpageAlignType, QuizStartpageType } from "@model/settingsData";
import { DESIGN_LIST } from "@/utils/designList";
type StartPageDesktopProps = {
@ -22,12 +19,7 @@ type StartPageDesktopProps = {
type LayoutProps = Omit<StartPageDesktopProps, "startpageType">;
const StandartLayout = ({
alignType,
quizHeaderBlock,
quizMainBlock,
backgroundBlock,
}: LayoutProps) => {
const StandartLayout = ({ alignType, quizHeaderBlock, quizMainBlock, backgroundBlock }: LayoutProps) => {
const size = useRootContainerSize();
const isTablet = size >= 700 && size < 1100;
const { settings } = useQuizData();
@ -41,15 +33,12 @@ const StandartLayout = ({
height: "100%",
backgroundPosition: "center",
backgroundSize: "cover",
backgroundImage: settings.cfg.design
? `url(${DESIGN_LIST[settings.cfg.theme]})`
: null,
backgroundImage: settings.cfg.design ? `url(${DESIGN_LIST[settings.cfg.theme]})` : null,
scrollbarWidth: "none",
"&::-webkit-scrollbar": {
width: 0,
},
overflowY: "auto",
}}
>
<Box
@ -58,10 +47,11 @@ const StandartLayout = ({
flexDirection: alignType === "left" ? "row" : "row-reverse",
padding: isTablet ? "15px" : "0",
width: "100%",
background: settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
? alignType === 'left'
background:
settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
? alignType === "left"
? "linear-gradient(90deg, #272626, transparent)"
: alignType === 'right'
: alignType === "right"
? "linear-gradient(-90deg, #272626, transparent)"
: "linear-gradient(0deg, #272626, transparent)"
: null,
@ -75,7 +65,7 @@ const StandartLayout = ({
flexDirection: "column",
justifyContent: "space-between",
alignItems: "flex-start",
p: isTablet ? "25px" : alignType === 'left' ? "25px 25px 25px 35px" : "25px 35px 25px 25px",
p: isTablet ? "25px" : alignType === "left" ? "25px 25px 25px 35px" : "25px 35px 25px 25px",
overflowY: "auto",
scrollbarWidth: "none",
"&::-webkit-scrollbar": {
@ -87,7 +77,8 @@ const StandartLayout = ({
{quizMainBlock}
</Box>
{settings.cfg.startpage.background.desktop && (
<Box sx={{width: "60%", overflow: "hidden"}}><Box
<Box sx={{ width: "60%", overflow: "hidden" }}>
<Box
sx={{
width: "100%",
height: "100%",
@ -96,19 +87,17 @@ const StandartLayout = ({
justifyContent: "center",
"& > img": { width: "100%", borderRadius: "12px" },
}}
>{backgroundBlock}</Box></Box>
>
{backgroundBlock}
</Box>
</Box>
)}
</Box>
</Box>
);
};
const ExpandedLayout = ({
alignType,
quizHeaderBlock,
quizMainBlock,
backgroundBlock,
}: LayoutProps) => {
const ExpandedLayout = ({ alignType, quizHeaderBlock, quizMainBlock, backgroundBlock }: LayoutProps) => {
const size = useRootContainerSize();
const isTablet = size >= 700 && size < 1100;
return (
@ -120,16 +109,17 @@ const ExpandedLayout = ({
display: "flex",
padding:
alignType === "center"
? isTablet ? "30px 40px" : "30px 35px"
? isTablet
? "30px 40px"
: "30px 35px"
: alignType === "left"
? isTablet ? "25px 0 31px 40px" : "25px 0 31px 35px"
: isTablet ? "25px 40px 31px 0" : "25px 35px 31px 0",
margin:
alignType === "center"
? "0 auto"
: alignType === "left"
? "0"
: "0 0 0 auto",
? isTablet
? "25px 0 31px 40px"
: "25px 0 31px 35px"
: isTablet
? "25px 40px 31px 0"
: "25px 35px 31px 0",
margin: alignType === "center" ? "0 auto" : alignType === "left" ? "0" : "0 0 0 auto",
scrollbarWidth: "none",
"&::-webkit-scrollbar": {
width: 0,
@ -143,12 +133,7 @@ const ExpandedLayout = ({
position: "relative",
width: "100%",
padding:
alignType === "center"
? "0"
: alignType === "left"
? "0 40px 0 0"
: "0 0 0 40px",
padding: alignType === "center" ? "0" : alignType === "left" ? "0 40px 0 0" : "0 0 0 40px",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
@ -180,13 +165,9 @@ const ExpandedLayout = ({
</Box>
</>
);
}
};
const CenteredLayout = ({
quizHeaderBlock,
quizMainBlock,
backgroundBlock,
}: LayoutProps) => {
const CenteredLayout = ({ quizHeaderBlock, quizMainBlock, backgroundBlock }: LayoutProps) => {
const isTablet = useRootContainerSize() < 1100;
const { settings } = useQuizData();
return (
@ -200,8 +181,11 @@ const CenteredLayout = ({
height: "100%",
backgroundPosition: "center",
backgroundSize: "cover",
backgroundImage: !settings.cfg.design ? null : settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
? `linear-gradient(0deg, #272626, transparent), url(${DESIGN_LIST[settings.cfg.theme]})` : `url(${DESIGN_LIST[settings.cfg.theme]})`,
backgroundImage: !settings.cfg.design
? null
: settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
? `linear-gradient(0deg, #272626, transparent), url(${DESIGN_LIST[settings.cfg.theme]})`
: `url(${DESIGN_LIST[settings.cfg.theme]})`,
scrollbarWidth: "none",
"&::-webkit-scrollbar": {
width: 0,

@ -17,11 +17,7 @@ type StartPageMobileProps = {
type MobileLayoutProps = Omit<StartPageMobileProps, "startpageType">;
const StandartMobileLayout = ({
quizHeaderBlock,
quizMainBlock,
backgroundBlock,
}: MobileLayoutProps) => {
const StandartMobileLayout = ({ quizHeaderBlock, quizMainBlock, backgroundBlock }: MobileLayoutProps) => {
const { settings } = useQuizData();
return (
@ -36,9 +32,7 @@ const StandartMobileLayout = ({
"&::-webkit-scrollbar": { width: 0 },
backgroundPosition: "center",
backgroundSize: "cover",
backgroundImage: settings.cfg.design
? `url(${DESIGN_LIST[settings.cfg.theme]})`
: null,
backgroundImage: settings.cfg.design ? `url(${DESIGN_LIST[settings.cfg.theme]})` : null,
}}
>
<Box
@ -65,9 +59,7 @@ const StandartMobileLayout = ({
},
}}
>
<Box sx={{marginBottom: "13px"}}>
{quizHeaderBlock}
</Box>
<Box sx={{ marginBottom: "13px" }}>{quizHeaderBlock}</Box>
{settings.cfg.startpage.background.desktop && (
<Box sx={{ width: "100%", overflow: "hidden" }}>
<Box
@ -78,7 +70,7 @@ const StandartMobileLayout = ({
justifyContent: "center",
"& > img": {
width: "100%",
borderRadius: "12px"
borderRadius: "12px",
},
}}
>
@ -94,7 +86,7 @@ const StandartMobileLayout = ({
flexDirection: "column",
justifyContent: "space-between",
width: "100%",
marginTop: "30px"
marginTop: "30px",
}}
>
{quizMainBlock}
@ -104,11 +96,7 @@ const StandartMobileLayout = ({
);
};
const ExpandedMobileLayout = ({
quizHeaderBlock,
quizMainBlock,
backgroundBlock,
}: MobileLayoutProps) => (
const ExpandedMobileLayout = ({ quizHeaderBlock, quizMainBlock, backgroundBlock }: MobileLayoutProps) => (
<Box
sx={{
display: "flex",
@ -172,11 +160,7 @@ const ExpandedMobileLayout = ({
</Box>
);
const CenteredMobileLayout = ({
quizHeaderBlock,
quizMainBlock,
backgroundBlock,
}: MobileLayoutProps) => {
const CenteredMobileLayout = ({ quizHeaderBlock, quizMainBlock, backgroundBlock }: MobileLayoutProps) => {
const { settings } = useQuizData();
return (
<Box
@ -189,8 +173,11 @@ const CenteredMobileLayout = ({
height: "100%",
backgroundPosition: "center",
backgroundSize: "cover",
backgroundImage: !settings.cfg.design ? null : settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
? `linear-gradient(0deg, #272626, transparent), url(${DESIGN_LIST[settings.cfg.theme]})` : `url(${DESIGN_LIST[settings.cfg.theme]})`,
backgroundImage: !settings.cfg.design
? null
: settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
? `linear-gradient(0deg, #272626, transparent), url(${DESIGN_LIST[settings.cfg.theme]})`
: `url(${DESIGN_LIST[settings.cfg.theme]})`,
"&::-webkit-scrollbar": { width: 0 },
}}
>
@ -237,7 +224,7 @@ const CenteredMobileLayout = ({
</Box>
</Box>
);
}
};
export const StartPageMobile = ({
quizHeaderBlock,

@ -1,12 +1,4 @@
import {
Box,
Button,
ButtonBase,
Link,
Paper,
Typography,
useTheme,
} from "@mui/material";
import { Box, Button, ButtonBase, Link, Paper, Typography, useTheme } from "@mui/material";
import { QuizPreviewLayoutByType } from "./QuizPreviewLayoutByType";
@ -29,9 +21,7 @@ export const StartPageViewPublication = () => {
const theme = useTheme();
const { settings, show_badge, quizId, questions } = useQuizData();
const { isMobileDevice } = useUADevice();
const setCurrentQuizStep = useQuizViewStore(
(state) => state.setCurrentQuizStep
);
const setCurrentQuizStep = useQuizViewStore((state) => state.setCurrentQuizStep);
const size = useRootContainerSize();
const isMobile = size < 700;
@ -50,18 +40,11 @@ export const StartPageViewPublication = () => {
const background =
settings.cfg.startpage.background.type === "image" ? (
<img
src={
settings.cfg.startpage.background.desktop ||
DESIGN_LIST[settings.cfg.theme] ||
""
}
src={settings.cfg.startpage.background.desktop || DESIGN_LIST[settings.cfg.theme] || ""}
alt=""
style={{
display: "block",
width:
isMobile || settings.cfg.startpageType === "expanded"
? "100%"
: undefined,
width: isMobile || settings.cfg.startpageType === "expanded" ? "100%" : undefined,
height: "100%",
minWidth: "100%",
maxHeight: "100%",
@ -75,10 +58,8 @@ export const StartPageViewPublication = () => {
videoUrl={settings.cfg.startpage.background.video}
containerSX={{
width: settings.cfg.startpageType === "centered" ? "550px" : "100%",
height:
settings.cfg.startpageType === "centered" ? "275px" : "100%",
borderRadius:
settings.cfg.startpageType === "centered" ? "10px" : "0",
height: settings.cfg.startpageType === "centered" ? "275px" : "100%",
borderRadius: settings.cfg.startpageType === "centered" ? "10px" : "0",
overflow: "hidden",
"& iframe": {
width: "100%",
@ -106,8 +87,7 @@ export const StartPageViewPublication = () => {
display: "flex",
alignItems: "center",
flexWrap:
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center"
? "nowrap"
: "wrap",
gap: isMobile ? "20px" : "30px",
@ -116,15 +96,11 @@ export const StartPageViewPublication = () => {
? isMobile
? "20px"
: "25px"
: settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center" &&
!isMobile
: settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center" && !isMobile
? 0
: "7px",
justifyContent:
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center" &&
isMobile
settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center" && isMobile
? "center"
: undefined,
}}
@ -143,13 +119,9 @@ export const StartPageViewPublication = () => {
<Typography
sx={{
fontSize: "12px",
color:
settings.cfg.startpageType === "expanded"
? "white"
: theme.palette.text.primary,
color: settings.cfg.startpageType === "expanded" ? "white" : theme.palette.text.primary,
wordBreak:
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center"
? "normal"
: "break-word",
}}
@ -164,8 +136,7 @@ export const StartPageViewPublication = () => {
<Box
component={Link}
target={"_blank"}
href={`https://${window.location.hostname.includes("s") ? "s" : ""
}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
href={`https://${window.location.hostname.includes("s") ? "s" : ""}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
sx={{
display: "flex",
alignItems: "center",
@ -223,14 +194,11 @@ export const StartPageViewPublication = () => {
vkMetrics.emailOpened();
yandexMetrics.emailOpened();
setTimeout(() => {
location.href = (
settings.cfg.info.site.includes("https")
? settings.cfg.info.site
: `https://${settings.cfg.info.site}`
settings.cfg.info.site.includes("https") ? settings.cfg.info.site : `https://${settings.cfg.info.site}`
).replace(/\s+/g, "");
}, 1000)
}, 1000);
};
return (
@ -242,8 +210,7 @@ export const StartPageViewPublication = () => {
width: "100%",
background:
settings.cfg.startpageType === "expanded"
? settings.cfg.startpage.position === "left" ||
(isMobile && settings.cfg.startpage.position === "right")
? settings.cfg.startpage.position === "left" || (isMobile && settings.cfg.startpage.position === "right")
? "linear-gradient(90deg, rgba(39, 38, 38, 0.95) 7.66%, rgba(42, 42, 46, 0.85) 42.12%, rgba(51, 54, 71, 0.4) 100%)"
: settings.cfg.startpage.position === "center"
? "linear-gradient(0deg, rgba(39, 38, 38, 0.95) 7.66%, rgba(42, 42, 46, 0.85) 42.12%, rgba(51, 54, 71, 0.4) 100%)"
@ -261,10 +228,7 @@ export const StartPageViewPublication = () => {
sx={{
display: "flex",
flexDirection: "column",
justifyContent:
settings.cfg.startpageType === "standard" && isMobile
? "start"
: "center",
justifyContent: settings.cfg.startpageType === "standard" && isMobile ? "start" : "center",
flexGrow: settings.cfg.startpageType === "centered" ? 0 : 1,
wordBreak: "break-word",
alignItems:
@ -275,12 +239,7 @@ export const StartPageViewPublication = () => {
? "center"
: "start"
: "start",
marginTop:
settings.cfg.startpageType === "centered"
? "30px"
: isMobile
? "0px"
: "5px",
marginTop: settings.cfg.startpageType === "centered" ? "30px" : isMobile ? "0px" : "5px",
maxWidth: isMobile
? "100%"
: settings.cfg.startpageType === "centered"
@ -302,14 +261,10 @@ export const StartPageViewPublication = () => {
overflowWrap: "break-word",
width: "100%",
textAlign:
settings.cfg.startpageType === "centered" ||
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "centered" || settings.cfg.startpage.position === "center"
? "center"
: "-moz-initial",
color:
settings.cfg.startpageType === "expanded"
? "white"
: theme.palette.text.primary,
color: settings.cfg.startpageType === "expanded" ? "white" : theme.palette.text.primary,
}}
>
{settings.name}
@ -323,23 +278,15 @@ export const StartPageViewPublication = () => {
overflowWrap: "break-word",
width: "100%",
textAlign:
settings.cfg.startpageType === "centered" ||
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "centered" || settings.cfg.startpage.position === "center"
? "center"
: "-moz-initial",
color:
settings.cfg.startpageType === "expanded"
? "white"
: theme.palette.text.primary,
color: settings.cfg.startpageType === "expanded" ? "white" : theme.palette.text.primary,
}}
>
{settings.cfg.startpage.description}
</Typography>
<Box
width={
settings.cfg.startpageType === "standard" ? "100%" : "auto"
}
>
<Box width={settings.cfg.startpageType === "standard" ? "100%" : "auto"}>
<Button
variant="contained"
disabled={realQuestionsCount === 0}
@ -352,21 +299,14 @@ export const StartPageViewPublication = () => {
}}
onClick={onQuizStart}
>
{settings.cfg.startpage.button.trim()
? settings.cfg.startpage.button
: "Пройти тест"}
{settings.cfg.startpage.button.trim() ? settings.cfg.startpage.button : "Пройти тест"}
</Button>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexGrow:
settings.cfg.startpageType === "centered"
? isMobile
? 0
: 1
: 0,
flexGrow: settings.cfg.startpageType === "centered" ? (isMobile ? 0 : 1) : 0,
gap: isMobile ? "30px" : "40px",
alignItems: "flex-end",
justifyContent:
@ -378,8 +318,7 @@ export const StartPageViewPublication = () => {
: "space-between",
width: "100%",
flexWrap:
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center"
? isMobile
? "wrap-reverse"
: "nowrap"
@ -403,8 +342,7 @@ export const StartPageViewPublication = () => {
flexDirection: "column",
alignItems: "center",
order:
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center"
? "2"
: "0",
}}
@ -432,10 +370,12 @@ export const StartPageViewPublication = () => {
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center" &&
!isMobile
? "end" : settings.cfg.startpageType === "expanded" &&
? "end"
: (settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center" &&
isMobile || settings.cfg.startpageType === "centered" &&
isMobile ? "center"
isMobile) ||
(settings.cfg.startpageType === "centered" && isMobile)
? "center"
: "start",
color: theme.palette.primary.main,
overflow: "hidden",
@ -454,15 +394,11 @@ export const StartPageViewPublication = () => {
sx={{
lineHeight: "19px",
textAlign:
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center"
? "end"
: "none",
fontSize: "16px",
color:
settings.cfg.startpageType === "expanded"
? "#FFFFFF"
: theme.palette.text.primary,
color: settings.cfg.startpageType === "expanded" ? "#FFFFFF" : theme.palette.text.primary,
}}
>
{settings.cfg.info.phonenumber}
@ -485,16 +421,12 @@ export const StartPageViewPublication = () => {
<Typography
sx={{
textAlign:
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center"
? "end"
: "none",
fontSize: "16px",
lineHeight: "19px",
color:
settings.cfg.startpageType === "expanded"
? "#FFFFFF"
: theme.palette.text.primary,
color: settings.cfg.startpageType === "expanded" ? "#FFFFFF" : theme.palette.text.primary,
}}
>
{settings.cfg.info.phonenumber}
@ -506,16 +438,12 @@ export const StartPageViewPublication = () => {
sx={{
lineHeight: "19px",
textAlign:
settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center"
settings.cfg.startpageType === "expanded" && settings.cfg.startpage.position === "center"
? "end"
: "none",
fontSize: "16px",
marginTop: "10px",
color:
settings.cfg.startpageType === "expanded"
? "#FFFFFF"
: theme.palette.text.primary,
color: settings.cfg.startpageType === "expanded" ? "#FFFFFF" : theme.palette.text.primary,
}}
>
{settings.cfg.info.phonenumber}
@ -536,18 +464,14 @@ export const StartPageViewPublication = () => {
: (settings.cfg.startpageType === "expanded" &&
settings.cfg.startpage.position === "center" &&
isMobile) ||
(settings.cfg.startpageType === "centered" &&
isMobile)
(settings.cfg.startpageType === "centered" && isMobile)
? "center"
: "none",
maxHeight: "120px",
overflow: "auto",
marginTop: "10px",
"&::-webkit-scrollbar": { width: 0 },
color:
settings.cfg.startpageType === "expanded"
? "white"
: theme.palette.text.primary,
color: settings.cfg.startpageType === "expanded" ? "white" : theme.palette.text.primary,
}}
>
{settings.cfg.info.law}

@ -18,13 +18,7 @@ import { useVKMetrics } from "@/utils/hooks/metrics/useVKMetrics";
import { ContactForm } from "@/components/ViewPublicationPage/ContactForm/ContactForm.tsx";
export default function ViewPublicationPage() {
const {
settings,
recentlyCompleted,
quizId,
preview,
changeFaviconAndTitle,
} = useQuizData();
const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizData();
const answers = useQuizViewStore((state) => state.answers);
let currentQuizStep = useQuizViewStore((state) => state.currentQuizStep);
const {
@ -40,9 +34,7 @@ export default function ViewPublicationPage() {
useYandexMetrics(settings?.cfg?.yandexMetricsNumber);
useVKMetrics(settings?.cfg?.vkMetricsNumber);
const isAnswer = answers.some(
(ans) => ans.questionId === currentQuestion?.id
);
const isAnswer = answers.some((ans) => ans.questionId === currentQuestion?.id);
useEffect(
function setFaviconAndTitle() {
@ -59,14 +51,11 @@ export default function ViewPublicationPage() {
);
if (recentlyCompleted) throw new Error("Quiz already completed");
if (currentQuizStep === "startpage" && settings.cfg.noStartPage)
currentQuizStep = "question";
if (currentQuizStep === "startpage" && settings.cfg.noStartPage) currentQuizStep = "question";
if (!currentQuestion)
return (
<ThemeProvider
theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}
>
<ThemeProvider theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}>
<Typography textAlign={"center"} mt="50px">
Вопрос не выбран
</Typography>
@ -91,10 +80,7 @@ export default function ViewPublicationPage() {
currentQuestion={currentQuestion}
currentQuestionStepNumber={currentQuestionStepNumber}
prevButton={
<PrevButton
isPreviousButtonEnabled={isPreviousButtonEnabled}
moveToPrevQuestion={moveToPrevQuestion}
/>
<PrevButton isPreviousButtonEnabled={isPreviousButtonEnabled} moveToPrevQuestion={moveToPrevQuestion} />
}
nextButton={
<NextButton
@ -116,23 +102,13 @@ export default function ViewPublicationPage() {
}}
/>
}
questionSelect={
<QuestionSelect
selectedQuestion={currentQuestion}
setQuestion={setQuestion}
/>
}
questionSelect={<QuestionSelect selectedQuestion={currentQuestion} setQuestion={setQuestion} />}
/>
);
break;
}
case "contactform": {
quizStepElement = (
<ContactForm
currentQuestion={currentQuestion}
onShowResult={showResultAfterContactForm}
/>
);
quizStepElement = <ContactForm currentQuestion={currentQuestion} onShowResult={showResultAfterContactForm} />;
break;
}
default:
@ -140,10 +116,6 @@ export default function ViewPublicationPage() {
}
return (
<ThemeProvider
theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}
>
{quizStepElement}
</ThemeProvider>
<ThemeProvider theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}>{quizStepElement}</ThemeProvider>
);
}

@ -25,9 +25,7 @@ export const Date = ({ currentQuestion }: DateProps) => {
const answers = useQuizViewStore((state) => state.answers);
const { updateAnswer } = useQuizViewStore((state) => state);
const theme = useTheme();
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer as string;
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string;
const currentAnswer = moment(answer) || moment();
const onDateChange = async (date: Moment | null) => {
@ -52,11 +50,7 @@ export const Date = ({ currentQuestion }: DateProps) => {
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<Box

@ -1,11 +1,4 @@
import {
Box,
FormControl,
FormControlLabel,
Radio,
Typography,
useTheme,
} from "@mui/material";
import { Box, FormControl, FormControlLabel, Radio, Typography, useTheme } from "@mui/material";
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
import { enqueueSnackbar } from "notistack";
@ -31,19 +24,12 @@ type EmojiVariantProps = {
setIsSending: (isSending: boolean) => void;
};
export const EmojiVariant = ({
currentQuestion,
variant,
index,
isSending,
setIsSending,
}: EmojiVariantProps) => {
export const EmojiVariant = ({ currentQuestion, variant, index, isSending, setIsSending }: EmojiVariantProps) => {
const { quizId, settings, preview } = useQuizData();
const answers = useQuizViewStore((state) => state.answers);
const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state);
const theme = useTheme();
const { answer } =
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const onVariantClick = async (event: MouseEvent<HTMLDivElement>) => {
event.preventDefault();
@ -54,9 +40,7 @@ export const EmojiVariant = ({
await sendAnswer({
questionId: currentQuestion.id,
body:
currentQuestion.content.variants[index].extendedText +
" " +
currentQuestion.content.variants[index].answer,
currentQuestion.content.variants[index].extendedText + " " + currentQuestion.content.variants[index].answer,
qid: quizId,
preview,
});
@ -94,8 +78,7 @@ export const EmojiVariant = ({
sx={{
borderRadius: "12px",
border: `1px solid`,
borderColor:
answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
overflow: "hidden",
maxWidth: "317px",
width: "100%",
@ -103,8 +86,7 @@ export const EmojiVariant = ({
background:
settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
? "rgba(255,255,255, 0.3)"
: (settings.cfg.design && quizThemes[settings.cfg.theme].isLight) ||
quizThemes[settings.cfg.theme].isLight
: (settings.cfg.design && quizThemes[settings.cfg.theme].isLight) || quizThemes[settings.cfg.theme].isLight
? "#FFFFFF"
: "transparent",
"&:hover": { borderColor: theme.palette.primary.main },
@ -128,9 +110,7 @@ export const EmojiVariant = ({
justifyContent: "center",
}}
>
{variant.extendedText && (
<Typography fontSize="100px">{variant.extendedText}</Typography>
)}
{variant.extendedText && <Typography fontSize="100px">{variant.extendedText}</Typography>}
</Box>
</Box>
<FormControlLabel
@ -168,9 +148,7 @@ export const EmojiVariant = ({
}
label={
<Box sx={{ display: "flex", gap: "10px" }}>
<Typography sx={{ wordBreak: "break-word", lineHeight: "normal" }}>
{variant.answer}
</Typography>
<Typography sx={{ wordBreak: "break-word", lineHeight: "normal" }}>{variant.answer}</Typography>
</Box>
}
/>

@ -18,23 +18,16 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
const answers = useQuizViewStore((state) => state.answers);
const { updateAnswer } = useQuizViewStore((state) => state);
const theme = useTheme();
const { answer } =
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<RadioGroup
name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex(
({ id }) => answer === id
)}
value={currentQuestion.content.variants.findIndex(({ id }) => answer === id)}
onChange={({ target }) =>
updateAnswer(
currentQuestion.id,
@ -50,9 +43,7 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
marginTop: "20px",
}}
>
<Box
sx={{ display: "flex", width: "100%", gap: "42px", flexWrap: "wrap" }}
>
<Box sx={{ display: "flex", width: "100%", gap: "42px", flexWrap: "wrap" }}>
{currentQuestion.content.variants.map((variant, index) => (
<EmojiVariant
key={variant.id}

@ -26,32 +26,24 @@ type UploadFileProps = {
setIsSending: (isSending: boolean) => void;
};
export const UploadFile = ({
currentQuestion,
setModalWarningType,
isSending,
setIsSending,
}: UploadFileProps) => {
export const UploadFile = ({ currentQuestion, setModalWarningType, isSending, setIsSending }: UploadFileProps) => {
const { quizId, preview } = useQuizData();
const [isDropzoneHighlighted, setIsDropzoneHighlighted] =
useState<boolean>(false);
const [isDropzoneHighlighted, setIsDropzoneHighlighted] = useState<boolean>(false);
const theme = useTheme();
const answers = useQuizViewStore((state) => state.answers);
const { updateAnswer } = useQuizViewStore((state) => state);
const isMobile = useRootContainerSize() < 500;
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer as string;
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string;
const uploadFile = async (file: File | undefined) => {
if (isSending) return;
if (!file) return;
if (file.size > MAX_FILE_SIZE) return setModalWarningType("errorSize");
const isFileTypeAccepted = ACCEPT_SEND_FILE_TYPES_MAP[
currentQuestion.content.type
].some((fileType) => file.name.toLowerCase().endsWith(fileType));
const isFileTypeAccepted = ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].some((fileType) =>
file.name.toLowerCase().endsWith(fileType)
);
if (!isFileTypeAccepted) return setModalWarningType("errorType");
@ -76,11 +68,7 @@ export const UploadFile = ({
preview,
});
updateAnswer(
currentQuestion.id,
`${file.name}|${URL.createObjectURL(file)}`,
0
);
updateAnswer(currentQuestion.id, `${file.name}|${URL.createObjectURL(file)}`, 0);
} catch (error) {
console.error(error);
enqueueSnackbar("ответ не был засчитан");
@ -101,28 +89,18 @@ export const UploadFile = ({
return (
<Box sx={{ display: "flex", alignItems: "center" }}>
{isSending ? (
<Skeleton
variant="rounded"
sx={{ width: "100%", height: "120px", maxWidth: "560px" }}
/>
<Skeleton variant="rounded" sx={{ width: "100%", height: "120px", maxWidth: "560px" }} />
) : (
<ButtonBase
component="label"
sx={{ justifyContent: "flex-start", width: "100%" }}
>
<ButtonBase component="label" sx={{ justifyContent: "flex-start", width: "100%" }}>
<input
onChange={({ target }) => uploadFile(target.files?.[0])}
hidden
accept={ACCEPT_SEND_FILE_TYPES_MAP[
currentQuestion.content.type
].join(",")}
accept={ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].join(",")}
multiple
type="file"
/>
<Box
onDragEnter={() =>
!answer?.split("|")[0] && setIsDropzoneHighlighted(true)
}
onDragEnter={() => !answer?.split("|")[0] && setIsDropzoneHighlighted(true)}
onDragLeave={() => setIsDropzoneHighlighted(false)}
onDragOver={(event) => event.preventDefault()}
onDrop={onDrop}
@ -142,10 +120,7 @@ export const UploadFile = ({
<UploadIcon />
<Box>
<Typography sx={{ color: "#9A9AAF", fontWeight: 500 }}>
{
UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type]
.title
}
{UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type].title}
</Typography>
<Typography
sx={{
@ -154,10 +129,7 @@ export const UploadFile = ({
lineHeight: "19px",
}}
>
{
UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type]
.description
}
{UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type].description}
</Typography>
</Box>
</Box>

@ -13,18 +13,13 @@ type UploadedFileProps = {
setIsSending: (isSending: boolean) => void;
};
export const UploadedFile = ({
currentQuestion,
setIsSending,
}: UploadedFileProps) => {
export const UploadedFile = ({ currentQuestion, setIsSending }: UploadedFileProps) => {
const { quizId, preview } = useQuizData();
const answers = useQuizViewStore((state) => state.answers);
const { updateAnswer } = useQuizViewStore((state) => state);
const theme = useTheme();
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer as string;
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string;
const deleteFile = async () => {
if (answer.length > 0) {

@ -11,14 +11,7 @@ import { ACCEPT_SEND_FILE_TYPES_MAP } from "@/components/ViewPublicationPage/too
import type { QuizQuestionFile } from "@model/questionTypes/file";
export type ModalWarningType =
| "errorType"
| "errorSize"
| "picture"
| "video"
| "audio"
| "document"
| null;
export type ModalWarningType = "errorType" | "errorSize" | "picture" | "video" | "audio" | "document" | null;
type FileProps = {
currentQuestion: QuizQuestionFile;
@ -27,22 +20,15 @@ type FileProps = {
export const File = ({ currentQuestion }: FileProps) => {
const theme = useTheme();
const answers = useQuizViewStore((state) => state.answers);
const [modalWarningType, setModalWarningType] =
useState<ModalWarningType>(null);
const [modalWarningType, setModalWarningType] = useState<ModalWarningType>(null);
const [isSending, setIsSending] = useState<boolean>(false);
const isMobile = useRootContainerSize() < 500;
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer as string;
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string;
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<Box
@ -55,10 +41,7 @@ export const File = ({ currentQuestion }: FileProps) => {
}}
>
{answer?.split("|")[0] ? (
<UploadedFile
currentQuestion={currentQuestion}
setIsSending={setIsSending}
/>
<UploadedFile currentQuestion={currentQuestion} setIsSending={setIsSending} />
) : (
<UploadFile
currentQuestion={currentQuestion}
@ -68,11 +51,7 @@ export const File = ({ currentQuestion }: FileProps) => {
/>
)}
{answer && currentQuestion.content.type === "picture" && (
<img
src={answer.split("|")[1]}
style={{ marginTop: "15px", maxWidth: "300px", maxHeight: "300px" }}
alt=""
/>
<img src={answer.split("|")[1]} style={{ marginTop: "15px", maxWidth: "300px", maxHeight: "300px" }} alt="" />
)}
{answer && currentQuestion.content.type === "video" && (
<video
@ -86,10 +65,7 @@ export const File = ({ currentQuestion }: FileProps) => {
/>
)}
</Box>
<Modal
open={modalWarningType !== null}
onClose={() => setModalWarningType(null)}
>
<Modal open={modalWarningType !== null} onClose={() => setModalWarningType(null)}>
<Box
sx={{
position: "absolute",
@ -117,17 +93,13 @@ const CurrentModal = ({ status }: { status: ModalWarningType }) => {
case "errorType":
return <Typography>Выбран некорректный тип файла</Typography>;
case "errorSize":
return (
<Typography>Файл слишком большой. Максимальный размер 50 МБ</Typography>
);
return <Typography>Файл слишком большой. Максимальный размер 50 МБ</Typography>;
default:
return (
<>
<Typography>Допустимые расширения файлов:</Typography>
<Typography>
{ACCEPT_SEND_FILE_TYPES_MAP[status].join(" ")}
</Typography>
<Typography>{ACCEPT_SEND_FILE_TYPES_MAP[status].join(" ")}</Typography>
</>
);
}

@ -21,21 +21,13 @@ type ImagesProps = {
index: number;
};
export const ImageVariant = ({
currentQuestion,
variant,
isSending,
setIsSending,
index,
}: ImagesProps) => {
export const ImageVariant = ({ currentQuestion, variant, isSending, setIsSending, index }: ImagesProps) => {
const { quizId, preview } = useQuizData();
const { settings } = useQuizData();
const answers = useQuizViewStore((state) => state.answers);
const { deleteAnswer, updateAnswer } = useQuizViewStore((state) => state);
const theme = useTheme();
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer;
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer;
const onVariantClick = async (event: MouseEvent<HTMLDivElement>) => {
event.preventDefault();
@ -81,14 +73,12 @@ export const ImageVariant = ({
cursor: "pointer",
borderRadius: "12px",
border: `1px solid`,
borderColor:
answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
"&:hover": { borderColor: theme.palette.primary.main },
background:
settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
? "rgba(255,255,255, 0.3)"
: (settings.cfg.design && quizThemes[settings.cfg.theme].isLight) ||
quizThemes[settings.cfg.theme].isLight
: (settings.cfg.design && quizThemes[settings.cfg.theme].isLight) || quizThemes[settings.cfg.theme].isLight
? "#FFFFFF"
: "transparent",
}}

@ -16,26 +16,18 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
const [isSending, setIsSending] = useState<boolean>(false);
const answers = useQuizViewStore((state) => state.answers);
const theme = useTheme();
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer;
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer;
const isTablet = useRootContainerSize() < 1000;
const isMobile = useRootContainerSize() < 500;
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<RadioGroup
name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex(
({ id }) => answer === id
)}
value={currentQuestion.content.variants.findIndex(({ id }) => answer === id)}
sx={{
display: "flex",
flexWrap: "wrap",
@ -48,11 +40,7 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
sx={{
display: "grid",
gap: "15px",
gridTemplateColumns: isTablet
? isMobile
? "repeat(1, 1fr)"
: "repeat(2, 1fr)"
: "repeat(3, 1fr)",
gridTemplateColumns: isTablet ? (isMobile ? "repeat(1, 1fr)" : "repeat(2, 1fr)") : "repeat(3, 1fr)",
width: "100%",
}}
>

@ -27,29 +27,22 @@ export const Number = ({ currentQuestion }: NumberProps) => {
const [maxRange, setMaxRange] = useState<string>("100000000000");
const [reversedInputValue, setReversedInputValue] = useState<string>("0");
const [reversedMinRange, setReversedMinRange] = useState<string>("0");
const [reversedMaxRange, setReversedMaxRange] =
useState<string>("100000000000");
const [reversedMaxRange, setReversedMaxRange] = useState<string>("100000000000");
const { settings, quizId, preview } = useQuizData();
const { updateAnswer } = useQuizViewStore((state) => state);
const answers = useQuizViewStore((state) => state.answers);
const theme = useTheme();
const [minBorder, maxBorder] = currentQuestion.content.range
.split("—")
.map(window.Number);
const [minBorder, maxBorder] = currentQuestion.content.range.split("—").map(window.Number);
const min = minBorder < maxBorder ? minBorder : maxBorder;
const max = minBorder < maxBorder ? maxBorder : minBorder;
const reversed = minBorder > maxBorder;
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer as string;
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string;
const sliderValue =
answer ||
(reversed
? max + min - currentQuestion.content.start + "—" + max
: currentQuestion.content.start + "—" + max);
(reversed ? max + min - currentQuestion.content.start + "—" + max : currentQuestion.content.start + "—" + max);
useEffect(() => {
console.log("reversed:", reversed);
@ -85,11 +78,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
: value;
setReversedInputValue(newValue);
updateAnswer(
currentQuestion.id,
String(max + min - window.Number(newValue)),
0
);
updateAnswer(currentQuestion.id, String(max + min - window.Number(newValue)), 0);
await sendAnswerToBackend(String(window.Number(newValue)), true);
return;
@ -106,8 +95,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
await sendAnswerToBackend(newValue);
}, 1000);
const updateMinRangeDebounced = useDebouncedCallback(
async (value: string, crowded = false) => {
const updateMinRangeDebounced = useDebouncedCallback(async (value: string, crowded = false) => {
if (reversed) {
const newMinRange = crowded
? window.Number(value.split("—")[1])
@ -115,23 +103,11 @@ export const Number = ({ currentQuestion }: NumberProps) => {
? min
: max + min - window.Number(value.split("—")[0]);
const newMinValue =
window.Number(value.split("—")[0]) > max
? String(max)
: value.split("—")[0];
const newMinValue = window.Number(value.split("—")[0]) > max ? String(max) : value.split("—")[0];
setReversedMinRange(
crowded ? String(max + min - window.Number(newMinValue)) : newMinValue
);
updateAnswer(
currentQuestion.id,
`${newMinRange}${value.split("—")[1]}`,
0
);
await sendAnswerToBackend(
`${newMinValue}${value.split("—")[1]}`,
true
);
setReversedMinRange(crowded ? String(max + min - window.Number(newMinValue)) : newMinValue);
updateAnswer(currentQuestion.id, `${newMinRange}${value.split("—")[1]}`, 0);
await sendAnswerToBackend(`${newMinValue}${value.split("—")[1]}`, true);
return;
}
@ -144,12 +120,9 @@ export const Number = ({ currentQuestion }: NumberProps) => {
setMinRange(newMinValue);
await sendAnswerToBackend(`${newMinValue}${value.split("—")[1]}`);
},
1000
);
}, 1000);
const updateMaxRangeDebounced = useDebouncedCallback(
async (value: string, crowded = false) => {
const updateMaxRangeDebounced = useDebouncedCallback(async (value: string, crowded = false) => {
if (reversed) {
const newMaxRange = crowded
? window.Number(value.split("—")[1])
@ -157,23 +130,11 @@ export const Number = ({ currentQuestion }: NumberProps) => {
? max
: max + min - window.Number(value.split("—")[1]);
const newMaxValue =
window.Number(value.split("—")[1]) < min
? String(min)
: value.split("—")[1];
const newMaxValue = window.Number(value.split("—")[1]) < min ? String(min) : value.split("—")[1];
setReversedMaxRange(
crowded ? String(max + min - window.Number(newMaxValue)) : newMaxValue
);
updateAnswer(
currentQuestion.id,
`${value.split("—")[0]}${newMaxRange}`,
0
);
await sendAnswerToBackend(
`${value.split("—")[0]}${newMaxValue}`,
true
);
setReversedMaxRange(crowded ? String(max + min - window.Number(newMaxValue)) : newMaxValue);
updateAnswer(currentQuestion.id, `${value.split("—")[0]}${newMaxRange}`, 0);
await sendAnswerToBackend(`${value.split("—")[0]}${newMaxValue}`, true);
return;
}
@ -186,20 +147,14 @@ export const Number = ({ currentQuestion }: NumberProps) => {
setMaxRange(newMaxValue);
await sendAnswerToBackend(`${value.split("—")[0]}${newMaxValue}`);
},
1000
);
}, 1000);
useEffect(() => {
if (answer) {
if (answer.includes("—")) {
if (reversed) {
setReversedMinRange(
String(max + min - window.Number(answer.split("—")[0]))
);
setReversedMaxRange(
String(max + min - window.Number(answer.split("—")[1]))
);
setReversedMinRange(String(max + min - window.Number(answer.split("—")[0])));
setReversedMaxRange(String(max + min - window.Number(answer.split("—")[1])));
} else {
setMinRange(answer.split("—")[0]);
setMaxRange(answer.split("—")[1]);
@ -228,17 +183,12 @@ export const Number = ({ currentQuestion }: NumberProps) => {
}, []);
const onSliderChange = (_: Event, value: number | number[]) => {
const range = Array.isArray(value)
? `${value[0]}${value[1]}`
: String(value);
const range = Array.isArray(value) ? `${value[0]}${value[1]}` : String(value);
updateAnswer(currentQuestion.id, range, 0);
};
const onChangeCommitted = async (
_: Event | SyntheticEvent<Element, Event>,
value: number | number[]
) => {
const onChangeCommitted = async (_: Event | SyntheticEvent<Element, Event>, value: number | number[]) => {
if (currentQuestion.content.chooseRange && Array.isArray(value)) {
if (reversed) {
const newMinReversedValue = String(max + min - value[0]);
@ -248,10 +198,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
setMaxRange(String(value[1]));
setReversedMinRange(newMinReversedValue);
setReversedMaxRange(newMaxReversedValue);
await sendAnswerToBackend(
`${newMinReversedValue}${newMaxReversedValue}`,
true
);
await sendAnswerToBackend(`${newMinReversedValue}${newMaxReversedValue}`, true);
return;
}
@ -277,9 +224,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
return value;
}
const [minSliderBorder, maxSliderBorder] = sliderValue
.split("—")
.map(window.Number);
const [minSliderBorder, maxSliderBorder] = sliderValue.split("—").map(window.Number);
if (value === minSliderBorder) {
return max + min - minSliderBorder;
@ -313,9 +258,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
return;
}
updateMinRangeDebounced(
`${newValue}${max + min - window.Number(reversedMaxRange)}`
);
updateMinRangeDebounced(`${newValue}${max + min - window.Number(reversedMaxRange)}`);
return;
}
@ -344,9 +287,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
return;
}
updateMaxRangeDebounced(
`${max + min - window.Number(reversedMinRange)}${newValue}`
);
updateMaxRangeDebounced(`${max + min - window.Number(reversedMinRange)}${newValue}`);
return;
}
@ -364,11 +305,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<Box
@ -417,9 +354,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
"& .MuiOutlinedInput-root": { background: "transparent" },
"& .MuiInputBase-input": { textAlign: "center", zIndex: 1 },
"& .MuiOutlinedInput-notchedOutline": {
backgroundColor: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
backgroundColor: quizThemes[settings.cfg.theme].isLight ? "white" : theme.palette.background.default,
borderColor: "#9A9AAF",
},
}}
@ -445,9 +380,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
"& .MuiOutlinedInput-root": { background: "transparent" },
"& .MuiInputBase-input": { textAlign: "center", zIndex: 1 },
"& .MuiOutlinedInput-notchedOutline": {
backgroundColor: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
backgroundColor: quizThemes[settings.cfg.theme].isLight ? "white" : theme.palette.background.default,
borderColor: "#9A9AAF",
},
}}
@ -462,9 +395,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
"& .MuiOutlinedInput-root": { background: "transparent" },
"& .MuiInputBase-input": { textAlign: "center", zIndex: 1 },
"& .MuiOutlinedInput-notchedOutline": {
backgroundColor: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
backgroundColor: quizThemes[settings.cfg.theme].isLight ? "white" : theme.palette.background.default,
borderColor: "#9A9AAF",
},
}}

@ -23,10 +23,7 @@ export const Page = ({ currentQuestion }: PageProps) => {
>
{currentQuestion.title}
</Typography>
<Typography
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.content.text}
</Typography>
<Box

@ -1,10 +1,5 @@
import { useState } from "react";
import {
Box,
Rating as RatingComponent,
Typography,
useTheme,
} from "@mui/material";
import { Box, Rating as RatingComponent, Typography, useTheme } from "@mui/material";
import { enqueueSnackbar } from "notistack";
import { sendAnswer } from "@api/quizRelase";
@ -25,45 +20,31 @@ import type { QuizQuestionRating } from "@model/questionTypes/rating";
const RATING_FORM_BUTTONS = [
{
name: "star",
icon: (color: string, width: number) => (
<StarIconMini width={width} color={color} />
),
icon: (color: string, width: number) => <StarIconMini width={width} color={color} />,
},
{
name: "trophie",
icon: (color: string, width: number) => (
<TropfyIcon width={width} color={color} />
),
icon: (color: string, width: number) => <TropfyIcon width={width} color={color} />,
},
{
name: "flag",
icon: (color: string, width: number) => (
<FlagIcon width={width} color={color} />
),
icon: (color: string, width: number) => <FlagIcon width={width} color={color} />,
},
{
name: "heart",
icon: (color: string, width: number) => (
<HeartIcon width={width} color={color} />
),
icon: (color: string, width: number) => <HeartIcon width={width} color={color} />,
},
{
name: "like",
icon: (color: string, width: number) => (
<LikeIcon width={width} color={color} />
),
icon: (color: string, width: number) => <LikeIcon width={width} color={color} />,
},
{
name: "bubble",
icon: (color: string, width: number) => (
<LightbulbIcon width={width} color={color} />
),
icon: (color: string, width: number) => <LightbulbIcon width={width} color={color} />,
},
{
name: "hashtag",
icon: (color: string, width: number) => (
<HashtagIcon width={width} color={color} />
),
icon: (color: string, width: number) => <HashtagIcon width={width} color={color} />,
},
];
@ -79,11 +60,8 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
const theme = useTheme();
const isMobile = useRootContainerSize() < 650;
const isTablet = useRootContainerSize() < 750;
const { answer } =
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const form = RATING_FORM_BUTTONS.find(
({ name }) => name === currentQuestion.content.form
);
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const form = RATING_FORM_BUTTONS.find(({ name }) => name === currentQuestion.content.form);
const sendRating = async (value: number | null) => {
setIsSending(true);
@ -106,11 +84,7 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<Box
@ -134,14 +108,8 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
"& .MuiRating-icon": { mr: isMobile ? undefined : "15px" },
}}
max={currentQuestion.content.steps}
icon={form?.icon(
theme.palette.primary.main,
isMobile ? 30 : isTablet ? 40 : 50
)}
emptyIcon={form?.icon(
"#9A9AAF",
isMobile ? 30 : isTablet ? 40 : 50
)}
icon={form?.icon(theme.palette.primary.main, isMobile ? 30 : isTablet ? 40 : 50)}
emptyIcon={form?.icon("#9A9AAF", isMobile ? 30 : isTablet ? 40 : 50)}
/>
</Box>
<Box
@ -152,12 +120,8 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
width: "100%",
}}
>
<Typography sx={{ color: "#9A9AAF" }}>
{currentQuestion.content.ratingNegativeDescription}
</Typography>
<Typography sx={{ color: "#9A9AAF" }}>
{currentQuestion.content.ratingPositiveDescription}
</Typography>
<Typography sx={{ color: "#9A9AAF" }}>{currentQuestion.content.ratingNegativeDescription}</Typography>
<Typography sx={{ color: "#9A9AAF" }}>{currentQuestion.content.ratingPositiveDescription}</Typography>
</Box>
</Box>
</Box>

@ -22,8 +22,7 @@ export const Select = ({ currentQuestion }: SelectProps) => {
const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state);
const answers = useQuizViewStore((state) => state.answers);
const theme = useTheme();
const { answer } =
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const sendSelectedAnswer = async (value: number) => {
setIsSending(true);
@ -63,11 +62,7 @@ export const Select = ({ currentQuestion }: SelectProps) => {
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<Box

@ -18,11 +18,7 @@ interface TextNormalProps {
stepNumber?: number | null;
}
export const TextNormal = ({
currentQuestion,
answer,
inputHC,
}: TextNormalProps) => {
export const TextNormal = ({ currentQuestion, answer, inputHC }: TextNormalProps) => {
const { settings } = useQuizData();
const { updateAnswer } = useQuizViewStore((state) => state);
const isMobile = useRootContainerSize() < 650;
@ -35,11 +31,7 @@ export const TextNormal = ({
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<Box
@ -67,8 +59,7 @@ export const TextNormal = ({
"&:focus-visible": { borderColor: theme.palette.primary.main },
}}
/>
{currentQuestion.content.back &&
currentQuestion.content.back !== " " && (
{currentQuestion.content.back && currentQuestion.content.back !== " " && (
<Box
sx={{
maxWidth: "400px",

@ -1,10 +1,4 @@
import {
Box,
TextField as MuiTextField,
TextFieldProps,
Typography,
useTheme,
} from "@mui/material";
import { Box, TextField as MuiTextField, TextFieldProps, Typography, useTheme } from "@mui/material";
import { Answer, useQuizViewStore } from "@stores/quizView";
import { useQuizData } from "@contexts/QuizDataContext";
@ -51,12 +45,7 @@ interface TextSpecialProps {
stepNumber?: number | null;
}
export const TextSpecial = ({
currentQuestion,
answer,
inputHC,
stepNumber,
}: TextSpecialProps) => {
export const TextSpecial = ({ currentQuestion, answer, inputHC, stepNumber }: TextSpecialProps) => {
const { settings } = useQuizData();
const { updateAnswer } = useQuizViewStore((state) => state);
const isHorizontal = ORIENTATION[Number(stepNumber) - 1].horizontal;
@ -86,16 +75,10 @@ export const TextSpecial = ({
gap: "20px",
}}
>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
{isHorizontal &&
currentQuestion.content.back &&
currentQuestion.content.back !== " " && (
{isHorizontal && currentQuestion.content.back && currentQuestion.content.back !== " " && (
<Box sx={{ margin: "30px", width: "50vw", maxHeight: "550px" }}>
<img
key={currentQuestion.id}
@ -124,9 +107,7 @@ export const TextSpecial = ({
sx={{
width: "100%",
"& .MuiOutlinedInput-root": {
backgroundColor: settings.cfg.design
? "rgba(154,154,175, 0.2)"
: "#FFFFFF",
backgroundColor: settings.cfg.design ? "rgba(154,154,175, 0.2)" : "#FFFFFF",
},
"&:focus-visible": {
borderColor: theme.palette.primary.main,
@ -135,9 +116,7 @@ export const TextSpecial = ({
/>
}
</Box>
{!isHorizontal &&
currentQuestion.content.back &&
currentQuestion.content.back !== " " && (
{!isHorizontal && currentQuestion.content.back && currentQuestion.content.back !== " " && (
<Box sx={{ margin: "15px", width: "40vw" }}>
<img
key={currentQuestion.id}

@ -21,8 +21,7 @@ export const Text = ({ currentQuestion, stepNumber }: TextProps) => {
const { settings, preview } = useQuizData();
const { quizId } = useQuizData();
const answers = useQuizViewStore((state) => state.answers);
const { answer } =
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const inputHC = useDebouncedCallback(async (text) => {
setIsSending(true);
@ -48,30 +47,13 @@ export const Text = ({ currentQuestion, stepNumber }: TextProps) => {
switch (settings.cfg.spec) {
case true:
return (
<TextSpecial
currentQuestion={currentQuestion}
answer={answer}
inputHC={inputHC}
stepNumber={stepNumber}
/>
<TextSpecial currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} stepNumber={stepNumber} />
);
case undefined:
return (
<TextNormal
currentQuestion={currentQuestion}
answer={answer}
inputHC={inputHC}
/>
);
return <TextNormal currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} />;
default:
return (
<TextNormal
currentQuestion={currentQuestion}
answer={answer}
inputHC={inputHC}
/>
);
return <TextNormal currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} />;
}
};

@ -1,11 +1,4 @@
import {
Checkbox,
FormControlLabel,
TextField as MuiTextField,
Radio,
TextFieldProps,
useTheme,
} from "@mui/material";
import { Checkbox, FormControlLabel, TextField as MuiTextField, Radio, TextFieldProps, useTheme } from "@mui/material";
import { enqueueSnackbar } from "notistack";
import { sendAnswer } from "@api/quizRelase";
@ -96,9 +89,7 @@ export const VariantItem = ({
updateAnswer(
currentQuestion.id,
variantId,
answer === variantId
? 0
: currentQuestion.content.variants[index].points || 0
answer === variantId ? 0 : currentQuestion.content.variants[index].points || 0
);
} catch (error) {
console.error(error);
@ -133,8 +124,7 @@ export const VariantItem = ({
color: theme.palette.text.primary,
padding: "15px",
border: `1px solid`,
borderColor:
answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
backgroundColor: settings.cfg.design
? quizThemes[settings.cfg.theme].isLight
? "#FFFFFF"
@ -167,16 +157,11 @@ export const VariantItem = ({
currentQuestion.content.multi ? (
<Checkbox
checked={!!answer?.includes(variant.id)}
checkedIcon={
<CheckboxIcon checked color={theme.palette.primary.main} />
}
checkedIcon={<CheckboxIcon checked color={theme.palette.primary.main} />}
icon={<CheckboxIcon />}
/>
) : (
<Radio
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
icon={<RadioIcon />}
/>
<Radio checkedIcon={<RadioCheck color={theme.palette.primary.main} />} icon={<RadioIcon />} />
)
}
label={own ? <TextField label="Другое..." /> : variant.answer}

@ -1,11 +1,5 @@
import { useEffect, useState } from "react";
import {
Box,
FormGroup,
RadioGroup,
Typography,
useTheme,
} from "@mui/material";
import { Box, FormGroup, RadioGroup, Typography, useTheme } from "@mui/material";
import { VariantItem } from "./VariantItem";
@ -26,11 +20,8 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
const theme = useTheme();
const isMobile = useRootContainerSize() < 650;
const { answer } =
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const ownVariant = ownVariants.find(
(variant) => variant.id === currentQuestion.id
);
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const ownVariant = ownVariants.find((variant) => variant.id === currentQuestion.id);
const Group = currentQuestion.content.multi ? FormGroup : RadioGroup;
@ -44,11 +35,7 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<Box
@ -61,9 +48,7 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
>
<Group
name={currentQuestion.id.toString()}
value={currentQuestion.content.variants.findIndex(
({ id }) => answer === id
)}
value={currentQuestion.content.variants.findIndex(({ id }) => answer === id)}
sx={{
display: "flex",
flexWrap: "wrap",
@ -107,8 +92,7 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
)}
</Box>
</Group>
{currentQuestion.content.back &&
currentQuestion.content.back !== " " && (
{currentQuestion.content.back && currentQuestion.content.back !== " " && (
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px" }}>
<img
key={currentQuestion.id}

@ -23,21 +23,14 @@ type VarimgVariantProps = {
setIsSending: (isSending: boolean) => void;
};
export const VarimgVariant = ({
currentQuestion,
variant,
index,
isSending,
setIsSending,
}: VarimgVariantProps) => {
export const VarimgVariant = ({ currentQuestion, variant, index, isSending, setIsSending }: VarimgVariantProps) => {
const { settings, quizId, preview } = useQuizData();
const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state);
const answers = useQuizViewStore((state) => state.answers);
const theme = useTheme();
const { answer } =
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const sendVariant = async (event: MouseEvent<HTMLLabelElement>) => {
event.preventDefault();
@ -96,8 +89,7 @@ export const VarimgVariant = ({
? "white"
: theme.palette.background.default,
border: `1px solid`,
borderColor:
answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
display: "flex",
margin: 0,
justifyContent: "space-between",
@ -118,12 +110,7 @@ export const VarimgVariant = ({
value={index}
onClick={sendVariant}
label={variant.answer}
control={
<Radio
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
icon={<RadioIcon />}
/>
}
control={<Radio checkedIcon={<RadioCheck color={theme.palette.primary.main} />} icon={<RadioIcon />} />}
/>
);
};

@ -21,19 +21,12 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
const theme = useTheme();
const isMobile = useRootContainerSize() < 650;
const { answer } =
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const variant = currentQuestion.content.variants.find(
({ id }) => answer === id
);
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const variant = currentQuestion.content.variants.find(({ id }) => answer === id);
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title}
</Typography>
<Box
@ -47,9 +40,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
>
<RadioGroup
name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex(
({ id }) => answer === id
)}
value={currentQuestion.content.variants.findIndex(({ id }) => answer === id)}
sx={{
display: "flex",
flexWrap: "wrap",
@ -116,8 +107,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
style={{ width: "100%", height: "100%", objectFit: "cover" }}
alt=""
/>
) : currentQuestion.content.replText !== " " &&
currentQuestion.content.replText.length > 0 ? (
) : currentQuestion.content.replText !== " " && currentQuestion.content.replText.length > 0 ? (
currentQuestion.content.replText
) : variant?.extendedText || isMobile ? (
"Выберите вариант ответа ниже"

@ -3,8 +3,8 @@ import { quizThemes } from "@utils/themes/Publication/themePublication";
import { useQuizData } from "@contexts/QuizDataContext";
interface Props {
isNextButtonEnabled: boolean,
moveToNextQuestion: () => void,
isNextButtonEnabled: boolean;
moveToNextQuestion: () => void;
}
export default function NextButton({ isNextButtonEnabled, moveToNextQuestion }: Props) {
@ -18,11 +18,12 @@ export default function NextButton ({isNextButtonEnabled, moveToNextQuestion}: P
fontSize: "16px",
padding: "10px 15px",
"&:disabled": {
background: quizThemes[settings.cfg.theme].isLight ? "#F2F3F7" : "#FFFFFF26"
background: quizThemes[settings.cfg.theme].isLight ? "#F2F3F7" : "#FFFFFF26",
},
}}
onClick={moveToNextQuestion}
>
Далее
</Button>
)}
);
}

@ -4,8 +4,8 @@ import { quizThemes } from "@utils/themes/Publication/themePublication";
import { useQuizData } from "@contexts/QuizDataContext";
interface Props {
isPreviousButtonEnabled: boolean,
moveToPrevQuestion: () => void,
isPreviousButtonEnabled: boolean;
moveToPrevQuestion: () => void;
}
export default function PrevButton({ isPreviousButtonEnabled, moveToPrevQuestion }: Props) {
@ -21,14 +21,16 @@ export default function PrevButton({ isPreviousButtonEnabled, moveToPrevQuestion
fontSize: "16px",
padding: "10px 15px",
color: quizThemes[settings.cfg.theme].isLight ? theme.palette.primary.main : "#FFFFFF",
border: quizThemes[settings.cfg.theme].isLight ? `1px solid ${theme.palette.primary.main}` : "1px solid #9A9AAF",
border: quizThemes[settings.cfg.theme].isLight
? `1px solid ${theme.palette.primary.main}`
: "1px solid #9A9AAF",
background: quizThemes[settings.cfg.theme].isLight ? "#FFFFFF" : "#FFFFFF26",
"&:hover": {
color: "#FFFFFF",
border: `1px solid ${theme.palette.primary.dark}`,
},
"&:disabled": {
background: quizThemes[settings.cfg.theme].isLight ? "#F2F3F7" : "#FFFFFF26"
background: quizThemes[settings.cfg.theme].isLight ? "#F2F3F7" : "#FFFFFF26",
},
}}
onClick={moveToPrevQuestion}

@ -1,11 +1,5 @@
import { useState, useEffect } from "react";
import {
Select as MuiSelect,
MenuItem,
FormControl,
Typography,
useTheme,
} from "@mui/material";
import { Select as MuiSelect, MenuItem, FormControl, Typography, useTheme } from "@mui/material";
import ArrowDown from "@icons/ArrowDownIcon";
@ -34,9 +28,7 @@ export const Select = ({
colorPlaceholder = "#9A9AAF",
disabled = false,
}: SelectProps) => {
const [activeItem, setActiveItem] = useState<number>(
empty ? -1 : activeItemIndex
);
const [activeItem, setActiveItem] = useState<number>(empty ? -1 : activeItemIndex);
const theme = useTheme();
useEffect(() => {
@ -58,22 +50,11 @@ export const Select = ({
};
return (
<FormControl
disabled={disabled}
fullWidth
size="small"
sx={{ width: "100%", height: "48px", ...sx }}
>
<FormControl disabled={disabled} fullWidth size="small" sx={{ width: "100%", height: "48px", ...sx }}>
<MuiSelect
displayEmpty
renderValue={(value) =>
value ? (
items[Number(value)]
) : (
<Typography sx={{ color: colorPlaceholder }}>
{placeholder}
</Typography>
)
value ? items[Number(value)] : <Typography sx={{ color: colorPlaceholder }}>{placeholder}</Typography>
}
id="display-select"
variant="outlined"
@ -88,8 +69,8 @@ export const Select = ({
borderRadius: "10px",
},
"& .MuiSelect-icon": {
color: theme.palette.primary.main
}
color: theme.palette.primary.main,
},
}}
MenuProps={{
PaperProps: {

@ -2,15 +2,16 @@ import { QuizQuestionResult } from "@model/questionTypes/result";
export const isResultQuestionEmpty = (resultQuestion: QuizQuestionResult) => {
if (
(resultQuestion.title.length > 0 && resultQuestion.title !== " ")
|| (resultQuestion.description.length > 0 && resultQuestion.description !== " ")
|| (resultQuestion.content.back.length > 0 && resultQuestion.content.back !== " ")
|| (resultQuestion.content.originalBack.length > 0 && resultQuestion.content.originalBack !== " ")
|| (resultQuestion.content.innerName.length > 0 && resultQuestion.content.innerName !== " ")
|| (resultQuestion.content.text.length > 0 && resultQuestion.content.text !== " ")
|| (resultQuestion.content.video.length > 0 && resultQuestion.content.video !== " ")
|| (resultQuestion.content.hint.text.length > 0 && resultQuestion.content.hint.text !== " ")
) return false;
(resultQuestion.title.length > 0 && resultQuestion.title !== " ") ||
(resultQuestion.description.length > 0 && resultQuestion.description !== " ") ||
(resultQuestion.content.back.length > 0 && resultQuestion.content.back !== " ") ||
(resultQuestion.content.originalBack.length > 0 && resultQuestion.content.originalBack !== " ") ||
(resultQuestion.content.innerName.length > 0 && resultQuestion.content.innerName !== " ") ||
(resultQuestion.content.text.length > 0 && resultQuestion.content.text !== " ") ||
(resultQuestion.content.video.length > 0 && resultQuestion.content.video !== " ") ||
(resultQuestion.content.hint.text.length > 0 && resultQuestion.content.hint.text !== " ")
)
return false;
return true;
};

@ -1,6 +1,5 @@
import { UploadFileType } from "@model/questionTypes/file";
export const MAX_FILE_SIZE = 419430400;
export const UPLOAD_FILE_DESCRIPTIONS_MAP = {
@ -14,56 +13,11 @@ export const UPLOAD_FILE_DESCRIPTIONS_MAP = {
},
audio: { title: "Добавить аудиофайл", description: "Принимает аудиофайлы" },
document: { title: "Добавить документ", description: "Принимает документы" },
} as const satisfies Record<UploadFileType, { title: string; description: string; }>;
} as const satisfies Record<UploadFileType, { title: string; description: string }>;
export const ACCEPT_SEND_FILE_TYPES_MAP = {
picture: [
".jpeg",
".jpg",
".png",
".ico",
".gif",
".tiff",
".webp",
".eps",
".svg"
],
video: [
".mp4",
".mov",
".wmv",
".avi",
".avchd",
".flv",
".f4v",
".swf",
".mkv",
".webm",
".mpeg-2"
],
audio: [
".aac",
".aiff",
".dsd",
".flac",
".mp3",
".mqa",
".ogg",
".wav",
".wma"
],
document: [
".doc",
".docx",
".dotx",
".rtf",
".odt",
".pdf",
".txt",
".xls",
".ppt",
".xlsx",
".pptx",
".pages",
],
picture: [".jpeg", ".jpg", ".png", ".ico", ".gif", ".tiff", ".webp", ".eps", ".svg"],
video: [".mp4", ".mov", ".wmv", ".avi", ".avchd", ".flv", ".f4v", ".swf", ".mkv", ".webm", ".mpeg-2"],
audio: [".aac", ".aiff", ".dsd", ".flac", ".mp3", ".mqa", ".ogg", ".wav", ".wma"],
document: [".doc", ".docx", ".dotx", ".rtf", ".odt", ".pdf", ".txt", ".xls", ".ppt", ".xlsx", ".pptx", ".pages"],
} as const;

@ -11,11 +11,7 @@ export const replaceSpacesToEmptyLines = <T = unknown>(object: T): T => {
for (const [key, value] of Object.entries(object)) {
if (typeof value === "string") {
result[key] = value.replace(
"squiz.pena.digital",
"storage.yandexcloud.net"
);
result[key] = value.replace("squiz.pena.digital", "storage.yandexcloud.net");
continue;
}

@ -1,6 +1,5 @@
import { createContext, useContext } from "react";
export const RootContainerWidthContext = createContext<number | null>(null);
export const useRootContainerSize = () => {

@ -36,7 +36,7 @@ export function parseQuizData(quizDataResponse: GetQuizDataResponse): Omit<QuizS
required: item.req,
title: item.title,
type: item.typ,
content
content,
} as unknown as AnyTypedQuizQuestion;
});
@ -48,7 +48,7 @@ export function parseQuizData(quizDataResponse: GetQuizDataResponse): Omit<QuizS
lim: quizDataResponse.settings.lim,
due: quizDataResponse.settings.due,
delay: quizDataResponse.settings.delay,
pausable: quizDataResponse.settings.pausable
pausable: quizDataResponse.settings.pausable,
};
return { cnt: quizDataResponse.cnt, settings, questions: items, show_badge: quizDataResponse.show_badge };

@ -1,8 +1 @@
export type MetricsMessengers =
| "telegram"
| "viber"
| "whatsapp"
| "vkontakte"
| "messenger"
| "skype"
| "instagram";
export type MetricsMessengers = "telegram" | "viber" | "whatsapp" | "vkontakte" | "messenger" | "skype" | "instagram";

@ -1,8 +1,4 @@
import type {
QuizQuestionBase,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionHint, QuestionBranchingRule } from "./shared";
export interface QuizQuestionDate extends QuizQuestionBase {
type: "date";

@ -1,9 +1,4 @@
import type {
QuizQuestionBase,
QuestionVariant,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionVariant, QuestionHint, QuestionBranchingRule } from "./shared";
export interface QuizQuestionEmoji extends QuizQuestionBase {
type: "emoji";

@ -1,8 +1,4 @@
import type {
QuizQuestionBase,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionHint, QuestionBranchingRule } from "./shared";
export const UPLOAD_FILE_TYPES_MAP = {
picture: "Изображения",

@ -1,9 +1,4 @@
import type {
QuestionHint,
QuestionVariant,
QuizQuestionBase,
QuestionBranchingRule,
} from "./shared";
import type { QuestionHint, QuestionVariant, QuizQuestionBase, QuestionBranchingRule } from "./shared";
export interface QuizQuestionImages extends QuizQuestionBase {
type: "images";

@ -1,8 +1,4 @@
import type {
QuizQuestionBase,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionHint, QuestionBranchingRule } from "./shared";
export interface QuizQuestionNumber extends QuizQuestionBase {
type: "number";

@ -1,8 +1,4 @@
import type {
QuizQuestionBase,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionHint, QuestionBranchingRule } from "./shared";
export interface QuizQuestionPage extends QuizQuestionBase {
type: "page";

@ -1,8 +1,4 @@
import type {
QuizQuestionBase,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionHint, QuestionBranchingRule } from "./shared";
export interface QuizQuestionRating extends QuizQuestionBase {
type: "rating";

@ -1,11 +1,7 @@
import type {
QuizQuestionBase,
QuestionBranchingRule,
QuestionHint,
} from "./shared";
import type { QuizQuestionBase, QuestionBranchingRule, QuestionHint } from "./shared";
interface ResultQuestionBranchingRule extends QuestionBranchingRule {
minScore?: number
minScore?: number;
}
export interface QuizQuestionResult extends QuizQuestionBase {
type: "result";
@ -18,9 +14,9 @@ export interface QuizQuestionResult extends QuizQuestionBase {
text: string;
price: [number] | [number, number];
useImage: boolean;
rule: ResultQuestionBranchingRule,
rule: ResultQuestionBranchingRule;
hint: QuestionHint;
autofill: boolean;
redirect: string
redirect: string;
};
}

@ -1,9 +1,4 @@
import type {
QuizQuestionBase,
QuestionVariant,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionVariant, QuestionHint, QuestionBranchingRule } from "./shared";
export interface QuizQuestionSelect extends QuizQuestionBase {
type: "select";

@ -103,19 +103,25 @@ export type AnyTypedQuizQuestion =
export type RealTypedQuizQuestion = Exclude<AnyTypedQuizQuestion, QuizQuestionResult>;
type FilterQuestionsWithVariants<T> = T extends {
content: { variants: QuestionVariant[]; };
} ? T : never;
content: { variants: QuestionVariant[] };
}
? T
: never;
export type QuizQuestionsWithVariants = FilterQuestionsWithVariants<AnyTypedQuizQuestion>;
export const createBranchingRuleMain: (targetId: string, parentId: string) => QuestionBranchingRuleMain = (targetId, parentId) => ({
export const createBranchingRuleMain: (targetId: string, parentId: string) => QuestionBranchingRuleMain = (
targetId,
parentId
) => ({
next: targetId,
or: false,
rules: [{
rules: [
{
question: parentId,
answers: [] as string[],
}]
},
],
});
export const createQuestionVariant: () => QuestionVariant = () => ({

@ -1,8 +1,4 @@
import type {
QuizQuestionBase,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionHint, QuestionBranchingRule } from "./shared";
export interface QuizQuestionText extends QuizQuestionBase {
type: "text";

@ -1,9 +1,4 @@
import type {
QuizQuestionBase,
QuestionVariant,
QuestionHint,
QuestionBranchingRule,
} from "./shared";
import type { QuizQuestionBase, QuestionVariant, QuestionHint, QuestionBranchingRule } from "./shared";
export interface QuizQuestionVariant extends QuizQuestionBase {
type: "variant";

@ -1,9 +1,4 @@
import type {
QuestionHint,
QuestionVariant,
QuizQuestionBase,
QuestionBranchingRule,
} from "./shared";
import type { QuestionHint, QuestionVariant, QuizQuestionBase, QuestionBranchingRule } from "./shared";
export interface QuizQuestionVarImg extends QuizQuestionBase {
type: "varimg";

@ -50,7 +50,7 @@ export type QuizSettingsConfig = {
delay: number;
pausable: boolean;
cfg: QuizConfig;
}
};
export type QuizSettings = {
questions: AnyTypedQuizQuestion[];
@ -114,12 +114,7 @@ export interface QuizConfig {
vkMetricsNumber: number | undefined;
}
export type FormContactFieldName =
| "name"
| "email"
| "phone"
| "text"
| "address";
export type FormContactFieldName = "name" | "email" | "phone" | "text" | "address";
export type FormContactFieldData = {
text: string;

@ -2,7 +2,7 @@ export interface BannerWidgetComponentProps {
quizId: string;
position: "topleft" | "topright" | "bottomleft" | "bottomright";
onWidgetClose?: () => void;
dialogDimensions?: { width: string; height: string; };
dialogDimensions?: { width: string; height: string };
appealText?: string;
quizHeaderText?: string;
buttonTextColor?: string;

@ -1,7 +1,7 @@
export interface ButtonWidgetComponentProps {
quizId: string;
fixedSide?: "left" | "right";
dialogDimensions?: { width: string; height: string; };
dialogDimensions?: { width: string; height: string };
/**
* Открыть квиз через X секунд, 0 - сразу, null - не открывать
*/

@ -3,7 +3,7 @@ import { ButtonWidgetComponentProps } from "./button";
export type ContainerWidgetComponentProps = ButtonWidgetComponentProps & {
quizId: string;
showButtonOnMobile?: boolean;
dimensions?: { width: string; height: string; };
dimensions?: { width: string; height: string };
};
export type ContainerWidgetParams = ContainerWidgetComponentProps & {

@ -1,6 +1,6 @@
export interface PopupWidgetComponentProps {
quizId: string;
dialogDimensions?: { width: string; height: string; };
dialogDimensions?: { width: string; height: string };
/**
* Открыть квиз через X секунд, 0 - сразу, null - не открывать
*/

@ -3,7 +3,7 @@ export interface SideWidgetComponentProps {
position: "left" | "right";
buttonBackgroundColor?: string;
buttonTextColor?: string;
dialogDimensions?: { width: string; height: string; };
dialogDimensions?: { width: string; height: string };
fullScreen?: boolean;
buttonFlash?: boolean;
/**

@ -10,7 +10,7 @@ export type Answer = string | string[] | Moment;
type QuestionAnswer = {
questionId: string;
answer: Answer
answer: Answer;
};
type OwnVariant = {
@ -43,17 +43,17 @@ export function useQuizViewStore<U>(selector: (state: QuizViewStore & QuizViewAc
return useStore(store, selector);
}
export const createQuizViewStore = () => createStore<QuizViewStore & QuizViewActions>()(
immer(
(set, get) => ({
export const createQuizViewStore = () =>
createStore<QuizViewStore & QuizViewActions>()(
immer((set, get) => ({
answers: [],
ownVariants: [],
points: {},
pointsSum: 0,
currentQuizStep: "startpage",
updateAnswer(questionId, answer, points) {
set(state => {
const index = state.answers.findIndex(answer => questionId === answer.questionId);
set((state) => {
const index = state.answers.findIndex((answer) => questionId === answer.questionId);
if (index < 0) {
state.answers.push({ questionId, answer });
@ -67,12 +67,12 @@ export const createQuizViewStore = () => createStore<QuizViewStore & QuizViewAct
});
},
deleteAnswer(questionId) {
set(state => {
state.answers = state.answers.filter(answer => questionId !== answer.questionId);
set((state) => {
state.answers = state.answers.filter((answer) => questionId !== answer.questionId);
});
},
updateOwnVariant(id, answer) {
set(state => {
set((state) => {
const index = state.ownVariants.findIndex((variant) => variant.id === id);
if (index < 0) {
@ -92,13 +92,12 @@ export const createQuizViewStore = () => createStore<QuizViewStore & QuizViewAct
});
},
deleteOwnVariant(id) {
set(state => {
set((state) => {
state.ownVariants = state.ownVariants.filter((variant) => variant.id !== id);
});
},
setCurrentQuizStep(step) {
set({ currentQuizStep: step });
},
})
)
}))
);

@ -15,7 +15,6 @@ interface Props {
}
export default function CustomCheckbox({ label, handleChange, checked, sx, dataCy, colorIcon }: Props) {
return (
<FormControlLabel
control={

@ -10,10 +10,7 @@ type CustomSliderProps = {
step?: number;
sx?: SxProps<Theme>;
onChange?: (_: Event, value: number | number[]) => void;
onChangeCommitted?: (
_: React.SyntheticEvent | Event,
value: number | number[]
) => void;
onChangeCommitted?: (_: React.SyntheticEvent | Event, value: number | number[]) => void;
valueLabelFormat?: (value: number, index: number) => ReactNode;
};

@ -4,7 +4,6 @@ import type { InputProps, TextFieldProps } from "@mui/material";
import type { ChangeEvent, FC, FocusEvent, KeyboardEvent } from "react";
import { Answer } from "@stores/quizView.ts";
const TextField = MuiTextField as unknown as FC<TextFieldProps>; // temporary fix ts(2590)
interface CustomTextFieldProps {

@ -1,8 +1,6 @@
import { Skeleton } from "@mui/material";
export default function LoadingSkeleton() {
return (
<Skeleton
component="div"

@ -8,7 +8,6 @@ export default function RadioCheck({ color = "#7E2AEA" }: Props) {
return (
<Box
sx={{
height: "26px",
width: "26px",

@ -1,12 +1,10 @@
import { Box, useTheme } from "@mui/material";
export default function RadioIcon() {
const theme = useTheme();
return (
<Box
sx={{
height: "26px",
width: "26px",

@ -6,11 +6,12 @@ let domain = "https://hbpn.link";
const currentDomain = location.hostname;
if (
currentDomain === "s.hbpn.link"
currentDomain === "s.hbpn.link" ||
//Исключение - туризм. Он на стейджинговом квизе и на чужом для публикации домене
|| currentDomain === "tourism.pena.digital"
|| currentDomain.includes("localhost")
|| currentDomain.includes("127.0.0.1")
) domain = "https://s.hbpn.link";
currentDomain === "tourism.pena.digital" ||
currentDomain.includes("localhost") ||
currentDomain.includes("127.0.0.1")
)
domain = "https://s.hbpn.link";
export { domain };

@ -1,7 +1,6 @@
import type { QuizTheme } from "@model/settingsData";
import { domain } from "./defineDomain";
export const DESIGN_LIST: Record<QuizTheme, string> = {
Design1: `${domain}/designs/design1.jpg`,
Design2: `${domain}/designs/design2.jpg`,

@ -1,6 +1,5 @@
import { ErrorInfo } from "react";
interface ComponentError {
timestamp: number;
message: string;

@ -2,11 +2,7 @@ import { useEffect } from "react";
export const useVKMetrics = (vkMetricsNumber: number | undefined) => {
useEffect(() => {
if (
vkMetricsNumber &&
typeof vkMetricsNumber === "number" &&
!Number.isNaN(vkMetricsNumber)
) {
if (vkMetricsNumber && typeof vkMetricsNumber === "number" && !Number.isNaN(vkMetricsNumber)) {
const script = document.createElement("script");
script.type = "text/javascript";
script.innerHTML = `

Some files were not shown because too many files have changed in this diff Show More