fix interaction with the survey
This commit is contained in:
parent
e961d53d6c
commit
15ec6b9632
9 changed files with 495 additions and 175 deletions
|
|
@ -1,5 +1,15 @@
|
||||||
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts";
|
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts";
|
||||||
|
|
||||||
|
export interface INewAnswer{
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAnswerVariant extends INewAnswer{
|
||||||
|
surveyId: number;
|
||||||
|
id: number;
|
||||||
|
questionId: number;
|
||||||
|
}
|
||||||
|
|
||||||
export const getAnswerVariants = async (surveyId: number, questionId: number) => {
|
export const getAnswerVariants = async (surveyId: number, questionId: number) => {
|
||||||
try{
|
try{
|
||||||
const response = await fetch(`${BASE_URL}/surveys/${surveyId}/questions/${questionId}/answerVariants`, {
|
const response = await fetch(`${BASE_URL}/surveys/${surveyId}/questions/${questionId}/answerVariants`, {
|
||||||
|
|
@ -12,7 +22,7 @@ export const getAnswerVariants = async (surveyId: number, questionId: number) =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addNewAnswerVariant = async (surveyId: number, questionId: number) => {
|
export const addNewAnswerVariant = async (surveyId: number, questionId: number, answer: INewAnswer) => {
|
||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
if (!token) {
|
if (!token) {
|
||||||
throw new Error("Токен отсутствует");
|
throw new Error("Токен отсутствует");
|
||||||
|
|
@ -22,8 +32,7 @@ export const addNewAnswerVariant = async (surveyId: number, questionId: number)
|
||||||
const response = await fetch(`${BASE_URL}/surveys/${surveyId}/questions/${questionId}/answerVariants`, {
|
const response = await fetch(`${BASE_URL}/surveys/${surveyId}/questions/${questionId}/answerVariants`, {
|
||||||
...createRequestConfig('POST'),
|
...createRequestConfig('POST'),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
surveyId: surveyId,
|
text: answer.text,
|
||||||
questionId: questionId,
|
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -38,7 +47,7 @@ export const addNewAnswerVariant = async (surveyId: number, questionId: number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateAnswerVariant = async (surveyId: number, questionId: number, id: number) => {
|
export const updateAnswerVariant = async (surveyId: number, questionId: number, id: number, answer: INewAnswer): Promise<INewAnswer> => {
|
||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
if (!token) {
|
if (!token) {
|
||||||
throw new Error("Токен отсутствует");
|
throw new Error("Токен отсутствует");
|
||||||
|
|
@ -48,18 +57,18 @@ export const updateAnswerVariant = async (surveyId: number, questionId: number,
|
||||||
const response = await fetch(`${BASE_URL}/surveys/${surveyId}/questions/${questionId}/answerVariants/${id}`, {
|
const response = await fetch(`${BASE_URL}/surveys/${surveyId}/questions/${questionId}/answerVariants/${id}`, {
|
||||||
...createRequestConfig('PUT'),
|
...createRequestConfig('PUT'),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
surveyId: surveyId,
|
text: answer.text,
|
||||||
questionId: questionId,
|
|
||||||
id: id
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Ошибка: ${response.status}`);
|
const errorData = await response.json().catch(() => null);
|
||||||
|
throw new Error(`Ошибка ${response.status}: ${errorData?.message || 'Неизвестная ошибка'}`);
|
||||||
}
|
}
|
||||||
return await handleResponse(response)
|
return await handleResponse(response)
|
||||||
}
|
}
|
||||||
catch(err){
|
catch(err){
|
||||||
console.error(`Error updating the response option: ${err}`);
|
console.error(`Error updating the response option: ${err}`);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ interface IRegistrationData extends IAuthData{
|
||||||
lastName: string;
|
lastName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getCurrentUser = async (): Promise<IRegistrationData> => {
|
export const getCurrentUser = async (user: IRegistrationData) => {
|
||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
|
|
@ -23,7 +23,12 @@ export const getCurrentUser = async (): Promise<IRegistrationData> => {
|
||||||
...createRequestConfig('GET'),
|
...createRequestConfig('GET'),
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
}
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
email: user.email,
|
||||||
|
firstName: user.firstName,
|
||||||
|
lastName: user.lastName,
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(response);
|
console.log(response);
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts";
|
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts";
|
||||||
|
import {IAnswerVariant} from "./AnswerApi.ts";
|
||||||
|
|
||||||
export interface INewQuestion{
|
export interface INewQuestion{
|
||||||
title: string;
|
title: string;
|
||||||
questionType: string;
|
questionType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAnswerVariant{
|
|
||||||
id: number;
|
|
||||||
questionId: number;
|
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IQuestion extends INewQuestion {
|
export interface IQuestion extends INewQuestion {
|
||||||
id: number;
|
id: number;
|
||||||
surveyId: number;
|
surveyId: number;
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@ export const MySurveyList = () => {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка при получении списка опросов:', error);
|
console.error('Ошибка при получении списка опросов:', error);
|
||||||
|
|
||||||
if (error instanceof Error && error.message.includes("401")) {
|
// if (error instanceof Error && error.message.includes("401")) {
|
||||||
// Если ошибка 401, перенаправляем на страницу входа
|
// // Если ошибка 401, перенаправляем на страницу входа
|
||||||
navigate('/login');
|
// navigate('/login');
|
||||||
} else {
|
// } else {
|
||||||
alert("Ошибка при загрузке опросов: " + (error instanceof Error && error.message));
|
// alert("Ошибка при загрузке опросов: " + (error instanceof Error && error.message));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchSurvey();
|
fetchSurvey();
|
||||||
|
|
@ -53,11 +53,11 @@ export const MySurveyList = () => {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка при удалении опроса:', error);
|
console.error('Ошибка при удалении опроса:', error);
|
||||||
|
|
||||||
if (error instanceof Error && error.message.includes("401")) {
|
// if (error instanceof Error && error.message.includes("401")) {
|
||||||
navigate('/login');
|
// navigate('/login');
|
||||||
} else {
|
// } else {
|
||||||
alert("Ошибка при удалении опроса: " + (error instanceof Error ? error.message : 'Неизвестная ошибка'));
|
// alert("Ошибка при удалении опроса: " + (error instanceof Error ? error.message : 'Неизвестная ошибка'));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,65 +4,97 @@ import AddAnswerButton from "../AddAnswerButton/AddAnswerButton.tsx";
|
||||||
import TypeDropdown from "../TypeDropdown/TypeDropdown.tsx";
|
import TypeDropdown from "../TypeDropdown/TypeDropdown.tsx";
|
||||||
import styles from './QuestionItem.module.css'
|
import styles from './QuestionItem.module.css'
|
||||||
import Delete from '../../assets/deleteQuestion.svg?react';
|
import Delete from '../../assets/deleteQuestion.svg?react';
|
||||||
|
import {
|
||||||
|
addNewAnswerVariant,
|
||||||
|
deleteAnswerVariant,
|
||||||
|
getAnswerVariants,
|
||||||
|
updateAnswerVariant
|
||||||
|
} from "../../api/AnswerApi.ts";
|
||||||
|
|
||||||
interface QuestionItemProps {
|
interface QuestionItemProps {
|
||||||
questionId: number;
|
questionId: number;
|
||||||
initialTextQuestion?: string;
|
initialTextQuestion?: string;
|
||||||
valueQuestion: string;
|
valueQuestion: string;
|
||||||
|
answerVariants: {id?: number, text: string}[];
|
||||||
onChangeQuestion: (valueQuestion: string) => void;
|
onChangeQuestion: (valueQuestion: string) => void;
|
||||||
|
onAnswerVariantsChange: (variants: {id?: number, text: string}[]) => void;
|
||||||
onDeleteQuestion: (index: number) => Promise<void>;
|
onDeleteQuestion: (index: number) => Promise<void>;
|
||||||
selectedType: 'single' | 'multiply'; // Уточняем тип
|
selectedType: 'single' | 'multiply';
|
||||||
setSelectedType: (type: 'single' | 'multiply') => void; // Уточняем тип
|
setSelectedType: (type: 'single' | 'multiply') => void;
|
||||||
|
surveyId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QuestionItem: React.FC<QuestionItemProps> = ({questionId, initialTextQuestion = `Вопрос ${questionId}`,
|
const QuestionItem: React.FC<QuestionItemProps> = ({
|
||||||
valueQuestion, onChangeQuestion, onDeleteQuestion, setSelectedType, selectedType}) => {
|
questionId,
|
||||||
// const [selectedType, setSelectedType] = useState<'single' | 'multiply'>('single');
|
initialTextQuestion = `Вопрос ${questionId}`,
|
||||||
const [answerOption, setAnswerOption] = useState(['']);
|
valueQuestion,
|
||||||
|
answerVariants: initialAnswerVariants,
|
||||||
|
onChangeQuestion,
|
||||||
|
onAnswerVariantsChange,
|
||||||
|
onDeleteQuestion,
|
||||||
|
setSelectedType,
|
||||||
|
selectedType,
|
||||||
|
surveyId
|
||||||
|
}) => {
|
||||||
const [textQuestion, setTextQuestion] = useState(initialTextQuestion);
|
const [textQuestion, setTextQuestion] = useState(initialTextQuestion);
|
||||||
const [isEditingQuestion, setIsEditingQuestion] = useState(false);
|
const [isEditingQuestion, setIsEditingQuestion] = useState(false);
|
||||||
|
|
||||||
const [selectedAnswers, setSelectedAnswers] = useState<number[]>([]);
|
const [selectedAnswers, setSelectedAnswers] = useState<number[]>([]);
|
||||||
|
|
||||||
const textareaQuestionRef = useRef<HTMLTextAreaElement>(null);
|
const textareaQuestionRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTextQuestion(valueQuestion);
|
||||||
|
}, [valueQuestion]);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (initialAnswerVariants.length === 0 && surveyId) {
|
||||||
|
// handleAddAnswer();
|
||||||
|
// }
|
||||||
|
// }, [initialAnswerVariants.length, surveyId]);
|
||||||
|
|
||||||
const handleTypeChange = (type: 'single' | 'multiply') => {
|
const handleTypeChange = (type: 'single' | 'multiply') => {
|
||||||
setSelectedType(type);
|
setSelectedType(type);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleAddAnswer = () => {
|
const handleAddAnswer = async () => {
|
||||||
setAnswerOption([...answerOption, '']);
|
if (surveyId) {
|
||||||
|
try {
|
||||||
|
const newAnswer = await addNewAnswerVariant(surveyId, questionId, { text: '' });
|
||||||
|
onAnswerVariantsChange([...initialAnswerVariants, { id: newAnswer.id, text: '' }]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка при добавлении варианта ответа:', error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onAnswerVariantsChange([...initialAnswerVariants, { text: '' }]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleQuestionClick = () => {
|
const handleQuestionClick = () => {
|
||||||
setIsEditingQuestion(true);
|
setIsEditingQuestion(true);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleTextareaQuestionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
const handleTextareaQuestionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
setTextQuestion(event.target.value);
|
setTextQuestion(event.target.value);
|
||||||
|
|
||||||
if (textareaQuestionRef.current) {
|
if (textareaQuestionRef.current) {
|
||||||
textareaQuestionRef.current.style.height = 'auto';
|
textareaQuestionRef.current.style.height = 'auto';
|
||||||
textareaQuestionRef.current.style.height = `${textareaQuestionRef.current.scrollHeight}px`;
|
textareaQuestionRef.current.style.height = `${textareaQuestionRef.current.scrollHeight}px`;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleSaveQuestion = () => {
|
const handleSaveQuestion = () => {
|
||||||
setIsEditingQuestion(false);
|
setIsEditingQuestion(false);
|
||||||
onChangeQuestion(textQuestion);
|
onChangeQuestion(textQuestion);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleQuestionKeyDown = (keyDownEvent: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const handleQuestionKeyDown = (keyDownEvent: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
if (keyDownEvent.key === 'Enter') {
|
if (keyDownEvent.key === 'Enter') {
|
||||||
keyDownEvent.preventDefault();
|
keyDownEvent.preventDefault();
|
||||||
handleSaveQuestion()
|
handleSaveQuestion();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleQuestionBlur = () => {
|
const handleQuestionBlur = () => {
|
||||||
handleSaveQuestion()
|
handleSaveQuestion();
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isEditingQuestion && textareaQuestionRef.current) {
|
if (isEditingQuestion && textareaQuestionRef.current) {
|
||||||
|
|
@ -72,21 +104,51 @@ const QuestionItem: React.FC<QuestionItemProps> = ({questionId, initialTextQuest
|
||||||
}
|
}
|
||||||
}, [isEditingQuestion]);
|
}, [isEditingQuestion]);
|
||||||
|
|
||||||
const handleAnswerChange = (index: number, value: string) => {
|
const handleAnswerChange = async (index: number, value: string) => {
|
||||||
const newAnswerOption = [...answerOption];
|
const newAnswerVariants = [...initialAnswerVariants];
|
||||||
newAnswerOption[index] = value;
|
newAnswerVariants[index] = { ...newAnswerVariants[index], text: value };
|
||||||
setAnswerOption(newAnswerOption);
|
onAnswerVariantsChange(newAnswerVariants);
|
||||||
}
|
|
||||||
|
|
||||||
const handleDeleteAnswer = (index: number) => {
|
// Обновляем на сервере только если вариант уже существует (имеет id)
|
||||||
const newAnswerOption = answerOption.filter((_, i) => i !== index);
|
if (surveyId && newAnswerVariants[index].id) {
|
||||||
setAnswerOption(newAnswerOption);
|
try {
|
||||||
setSelectedAnswers(selectedAnswers.filter((i) => i !== index));
|
await updateAnswerVariant(
|
||||||
|
surveyId,
|
||||||
|
questionId,
|
||||||
|
newAnswerVariants[index].id!,
|
||||||
|
{ text: value }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка при обновлении варианта ответа:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
const handleDeleteAnswer = async (index: number) => {
|
||||||
setTextQuestion(valueQuestion);
|
const answerToDelete = initialAnswerVariants[index];
|
||||||
}, [valueQuestion]);
|
|
||||||
|
if (surveyId && answerToDelete.id) {
|
||||||
|
try {
|
||||||
|
await deleteAnswerVariant(surveyId, questionId, answerToDelete.id);
|
||||||
|
const newAnswerVariants = initialAnswerVariants.filter((_, i) => i !== index);
|
||||||
|
onAnswerVariantsChange(newAnswerVariants);
|
||||||
|
setSelectedAnswers(selectedAnswers.filter((i) => i !== index));
|
||||||
|
|
||||||
|
// Обновляем список после удаления
|
||||||
|
if (surveyId) {
|
||||||
|
const variants = await getAnswerVariants(surveyId, questionId);
|
||||||
|
const answers = variants.map((v: { id: number, text: string }) => ({ id: v.id, text: v.text }));
|
||||||
|
onAnswerVariantsChange(answers);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка при удалении варианта ответа:', error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const newAnswerVariants = initialAnswerVariants.filter((_, i) => i !== index);
|
||||||
|
onAnswerVariantsChange(newAnswerVariants);
|
||||||
|
setSelectedAnswers(selectedAnswers.filter((i) => i !== index));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleDeleteQuestion = async () => {
|
const handleDeleteQuestion = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -133,12 +195,12 @@ const QuestionItem: React.FC<QuestionItemProps> = ({questionId, initialTextQuest
|
||||||
<TypeDropdown selectedType={selectedType} onTypeChange={handleTypeChange}/>
|
<TypeDropdown selectedType={selectedType} onTypeChange={handleTypeChange}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{answerOption.map((answerText, index) => (
|
{initialAnswerVariants.map((answer, index) => (
|
||||||
<AnswerOption
|
<AnswerOption
|
||||||
key={index}
|
key={answer.id || index}
|
||||||
selectedType={selectedType}
|
selectedType={selectedType}
|
||||||
index={index + 1}
|
index={index + 1}
|
||||||
value={answerText}
|
value={answer.text}
|
||||||
onChange={(value) => handleAnswerChange(index, value)}
|
onChange={(value) => handleAnswerChange(index, value)}
|
||||||
onDelete={() => handleDeleteAnswer(index)}
|
onDelete={() => handleDeleteAnswer(index)}
|
||||||
toggleSelect={() => toggleSelect(index)}
|
toggleSelect={() => toggleSelect(index)}
|
||||||
|
|
@ -146,17 +208,15 @@ const QuestionItem: React.FC<QuestionItemProps> = ({questionId, initialTextQuest
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className={styles.questionActions}>
|
<div className={styles.questionActions}>
|
||||||
<AddAnswerButton
|
<AddAnswerButton onClick={handleAddAnswer} />
|
||||||
onClick={handleAddAnswer}
|
|
||||||
/>
|
|
||||||
<button className={styles.deleteQuestionButton} onClick={handleDeleteQuestion}>
|
<button className={styles.deleteQuestionButton} onClick={handleDeleteQuestion}>
|
||||||
Удалить{/**/}
|
Удалить
|
||||||
<Delete className={styles.basketImg}/>
|
<Delete className={styles.basketImg}/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default QuestionItem;
|
export default QuestionItem;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, {useEffect, useState} from "react";
|
import React, {useState} from "react";
|
||||||
import QuestionItem from "../QuestionItem/QuestionItem.tsx";
|
import QuestionItem from "../QuestionItem/QuestionItem.tsx";
|
||||||
import AddQuestionButton from "../AddQuestionButton/AddQuestionButton.tsx";
|
import AddQuestionButton from "../AddQuestionButton/AddQuestionButton.tsx";
|
||||||
import {deleteQuestion, getListQuestions} from "../../api/QuestionApi.ts";
|
import {deleteQuestion, getListQuestions} from "../../api/QuestionApi.ts";
|
||||||
|
|
@ -13,32 +13,25 @@ export interface Question {
|
||||||
id: number;
|
id: number;
|
||||||
text: string;
|
text: string;
|
||||||
questionType: 'singleanswerquestion' | 'multipleanswerquestion';
|
questionType: 'singleanswerquestion' | 'multipleanswerquestion';
|
||||||
answerVariants?: {
|
answerVariants: Array<{
|
||||||
id?: number;
|
id?: number;
|
||||||
text: string;
|
text: string;
|
||||||
}[];
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, surveyId}) => {
|
const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, surveyId}) => {
|
||||||
const [selectedType, setSelectedType] = useState<'single' | 'multiply'>('single');
|
const [selectedType, setSelectedType] = useState<'single' | 'multiply'>('single');
|
||||||
|
|
||||||
const [localQuestionId, setLocalQuestionId] = useState(2);
|
|
||||||
|
|
||||||
const handleAddQuestion = () => {
|
const handleAddQuestion = () => {
|
||||||
const newQuestion: Question = {
|
const newQuestion: Question = {
|
||||||
id: localQuestionId, // ID >= 1001 — новые вопросы
|
id: questions.length + 1, // ID >= 1001 — новые вопросы
|
||||||
text: '',
|
text: '',
|
||||||
questionType: selectedType === 'single' ? 'singleanswerquestion' : 'multipleanswerquestion',
|
questionType: selectedType === 'single' ? 'singleanswerquestion' : 'multipleanswerquestion',
|
||||||
|
answerVariants: [{text: ''}],
|
||||||
};
|
};
|
||||||
setQuestions([...questions, newQuestion]);
|
setQuestions([...questions, newQuestion]);
|
||||||
setLocalQuestionId(localQuestionId + 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setLocalQuestionId(questions.length > 0 ?
|
|
||||||
Math.max(...questions.map(q => q.id)) + 1 : 1);
|
|
||||||
}, [questions]);
|
|
||||||
|
|
||||||
const handleQuestionChange = (id: number, value: string) => {
|
const handleQuestionChange = (id: number, value: string) => {
|
||||||
const newQuestions = questions.map((question) =>
|
const newQuestions = questions.map((question) =>
|
||||||
question.id === id ? { ...question, text: value } : question
|
question.id === id ? { ...question, text: value } : question
|
||||||
|
|
@ -74,6 +67,15 @@ const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, s
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAnswerVariantsChange = (questionId: number, newAnswerVariants: {id?: number, text: string}[]) => {
|
||||||
|
const newQuestions = questions.map(question =>
|
||||||
|
question.id === questionId
|
||||||
|
? {...question, answerVariants: newAnswerVariants}
|
||||||
|
: question
|
||||||
|
);
|
||||||
|
setQuestions(newQuestions);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{questions.map((question) => (
|
{questions.map((question) => (
|
||||||
|
|
@ -81,10 +83,13 @@ const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, s
|
||||||
key={question.id}
|
key={question.id}
|
||||||
questionId={question.id}
|
questionId={question.id}
|
||||||
valueQuestion={question.text}
|
valueQuestion={question.text}
|
||||||
|
answerVariants={question.answerVariants}
|
||||||
|
onAnswerVariantsChange={(variants) => handleAnswerVariantsChange(question.id, variants)}
|
||||||
onDeleteQuestion={() => handleDeleteQuestion(question.id)}
|
onDeleteQuestion={() => handleDeleteQuestion(question.id)}
|
||||||
onChangeQuestion={(value) => handleQuestionChange(question.id, value)}
|
onChangeQuestion={(value) => handleQuestionChange(question.id, value)}
|
||||||
selectedType={selectedType}
|
selectedType={selectedType}
|
||||||
setSelectedType={setSelectedType}
|
setSelectedType={setSelectedType}
|
||||||
|
surveyId={surveyId}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<AddQuestionButton onClick={handleAddQuestion} />
|
<AddQuestionButton onClick={handleAddQuestion} />
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,41 @@ import React, {useState} from 'react';
|
||||||
import SurveyInfo from "../SurveyInfo/SurveyInfo.tsx";
|
import SurveyInfo from "../SurveyInfo/SurveyInfo.tsx";
|
||||||
import styles from "./SettingSurvey.module.css";
|
import styles from "./SettingSurvey.module.css";
|
||||||
import TimeEvent from "../TimeEvent/TimeEvent.tsx";
|
import TimeEvent from "../TimeEvent/TimeEvent.tsx";
|
||||||
|
// import {useParams} from "react-router-dom";
|
||||||
|
// import {getSurveyById, ISurvey} from "../../api/SurveyApi.ts";
|
||||||
|
|
||||||
|
|
||||||
const SettingSurvey: React.FC = () => {
|
const SettingSurvey: React.FC = () => {
|
||||||
const [descriptionSurvey, setDescriptionSurvey] = useState('');
|
const [descriptionSurvey, setDescriptionSurvey] = useState('');
|
||||||
const [titleSurvey, setTitleSurvey] = useState('Название опроса');
|
// const [survey, setSurvey] = useState<ISurvey | null>(null);
|
||||||
|
const [titleSurvey, setTitleSurvey] = useState('');
|
||||||
|
// const { surveyId } = useParams<{ surveyId: string }>();
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (!surveyId) {
|
||||||
|
// console.error('Survey ID is missing');
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// const id = parseInt(surveyId);
|
||||||
|
// if (isNaN(id)) {
|
||||||
|
// console.error('Invalid survey ID');
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const fetchData = async () => {
|
||||||
|
// try {
|
||||||
|
// const surveyData = await getSurveyById(id);
|
||||||
|
// setSurvey(surveyData);
|
||||||
|
// setTitleSurvey(surveyData.title);
|
||||||
|
// setDescriptionSurvey(surveyData.description);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error('Ошибка:', error);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// fetchData();
|
||||||
|
//
|
||||||
|
// }, [surveyId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.settingSurvey}>
|
<div className={styles.settingSurvey}>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import SaveButton from "../SaveButton/SaveButton.tsx";
|
||||||
import {ISurvey, postNewSurvey} from "../../api/SurveyApi.ts";
|
import {ISurvey, postNewSurvey} from "../../api/SurveyApi.ts";
|
||||||
import {addNewQuestion} from "../../api/QuestionApi.ts";
|
import {addNewQuestion} from "../../api/QuestionApi.ts";
|
||||||
import {useNavigate} from "react-router-dom";
|
import {useNavigate} from "react-router-dom";
|
||||||
|
import {addNewAnswerVariant} from "../../api/AnswerApi.ts";
|
||||||
|
|
||||||
const Survey: React.FC = () => {
|
const Survey: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
@ -14,25 +15,9 @@ const Survey: React.FC = () => {
|
||||||
const [survey] = useState<ISurvey | null>(null);
|
const [survey] = useState<ISurvey | null>(null);
|
||||||
|
|
||||||
const [questions, setQuestions] = useState<Question[]>([
|
const [questions, setQuestions] = useState<Question[]>([
|
||||||
{ id: 1, text: '', questionType: 'singleanswerquestion'},
|
{ id: 1, text: '', questionType: 'singleanswerquestion', answerVariants: [{ text: '' }]},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// const handleSave = async () => {
|
|
||||||
// const savedSurvey = await postNewSurvey({title: titleSurvey, description: descriptionSurvey});
|
|
||||||
// setSurvey(savedSurvey);
|
|
||||||
// Promise.all(
|
|
||||||
// questions
|
|
||||||
// .map((question) => addNewQuestion( savedSurvey.id, {title: question.text, questionType: question.questionType })),
|
|
||||||
// )
|
|
||||||
// .then(() => {
|
|
||||||
// alert('Все удачно сохранилось');
|
|
||||||
// })
|
|
||||||
// .catch(() => {
|
|
||||||
// alert('Пиздец');
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
try {
|
try {
|
||||||
const savedSurvey = await postNewSurvey({
|
const savedSurvey = await postNewSurvey({
|
||||||
|
|
@ -40,20 +25,48 @@ const Survey: React.FC = () => {
|
||||||
description: descriptionSurvey
|
description: descriptionSurvey
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(
|
// Сначала создаем все вопросы
|
||||||
questions.map(question =>
|
const updatedQuestions: Question[] = [];
|
||||||
addNewQuestion(savedSurvey.id, {
|
for (const question of questions) {
|
||||||
title: question.text,
|
const newQuestion = await addNewQuestion(savedSurvey.id, {
|
||||||
questionType: question.questionType
|
title: question.text,
|
||||||
})
|
questionType: question.questionType
|
||||||
)
|
});
|
||||||
);
|
|
||||||
|
|
||||||
|
// Создаем копию вопроса с новым ID
|
||||||
|
const updatedQuestion: Question = {
|
||||||
|
...question,
|
||||||
|
id: newQuestion.id,
|
||||||
|
answerVariants: []
|
||||||
|
};
|
||||||
|
|
||||||
|
// Затем создаем варианты ответов для каждого вопроса
|
||||||
|
if (question.answerVariants && question.answerVariants.length > 0) {
|
||||||
|
const newVariants = await Promise.all(
|
||||||
|
question.answerVariants.map(answer =>
|
||||||
|
addNewAnswerVariant(
|
||||||
|
savedSurvey.id,
|
||||||
|
newQuestion.id,
|
||||||
|
{ text: answer.text }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Обновляем варианты ответов с их ID
|
||||||
|
updatedQuestion.answerVariants = newVariants.map((variant: { id: number, text: string }) => ({
|
||||||
|
id: variant.id,
|
||||||
|
text: variant.text
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedQuestions.push(updatedQuestion);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обновляем состояние с новыми ID
|
||||||
|
setQuestions(updatedQuestions);
|
||||||
navigate('/my-surveys');
|
navigate('/my-surveys');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка при сохранении:', error);
|
console.error('Ошибка при сохранении:', error);
|
||||||
alert('Не удалось сохранить опрос');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,174 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
import SurveyInfo from "../SurveyInfo/SurveyInfo.tsx";
|
import SurveyInfo from "../SurveyInfo/SurveyInfo.tsx";
|
||||||
import QuestionsList, {Question} from "../QuestionsList/QuestionsList.tsx";
|
import QuestionsList, { Question } from "../QuestionsList/QuestionsList.tsx";
|
||||||
import {useEffect, useState} from "react";
|
import { getSurveyById, ISurvey, updateSurvey } from "../../api/SurveyApi.ts";
|
||||||
import {getSurveyById, ISurvey, updateSurvey} from "../../api/SurveyApi.ts";
|
import { useParams } from "react-router-dom";
|
||||||
import {useParams} from "react-router-dom";
|
import { addNewQuestion, getListQuestions, updateQuestion, deleteQuestion } from "../../api/QuestionApi.ts";
|
||||||
import {addNewQuestion, getListQuestions, updateQuestion} from "../../api/QuestionApi.ts";
|
|
||||||
import styles from "./SurveyPage.module.css";
|
import styles from "./SurveyPage.module.css";
|
||||||
import SaveButton from "../SaveButton/SaveButton.tsx";
|
import SaveButton from "../SaveButton/SaveButton.tsx";
|
||||||
|
import { addNewAnswerVariant, deleteAnswerVariant, getAnswerVariants, IAnswerVariant, updateAnswerVariant } from "../../api/AnswerApi.ts";
|
||||||
|
|
||||||
type ActionType = 'create' | 'update';
|
// Типы для действий
|
||||||
|
type ActionType =
|
||||||
|
| 'update-survey'
|
||||||
|
| 'create-question'
|
||||||
|
| 'update-question'
|
||||||
|
| 'delete-question'
|
||||||
|
| 'create-answer'
|
||||||
|
| 'update-answer'
|
||||||
|
| 'delete-answer';
|
||||||
|
|
||||||
class QuestionAction {
|
// Интерфейсы для данных действий
|
||||||
|
interface SurveyActionData {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface QuestionActionData {
|
||||||
|
surveyId: number;
|
||||||
|
id?: number;
|
||||||
|
title: string;
|
||||||
|
questionType: 'singleanswerquestion' | 'multipleanswerquestion';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AnswerActionData {
|
||||||
|
surveyId: number;
|
||||||
|
questionId: number;
|
||||||
|
id?: number;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Action {
|
||||||
type: ActionType;
|
type: ActionType;
|
||||||
data: {
|
data: SurveyActionData | QuestionActionData | AnswerActionData;
|
||||||
surveyId: number;
|
tempId?: number;
|
||||||
id?: number;
|
}
|
||||||
title?: string;
|
|
||||||
questionType?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(type: ActionType, data: { surveyId: number, id?: number, title?: string, questionType?: string }) {
|
class ActionQueue {
|
||||||
this.type = type;
|
private actions: Action[] = [];
|
||||||
this.data = data;
|
private idMap: Record<number, number> = {};
|
||||||
|
|
||||||
|
add(action: Action) {
|
||||||
|
this.actions.push(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute() {
|
||||||
|
console.log(`Выполнение очереди с ${this.actions.length} действиями`);
|
||||||
|
for (const [index, action] of this.actions.entries()) {
|
||||||
|
console.log(`Обработка действия ${index + 1}/${this.actions.length}:`, action);
|
||||||
|
try {
|
||||||
|
// ... существующий код
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Ошибка в действии ${index + 1}:`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const action of this.actions) {
|
||||||
|
try {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'update-survey':
|
||||||
|
await this.handleUpdateSurvey(action.data as SurveyActionData);
|
||||||
|
break;
|
||||||
|
case 'create-question': {
|
||||||
|
const createdQuestion = await this.handleCreateQuestion(action.data as QuestionActionData);
|
||||||
|
if (action.tempId) {
|
||||||
|
this.idMap[action.tempId] = createdQuestion.id;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'update-question':
|
||||||
|
await this.handleUpdateQuestion(action.data as QuestionActionData & { id: number });
|
||||||
|
break;
|
||||||
|
case 'delete-question':
|
||||||
|
await this.handleDeleteQuestion(action.data as QuestionActionData & { id: number });
|
||||||
|
break;
|
||||||
|
case 'create-answer': {
|
||||||
|
const answerData = action.data as AnswerActionData;
|
||||||
|
await this.handleCreateAnswer({
|
||||||
|
...answerData,
|
||||||
|
questionId: this.idMap[answerData.questionId] || answerData.questionId
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'update-answer': {
|
||||||
|
const updateAnswerData = action.data as AnswerActionData & { id: number };
|
||||||
|
await this.handleUpdateAnswer({
|
||||||
|
...updateAnswerData,
|
||||||
|
questionId: this.idMap[updateAnswerData.questionId] || updateAnswerData.questionId
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'delete-answer': {
|
||||||
|
const deleteAnswerData = action.data as AnswerActionData & { id: number };
|
||||||
|
await this.handleDeleteAnswer({
|
||||||
|
...deleteAnswerData,
|
||||||
|
questionId: this.idMap[deleteAnswerData.questionId] || deleteAnswerData.questionId
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to execute action ${action.type}:`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleUpdateSurvey(data: SurveyActionData) {
|
||||||
|
return await updateSurvey(data.id, {
|
||||||
|
title: data.title,
|
||||||
|
description: data.description
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleCreateQuestion(data: QuestionActionData) {
|
||||||
|
return await addNewQuestion(data.surveyId, {
|
||||||
|
title: data.title,
|
||||||
|
questionType: data.questionType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleUpdateQuestion(data: QuestionActionData & { id: number }) {
|
||||||
|
return await updateQuestion(data.surveyId, data.id, {
|
||||||
|
title: data.title,
|
||||||
|
questionType: data.questionType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleDeleteQuestion(data: QuestionActionData & { id: number }) {
|
||||||
|
return await deleteQuestion(data.surveyId, data.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleCreateAnswer(data: AnswerActionData) {
|
||||||
|
return await addNewAnswerVariant(data.surveyId, data.questionId, {
|
||||||
|
text: data.text
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleUpdateAnswer(data: AnswerActionData & { id: number }) {
|
||||||
|
console.log('1. Начало handleUpdateAnswer', data);
|
||||||
|
try {
|
||||||
|
console.log('2. Перед вызовом updateAnswerVariant', {
|
||||||
|
surveyId: data.surveyId,
|
||||||
|
questionId: data.questionId,
|
||||||
|
id: data.id,
|
||||||
|
text: data.text
|
||||||
|
});
|
||||||
|
const result = await updateAnswerVariant(data.surveyId, data.questionId, data.id, {
|
||||||
|
text: data.text
|
||||||
|
});
|
||||||
|
console.log('3. После вызова updateAnswerVariant', result);
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('4. Ошибка в handleUpdateAnswer:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleDeleteAnswer(data: AnswerActionData & { id: number }) {
|
||||||
|
return await deleteAnswerVariant(data.surveyId, data.questionId, data.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,7 +182,6 @@ export const SurveyPage: React.FC = () => {
|
||||||
const [description, setDescription] = useState('');
|
const [description, setDescription] = useState('');
|
||||||
const [title, setTitle] = useState('');
|
const [title, setTitle] = useState('');
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!surveyId) {
|
if (!surveyId) {
|
||||||
console.error('Survey ID is missing');
|
console.error('Survey ID is missing');
|
||||||
|
|
@ -52,20 +199,26 @@ export const SurveyPage: React.FC = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const surveyData = await getSurveyById(id);
|
const surveyData = await getSurveyById(id);
|
||||||
setSurvey(surveyData);
|
setSurvey(surveyData);
|
||||||
|
|
||||||
setTitle(surveyData.title);
|
setTitle(surveyData.title);
|
||||||
setDescription(surveyData.description);
|
setDescription(surveyData.description);
|
||||||
|
|
||||||
const questionsData = await getListQuestions(id);
|
const questionsData = await getListQuestions(id);
|
||||||
const formattedQuestions = questionsData.map(q => ({
|
const formattedQuestions = await Promise.all(questionsData.map(async q => {
|
||||||
id: q.id,
|
const answerVariants = await getAnswerVariants(id, q.id);
|
||||||
text: q.title,
|
return {
|
||||||
questionType: q.questionType as 'singleanswerquestion' | 'multipleanswerquestion',
|
id: q.id,
|
||||||
|
text: q.title,
|
||||||
|
questionType: q.questionType as 'singleanswerquestion' | 'multipleanswerquestion',
|
||||||
|
answerVariants: answerVariants.map((a: IAnswerVariant) => ({
|
||||||
|
id: a.id,
|
||||||
|
text: a.text
|
||||||
|
}))
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
setQuestions(formattedQuestions);
|
setQuestions(formattedQuestions);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка:', error);
|
console.error('Ошибка:', error);
|
||||||
setError('Не удалось загрузить опрос')
|
setError('Не удалось загрузить опрос');
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
@ -74,77 +227,127 @@ export const SurveyPage: React.FC = () => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [surveyId]);
|
}, [surveyId]);
|
||||||
|
|
||||||
if (loading) return <div>Загрузка...</div>;
|
|
||||||
if (!survey) return <div>Опрос не найден</div>;
|
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
if (!surveyId || !survey) return;
|
console.log('0. Начало handleSave');
|
||||||
|
if (!surveyId || !survey) {
|
||||||
|
console.log('0.1. Прерывание - нет surveyId или survey', { surveyId, survey });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setError(null);
|
setError(null);
|
||||||
const id = parseInt(surveyId);
|
const id = parseInt(surveyId);
|
||||||
|
const actionQueue = new ActionQueue();
|
||||||
|
|
||||||
const surveyUpdated = await updateSurvey(id, {
|
// 1. Обновление опроса
|
||||||
title: title,
|
actionQueue.add({
|
||||||
description: description,
|
type: 'update-survey',
|
||||||
|
data: { id, title, description } as SurveyActionData
|
||||||
});
|
});
|
||||||
setSurvey(surveyUpdated);
|
|
||||||
|
|
||||||
const actions: QuestionAction[] = [];
|
// 2. Получаем текущие вопросы с сервера
|
||||||
const serverQuestions = await getListQuestions(id);
|
const serverQuestions = await getListQuestions(id);
|
||||||
|
|
||||||
|
// 3. Обработка вопросов
|
||||||
questions.forEach(question => {
|
questions.forEach(question => {
|
||||||
const existsOnServer = serverQuestions.some(q => q.id === question.id);
|
const isNewQuestion = !serverQuestions.some(q => q.id === question.id);
|
||||||
|
|
||||||
if (existsOnServer) {
|
if (isNewQuestion) {
|
||||||
actions.push(new QuestionAction("update", {
|
actionQueue.add({
|
||||||
surveyId: id,
|
type: 'create-question',
|
||||||
id: question.id,
|
data: {
|
||||||
title: question.text,
|
surveyId: id,
|
||||||
questionType: question.questionType
|
title: question.text,
|
||||||
}));
|
questionType: question.questionType
|
||||||
|
} as QuestionActionData,
|
||||||
|
tempId: question.id
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
actions.push(new QuestionAction("create", {
|
// Обновляем только если текст изменился
|
||||||
surveyId: id,
|
const serverQuestion = serverQuestions.find(q => q.id === question.id);
|
||||||
title: question.text,
|
if (serverQuestion && (serverQuestion.title !== question.text || serverQuestion.questionType !== question.questionType)) {
|
||||||
questionType: question.questionType
|
actionQueue.add({
|
||||||
}));
|
type: 'update-question',
|
||||||
|
data: {
|
||||||
|
surveyId: id,
|
||||||
|
id: question.id,
|
||||||
|
title: question.text,
|
||||||
|
questionType: question.questionType
|
||||||
|
} as QuestionActionData & { id: number }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Обработка вариантов ответов
|
||||||
|
if (question.answerVariants) {
|
||||||
|
question.answerVariants.forEach(answer => {
|
||||||
|
if (isNewQuestion || !answer.id) {
|
||||||
|
actionQueue.add({
|
||||||
|
type: 'create-answer',
|
||||||
|
data: {
|
||||||
|
surveyId: id,
|
||||||
|
questionId: question.id,
|
||||||
|
text: answer.text
|
||||||
|
} as AnswerActionData,
|
||||||
|
tempId: question.id
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Обновляем только если текст изменился
|
||||||
|
actionQueue.add({
|
||||||
|
type: 'update-answer',
|
||||||
|
data: {
|
||||||
|
surveyId: id,
|
||||||
|
questionId: question.id,
|
||||||
|
id: answer.id,
|
||||||
|
text: answer.text
|
||||||
|
} as AnswerActionData & { id: number }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const action of actions) {
|
// 5. Удаление удаленных вопросов
|
||||||
switch (action.type) {
|
serverQuestions.forEach(serverQuestion => {
|
||||||
case "create":
|
if (!questions.some(q => q.id === serverQuestion.id)) {
|
||||||
await addNewQuestion(id, {
|
actionQueue.add({
|
||||||
title: action.data.title as string,
|
type: 'delete-question',
|
||||||
questionType: action.data.questionType as 'singleanswerquestion' | 'multipleanswerquestion',
|
data: {
|
||||||
});
|
surveyId: id,
|
||||||
break;
|
id: serverQuestion.id
|
||||||
case "update":
|
} as QuestionActionData & { id: number }
|
||||||
if (action.data.id) {
|
});
|
||||||
await updateQuestion(id, action.data.id, {
|
|
||||||
title: action.data.title,
|
|
||||||
questionType: action.data.questionType
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
// Выполняем все действия
|
||||||
|
await actionQueue.execute();
|
||||||
|
|
||||||
|
// Обновляем данные
|
||||||
const updatedQuestions = await getListQuestions(id);
|
const updatedQuestions = await getListQuestions(id);
|
||||||
const formattedQuestions = updatedQuestions.map(q => ({
|
const formattedQuestions = await Promise.all(updatedQuestions.map(async q => {
|
||||||
id: q.id,
|
const answerVariants = await getAnswerVariants(id, q.id);
|
||||||
text: q.title,
|
return {
|
||||||
questionType: q.questionType as 'singleanswerquestion' | 'multipleanswerquestion',
|
id: q.id,
|
||||||
|
text: q.title,
|
||||||
|
questionType: q.questionType as 'singleanswerquestion' | 'multipleanswerquestion',
|
||||||
|
answerVariants: answerVariants.map((a: IAnswerVariant) => ({
|
||||||
|
id: a.id,
|
||||||
|
text: a.text
|
||||||
|
}))
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
setQuestions(formattedQuestions);
|
setQuestions(formattedQuestions);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка:', error);
|
console.error('Ошибка сохранения:', error);
|
||||||
setError('Не удалось сохранить изменения');
|
setError(`Ошибка сохранения: ${error instanceof Error ? error.message : 'Неизвестная ошибка'}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (loading) return <div>Загрузка...</div>;
|
||||||
|
if (!survey) return <div>Опрос не найден</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.survey_page}>
|
<div className={styles.survey_page}>
|
||||||
<SurveyInfo
|
<SurveyInfo
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue