fix add new answer

This commit is contained in:
Tatiana Nikolaeva 2025-05-25 20:24:54 +05:00
parent 15ec6b9632
commit 6eb03dc112
10 changed files with 87 additions and 160 deletions

View file

@ -11,7 +11,7 @@ interface IRegistrationData extends IAuthData{
lastName: string; lastName: string;
} }
export const getCurrentUser = async (user: IRegistrationData) => { export const getCurrentUser = async () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
if (!token) { if (!token) {
@ -23,12 +23,7 @@ export const getCurrentUser = async (user: 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);

View file

@ -51,30 +51,6 @@ export const getAllSurveys = async (): Promise<ISurvey[]> => {
* postNewSurvey - добавление нового опроса * postNewSurvey - добавление нового опроса
* @param survey * @param survey
*/ */
// export const postNewSurvey = async (survey: INewSurvey): Promise<ISurvey> => {
// const token = localStorage.getItem("token");
// if (!token) {
// throw new Error("Токен отсутствует");
// }
//
// try{
// const response = await fetch(`${BASE_URL}/surveys`, {
// ...createRequestConfig('POST'),
// body: JSON.stringify(survey)
// })
//
// // return await handleResponse(response);
//
// if (response.status === 200) {
// return await handleResponse(response);
// }
// throw new Error(`Ожидался код 200, получен ${response.status}`);
// } catch (error) {
// console.error(`Error when adding a new survey: ${error}`);
// throw error;
// }
// }
export const postNewSurvey = async (survey: INewSurvey): Promise<ISurvey> => { export const postNewSurvey = async (survey: INewSurvey): Promise<ISurvey> => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
if (!token) { if (!token) {

View file

@ -29,7 +29,6 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDe
const handleTextareaChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => { const handleTextareaChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
setCurrentValue(event.target.value); setCurrentValue(event.target.value);
// Автоматическое изменение высоты
if (textAreaRef.current) { if (textAreaRef.current) {
textAreaRef.current.style.height = 'auto'; textAreaRef.current.style.height = 'auto';
textAreaRef.current.style.height = `${textAreaRef.current.scrollHeight}px`; textAreaRef.current.style.height = `${textAreaRef.current.scrollHeight}px`;

View file

@ -24,13 +24,6 @@ export const MySurveyList = () => {
setSurveys(surveysWithStatus); setSurveys(surveysWithStatus);
} catch (error) { } catch (error) {
console.error('Ошибка при получении списка опросов:', error); console.error('Ошибка при получении списка опросов:', error);
// if (error instanceof Error && error.message.includes("401")) {
// // Если ошибка 401, перенаправляем на страницу входа
// navigate('/login');
// } else {
// alert("Ошибка при загрузке опросов: " + (error instanceof Error && error.message));
// }
} }
}; };
fetchSurvey(); fetchSurvey();
@ -52,12 +45,6 @@ export const MySurveyList = () => {
} }
} catch (error) { } catch (error) {
console.error('Ошибка при удалении опроса:', error); console.error('Ошибка при удалении опроса:', error);
// if (error instanceof Error && error.message.includes("401")) {
// navigate('/login');
// } else {
// alert("Ошибка при удалении опроса: " + (error instanceof Error ? error.message : 'Неизвестная ошибка'));
// }
} }
}; };

View file

@ -26,7 +26,8 @@ interface QuestionItemProps {
const QuestionItem: React.FC<QuestionItemProps> = ({ const QuestionItem: React.FC<QuestionItemProps> = ({
questionId, questionId,
initialTextQuestion = `Вопрос ${questionId}`, // initialTextQuestion = `Вопрос ${questionId}`,
initialTextQuestion = `Вопрос`,
valueQuestion, valueQuestion,
answerVariants: initialAnswerVariants, answerVariants: initialAnswerVariants,
onChangeQuestion, onChangeQuestion,
@ -45,26 +46,24 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
setTextQuestion(valueQuestion); setTextQuestion(valueQuestion);
}, [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 = async () => { const handleAddAnswer = async () => {
if (surveyId) { 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: '' }]); onAnswerVariantsChange([...initialAnswerVariants, { text: '' }]);
return;
}
try {
const newAnswer = await addNewAnswerVariant(surveyId, questionId, { text: '' });
onAnswerVariantsChange([...initialAnswerVariants, {
id: newAnswer.id,
text: newAnswer.text
}]);
} catch (error) {
console.error('Ошибка при добавлении варианта ответа:', error);
} }
}; };
@ -109,7 +108,6 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
newAnswerVariants[index] = { ...newAnswerVariants[index], text: value }; newAnswerVariants[index] = { ...newAnswerVariants[index], text: value };
onAnswerVariantsChange(newAnswerVariants); onAnswerVariantsChange(newAnswerVariants);
// Обновляем на сервере только если вариант уже существует (имеет id)
if (surveyId && newAnswerVariants[index].id) { if (surveyId && newAnswerVariants[index].id) {
try { try {
await updateAnswerVariant( await updateAnswerVariant(
@ -134,7 +132,6 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
onAnswerVariantsChange(newAnswerVariants); onAnswerVariantsChange(newAnswerVariants);
setSelectedAnswers(selectedAnswers.filter((i) => i !== index)); setSelectedAnswers(selectedAnswers.filter((i) => i !== index));
// Обновляем список после удаления
if (surveyId) { if (surveyId) {
const variants = await getAnswerVariants(surveyId, questionId); const variants = await getAnswerVariants(surveyId, questionId);
const answers = variants.map((v: { id: number, text: string }) => ({ id: v.id, text: v.text })); const answers = variants.map((v: { id: number, text: string }) => ({ id: v.id, text: v.text }));

View file

@ -1,7 +1,8 @@
import React, {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 {addNewQuestion, deleteQuestion, getListQuestions} from "../../api/QuestionApi.ts";
import {addNewAnswerVariant} from "../../api/AnswerApi.ts";
interface QuestionsListProps { interface QuestionsListProps {
questions: Question[]; questions: Question[];
@ -22,14 +23,38 @@ export interface Question {
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 handleAddQuestion = () => { const handleAddQuestion = async () => {
const newQuestion: Question = { if (!surveyId) {
id: questions.length + 1, // ID >= 1001 — новые вопросы const newQuestion: Question = {
text: '', id: questions.length + 1,
questionType: selectedType === 'single' ? 'singleanswerquestion' : 'multipleanswerquestion', text: '',
answerVariants: [{text: ''}], questionType: selectedType === 'single' ? 'singleanswerquestion' : 'multipleanswerquestion',
}; answerVariants: [{ text: '' }],
setQuestions([...questions, newQuestion]); };
setQuestions([...questions, newQuestion]);
return;
}
try {
const newQuestion = await addNewQuestion(surveyId, {
title: '',
questionType: selectedType === 'single' ? 'singleanswerquestion' : 'multipleanswerquestion'
});
const questionToAdd: Question = {
id: newQuestion.id,
text: newQuestion.title,
questionType: newQuestion.questionType as 'singleanswerquestion' | 'multipleanswerquestion',
answerVariants: []
};
const newAnswer = await addNewAnswerVariant(surveyId, newQuestion.id, { text: '' });
questionToAdd.answerVariants = [{ id: newAnswer.id, text: newAnswer.text }];
setQuestions([...questions, questionToAdd]);
} catch (error) {
console.error('Ошибка при добавлении вопроса:', error);
}
}; };
const handleQuestionChange = (id: number, value: string) => { const handleQuestionChange = (id: number, value: string) => {

View file

@ -48,14 +48,13 @@
opacity: 0; opacity: 0;
} }
/* Отключаем стиль для input, когда в нём есть данные */
.input:not(:placeholder-shown) { .input:not(:placeholder-shown) {
color: black; color: black;
opacity: 1; opacity: 1;
} }
.input:focus { .input:focus {
border-bottom: 2px solid black; /* Чёрная граница при фокусе */ border-bottom: 2px solid black;
} }
.signUp{ .signUp{

View file

@ -25,7 +25,6 @@ const Survey: React.FC = () => {
description: descriptionSurvey description: descriptionSurvey
}); });
// Сначала создаем все вопросы
const updatedQuestions: Question[] = []; const updatedQuestions: Question[] = [];
for (const question of questions) { for (const question of questions) {
const newQuestion = await addNewQuestion(savedSurvey.id, { const newQuestion = await addNewQuestion(savedSurvey.id, {
@ -33,14 +32,12 @@ const Survey: React.FC = () => {
questionType: question.questionType questionType: question.questionType
}); });
// Создаем копию вопроса с новым ID
const updatedQuestion: Question = { const updatedQuestion: Question = {
...question, ...question,
id: newQuestion.id, id: newQuestion.id,
answerVariants: [] answerVariants: []
}; };
// Затем создаем варианты ответов для каждого вопроса
if (question.answerVariants && question.answerVariants.length > 0) { if (question.answerVariants && question.answerVariants.length > 0) {
const newVariants = await Promise.all( const newVariants = await Promise.all(
question.answerVariants.map(answer => question.answerVariants.map(answer =>
@ -52,7 +49,6 @@ const Survey: React.FC = () => {
) )
); );
// Обновляем варианты ответов с их ID
updatedQuestion.answerVariants = newVariants.map((variant: { id: number, text: string }) => ({ updatedQuestion.answerVariants = newVariants.map((variant: { id: number, text: string }) => ({
id: variant.id, id: variant.id,
text: variant.text text: variant.text
@ -62,7 +58,6 @@ const Survey: React.FC = () => {
updatedQuestions.push(updatedQuestion); updatedQuestions.push(updatedQuestion);
} }
// Обновляем состояние с новыми ID
setQuestions(updatedQuestions); setQuestions(updatedQuestions);
navigate('/my-surveys'); navigate('/my-surveys');
} catch (error) { } catch (error) {

View file

@ -8,7 +8,6 @@ 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"; import { addNewAnswerVariant, deleteAnswerVariant, getAnswerVariants, IAnswerVariant, updateAnswerVariant } from "../../api/AnswerApi.ts";
// Типы для действий
type ActionType = type ActionType =
| 'update-survey' | 'update-survey'
| 'create-question' | 'create-question'
@ -18,7 +17,6 @@ type ActionType =
| 'update-answer' | 'update-answer'
| 'delete-answer'; | 'delete-answer';
// Интерфейсы для данных действий
interface SurveyActionData { interface SurveyActionData {
id: number; id: number;
title: string; title: string;
@ -54,16 +52,6 @@ class ActionQueue {
} }
async execute() { 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) { for (const action of this.actions) {
try { try {
switch (action.type) { switch (action.type) {
@ -147,21 +135,13 @@ class ActionQueue {
} }
private async handleUpdateAnswer(data: AnswerActionData & { id: number }) { private async handleUpdateAnswer(data: AnswerActionData & { id: number }) {
console.log('1. Начало handleUpdateAnswer', data);
try { 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, { const result = await updateAnswerVariant(data.surveyId, data.questionId, data.id, {
text: data.text text: data.text
}); });
console.log('3. После вызова updateAnswerVariant', result);
return result; return result;
} catch (error) { } catch (error) {
console.error('4. Ошибка в handleUpdateAnswer:', error); console.error(error);
throw error; throw error;
} }
@ -228,86 +208,62 @@ export const SurveyPage: React.FC = () => {
}, [surveyId]); }, [surveyId]);
const handleSave = async () => { const handleSave = async () => {
console.log('0. Начало handleSave'); if (!surveyId || !survey) return;
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 actionQueue = new ActionQueue();
// 1. Обновление опроса
actionQueue.add({ actionQueue.add({
type: 'update-survey', type: 'update-survey',
data: { id, title, description } as SurveyActionData data: { id, title, description } as SurveyActionData
}); });
// 2. Получаем текущие вопросы с сервера
const serverQuestions = await getListQuestions(id); const serverQuestions = await getListQuestions(id);
// 3. Обработка вопросов
questions.forEach(question => { questions.forEach(question => {
const isNewQuestion = !serverQuestions.some(q => q.id === question.id); const serverQuestion = serverQuestions.find(q => q.id === question.id);
if (serverQuestion &&
if (isNewQuestion) { (serverQuestion.title !== question.text ||
serverQuestion.questionType !== question.questionType)) {
actionQueue.add({ actionQueue.add({
type: 'create-question', type: 'update-question',
data: { data: {
surveyId: id, surveyId: id,
id: question.id,
title: question.text, title: question.text,
questionType: question.questionType questionType: question.questionType
} as QuestionActionData, } as QuestionActionData & { id: number }
tempId: question.id
});
} else {
// Обновляем только если текст изменился
const serverQuestion = serverQuestions.find(q => q.id === question.id);
if (serverQuestion && (serverQuestion.title !== question.text || serverQuestion.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 }
});
}
}); });
} }
}); });
// 5. Удаление удаленных вопросов questions.forEach(question => {
question.answerVariants.forEach(answer => {
if (!answer.id) {
actionQueue.add({
type: 'create-answer',
data: {
surveyId: id,
questionId: question.id,
text: answer.text
} as AnswerActionData
});
} else {
actionQueue.add({
type: 'update-answer',
data: {
surveyId: id,
questionId: question.id,
id: answer.id,
text: answer.text
} as AnswerActionData & { id: number }
});
}
});
});
serverQuestions.forEach(serverQuestion => { serverQuestions.forEach(serverQuestion => {
if (!questions.some(q => q.id === serverQuestion.id)) { if (!questions.some(q => q.id === serverQuestion.id)) {
actionQueue.add({ actionQueue.add({
@ -320,10 +276,8 @@ export const SurveyPage: React.FC = () => {
} }
}); });
// Выполняем все действия
await actionQueue.execute(); await actionQueue.execute();
// Обновляем данные
const updatedQuestions = await getListQuestions(id); const updatedQuestions = await getListQuestions(id);
const formattedQuestions = await Promise.all(updatedQuestions.map(async q => { const formattedQuestions = await Promise.all(updatedQuestions.map(async q => {
const answerVariants = await getAnswerVariants(id, q.id); const answerVariants = await getAnswerVariants(id, q.id);

View file

@ -23,7 +23,7 @@
.inputDate{ .inputDate{
border: 3px solid #007AFF26; border: 3px solid #007AFF26;
padding: 12px 107px 12px 21px; padding: 12px 107px 12px 21px;
font-size: 20px; /*??????????????????????? в макете указано bodyLarge/Size*/ font-size: 20px;
font-weight: 400; font-weight: 400;
border-radius: 3px; border-radius: 3px;
} }
@ -31,7 +31,7 @@
.inputTime{ .inputTime{
border: 3px solid #007AFF26; border: 3px solid #007AFF26;
padding: 12px 42px; padding: 12px 42px;
font-size: 20px; /*??????????????????????? в макете указано bodyLarge/Size*/ font-size: 20px;
font-weight: 400; font-weight: 400;
border-radius: 3px; border-radius: 3px;
} }