fix: endless errors(WIP)

This commit is contained in:
IlyaDoronin 2023-10-03 17:03:57 +03:00
parent 6f21c992a6
commit ade9e25d5f
50 changed files with 960 additions and 783 deletions

16
src/constants/base.ts Normal file

@ -0,0 +1,16 @@
import type { QuizQuestionBase } from "../model/questionTypes/shared";
export const QUIZ_QUESTION_BASE: Omit<QuizQuestionBase, "id"> = {
title: "",
type: "",
expanded: false,
required: false,
content: {
hint: {
text: "",
video: "",
},
back: "",
autofill: false,
},
};

@ -1,9 +1,12 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionDate } from "../model/questionTypes/date"; import type { QuizQuestionDate } from "../model/questionTypes/date";
export const QuizQuestionDateEmpty: Omit<QuizQuestionDate, "id"> = { export const QUIZ_QUESTION_DATE: Omit<QuizQuestionDate, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "date", type: "date",
content: { content: {
...QUIZ_QUESTION_BASE.content,
required: false, required: false,
innerNameCheck: false, innerNameCheck: false,
innerName: "", innerName: "",

@ -1,9 +1,12 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionEmoji } from "../model/questionTypes/emoji"; import type { QuizQuestionEmoji } from "../model/questionTypes/emoji";
export const QuizQuestionEmojiEmpty: Omit<QuizQuestionEmoji, "id"> = { export const QUIZ_QUESTION_EMOJI: Omit<QuizQuestionEmoji, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "emoji", type: "emoji",
content: { content: {
...QUIZ_QUESTION_BASE.content,
multi: false, multi: false,
own: false, own: false,
innerNameCheck: false, innerNameCheck: false,
@ -13,7 +16,7 @@ export const QuizQuestionEmojiEmpty: Omit<QuizQuestionEmoji, "id"> = {
{ {
answer: "", answer: "",
hints: "", hints: "",
emoji: "", extendedText: "",
}, },
], ],
hint: { hint: {

@ -1,13 +1,15 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionFile } from "../model/questionTypes/file"; import type { QuizQuestionFile } from "../model/questionTypes/file";
export const QuizQuestionFileEmpty: Omit<QuizQuestionFile, "id"> = { export const QUIZ_QUESTION_FILE: Omit<QuizQuestionFile, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "file", type: "file",
content: { content: {
...QUIZ_QUESTION_BASE.content,
required: false, required: false,
innerNameCheck: false, innerNameCheck: false,
innerName: "", innerName: "",
autofill: false,
type: "all", type: "all",
hint: { hint: {
text: "", text: "",

@ -1,9 +1,12 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionImages } from "../model/questionTypes/images"; import type { QuizQuestionImages } from "../model/questionTypes/images";
export const QuizQuestionImagesEmpty: Omit<QuizQuestionImages, "id"> = { export const QUIZ_QUESTION_IMAGES: Omit<QuizQuestionImages, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "images", type: "images",
content: { content: {
...QUIZ_QUESTION_BASE.content,
own: false, own: false,
multi: false, multi: false,
xy: "1:1", xy: "1:1",
@ -16,6 +19,7 @@ export const QuizQuestionImagesEmpty: Omit<QuizQuestionImages, "id"> = {
{ {
answer: "", answer: "",
hints: "", hints: "",
extendedText: "",
}, },
], ],
hint: { hint: {
@ -32,5 +36,6 @@ export const QuizQuestionImagesEmpty: Omit<QuizQuestionImages, "id"> = {
}, },
], ],
}, },
largeCheck: false,
}, },
}; };

@ -1,15 +1,20 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionNumber } from "../model/questionTypes/number"; import type { QuizQuestionNumber } from "../model/questionTypes/number";
export const QuizQuestionNumberEmpty: Omit<QuizQuestionNumber, "id"> = { export const QUIZ_QUESTION_NUMBER: Omit<QuizQuestionNumber, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "number", type: "number",
content: { content: {
...QUIZ_QUESTION_BASE.content,
required: false, required: false,
innerNameCheck: false, innerNameCheck: false,
innerName: "", innerName: "",
range: [0, 1], range: "",
defaultValue: 0, defaultValue: 0,
step: 1, step: 1,
steps: 5,
start: 50,
chooseRange: false, chooseRange: false,
hint: { hint: {
text: "", text: "",
@ -25,5 +30,6 @@ export const QuizQuestionNumberEmpty: Omit<QuizQuestionNumber, "id"> = {
}, },
], ],
}, },
form: "star",
}, },
}; };

@ -1,9 +1,12 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionPage } from "../model/questionTypes/page"; import type { QuizQuestionPage } from "../model/questionTypes/page";
export const QuizQuestionPageEmpty: Omit<QuizQuestionPage, "id"> = { export const QUIZ_QUESTION_PAGE: Omit<QuizQuestionPage, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "page", type: "page",
content: { content: {
...QUIZ_QUESTION_BASE.content,
innerNameCheck: false, innerNameCheck: false,
innerName: "", innerName: "",
text: "", text: "",

@ -1,9 +1,12 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionRating } from "../model/questionTypes/rating"; import type { QuizQuestionRating } from "../model/questionTypes/rating";
export const QuizQuestionRatingEmpty: Omit<QuizQuestionRating, "id"> = { export const QUIZ_QUESTION_RATING: Omit<QuizQuestionRating, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "rating", type: "rating",
content: { content: {
...QUIZ_QUESTION_BASE.content,
required: false, required: false,
innerNameCheck: false, innerNameCheck: false,
innerName: "", innerName: "",

@ -1,9 +1,12 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionSelect } from "../model/questionTypes/select"; import type { QuizQuestionSelect } from "../model/questionTypes/select";
export const QuizQuestionSelectEmpty: Omit<QuizQuestionSelect, "id"> = { export const QUIZ_QUESTION_SELECT: Omit<QuizQuestionSelect, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "select", type: "select",
content: { content: {
...QUIZ_QUESTION_BASE.content,
multi: false, multi: false,
required: false, required: false,
innerNameCheck: false, innerNameCheck: false,

@ -1,14 +1,16 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionText } from "../model/questionTypes/text"; import type { QuizQuestionText } from "../model/questionTypes/text";
export const QuizQuestionTextEmpty: Omit<QuizQuestionText, "id"> = { export const QUIZ_QUESTION_TEXT: Omit<QuizQuestionText, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "text", type: "text",
content: { content: {
...QUIZ_QUESTION_BASE.content,
placeholder: "", placeholder: "",
innerNameCheck: false, innerNameCheck: false,
innerName: "", innerName: "",
required: false, required: false,
autofill: false,
answerType: "single", answerType: "single",
hint: { hint: {
text: "", text: "",

@ -1,21 +1,19 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionVariant } from "../model/questionTypes/variant"; import type { QuizQuestionVariant } from "../model/questionTypes/variant";
export const QuizQuestionVariantEmpty: Omit<QuizQuestionVariant, "id"> = { export const QUIZ_QUESTION_VARIANT: Omit<QuizQuestionVariant, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "variant", type: "variant",
content: { content: {
...QUIZ_QUESTION_BASE.content,
largeCheck: false, largeCheck: false,
multi: false, multi: false,
own: false, own: false,
innerNameCheck: false, innerNameCheck: false,
required: false, required: false,
innerName: "", innerName: "",
variants: [ variants: [{ answer: "", hints: "", extendedText: "" }],
{
answer: "",
hints: "",
},
],
hint: { hint: {
text: "", text: "",
video: "", video: "",

@ -1,19 +1,17 @@
import { QUIZ_QUESTION_BASE } from "./base";
import type { QuizQuestionVarImg } from "../model/questionTypes/varimg"; import type { QuizQuestionVarImg } from "../model/questionTypes/varimg";
export const QuizQuestionVarImgEmpty: Omit<QuizQuestionVarImg, "id"> = { export const QUIZ_QUESTION_VARIMG: Omit<QuizQuestionVarImg, "id"> = {
title: "", ...QUIZ_QUESTION_BASE,
type: "varimg", type: "varimg",
content: { content: {
...QUIZ_QUESTION_BASE.content,
own: false, own: false,
innerNameCheck: false, innerNameCheck: false,
innerName: "", innerName: "",
required: false, required: false,
variants: [ variants: [{ answer: "", hints: "", extendedText: "" }],
{
answer: "",
hints: "",
},
],
hint: { hint: {
text: "", text: "",
video: "", video: "",
@ -28,5 +26,7 @@ export const QuizQuestionVarImgEmpty: Omit<QuizQuestionVarImg, "id"> = {
}, },
], ],
}, },
largeCheck: false,
replText: "",
}, },
}; };

@ -1,19 +1,24 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
} from "./shared";
export interface QuizQuestionDate extends QuizQuestionBase { export interface QuizQuestionDate extends QuizQuestionBase {
type: "date"; type: "date";
content: { content: {
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
type: "calendar" | "mask"; type: "calendar" | "mask";
dateRange: boolean; dateRange: boolean;
time: boolean; time: boolean;
hint: QuizQuestionHint; hint: QuizQuestionHint;
rule: QuizQuestionBranchingRules; rule: QuizQuestionBranchingRules;
}; back: string;
autofill: boolean;
};
} }

@ -1,25 +1,27 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
Variant,
} from "./shared";
export interface QuizQuestionEmoji extends QuizQuestionBase { export interface QuizQuestionEmoji extends QuizQuestionBase {
type: "emoji"; type: "emoji";
content: { content: {
/** Чекбокс "Можно несколько" */ /** Чекбокс "Можно несколько" */
multi: boolean; multi: boolean;
/** Чекбокс "Вариант "свой ответ"" */ /** Чекбокс "Вариант "свой ответ"" */
own: boolean; own: boolean;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
variants: { variants: Variant[];
answer: string; hint: QuizQuestionHint;
hints: string; rule: QuizQuestionBranchingRules;
emoji: string; back: string;
}[]; autofill: boolean;
hint: QuizQuestionHint; };
rule: QuizQuestionBranchingRules;
};
} }

@ -1,29 +1,33 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
} from "./shared";
export const uploadFileTypesMap = { export const uploadFileTypesMap = {
"all": "Все типы файлов", all: "Все типы файлов",
"picture": "Изображения", picture: "Изображения",
"video": "Видео", video: "Видео",
"audio": "Аудио", audio: "Аудио",
"document": "Документ", document: "Документ",
} as const; } as const;
export type UploadFileType = keyof typeof uploadFileTypesMap; export type UploadFileType = keyof typeof uploadFileTypesMap;
export interface QuizQuestionFile extends QuizQuestionBase { export interface QuizQuestionFile extends QuizQuestionBase {
type: "file"; type: "file";
content: { content: {
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
/** Чекбокс "Автозаполнение адреса" */ /** Чекбокс "Автозаполнение адреса" */
autofill: boolean; autofill: boolean;
type: UploadFileType; type: UploadFileType;
hint: QuizQuestionHint; hint: QuizQuestionHint;
rule: QuizQuestionBranchingRules; rule: QuizQuestionBranchingRules;
}; back: string;
};
} }

@ -1,31 +1,35 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
Variant,
} from "./shared";
export interface QuizQuestionImages extends QuizQuestionBase { export interface QuizQuestionImages extends QuizQuestionBase {
type: "images"; type: "images";
content: { content: {
/** Чекбокс "Вариант "свой ответ"" */ /** Чекбокс "Вариант "свой ответ"" */
own: boolean; own: boolean;
/** Чекбокс "Можно несколько" */ /** Чекбокс "Можно несколько" */
multi: boolean; multi: boolean;
/** Пропорции */ /** Пропорции */
xy: "1:1" | "1:2" | "2:1"; xy: "1:1" | "1:2" | "2:1";
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
/** Чекбокс "Большие картинки" */ /** Чекбокс "Большие картинки" */
large: boolean; large: boolean;
/** Форма */ /** Форма */
format: "carousel" | "masonry"; format: "carousel" | "masonry";
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
/** Варианты (картинки) */ /** Варианты (картинки) */
variants: { variants: Variant[];
answer: string; hint: QuizQuestionHint;
hints: string; rule: QuizQuestionBranchingRules;
}[]; back: string;
hint: QuizQuestionHint; autofill: boolean;
rule: QuizQuestionBranchingRules; largeCheck: boolean;
}; };
} }

@ -1,24 +1,33 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
} from "./shared";
export interface QuizQuestionNumber extends QuizQuestionBase { export interface QuizQuestionNumber extends QuizQuestionBase {
type: "number"; type: "number";
content: { content: {
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
/** Диапазон */ /** Диапазон */
range: [number, number]; range: string;
/** Начальное значение */ /** Начальное значение */
defaultValue: number; start: number;
/** Шаг */ /** Начальное значение */
step: number; defaultValue: number;
/** Чекбокс "Выбор диапазона (два ползунка)" */ /** Шаг */
chooseRange: boolean; step: number;
hint: QuizQuestionHint; steps: number;
rule: QuizQuestionBranchingRules; /** Чекбокс "Выбор диапазона (два ползунка)" */
}; chooseRange: boolean;
hint: QuizQuestionHint;
rule: QuizQuestionBranchingRules;
back: string;
autofill: boolean;
form: "star" | "trophie" | "flag" | "heart" | "like" | "bubble" | "hashtag";
};
} }

@ -1,16 +1,21 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
} from "./shared";
export interface QuizQuestionPage extends QuizQuestionBase { export interface QuizQuestionPage extends QuizQuestionBase {
type: "page"; type: "page";
content: { content: {
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
text: string; text: string;
video: string; video: string;
hint: QuizQuestionHint; hint: QuizQuestionHint;
rule: QuizQuestionBranchingRules; rule: QuizQuestionBranchingRules;
}; back: string;
autofill: boolean;
};
} }

@ -1,21 +1,26 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
} from "./shared";
export interface QuizQuestionRating extends QuizQuestionBase { export interface QuizQuestionRating extends QuizQuestionBase {
type: "rating"; type: "rating";
content: { content: {
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
steps: number; steps: number;
ratingExpanded: boolean; ratingExpanded: boolean;
ratingDescription: string; ratingDescription: string;
/** Форма иконки */ /** Форма иконки */
form: string; form: string;
hint: QuizQuestionHint; hint: QuizQuestionHint;
rule: QuizQuestionBranchingRules; rule: QuizQuestionBranchingRules;
}; back: string;
autofill: boolean;
};
} }

@ -1,20 +1,27 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
Variant,
} from "./shared";
export interface QuizQuestionSelect extends QuizQuestionBase { export interface QuizQuestionSelect extends QuizQuestionBase {
type: "select"; type: "select";
content: { content: {
/** Чекбокс "Можно несколько" */ /** Чекбокс "Можно несколько" */
multi: boolean; multi: boolean;
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
/** Поле "Текст в выпадающем списке" */ /** Поле "Текст в выпадающем списке" */
default: string; default: string;
hint: QuizQuestionHint; hint: QuizQuestionHint;
rule: QuizQuestionBranchingRules; rule: QuizQuestionBranchingRules;
}; variants: Variant[];
back: string;
autofill: boolean;
};
} }

@ -10,41 +10,60 @@ import type { QuizQuestionText } from "./text";
import type { QuizQuestionVariant } from "./variant"; import type { QuizQuestionVariant } from "./variant";
import type { QuizQuestionVarImg } from "./varimg"; import type { QuizQuestionVarImg } from "./varimg";
export interface QuizQuestionBranchingRules { export interface QuizQuestionBranchingRules {
/** Радиокнопка "Все условия обязательны" */ /** Радиокнопка "Все условия обязательны" */
or: boolean; or: boolean;
show: boolean; show: boolean;
reqs: { reqs: {
id: string; id: string;
/** Список выбранных вариантов */ /** Список выбранных вариантов */
vars: number[]; vars: number[];
}[]; }[];
} }
export interface QuizQuestionHint { export interface QuizQuestionHint {
/** Текст подсказки */ /** Текст подсказки */
text: string; text: string;
/** URL видео подсказки */ /** URL видео подсказки */
video: string; video: string;
} }
export type Variant = {
answer: string;
hints: string;
extendedText: string;
};
export type Hint = {
text: string;
video: string;
};
export interface QuizQuestionBase { export interface QuizQuestionBase {
id: number; id: number;
title: string; title: string;
type: string;
expanded: boolean;
required: boolean;
content: {
hint: Hint;
back: string;
autofill: boolean;
};
} }
export type AnyQuizQuestion = export type AnyQuizQuestion =
| QuizQuestionVariant | QuizQuestionVariant
| QuizQuestionImages | QuizQuestionImages
| QuizQuestionVarImg | QuizQuestionVarImg
| QuizQuestionEmoji | QuizQuestionEmoji
| QuizQuestionText | QuizQuestionText
| QuizQuestionSelect | QuizQuestionSelect
| QuizQuestionDate | QuizQuestionDate
| QuizQuestionNumber | QuizQuestionNumber
| QuizQuestionFile | QuizQuestionFile
| QuizQuestionPage | QuizQuestionPage
| QuizQuestionRating; | QuizQuestionRating
| QuizQuestionBase;
export type QuizQuestionType = AnyQuizQuestion["type"]; export type QuizQuestionType = AnyQuizQuestion["type"];

@ -1,20 +1,24 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
} from "./shared";
export interface QuizQuestionText extends QuizQuestionBase { export interface QuizQuestionText extends QuizQuestionBase {
type: "text"; type: "text";
content: { content: {
placeholder: string; placeholder: string;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
/** Чекбокс "Автозаполнение адреса" */ /** Чекбокс "Автозаполнение адреса" */
autofill: boolean; autofill: boolean;
answerType: "single" | "multi" | "number"; answerType: "single" | "multi" | "number";
hint: QuizQuestionHint; hint: QuizQuestionHint;
rule: QuizQuestionBranchingRules; rule: QuizQuestionBranchingRules;
}; back: string;
};
} }

@ -1,27 +1,30 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
Variant,
} from "./shared";
export interface QuizQuestionVariant extends QuizQuestionBase { export interface QuizQuestionVariant extends QuizQuestionBase {
type: "variant"; type: "variant";
content: { content: {
/** Чекбокс "Длинный текстовый ответ" */ /** Чекбокс "Длинный текстовый ответ" */
largeCheck: boolean; largeCheck: boolean;
/** Чекбокс "Можно несколько" */ /** Чекбокс "Можно несколько" */
multi: boolean; multi: boolean;
/** Чекбокс "Вариант "свой ответ"" */ /** Чекбокс "Вариант "свой ответ"" */
own: boolean; own: boolean;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
/** Варианты ответов */ /** Варианты ответов */
variants: { variants: Variant[];
answer: string; hint: QuizQuestionHint;
hints: string; rule: QuizQuestionBranchingRules;
}[]; back: string;
hint: QuizQuestionHint; autofill: boolean;
rule: QuizQuestionBranchingRules; };
};
} }

@ -1,19 +1,27 @@
import { QuizQuestionBase, QuizQuestionBranchingRules, QuizQuestionHint } from "./shared"; import type {
QuizQuestionBase,
QuizQuestionBranchingRules,
QuizQuestionHint,
Variant,
} from "./shared";
export interface QuizQuestionVarImg extends QuizQuestionBase { export interface QuizQuestionVarImg extends QuizQuestionBase {
type: "varimg"; type: "varimg";
content: { content: {
/** Чекбокс "Вариант "свой ответ"" */ /** Чекбокс "Вариант "свой ответ"" */
own: boolean; own: boolean;
/** Чекбокс "Внутреннее название вопроса" */ /** Чекбокс "Внутреннее название вопроса" */
innerNameCheck: boolean; innerNameCheck: boolean;
/** Поле "Внутреннее название вопроса" */ /** Поле "Внутреннее название вопроса" */
innerName: string; innerName: string;
/** Чекбокс "Необязательный вопрос" */ /** Чекбокс "Необязательный вопрос" */
required: boolean; required: boolean;
variants: unknown; variants: Variant[];
hint: QuizQuestionHint; hint: QuizQuestionHint;
rule: QuizQuestionBranchingRules; rule: QuizQuestionBranchingRules;
}; back: string;
autofill: boolean;
largeCheck: boolean;
replText: string;
};
} }

@ -12,6 +12,8 @@ import CustomTextField from "@ui_kit/CustomTextField";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import { questionStore, updateQuestionsList } from "@root/questions"; import { questionStore, updateQuestionsList } from "@root/questions";
import type { QuizQuestionDate } from "../../../model/questionTypes/date";
type SettingsDataProps = { type SettingsDataProps = {
totalIndex: number; totalIndex: number;
}; };
@ -22,11 +24,11 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
const theme = useTheme(); const theme = useTheme();
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const question = listQuestions[quizId][totalIndex] as QuizQuestionDate;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerName = value; content: { ...question.content, innerName: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
return ( return (
@ -42,21 +44,21 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Выбор диапазона дат"} label={"Выбор диапазона дат"}
checked={listQuestions[quizId][totalIndex].content.dateRange} checked={question.content.dateRange}
handleChange={({ target }) => { handleChange={({ target }) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.dateRange = target.checked; content: { ...question.content, dateRange: target.checked },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Выбор времени"} label={"Выбор времени"}
checked={listQuestions[quizId][totalIndex].content.time} checked={question.content.time}
handleChange={({ target }) => { handleChange={({ target }) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.time = target.checked; content: { ...question.content, time: target.checked },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
</Box> </Box>
@ -73,27 +75,32 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!listQuestions[quizId][totalIndex].required} checked={!question.required}
handleChange={(e) => { handleChange={({ target }) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
required: !e.target.checked, required: !target.checked,
}); });
}} }}
/> />
<Box sx={{ width: isMobile ? "93%" : "auto", display: "flex", alignItems: "center" }}> <Box
sx={{
width: isMobile ? "93%" : "auto",
display: "flex",
alignItems: "center",
}}
>
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerNameCheck = e.target.checked; content: {
...question.content,
if (!e.target.checked) { innerNameCheck: target.checked,
clonContent.innerName = ""; innerName: target.checked ? question.content.innerName : "",
} },
});
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}} }}
/> />
<Tooltip <Tooltip
@ -105,10 +112,10 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Развёрнутое описание вопроса"} placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -16,11 +16,14 @@ import {
import { import {
questionStore, questionStore,
updateQuestionsList, updateQuestionsList,
removeQuestion,
createQuestion,
DEFAULT_QUESTION, DEFAULT_QUESTION,
} from "@root/questions"; } from "@root/questions";
import { BUTTON_TYPE_QUESTIONS } from "../TypeQuestions"; import { BUTTON_TYPE_QUESTIONS } from "../TypeQuestions";
import type { RefObject } from "react"; import type { RefObject } from "react";
import type { QuizQuestionType } from "../../../model/questionTypes/shared";
type ChooseAnswerModalProps = { type ChooseAnswerModalProps = {
open: boolean; open: boolean;
@ -36,7 +39,7 @@ export const ChooseAnswerModal = ({
totalIndex, totalIndex,
}: ChooseAnswerModalProps) => { }: ChooseAnswerModalProps) => {
const [openModal, setOpenModal] = useState<boolean>(false); const [openModal, setOpenModal] = useState<boolean>(false);
const [selectedValue, setSelectedValue] = useState<string>(""); const [selectedValue, setSelectedValue] = useState<QuizQuestionType>("text");
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
@ -110,10 +113,11 @@ export const ChooseAnswerModal = ({
setOpenModal(false); setOpenModal(false);
const question = listQuestions[quizId][totalIndex]; const question = listQuestions[quizId][totalIndex];
removeQuestion(quizId, totalIndex);
createQuestion(quizId, selectedValue, totalIndex);
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
...DEFAULT_QUESTION,
expanded: question.expanded, expanded: question.expanded,
type: selectedValue,
}); });
}} }}
> >

@ -338,7 +338,7 @@ export default function QuestionsPageCard({
}} }}
> >
<Box <Box
onClick={() => createQuestion(quizId, totalIndex + 1)} onClick={() => createQuestion(quizId, "", totalIndex + 1)}
sx={{ sx={{
display: plusVisible && !isDragging ? "flex" : "none", display: plusVisible && !isDragging ? "flex" : "none",
width: "100%", width: "100%",

@ -9,6 +9,8 @@ import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
import SwitchDropDown from "./switchDropDown"; import SwitchDropDown from "./switchDropDown";
import ButtonsOptions from "../ButtonsOptions"; import ButtonsOptions from "../ButtonsOptions";
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
} }
@ -19,21 +21,18 @@ export default function DropDown({ totalIndex }: Props) {
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const variants = listQuestions[quizId][totalIndex].content.variants; const question = listQuestions[quizId][totalIndex] as QuizQuestionSelect;
const SSHC = (data: string) => { const SSHC = (data: string) => {
setSwitchState(data); setSwitchState(data);
}; };
const addNewAnswer = () => { const addNewAnswer = () => {
const answerNew = variants.slice(); const answerNew = question.content.variants.slice();
answerNew.push({ answer: "", hints: "", emoji: "" }); answerNew.push({ answer: "", hints: "", extendedText: "" });
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, variants: answerNew },
...listQuestions[quizId][totalIndex].content,
variants: answerNew,
},
}); });
}; };
@ -44,7 +43,7 @@ export default function DropDown({ totalIndex }: Props) {
padding: isMobile ? "15px 20px 20px 20px" : "20px 20px 20px 20px ", padding: isMobile ? "15px 20px 20px 20px" : "20px 20px 20px 20px ",
}} }}
> >
{variants.length === 0 ? ( {question.content.variants.length === 0 ? (
<Typography <Typography
sx={{ sx={{
padding: "0 0 33px 80px", padding: "0 0 33px 80px",
@ -57,7 +56,10 @@ export default function DropDown({ totalIndex }: Props) {
Добавьте ответ Добавьте ответ
</Typography> </Typography>
) : ( ) : (
<AnswerDraggableList variants={variants} totalIndex={totalIndex} /> <AnswerDraggableList
variants={question.content.variants}
totalIndex={totalIndex}
/>
)} )}
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}> <Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
<Link <Link

@ -8,6 +8,8 @@ import { questionStore, updateQuestionsList } from "@root/questions";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
type SettingDropDownProps = { type SettingDropDownProps = {
totalIndex: number; totalIndex: number;
}; };
@ -17,17 +19,17 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const question = listQuestions[quizId][totalIndex] as QuizQuestionSelect;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerName = value; content: { ...question.content, innerName: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
const debounceAnswer = useDebouncedCallback((value) => { const debounceAnswer = useDebouncedCallback((value) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.default = value; content: { ...question.content, default: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
return ( return (
@ -52,13 +54,10 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
</Typography> </Typography>
<CustomCheckbox <CustomCheckbox
label={"Можно несколько"} label={"Можно несколько"}
checked={listQuestions[quizId][totalIndex].content.multi} checked={question.content.multi}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, multi: target.checked },
...listQuestions[quizId][totalIndex].content,
multi: target.checked,
},
}) })
} }
/> />
@ -69,7 +68,7 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
<CustomTextField <CustomTextField
sx={{ maxWidth: "360px" }} sx={{ maxWidth: "360px" }}
placeholder={"Выберите вариант"} placeholder={"Выберите вариант"}
text={listQuestions[quizId][totalIndex].content.default} text={question.content.default}
onChange={({ target }) => debounceAnswer(target.value)} onChange={({ target }) => debounceAnswer(target.value)}
/> />
</Box> </Box>
@ -80,7 +79,7 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
</Typography> </Typography>
<CustomCheckbox <CustomCheckbox
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!listQuestions[quizId][totalIndex].required} checked={!question.required}
handleChange={(e) => { handleChange={(e) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
required: !e.target.checked, required: !e.target.checked,
@ -92,17 +91,14 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
> >
<CustomCheckbox <CustomCheckbox
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.innerNameCheck = e.target.checked;
if (!e.target.checked) {
clonContent.innerName = "";
}
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: {
...question.content,
innerNameCheck: target.checked,
innerName: target.checked ? question.content.innerName : "",
},
}); });
}} }}
/> />
@ -126,14 +122,14 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
</Typography> </Typography>
<CustomTextField <CustomTextField
placeholder={"Выберите вариант"} placeholder={"Выберите вариант"}
text={listQuestions[quizId][totalIndex].content.default} text={question.content.default}
onChange={({ target }) => debounceAnswer(target.value)} onChange={({ target }) => debounceAnswer(target.value)}
/> />
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Развёрнутое описание вопроса"} placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -40,7 +40,7 @@ export default function Emoji({ totalIndex }: Props) {
sx={{ color: theme.palette.brightPurple.main }} sx={{ color: theme.palette.brightPurple.main }}
onClick={() => { onClick={() => {
const answerNew = question.content.variants.slice(); const answerNew = question.content.variants.slice();
answerNew.push({ answer: "", hints: "", emoji: "" }); answerNew.push({ answer: "", hints: "", extendedText: "" });
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: {

@ -12,6 +12,8 @@ import CustomTextField from "@ui_kit/CustomTextField";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import { questionStore, updateQuestionsList } from "@root/questions"; import { questionStore, updateQuestionsList } from "@root/questions";
import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji";
type SettingEmojiProps = { type SettingEmojiProps = {
totalIndex: number; totalIndex: number;
}; };
@ -22,10 +24,11 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
const theme = useTheme(); const theme = useTheme();
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const question = listQuestions[quizId][totalIndex] as QuizQuestionEmoji;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerName = value; content: { ...question.content, innerName: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
return ( return (
@ -41,21 +44,21 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Можно несколько"} label={"Можно несколько"}
checked={listQuestions[quizId][totalIndex].content.multi} checked={question.content.multi}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.multi = e.target.checked; content: { ...question.content, multi: target.checked },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={'Вариант "свой ответ"'} label={'Вариант "свой ответ"'}
checked={listQuestions[quizId][totalIndex].content.own} checked={question.content.own}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.own = e.target.checked; content: { ...question.content, own: target },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
</Box> </Box>
@ -72,27 +75,32 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!listQuestions[quizId][totalIndex].required} checked={!question.required}
handleChange={(e) => { handleChange={(e) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
required: !e.target.checked, required: !e.target.checked,
}); });
}} }}
/> />
<Box sx={{ width: isMobile ? "90%" : "auto", display: "flex", alignItems: "center" }}> <Box
sx={{
width: isMobile ? "90%" : "auto",
display: "flex",
alignItems: "center",
}}
>
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerNameCheck = e.target.checked; content: {
...question.content,
if (!e.target.checked) { innerNameCheck: target.checked,
clonContent.innerName = ""; innerName: target.checked ? question.content.innerName : "",
} },
});
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}} }}
/> />
<Tooltip <Tooltip
@ -104,10 +112,10 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Развёрнутое описание вопроса"} placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -23,6 +23,8 @@ import PointsIcon from "@icons/questionsPage/PointsIcon";
import MessageIcon from "@icons/messagIcon"; import MessageIcon from "@icons/messagIcon";
import DeleteIcon from "@icons/questionsPage/deleteIcon"; import DeleteIcon from "@icons/questionsPage/deleteIcon";
import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
} }
@ -34,6 +36,7 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(1000)); const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const question = listQuestions[quizId][totalIndex] as QuizQuestionVarImg;
const SSHC = (data: string) => { const SSHC = (data: string) => {
setSwitchState(data); setSwitchState(data);
@ -43,54 +46,51 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
<> <>
<Box sx={{ padding: "20px" }}> <Box sx={{ padding: "20px" }}>
<Box sx={{ paddingBottom: "25px" }}> <Box sx={{ paddingBottom: "25px" }}>
{listQuestions[quizId][totalIndex].content.variants.map( {question.content.variants.map((_, index) => (
(_, index) => ( <ButtonBase
<ButtonBase key={index}
key={index} component="label"
component="label" sx={{
display: isTablet ? "none" : "flex",
cursor: "pointer",
alignItems: "center",
justifyContent: "flex-start",
marginBottom: "15px",
}}
>
<input
onChange={({ target }) => {
if (target.files?.length) {
const clonContent = { ...question.content };
clonContent.variants[index].answer = URL.createObjectURL(
target.files[0]
);
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}
}}
hidden
accept="image/*"
multiple
type="file"
/>
<AddImage />
<Typography
sx={{ sx={{
display: isTablet ? "none" : "flex", padding: "0 0 0 20px",
cursor: "pointer", fontWeight: 400,
alignItems: "center", fontSize: "18px",
justifyContent: "flex-start", lineHeight: "21.33px",
marginBottom: "15px", color: theme.palette.grey2.main,
}} }}
> >
<input Добавьте ответ
onChange={({ target }) => { </Typography>
if (target.files?.length) { </ButtonBase>
const clonContent = ))}
listQuestions[quizId][totalIndex].content;
clonContent.variants[index].answer = URL.createObjectURL(
target.files[0]
);
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}
}}
hidden
accept="image/*"
multiple
type="file"
/>
<AddImage />
<Typography
sx={{
padding: "0 0 0 20px",
fontWeight: 400,
fontSize: "18px",
lineHeight: "21.33px",
color: theme.palette.grey2.main,
}}
>
Добавьте ответ
</Typography>
</ButtonBase>
)
)}
<Box <Box
sx={{ sx={{
width: "100%", width: "100%",
@ -103,7 +103,7 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
fullWidth fullWidth
focused={false} focused={false}
placeholder={"Добавьте ответ"} placeholder={"Добавьте ответ"}
multiline={listQuestions[quizId][totalIndex].content.largeCheck} multiline={question.content.largeCheck}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
<> <>
@ -196,9 +196,8 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
variant="body2" variant="body2"
sx={{ color: theme.palette.brightPurple.main }} sx={{ color: theme.palette.brightPurple.main }}
onClick={() => { onClick={() => {
const clonContent = listQuestions[quizId][totalIndex].content; const clonContent = { ...question.content };
clonContent.variants.push({ answer: "", hints: "", emoji: "" }); clonContent.variants.push({ answer: "", hints: "", extendedText: "" });
updateQuestionsList(quizId, totalIndex, { content: clonContent }); updateQuestionsList(quizId, totalIndex, { content: clonContent });
}} }}
> >

@ -13,6 +13,8 @@ import InfoIcon from "../../../assets/icons/InfoIcon";
import { questionStore, updateQuestionsList } from "@root/questions"; import { questionStore, updateQuestionsList } from "@root/questions";
import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
type SettingOptionsAndPictProps = { type SettingOptionsAndPictProps = {
totalIndex: number; totalIndex: number;
}; };
@ -25,19 +27,15 @@ export default function SettingOptionsAndPict({
const theme = useTheme(); const theme = useTheme();
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(680)); const isMobile = useMediaQuery(theme.breakpoints.down(680));
const question = listQuestions[quizId][totalIndex] as QuizQuestionVarImg;
const debounced = useDebouncedCallback((replText) => { const debounced = useDebouncedCallback((replText) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, replText },
...listQuestions[quizId][totalIndex].content,
replText,
},
}); });
}, 1000); }, 1000);
const debounceDescription = useDebouncedCallback((value) => { const debounceDescription = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.innerName = value;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: { ...question.content, innerName: value },
}); });
}, 1000); }, 1000);
@ -51,20 +49,24 @@ export default function SettingOptionsAndPict({
flexDirection: isWrappColumn ? "column" : null, flexDirection: isWrappColumn ? "column" : null,
}} }}
> >
<Box sx={{ pt: "20px", pb: "20px", pl: "20px", width: isMobile ? "85%" : "100%" }}> <Box
sx={{
pt: "20px",
pb: "20px",
pl: "20px",
width: isMobile ? "85%" : "100%",
}}
>
<Typography sx={{ marginBottom: "15px" }}> <Typography sx={{ marginBottom: "15px" }}>
Настройки ответов Настройки ответов
</Typography> </Typography>
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={'Вариант "свой ответ"'} label={'Вариант "свой ответ"'}
checked={listQuestions[quizId][totalIndex].content.own} checked={question.content.own}
handleChange={({ target }) => { handleChange={({ target }) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, own: target.checked },
...listQuestions[quizId][totalIndex].content,
own: target.checked,
},
}); });
}} }}
/> />
@ -74,9 +76,13 @@ export default function SettingOptionsAndPict({
Текст-заглушка на картинке Текст-заглушка на картинке
</Typography> </Typography>
<CustomTextField <CustomTextField
sx={{ maxWidth: "330px", width: "100%", mr: isMobile ? "0px" : "16px" }} sx={{
maxWidth: "330px",
width: "100%",
mr: isMobile ? "0px" : "16px",
}}
placeholder={"Пример текста"} placeholder={"Пример текста"}
text={listQuestions[quizId][totalIndex].content.replText} text={question.content.replText}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
</> </>
@ -94,27 +100,27 @@ export default function SettingOptionsAndPict({
Настройки вопросов Настройки вопросов
</Typography> </Typography>
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={listQuestions[quizId][totalIndex].content.required} checked={question.content.required}
handleChange={({ target }) => { handleChange={({ target }) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, required: target.checked },
...listQuestions[quizId][totalIndex].content,
required: target.checked,
},
}); });
}} }}
/> />
<Box sx={{ display: "flex", alignItems: "center" }}> <Box sx={{ display: "flex", alignItems: "center" }}>
<CustomCheckbox <CustomCheckbox
sx={{ width: isMobile ? "90%" : "auto", mr: isMobile ? "0px" : "16px" }} sx={{
width: isMobile ? "90%" : "auto",
mr: isMobile ? "0px" : "16px",
}}
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={({ target }) => { handleChange={({ target }) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: {
...listQuestions[quizId][totalIndex].content, ...question.content,
innerNameCheck: target.checked, innerNameCheck: target.checked,
innerName: "", innerName: "",
}, },
@ -130,10 +136,10 @@ export default function SettingOptionsAndPict({
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Развёрнутое описание вопроса"} placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounceDescription(target.value)} onChange={({ target }) => debounceDescription(target.value)}
/> />
)} )}
@ -145,7 +151,7 @@ export default function SettingOptionsAndPict({
<CustomTextField <CustomTextField
sx={{ maxWidth: "330px", width: "100%" }} sx={{ maxWidth: "330px", width: "100%" }}
placeholder={"Пример текста"} placeholder={"Пример текста"}
text={listQuestions[quizId][totalIndex].content.replText} text={question.content.replText}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
</> </>

@ -27,6 +27,8 @@ import MessageIcon from "@icons/messagIcon";
import DeleteIcon from "@icons/questionsPage/deleteIcon"; import DeleteIcon from "@icons/questionsPage/deleteIcon";
import { ImageAddIcons } from "@icons/ImageAddIcons"; import { ImageAddIcons } from "@icons/ImageAddIcons";
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
} }
@ -38,23 +40,24 @@ export default function OptionsPicture({ totalIndex }: Props) {
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const [switchState, setSwitchState] = useState("setting"); const [switchState, setSwitchState] = useState("setting");
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const question = listQuestions[quizId][totalIndex] as QuizQuestionImages;
const SSHC = (data: string) => { const SSHC = (data: string) => {
setSwitchState(data); setSwitchState(data);
}; };
const addImage = ({ target }: ChangeEvent<HTMLInputElement>) => { const addImage = ({ target }: ChangeEvent<HTMLInputElement>) => {
if (target.files?.length) { // if (target.files?.length) {
const clonContent = listQuestions[quizId][totalIndex].content; // const clonContent = question.content;
clonContent.images.push(URL.createObjectURL(target.files[0])); // clonContent.images.push(URL.createObjectURL(target.files[0]));
updateQuestionsList(quizId, totalIndex, { content: clonContent }); // updateQuestionsList(quizId, totalIndex, {
} // content: { ...question.content, images },
// });
// }
}; };
console.log();
return ( return (
<> <>
<Box sx={{ padding: "20px" }}> <Box sx={{ padding: "20px" }}>
@ -91,7 +94,7 @@ export default function OptionsPicture({ totalIndex }: Props) {
fullWidth fullWidth
focused={false} focused={false}
placeholder={"Добавьте ответ"} placeholder={"Добавьте ответ"}
multiline={listQuestions[quizId][totalIndex].content.largeCheck} multiline={question.content.largeCheck}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
<> <>

@ -21,6 +21,8 @@ import ProportionsIcon11 from "../../../assets/icons/questionsPage/ProportionsIc
import ProportionsIcon21 from "../../../assets/icons/questionsPage/ProportionsIcon21"; import ProportionsIcon21 from "../../../assets/icons/questionsPage/ProportionsIcon21";
import ProportionsIcon12 from "../../../assets/icons/questionsPage/ProportionsIcon12"; import ProportionsIcon12 from "../../../assets/icons/questionsPage/ProportionsIcon12";
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
interface Props { interface Props {
Icon: React.ElementType; Icon: React.ElementType;
isActive?: boolean; isActive?: boolean;
@ -86,24 +88,23 @@ export default function SettingOpytionsPict({
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(1000)); const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const question = listQuestions[quizId][totalIndex] as QuizQuestionImages;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.innerName = value;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: { ...question.content, innerName: value },
}); });
}, 1000); }, 1000);
useEffect(() => { useEffect(() => {
if (!listQuestions[quizId][totalIndex].content.xy) { if (!question.content.xy) {
updateProportions("1:1"); updateProportions("1:1");
} }
}, []); }, []);
const updateProportions = (proportions: string) => { const updateProportions = (proportions: string) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.xy = proportions; content: { ...question.content, xy: proportions },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}; };
return ( return (
@ -129,9 +130,7 @@ export default function SettingOpytionsPict({
<SelectIconButton <SelectIconButton
key={index} key={index}
onClick={() => updateProportions(value)} onClick={() => updateProportions(value)}
isActive={ isActive={question.content.xy === value}
listQuestions[quizId][totalIndex].content.xy === value
}
Icon={icon} Icon={icon}
/> />
))} ))}
@ -144,39 +143,30 @@ export default function SettingOpytionsPict({
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Можно несколько"} label={"Можно несколько"}
checked={listQuestions[quizId][totalIndex].content.multi} checked={question.content.multi}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, multi: target.checked },
...listQuestions[quizId][totalIndex].content,
multi: target.checked,
},
}) })
} }
/> />
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Большие картинки"} label={"Большие картинки"}
checked={listQuestions[quizId][totalIndex].content.largeCheck} checked={question.content.largeCheck}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, largeCheck: target.checked },
...listQuestions[quizId][totalIndex].content,
largeCheck: target.checked,
},
}) })
} }
/> />
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={'Вариант "свой ответ"'} label={'Вариант "свой ответ"'}
checked={listQuestions[quizId][totalIndex].content.own} checked={question.content.own}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, own: target.checked },
...listQuestions[quizId][totalIndex].content,
own: target.checked,
},
}) })
} }
/> />
@ -193,29 +183,19 @@ export default function SettingOpytionsPict({
<SelectIconButton <SelectIconButton
onClick={() => onClick={() =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, format: "carousel" },
...listQuestions[quizId][totalIndex].content,
format: "carousel",
},
}) })
} }
isActive={ isActive={question.content.format === "carousel"}
listQuestions[quizId][totalIndex].content.format === "carousel"
}
Icon={FormatIcon2} Icon={FormatIcon2}
/> />
<SelectIconButton <SelectIconButton
onClick={() => onClick={() =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, format: "masonry" },
...listQuestions[quizId][totalIndex].content,
format: "masonry",
},
}) })
} }
isActive={ isActive={question.content.format === "masonry"}
listQuestions[quizId][totalIndex].content.format === "masonry"
}
Icon={FormatIcon1} Icon={FormatIcon1}
/> />
</Box> </Box>
@ -224,24 +204,27 @@ export default function SettingOpytionsPict({
</Typography> </Typography>
<CustomCheckbox <CustomCheckbox
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={listQuestions[quizId][totalIndex].content.required} checked={question.content.required}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, required: target.checked },
...listQuestions[quizId][totalIndex].content,
required: target.checked,
},
}) })
} }
/> />
<Box sx={{ width: isMobile ? "90%" : "auto", display: "flex", alignItems: "center" }}> <Box
sx={{
width: isMobile ? "90%" : "auto",
display: "flex",
alignItems: "center",
}}
>
<CustomCheckbox <CustomCheckbox
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: {
...listQuestions[quizId][totalIndex].content, ...question.content,
innerNameCheck: target.checked, innerNameCheck: target.checked,
innerName: "", innerName: "",
}, },
@ -257,10 +240,10 @@ export default function SettingOpytionsPict({
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Внутреннее описание вопроса"} placeholder={"Внутреннее описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -11,6 +11,8 @@ import { questionStore, updateQuestionsList } from "@root/questions";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import type { QuizQuestionText } from "../../../model/questionTypes/text";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
} }
@ -19,10 +21,11 @@ export default function OwnTextField({ totalIndex }: Props) {
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const theme = useTheme(); const theme = useTheme();
const question = listQuestions[quizId][totalIndex] as QuizQuestionText;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.placeholder = value; content: { ...question.content, placeholder: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
const SSHC = (data: string) => { const SSHC = (data: string) => {
@ -43,7 +46,7 @@ export default function OwnTextField({ totalIndex }: Props) {
> >
<CustomTextField <CustomTextField
placeholder={"Пример ответа"} placeholder={"Пример ответа"}
text={listQuestions[quizId][totalIndex].content.placeholder} text={question.content.placeholder}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
<Box sx={{ display: "flex", alignItems: "center", gap: "12px" }}> <Box sx={{ display: "flex", alignItems: "center", gap: "12px" }}>

@ -20,6 +20,8 @@ import CheckedIcon from "@ui_kit/RadioCheck";
import CheckIcon from "@ui_kit/RadioIcon"; import CheckIcon from "@ui_kit/RadioIcon";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import type { QuizQuestionText } from "../../../model/questionTypes/text";
type SettingTextFieldProps = { type SettingTextFieldProps = {
totalIndex: number; totalIndex: number;
}; };
@ -43,10 +45,11 @@ export default function SettingTextField({
const theme = useTheme(); const theme = useTheme();
const isWrapperColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrapperColumn = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const question = listQuestions[quizId][totalIndex] as QuizQuestionText;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerName = value; content: { ...question.content, innerName: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
return ( return (
@ -64,12 +67,24 @@ export default function SettingTextField({
<RadioGroup <RadioGroup
aria-labelledby="demo-controlled-radio-buttons-group" aria-labelledby="demo-controlled-radio-buttons-group"
name="controlled-radio-buttons-group" name="controlled-radio-buttons-group"
value={ANSWER_TYPES.findIndex( value={ANSWER_TYPES.findIndex(({ value }) => {
({ value }) => listQuestions[quizId][totalIndex].content[value] switch (value) {
)} case "multi":
return value === "multi";
case "number":
return value === "number";
case "single":
return value === "single";
default:
return false;
}
})}
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => { onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
const clonContent = { const clonContent = {
...listQuestions[quizId][totalIndex].content, ...question.content,
single: false, single: false,
multi: false, multi: false,
number: false, number: false,
@ -101,37 +116,42 @@ export default function SettingTextField({
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Автозаполнение адреса"} label={"Автозаполнение адреса"}
checked={listQuestions[quizId][totalIndex].content.autofill} checked={question.content.autofill}
handleChange={({ target }) => { handleChange={({ target }) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.autofill = target.checked; content: { ...question.content, autofill: target.checked },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!listQuestions[quizId][totalIndex].required} checked={!question.required}
handleChange={(e) => { handleChange={(e) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
required: !e.target.checked, required: !e.target.checked,
}); });
}} }}
/> />
<Box sx={{ width: isMobile ? "90%" : "auto", display: "flex", alignItems: "center" }}> <Box
sx={{
width: isMobile ? "90%" : "auto",
display: "flex",
alignItems: "center",
}}
>
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerNameCheck = e.target.checked; content: {
...question.content,
if (!e.target.checked) { innerNameCheck: target.checked,
clonContent.innerName = ""; innerName: target.checked ? question.content.innerName : "",
} },
});
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}} }}
/> />
<Tooltip <Tooltip
@ -143,10 +163,10 @@ export default function SettingTextField({
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Развёрнутое описание вопроса"} placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -13,6 +13,8 @@ import { UploadVideoModal } from "../UploadVideoModal";
import { AddPlusImage } from "@icons/questionsPage/addPlusImage"; import { AddPlusImage } from "@icons/questionsPage/addPlusImage";
import { AddPlusVideo } from "@icons/questionsPage/addPlusVideo"; import { AddPlusVideo } from "@icons/questionsPage/addPlusVideo";
import type { QuizQuestionPage } from "../../../model/questionTypes/page";
type Props = { type Props = {
disableInput?: boolean; disableInput?: boolean;
totalIndex: number; totalIndex: number;
@ -27,10 +29,11 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(980)); const isTablet = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(780)); const isMobile = useMediaQuery(theme.breakpoints.down(780));
const question = listQuestions[quizId][totalIndex] as QuizQuestionPage;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.text = value; content: { ...question.content, text: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
const SSHC = (data: string) => { const SSHC = (data: string) => {
@ -52,7 +55,7 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
<Box sx={{ display: disableInput ? "none" : "" }}> <Box sx={{ display: disableInput ? "none" : "" }}>
<CustomTextField <CustomTextField
placeholder={"Можно добавить текст"} placeholder={"Можно добавить текст"}
text={listQuestions[quizId][totalIndex].content.text} text={question.content.text}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
</Box> </Box>
@ -92,10 +95,11 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
onClose={() => setOpenImageModal(false)} onClose={() => setOpenImageModal(false)}
imgHC={(fileList) => { imgHC={(fileList) => {
if (fileList?.length) { if (fileList?.length) {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.picture = URL.createObjectURL(fileList[0]);
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: {
...question.content,
picture: URL.createObjectURL(fileList[0]),
},
}); });
} }
}} }}
@ -127,11 +131,11 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
<UploadVideoModal <UploadVideoModal
open={openVideoModal} open={openVideoModal}
onClose={() => setOpenVideoModal(false)} onClose={() => setOpenVideoModal(false)}
video={listQuestions[quizId][totalIndex].content.video} video={question.content.video}
onUpload={(url) => { onUpload={(url) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.video = url; content: { ...question.content, video: url },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
</Box> </Box>

@ -14,6 +14,8 @@ import { questionStore, updateQuestionsList } from "@root/questions";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import type { QuizQuestionPage } from "../../../model/questionTypes/page";
type SettingPageOptionsProps = { type SettingPageOptionsProps = {
totalIndex: number; totalIndex: number;
}; };
@ -23,11 +25,10 @@ export default function SettingPageOptions({
}: SettingPageOptionsProps) { }: SettingPageOptionsProps) {
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const question = listQuestions[quizId][totalIndex] as QuizQuestionPage;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.innerName = value;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: { ...question.content, innerName: value },
}); });
}, 1000); }, 1000);
@ -55,11 +56,11 @@ export default function SettingPageOptions({
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: {
...listQuestions[quizId][totalIndex].content, ...question.content,
innerNameCheck: target.checked, innerNameCheck: target.checked,
innerName: "", innerName: "",
}, },
@ -75,10 +76,10 @@ export default function SettingPageOptions({
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Внутреннее описание вопроса"} placeholder={"Внутреннее описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -14,6 +14,8 @@ import LightbulbIcon from "../../../assets/icons/questionsPage/lightbulbIcon";
import HashtagIcon from "../../../assets/icons/questionsPage/hashtagIcon"; import HashtagIcon from "../../../assets/icons/questionsPage/hashtagIcon";
import StarIconMini from "../../../assets/icons/questionsPage/StarIconMini"; import StarIconMini from "../../../assets/icons/questionsPage/StarIconMini";
import type { QuizQuestionRating } from "../../../model/questionTypes/rating";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
} }
@ -29,6 +31,7 @@ export default function RatingOptions({ totalIndex }: Props) {
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const question = listQuestions[quizId][totalIndex] as QuizQuestionRating;
const buttonRatingForm: ButtonRatingFrom[] = [ const buttonRatingForm: ButtonRatingFrom[] = [
{ name: "star", icon: <StarIconMini color={theme.palette.grey2.main} /> }, { name: "star", icon: <StarIconMini color={theme.palette.grey2.main} /> },
@ -51,9 +54,7 @@ export default function RatingOptions({ totalIndex }: Props) {
<> <>
<Box <Box
sx={{ sx={{
width: isMobile width: isMobile ? "auto" : `${question.content.steps * 44}px`,
? "auto"
: `${listQuestions[quizId][totalIndex].content.steps * 44}px`,
minWidth: "200px", minWidth: "200px",
maxWidth: "440px", maxWidth: "440px",
display: "flex", display: "flex",
@ -64,19 +65,15 @@ export default function RatingOptions({ totalIndex }: Props) {
> >
<Box sx={{ display: "flex", gap: isMobile ? "10px" : "15px" }}> <Box sx={{ display: "flex", gap: isMobile ? "10px" : "15px" }}>
{Array.from( {Array.from(
{ length: listQuestions[quizId][totalIndex].content.steps }, { length: question.content.steps },
(_, index) => index (_, index) => index
).map((itemNumber) => ( ).map((itemNumber) => (
<Box <Box
{...(itemNumber === 0 || {...(itemNumber === 0 || itemNumber === question.content.steps - 1
itemNumber === listQuestions[quizId][totalIndex].content.steps - 1
? { ? {
onClick: () => { onClick: () => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, ratingExpanded: true },
...listQuestions[quizId][totalIndex].content,
ratingExpanded: true,
},
}); });
}, },
sx: { sx: {
@ -92,14 +89,13 @@ export default function RatingOptions({ totalIndex }: Props) {
> >
{ {
buttonRatingForm.find( buttonRatingForm.find(
({ name }) => ({ name }) => question.content.form === name
listQuestions[quizId][totalIndex].content.form === name
)?.icon )?.icon
} }
</Box> </Box>
))} ))}
</Box> </Box>
{!listQuestions[quizId][totalIndex].content.ratingDescription && ( {!question.content.ratingDescription && (
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -127,22 +123,20 @@ export default function RatingOptions({ totalIndex }: Props) {
</Typography> </Typography>
</Box> </Box>
)} )}
{listQuestions[quizId][totalIndex].content.ratingExpanded && {question.content.ratingExpanded &&
(listQuestions[quizId][totalIndex].content.ratingDescription ? ( (question.content.ratingDescription ? (
<Typography> <Typography>{question.content.ratingDescription}</Typography>
{listQuestions[quizId][totalIndex].content.ratingDescription}
</Typography>
) : ( ) : (
<CustomTextField <CustomTextField
placeholder={"Описание"} placeholder={"Описание"}
text={listQuestions[quizId][totalIndex].content.ratingDescription} text={question.content.ratingDescription}
onKeyDown={({ target, key }) => { onKeyDown={({ target, key }) => {
if (key === "Enter") { if (key === "Enter") {
const currentTarget = target as HTMLInputElement; const currentTarget = target as HTMLInputElement;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: {
...listQuestions[quizId][totalIndex].content, ...question.content,
ratingDescription: currentTarget.value.substring(0, 20), ratingDescription: currentTarget.value.substring(0, 20),
}, },
}); });
@ -151,7 +145,7 @@ export default function RatingOptions({ totalIndex }: Props) {
onBlur={({ target }) => { onBlur={({ target }) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: {
...listQuestions[quizId][totalIndex].content, ...question.content,
ratingDescription: target.value.substring(0, 20), ratingDescription: target.value.substring(0, 20),
}, },
}); });

@ -24,6 +24,7 @@ import HashtagIcon from "../../../assets/icons/questionsPage/hashtagIcon";
import StarIconMini from "../../../assets/icons/questionsPage/StarIconMini"; import StarIconMini from "../../../assets/icons/questionsPage/StarIconMini";
import type { ButtonRatingFrom } from "./RatingOptions"; import type { ButtonRatingFrom } from "./RatingOptions";
import type { QuizQuestionNumber } from "../../../model/questionTypes/number";
type SettingSliderProps = { type SettingSliderProps = {
totalIndex: number; totalIndex: number;
@ -35,10 +36,11 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const question = listQuestions[quizId][totalIndex] as QuizQuestionNumber;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerName = value; content: { ...question.content, innerName: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
const buttonRatingForm: ButtonRatingFrom[] = [ const buttonRatingForm: ButtonRatingFrom[] = [
@ -80,19 +82,17 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
<ButtonBase <ButtonBase
key={index} key={index}
onClick={() => { onClick={() => {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.form = name;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: { ...question.content, form: name },
}); });
}} }}
sx={{ sx={{
backgroundColor: backgroundColor:
listQuestions[quizId][totalIndex].content.form === name question.content.form === name
? theme.palette.brightPurple.main ? theme.palette.brightPurple.main
: "transparent", : "transparent",
color: color:
listQuestions[quizId][totalIndex].content.form === name question.content.form === name
? "#ffffff" ? "#ffffff"
: theme.palette.grey3.main, : theme.palette.grey3.main,
width: "40px", width: "40px",
@ -114,16 +114,16 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
Количество Количество
</Typography> </Typography>
<Slider <Slider
value={listQuestions[quizId][totalIndex].content.steps} value={question.content.steps}
min={2} min={2}
max={10} max={10}
aria-label="Default" aria-label="Default"
valueLabelDisplay="auto" valueLabelDisplay="auto"
sx={{ color: theme.palette.brightPurple.main }} sx={{ color: theme.palette.brightPurple.main }}
onChange={(_, value) => { onChange={(_, value) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.steps = Number(value) || 1; content: { ...question.content, steps: Number(value) || 1 },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
</Box> </Box>
@ -149,16 +149,15 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerNameCheck = e.target.checked; content: {
...question.content,
if (!e.target.checked) { innerNameCheck: target.checked,
clonContent.innerName = ""; innerName: target.checked ? question.content.innerName : "",
} },
});
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}} }}
/> />
<Tooltip <Tooltip
@ -170,10 +169,10 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Развёрнутое описание вопроса"} placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -6,6 +6,8 @@ import CustomNumberField from "@ui_kit/CustomNumberField";
import SwitchSlider from "./switchSlider"; import SwitchSlider from "./switchSlider";
import { questionStore, updateQuestionsList } from "@root/questions"; import { questionStore, updateQuestionsList } from "@root/questions";
import type { QuizQuestionNumber } from "../../../model/questionTypes/number";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
} }
@ -18,6 +20,7 @@ export default function SliderOptions({ totalIndex }: Props) {
const [stepError, setStepError] = useState(""); const [stepError, setStepError] = useState("");
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const question = listQuestions[quizId][totalIndex] as QuizQuestionNumber;
const SSHC = (data: string) => { const SSHC = (data: string) => {
setSwitchState(data); setSwitchState(data);
@ -51,43 +54,36 @@ export default function SliderOptions({ totalIndex }: Props) {
placeholder={"0"} placeholder={"0"}
min={0} min={0}
max={99} max={99}
value={ value={question.content.range.split("—")[0]}
listQuestions[quizId][totalIndex].content.range.split("—")[0]
}
onChange={({ target }) => { onChange={({ target }) => {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.range = `${target.value}${
listQuestions[quizId][totalIndex].content.range.split("—")[1]
}`;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: {
...question.content,
range: `${target.value}${
question.content.range.split("—")[1]
}`,
},
}); });
}} }}
onBlur={({ target }) => { onBlur={({ target }) => {
const start = listQuestions[quizId][totalIndex].content.start; const start = question.content.start;
const min = Number(target.value); const min = Number(target.value);
const max = Number( const max = Number(question.content.range.split("—")[1]);
listQuestions[quizId][totalIndex].content.range.split("—")[1]
);
if (min >= max) { if (min >= max) {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.range = `${max - 1 >= 0 ? max - 1 : 0}${
listQuestions[quizId][totalIndex].content.range.split(
"—"
)[1]
}`;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: {
...question.content,
range: `${max - 1 >= 0 ? max - 1 : 0}${
question.content.range.split("—")[1]
}`,
},
}); });
} }
if (start < min) { if (start < min) {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, start: min },
...listQuestions[quizId][totalIndex].content,
start: min,
},
}); });
} }
}} }}
@ -97,54 +93,44 @@ export default function SliderOptions({ totalIndex }: Props) {
placeholder={"100"} placeholder={"100"}
min={0} min={0}
max={100} max={100}
value={ value={question.content.range.split("—")[1]}
listQuestions[quizId][totalIndex].content.range.split("—")[1]
}
onChange={({ target }) => { onChange={({ target }) => {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.range = `${
listQuestions[quizId][totalIndex].content.range.split("—")[0]
}${target.value}`;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: {
...question.content,
range: `${question.content.range.split("—")[0]}${
target.value
}`,
},
}); });
}} }}
onBlur={({ target }) => { onBlur={({ target }) => {
const start = listQuestions[quizId][totalIndex].content.start; const start = question.content.start;
const step = listQuestions[quizId][totalIndex].content.step; const step = question.content.step;
const min = Number( const min = Number(question.content.range.split("—")[0]);
listQuestions[quizId][totalIndex].content.range.split("—")[0]
);
const max = Number(target.value); const max = Number(target.value);
const range = max - min; const range = max - min;
if (max <= min) { if (max <= min) {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.range = `${
listQuestions[quizId][totalIndex].content.range.split(
"—"
)[0]
}${min + 1 >= 100 ? 100 : min + 1}`;
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: {
...question.content,
range: `${question.content.range.split("—")[0]}${
min + 1 >= 100 ? 100 : min + 1
}`,
},
}); });
} }
if (start > max) { if (start > max) {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, start: max },
...listQuestions[quizId][totalIndex].content,
start: max,
},
}); });
} }
if (step > max) { if (step > max) {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, step: max },
...listQuestions[quizId][totalIndex].content,
step: max,
},
}); });
if (range % step) { if (range % step) {
@ -183,18 +169,12 @@ export default function SliderOptions({ totalIndex }: Props) {
</Typography> </Typography>
<CustomNumberField <CustomNumberField
placeholder={"50"} placeholder={"50"}
min={Number( min={Number(question.content.range.split("—")[0])}
listQuestions[quizId][totalIndex].content.range.split("—")[0] max={Number(question.content.range.split("—")[1])}
)} value={String(question.content.start)}
max={Number(
listQuestions[quizId][totalIndex].content.range.split("—")[1]
)}
value={String(listQuestions[quizId][totalIndex].content.start)}
onChange={({ target }) => { onChange={({ target }) => {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.start = Number(target.value);
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: { ...question.content, start: Number(target.value) },
}); });
}} }}
/> />
@ -215,30 +195,21 @@ export default function SliderOptions({ totalIndex }: Props) {
max={100} max={100}
placeholder={"1"} placeholder={"1"}
error={stepError} error={stepError}
value={String(listQuestions[quizId][totalIndex].content.step)} value={String(question.content.step)}
onChange={({ target }) => { onChange={({ target }) => {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.step = Number(target.value);
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: clonContent, content: { ...question.content, step: Number(target.value) },
}); });
}} }}
onBlur={({ target }) => { onBlur={({ target }) => {
const min = Number( const min = Number(question.content.range.split("—")[0]);
listQuestions[quizId][totalIndex].content.range.split("—")[0] const max = Number(question.content.range.split("—")[1]);
);
const max = Number(
listQuestions[quizId][totalIndex].content.range.split("—")[1]
);
const range = max - min; const range = max - min;
const step = Number(target.value); const step = Number(target.value);
if (step > max) { if (step > max) {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: { ...question.content, step: max },
...listQuestions[quizId][totalIndex].content,
step: max,
},
}); });
} }

@ -12,6 +12,8 @@ import CustomTextField from "@ui_kit/CustomTextField";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import { questionStore, updateQuestionsList } from "@root/questions"; import { questionStore, updateQuestionsList } from "@root/questions";
import type { QuizQuestionNumber } from "../../../model/questionTypes/number";
type SettingSliderProps = { type SettingSliderProps = {
totalIndex: number; totalIndex: number;
}; };
@ -22,10 +24,11 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
const theme = useTheme(); const theme = useTheme();
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const question = listQuestions[quizId][totalIndex] as QuizQuestionNumber;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerName = value; content: { ...question.content, innerName: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
return ( return (
@ -41,11 +44,11 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Выбор диапозона (два ползунка)"} label={"Выбор диапозона (два ползунка)"}
checked={listQuestions[quizId][totalIndex].content.chooseRange} checked={question.content.chooseRange}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.chooseRange = e.target.checked; content: { ...question.content, chooseRange: target.checked },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
</Box> </Box>
@ -71,16 +74,15 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerNameCheck = e.target.checked; content: {
...question.content,
if (!e.target.checked) { innerNameCheck: target.checked,
clonContent.innerName = ""; innerName: target.checked ? question.content.innerName : "",
} },
});
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}} }}
/> />
<Tooltip <Tooltip
@ -92,10 +94,10 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Развёрнутое описание вопроса"} placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -13,7 +13,14 @@ import RatingIcon from "../../assets/icons/questionsPage/rating";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import React from "react"; import React from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { questionStore, updateQuestionsList } from "@root/questions"; import {
questionStore,
updateQuestionsList,
createQuestion,
removeQuestion,
} from "@root/questions";
import type { QuizQuestionType } from "../../model/questionTypes/shared";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
@ -22,7 +29,7 @@ interface Props {
type ButtonTypeQuestion = { type ButtonTypeQuestion = {
icon: JSX.Element; icon: JSX.Element;
title: string; title: string;
value: string; value: QuizQuestionType;
}; };
export const BUTTON_TYPE_QUESTIONS: ButtonTypeQuestion[] = [ export const BUTTON_TYPE_QUESTIONS: ButtonTypeQuestion[] = [
@ -101,8 +108,13 @@ export default function TypeQuestions({ totalIndex }: Props) {
<QuestionsMiniButton <QuestionsMiniButton
key={title} key={title}
onClick={() => { onClick={() => {
console.log(value); const question = listQuestions[quizId][totalIndex];
updateQuestionsList(quizId, totalIndex, { type: value });
removeQuestion(quizId, totalIndex);
createQuestion(quizId, value, totalIndex);
updateQuestionsList(quizId, totalIndex, {
expanded: question.expanded,
});
}} }}
icon={icon} icon={icon}
text={title} text={title}

@ -18,6 +18,8 @@ import InfoIcon from "../../../assets/icons/InfoIcon";
import ArrowDown from "../../../assets/icons/ArrowDownIcon"; import ArrowDown from "../../../assets/icons/ArrowDownIcon";
import SwitchUpload from "./switchUpload"; import SwitchUpload from "./switchUpload";
import type { QuizQuestionFile } from "../../../model/questionTypes/file";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
} }
@ -36,24 +38,27 @@ export default function UploadFile({ totalIndex }: Props) {
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(980)); const isTablet = useMediaQuery(theme.breakpoints.down(980));
const question = listQuestions[quizId][totalIndex] as QuizQuestionFile;
const SSHC = (data: string) => { const SSHC = (data: string) => {
setSwitchState(data); setSwitchState(data);
}; };
const handleChange = ({ target }: SelectChangeEvent) => { const handleChange = ({ target }: SelectChangeEvent) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.type = target.value; content: { ...question.content, type: target.value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}; };
useEffect(() => { useEffect(() => {
const isTypeSetted = DESIGN_TYPES.find(({ value }) => value === listQuestions[quizId][totalIndex].content.type); const isTypeSetted = DESIGN_TYPES.find(
({ value }) => value === question.content.type
);
if (!isTypeSetted) { if (!isTypeSetted) {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.type = DESIGN_TYPES[0].value; content: { ...question.content, type: DESIGN_TYPES[0].value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
} }
}, []); }, []);
@ -82,7 +87,7 @@ export default function UploadFile({ totalIndex }: Props) {
<Select <Select
id="category-select" id="category-select"
variant="outlined" variant="outlined"
value={listQuestions[quizId][totalIndex].content.type} value={question.type}
displayEmpty displayEmpty
onChange={handleChange} onChange={handleChange}
sx={{ sx={{
@ -159,7 +164,11 @@ export default function UploadFile({ totalIndex }: Props) {
<InfoIcon /> <InfoIcon />
</Box> </Box>
</Box> </Box>
<ButtonsOptions switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} /> <ButtonsOptions
switchState={switchState}
SSHC={SSHC}
totalIndex={totalIndex}
/>
<SwitchUpload switchState={switchState} totalIndex={totalIndex} /> <SwitchUpload switchState={switchState} totalIndex={totalIndex} />
</> </>
); );

@ -1,5 +1,11 @@
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { Box, Typography, useMediaQuery, useTheme, Tooltip } from "@mui/material"; import {
Box,
Typography,
useMediaQuery,
useTheme,
Tooltip,
} from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox"; import CustomCheckbox from "@ui_kit/CustomCheckbox";
import CustomTextField from "@ui_kit/CustomTextField"; import CustomTextField from "@ui_kit/CustomTextField";
import { useDebouncedCallback } from "use-debounce"; import { useDebouncedCallback } from "use-debounce";
@ -8,6 +14,8 @@ import { questionStore, updateQuestionsList } from "@root/questions";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import type { QuizQuestionFile } from "../../../model/questionTypes/file";
type SettingsUploadProps = { type SettingsUploadProps = {
totalIndex: number; totalIndex: number;
}; };
@ -16,50 +24,64 @@ export default function SettingsUpload({ totalIndex }: SettingsUploadProps) {
const theme = useTheme(); const theme = useTheme();
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const question = listQuestions[quizId][totalIndex] as QuizQuestionFile;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerName = value; content: { ...question.content, innerName: value },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}, 1000); }, 1000);
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
return ( return (
<Box sx={{ display: "flex", flexDirection: "column", pt: "20px", pb: "20px", pl: "20px" }}> <Box
sx={{
display: "flex",
flexDirection: "column",
pt: "20px",
pb: "20px",
pl: "20px",
}}
>
<Typography>Настройки вопроса</Typography> <Typography>Настройки вопроса</Typography>
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Автозаполнение адреса"} label={"Автозаполнение адреса"}
checked={listQuestions[quizId][totalIndex].content.autofill} checked={question.content.autofill}
handleChange={({ target }) => { handleChange={({ target }) => {
const clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.autofill = target.checked; content: { ...question.content, autofill: target.checked },
updateQuestionsList(quizId, totalIndex, { content: clonContent }); });
}} }}
/> />
<CustomCheckbox <CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!listQuestions[quizId][totalIndex].required} checked={!question.required}
handleChange={(e) => { handleChange={(e) => {
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
required: !e.target.checked, required: !e.target.checked,
}); });
}} }}
/> />
<Box sx={{ width: isMobile ? "90%" : "auto", display: "flex", alignItems: "center" }}> <Box
sx={{
width: isMobile ? "90%" : "auto",
display: "flex",
alignItems: "center",
}}
>
<CustomCheckbox <CustomCheckbox
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Внутреннее название вопроса"} label={"Внутреннее название вопроса"}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck} checked={question.content.innerNameCheck}
handleChange={(e) => { handleChange={({ target }) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.innerNameCheck = e.target.checked; content: {
...question.content,
if (!e.target.checked) { innerNameCheck: target.checked,
clonContent.innerName = ""; innerName: target.checked ? question.content.innerName : "",
} },
});
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}} }}
/> />
<Tooltip <Tooltip
@ -71,10 +93,10 @@ export default function SettingsUpload({ totalIndex }: SettingsUploadProps) {
</Box> </Box>
</Tooltip> </Tooltip>
</Box> </Box>
{listQuestions[quizId][totalIndex].content.innerNameCheck && ( {question.content.innerNameCheck && (
<CustomTextField <CustomTextField
placeholder={"Развёрнутое описание вопроса"} placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[quizId][totalIndex].content.innerName} text={question.content.innerName}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
)} )}

@ -9,6 +9,7 @@ import { questionStore, updateQuestionsList } from "@root/questions";
import { UploadImageModal } from "./UploadImageModal"; import { UploadImageModal } from "./UploadImageModal";
import type { DragEvent } from "react"; import type { DragEvent } from "react";
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
type UploadImageProps = { type UploadImageProps = {
totalIndex: number; totalIndex: number;
@ -19,6 +20,7 @@ export default function UploadImage({ totalIndex }: UploadImageProps) {
const theme = useTheme(); const theme = useTheme();
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const question = listQuestions[quizId][totalIndex] as QuizQuestionImages;
const handleOpen = () => setOpen(true); const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false); const handleClose = () => setOpen(false);
@ -26,9 +28,10 @@ export default function UploadImage({ totalIndex }: UploadImageProps) {
if (files?.length) { if (files?.length) {
const [file] = Array.from(files); const [file] = Array.from(files);
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.back = URL.createObjectURL(file); ...question,
updateQuestionsList(quizId, totalIndex, { content: clonContent }); back: URL.createObjectURL(file),
});
handleClose(); handleClose();
setOpened(true); setOpened(true);
@ -70,7 +73,7 @@ export default function UploadImage({ totalIndex }: UploadImageProps) {
<CropModal <CropModal
opened={opened} opened={opened}
onClose={() => setOpened(false)} onClose={() => setOpened(false)}
picture={listQuestions[quizId][totalIndex].content.back} picture={question.content.back}
/> />
</Box> </Box>
); );

@ -7,6 +7,8 @@ import { AnswerDraggableList } from "../AnswerDraggableList";
import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict"; import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict";
import { questionStore, updateQuestionsList } from "@root/questions"; import { questionStore, updateQuestionsList } from "@root/questions";
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
interface Props { interface Props {
totalIndex: number; totalIndex: number;
} }
@ -15,7 +17,7 @@ export default function AnswerOptions({ totalIndex }: Props) {
const [switchState, setSwitchState] = useState("setting"); const [switchState, setSwitchState] = useState("setting");
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const variants = listQuestions[quizId][totalIndex].content.variants; const question = listQuestions[quizId][totalIndex] as QuizQuestionVariant;
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
@ -24,8 +26,8 @@ export default function AnswerOptions({ totalIndex }: Props) {
}; };
const addNewAnswer = () => { const addNewAnswer = () => {
const answerNew = variants.slice(); const answerNew = question.content.variants.slice();
answerNew.push({ answer: "", hints: "", emoji: "" }); answerNew.push({ answer: "", hints: "", extendedText: "" });
updateQuestionsList(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: {
@ -38,7 +40,7 @@ export default function AnswerOptions({ totalIndex }: Props) {
return ( return (
<> <>
<Box sx={{ padding: "0 20px 20px 20px" }}> <Box sx={{ padding: "0 20px 20px 20px" }}>
{variants.length === 0 ? ( {question.content.variants.length === 0 ? (
<Typography <Typography
sx={{ sx={{
padding: "0 0 33px 80px", padding: "0 0 33px 80px",
@ -51,7 +53,10 @@ export default function AnswerOptions({ totalIndex }: Props) {
Добавьте ответ Добавьте ответ
</Typography> </Typography>
) : ( ) : (
<AnswerDraggableList variants={variants} totalIndex={totalIndex} /> <AnswerDraggableList
variants={question.content.variants}
totalIndex={totalIndex}
/>
)} )}
<Box <Box

@ -9,6 +9,8 @@ import UploadBox from "@ui_kit/UploadBox";
import { questionStore, updateQuestionsList } from "@root/questions"; import { questionStore, updateQuestionsList } from "@root/questions";
import { UploadVideoModal } from "./UploadVideoModal"; import { UploadVideoModal } from "./UploadVideoModal";
import type { QuizQuestionBase } from "../../model/questionTypes/shared";
type BackgroundType = "text" | "video"; type BackgroundType = "text" | "video";
type HelpQuestionsProps = { type HelpQuestionsProps = {
@ -20,16 +22,25 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
const [backgroundType, setBackgroundType] = useState<BackgroundType>("text"); const [backgroundType, setBackgroundType] = useState<BackgroundType>("text");
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const question = listQuestions[quizId][totalIndex] as QuizQuestionBase;
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
let clonContent = listQuestions[quizId][totalIndex].content; updateQuestionsList(quizId, totalIndex, {
clonContent.hint.text = value; content: {
updateQuestionsList(quizId, totalIndex, { content: clonContent }); ...question.content,
hint: { text: value, video: question.content.hint.video },
},
});
}, 1000); }, 1000);
const videoHC = (url: string) => { const videoHC = (url: string) => {
const clonContent = listQuestions[quizId][totalIndex].content; const clonContent = question.content;
clonContent.hint.video = url; clonContent.hint.video = url;
updateQuestionsList(quizId, totalIndex, { content: clonContent }); updateQuestionsList(quizId, totalIndex, {
content: {
...question.content,
hint: { video: url, text: question.content.hint.text },
},
});
}; };
return ( return (
@ -67,7 +78,7 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
<> <>
<CustomTextField <CustomTextField
placeholder={"Текст консультанта"} placeholder={"Текст консультанта"}
text={listQuestions[quizId][totalIndex].content.hint.text} text={question.content.hint.text}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
/> />
</> </>
@ -80,12 +91,8 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
onClick={() => setOpen(true)} onClick={() => setOpen(true)}
sx={{ justifyContent: "flex-start" }} sx={{ justifyContent: "flex-start" }}
> >
{listQuestions[quizId][totalIndex].content.hint.video ? ( {question.content.hint.video ? (
<video <video src={question.content.hint.video} width="400" controls />
src={listQuestions[quizId][totalIndex].content.hint.video}
width="400"
controls
/>
) : ( ) : (
<> <>
<UploadBox <UploadBox
@ -101,7 +108,7 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
<UploadVideoModal <UploadVideoModal
open={open} open={open}
onClose={() => setOpen(false)} onClose={() => setOpen(false)}
video={listQuestions[quizId][totalIndex].content.hint.video} video={question.content.hint.video}
onUpload={videoHC} onUpload={videoHC}
/> />
</Box> </Box>

@ -9,24 +9,21 @@ import { QuizQuestionVarImg } from "../model/questionTypes/varimg";
import type { import type {
AnyQuizQuestion, AnyQuizQuestion,
QuizQuestionType, QuizQuestionType,
Variant,
} from "../model/questionTypes/shared"; } from "../model/questionTypes/shared";
import { QuizQuestionDateEmpty } from "../constants/date";
import { QuizQuestionEmojiEmpty } from "../constants/emoji";
import { QuizQuestionFileEmpty } from "../constants/file";
import { QuizQuestionImagesEmpty } from "../constants/images";
import { QuizQuestionNumberEmpty } from "../constants/number";
import { QuizQuestionPageEmpty } from "../constants/page";
import { QuizQuestionRatingEmpty } from "../constants/rating";
import { QuizQuestionSelectEmpty } from "../constants/select";
import { QuizQuestionTextEmpty } from "../constants/text";
import { QuizQuestionVariantEmpty } from "../constants/variant";
import { QuizQuestionVarImgEmpty } from "../constants/varimg";
export type Variants = { import { QUIZ_QUESTION_BASE } from "../constants/base";
answer: string; import { QUIZ_QUESTION_DATE } from "../constants/date";
hints: string; import { QUIZ_QUESTION_EMOJI } from "../constants/emoji";
emoji: string; import { QUIZ_QUESTION_FILE } from "../constants/file";
}; import { QUIZ_QUESTION_IMAGES } from "../constants/images";
import { QUIZ_QUESTION_NUMBER } from "../constants/number";
import { QUIZ_QUESTION_PAGE } from "../constants/page";
import { QUIZ_QUESTION_RATING } from "../constants/rating";
import { QUIZ_QUESTION_SELECT } from "../constants/select";
import { QUIZ_QUESTION_TEXT } from "../constants/text";
import { QUIZ_QUESTION_VARIANT } from "../constants/variant";
import { QUIZ_QUESTION_VARIMG } from "../constants/varimg";
type Hint = { type Hint = {
text: string; text: string;
@ -53,7 +50,7 @@ export interface Question {
deleted: true; deleted: true;
page: number; page: number;
content: { content: {
variants: Variants[]; variants: Variant[];
hint: Hint; hint: Hint;
rule: Rule; rule: Rule;
images: string[]; images: string[];
@ -143,7 +140,7 @@ export const DEFAULT_QUESTION: Omit<Question, "id"> = {
{ {
answer: "", answer: "",
hints: "", hints: "",
emoji: "", extendedText: "",
}, },
], ],
hint: { hint: {
@ -195,7 +192,7 @@ export const updateQuestionsList = <T = AnyQuizQuestion>(
export const updateQuestionsListDragAndDrop = ( export const updateQuestionsListDragAndDrop = (
quizId: number, quizId: number,
updatedQuestions: Question[] updatedQuestions: AnyQuizQuestion[]
) => { ) => {
const questionListClone = { ...questionStore.getState()["listQuestions"] }; const questionListClone = { ...questionStore.getState()["listQuestions"] };
questionStore.setState({ questionStore.setState({
@ -206,7 +203,7 @@ export const updateQuestionsListDragAndDrop = (
export const updateVariants = ( export const updateVariants = (
quizId: number, quizId: number,
index: number, index: number,
variants: Variants[] variants: Variant[]
) => { ) => {
const listQuestions = { ...questionStore.getState()["listQuestions"] }; const listQuestions = { ...questionStore.getState()["listQuestions"] };
@ -235,7 +232,7 @@ export const updateVariants = (
export const createQuestion = ( export const createQuestion = (
quizId: number, quizId: number,
questionType: QuizQuestionType, questionType: QuizQuestionType = "",
placeIndex = -1 placeIndex = -1
) => { ) => {
const id = getRandom(1000000, 10000000); const id = getRandom(1000000, 10000000);
@ -246,17 +243,18 @@ export const createQuestion = (
} }
const defaultObject = [ const defaultObject = [
QuizQuestionDateEmpty, QUIZ_QUESTION_BASE,
QuizQuestionEmojiEmpty, QUIZ_QUESTION_DATE,
QuizQuestionFileEmpty, QUIZ_QUESTION_EMOJI,
QuizQuestionImagesEmpty, QUIZ_QUESTION_FILE,
QuizQuestionNumberEmpty, QUIZ_QUESTION_IMAGES,
QuizQuestionPageEmpty, QUIZ_QUESTION_NUMBER,
QuizQuestionRatingEmpty, QUIZ_QUESTION_PAGE,
QuizQuestionSelectEmpty, QUIZ_QUESTION_RATING,
QuizQuestionTextEmpty, QUIZ_QUESTION_SELECT,
QuizQuestionVariantEmpty, QUIZ_QUESTION_TEXT,
QuizQuestionVarImgEmpty, QUIZ_QUESTION_VARIANT,
QUIZ_QUESTION_VARIMG,
].find((defaultObjectItem) => defaultObjectItem.type === questionType); ].find((defaultObjectItem) => defaultObjectItem.type === questionType);
if (defaultObject) { if (defaultObject) {