fixed getting data for completing a survey
This commit is contained in:
parent
88dcb63232
commit
2ec9354fc1
13 changed files with 128 additions and 55 deletions
|
|
@ -9,7 +9,6 @@ import {MySurveyList} from "./components/MySurveyList/MySurveyList.tsx";
|
||||||
import AuthForm from "./pages/AuthForm/AuthForm.tsx";
|
import AuthForm from "./pages/AuthForm/AuthForm.tsx";
|
||||||
import {SurveyPage} from "./components/SurveyPage/SurveyPage.tsx";
|
import {SurveyPage} from "./components/SurveyPage/SurveyPage.tsx";
|
||||||
import CompleteSurvey from "./pages/CompleteSurvey/CompleteSurvey.tsx";
|
import CompleteSurvey from "./pages/CompleteSurvey/CompleteSurvey.tsx";
|
||||||
import CompletingSurvey from "./components/CompletingSurvey/CompletingSurvey.tsx";
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return(
|
return(
|
||||||
|
|
@ -33,9 +32,7 @@ const App = () => {
|
||||||
<Route path="results" element={<Results />} />
|
<Route path="results" element={<Results />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path='/complete-survey' element={<CompleteSurvey/>}>
|
<Route path='/complete-survey/:surveyId' element={<CompleteSurvey/>}/>
|
||||||
<Route index element={<CompletingSurvey/>}/>
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route path="*" element={<AuthForm />} />
|
<Route path="*" element={<AuthForm />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,9 @@
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
width: 70%;
|
/*width: 70%;*/
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
margin-right: 150px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import Multiple from '../../assets/emptyCheckbox.svg?react';
|
||||||
import SelectedSingle from '../../assets/radio_button_checked.svg?react'
|
import SelectedSingle from '../../assets/radio_button_checked.svg?react'
|
||||||
import SelectedMultiple from '../../assets/check_box.svg?react';
|
import SelectedMultiple from '../../assets/check_box.svg?react';
|
||||||
import TextareaAutosize from 'react-textarea-autosize';
|
import TextareaAutosize from 'react-textarea-autosize';
|
||||||
|
import {useRouteReadOnly} from "../../hooks/useRouteReadOnly.ts";
|
||||||
|
|
||||||
interface AnswerOptionProps{
|
interface AnswerOptionProps{
|
||||||
index: number;
|
index: number;
|
||||||
|
|
@ -15,14 +16,14 @@ interface AnswerOptionProps{
|
||||||
selectedType: 'SingleAnswerQuestion' | 'MultipleAnswerQuestion';
|
selectedType: 'SingleAnswerQuestion' | 'MultipleAnswerQuestion';
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
toggleSelect?: () => void;
|
toggleSelect?: () => void;
|
||||||
isCompleteSurveyActive?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDelete, selectedType, isSelected, toggleSelect, isCompleteSurveyActive = false}) => {
|
const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDelete, selectedType, isSelected, toggleSelect}) => {
|
||||||
const [currentValue, setCurrentValue] = useState(value);
|
const [currentValue, setCurrentValue] = useState(value);
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
|
|
||||||
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
const isReadOnly = useRouteReadOnly();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentValue(value);
|
setCurrentValue(value);
|
||||||
|
|
@ -71,7 +72,7 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDe
|
||||||
}, [isEditing]);
|
}, [isEditing]);
|
||||||
|
|
||||||
const handleMarkerClick = () => {
|
const handleMarkerClick = () => {
|
||||||
if (isCompleteSurveyActive && toggleSelect) {
|
if (isReadOnly && toggleSelect) {
|
||||||
toggleSelect();
|
toggleSelect();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -79,7 +80,7 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDe
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.answer}>
|
<div className={styles.answer}>
|
||||||
{isCompleteSurveyActive ? (
|
{isReadOnly ? (
|
||||||
<button
|
<button
|
||||||
className={`${styles.buttonMarker} ${isSelected ? styles.selected : ''}`}
|
className={`${styles.buttonMarker} ${isSelected ? styles.selected : ''}`}
|
||||||
onClick={handleMarkerClick}
|
onClick={handleMarkerClick}
|
||||||
|
|
@ -108,7 +109,7 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDe
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isCompleteSurveyActive ? (
|
{isReadOnly ? (
|
||||||
<button className={styles.textAnswer}>
|
<button className={styles.textAnswer}>
|
||||||
{currentValue || `Ответ ${index}`}
|
{currentValue || `Ответ ${index}`}
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -128,7 +129,7 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDe
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isCompleteSurveyActive && (
|
{!isReadOnly && (
|
||||||
<button className={styles.deleteButton} onClick={() => onDelete?.(index)}>
|
<button className={styles.deleteButton} onClick={() => onDelete?.(index)}>
|
||||||
<Delete />
|
<Delete />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,85 @@
|
||||||
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 {useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import styles from './CompletingSurvey.module.css'
|
import styles from './CompletingSurvey.module.css'
|
||||||
|
import { useParams} from "react-router-dom";
|
||||||
|
import {getSurveyById, ISurvey} from "../../api/SurveyApi.ts";
|
||||||
|
import {getListQuestions} from "../../api/QuestionApi.ts";
|
||||||
|
import {getAnswerVariants, IAnswerVariant} from "../../api/AnswerVariantsApi.ts";
|
||||||
|
|
||||||
export const CompletingSurvey = () => {
|
export const CompletingSurvey = () => {
|
||||||
const [titleSurvey, setTitleSurvey] = useState("Название опроса");
|
// const [titleSurvey, setTitleSurvey] = useState("Название опроса");
|
||||||
const [descriptionSurvey, setDescriptionSurvey] = useState("");
|
// const [descriptionSurvey, setDescriptionSurvey] = useState("");
|
||||||
const [questions, setQuestions] = useState<Question[]>([
|
// const [questions, setQuestions] = useState<Question[]>([
|
||||||
{ id: 1, text: 'Вопрос 1', questionType: 'SingleAnswerQuestion', answerVariants: [{ id: 1, text: 'Ответ 1' },
|
// { id: 1, text: 'Вопрос 1', questionType: 'SingleAnswerQuestion', answerVariants: [{ id: 1, text: 'Ответ 1' },
|
||||||
{ id: 2, text: 'Ответ 1' }, { id: 3, text: 'Ответ 1' }]},
|
// { id: 2, text: 'Ответ 1' }, { id: 3, text: 'Ответ 1' }]},
|
||||||
{ id: 2, text: 'Вопрос 2', questionType: 'MultipleAnswerQuestion', answerVariants: [{ id: 1, text: 'Ответ 1' },
|
// { id: 2, text: 'Вопрос 2', questionType: 'MultipleAnswerQuestion', answerVariants: [{ id: 1, text: 'Ответ 1' },
|
||||||
{ id: 2, text: 'Ответ 1' }, { id: 3, text: 'Ответ 1' }]}
|
// { id: 2, text: 'Ответ 1' }, { id: 3, text: 'Ответ 1' }]}
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
|
// const [questions, setQuestions] = useState<Question[]>([]);
|
||||||
|
// const [loading, setLoading] = useState(true);
|
||||||
|
// const [error, setError] = useState<string | null>(null);
|
||||||
|
//
|
||||||
|
// const [description, setDescription] = useState('');
|
||||||
|
// const [title, setTitle] = useState('');
|
||||||
|
//
|
||||||
|
// const { survey, setSurvey } = useOutletContext<{
|
||||||
|
// survey: ISurvey;
|
||||||
|
// setSurvey: (survey: ISurvey) => void;
|
||||||
|
// }>();
|
||||||
|
|
||||||
|
const {surveyId} = useParams<{surveyId: string}>();
|
||||||
|
const [survey, setSurvey] = useState<ISurvey | null>(null);
|
||||||
|
const [questions, setQuestions] = useState<Question[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchSurveyData = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
if (!surveyId) return;
|
||||||
|
|
||||||
|
const surveyData = await getSurveyById(parseInt(surveyId));
|
||||||
|
setSurvey(surveyData);
|
||||||
|
|
||||||
|
const questionsData = await getListQuestions(parseInt(surveyId));
|
||||||
|
const formattedQuestions = await Promise.all(questionsData.map(async q => {
|
||||||
|
const answerVariants = await getAnswerVariants(parseInt(surveyId), q.id);
|
||||||
|
return {
|
||||||
|
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);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка загрузки опроса:', error);
|
||||||
|
setError('Не удалось загрузить опрос');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchSurveyData();
|
||||||
|
}, [surveyId]);
|
||||||
|
|
||||||
|
if (loading) return <div>Загрузка...</div>;
|
||||||
|
if (error) return <div>{error}</div>;
|
||||||
|
if (!survey) return <div>Опрос не найден</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.survey}>
|
<div className={styles.survey}>
|
||||||
<SurveyInfo
|
<SurveyInfo
|
||||||
titleSurvey={titleSurvey}
|
titleSurvey={survey.title}
|
||||||
descriptionSurvey={descriptionSurvey}
|
descriptionSurvey={survey.description}
|
||||||
setDescriptionSurvey={setDescriptionSurvey}
|
setDescriptionSurvey={(value) => setSurvey({ ...survey, description: value })}
|
||||||
setTitleSurvey={setTitleSurvey}
|
setTitleSurvey={(value) => setSurvey({ ...survey, title: value })}
|
||||||
/>
|
/>
|
||||||
<QuestionsList
|
<QuestionsList
|
||||||
questions={questions}
|
questions={questions}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ const Header: React.FC = () => {
|
||||||
|
|
||||||
const isCreateSurveyActive = location.pathname.startsWith('/survey/create');
|
const isCreateSurveyActive = location.pathname.startsWith('/survey/create');
|
||||||
const isMySurveysActive = location.pathname === '/my-surveys';
|
const isMySurveysActive = location.pathname === '/my-surveys';
|
||||||
const isCompleteSurveyActive = location.pathname === '/complete-survey';
|
|
||||||
|
|
||||||
const isSurveyViewPage = location.pathname.startsWith('/survey/') &&
|
const isSurveyViewPage = location.pathname.startsWith('/survey/') &&
|
||||||
!location.pathname.startsWith('/survey/create');
|
!location.pathname.startsWith('/survey/create');
|
||||||
|
|
@ -37,13 +36,6 @@ const Header: React.FC = () => {
|
||||||
Мои опросы
|
Мои опросы
|
||||||
{(isMySurveysActive || isSurveyViewPage) && <hr className={styles.activeLine}/>}
|
{(isMySurveysActive || isSurveyViewPage) && <hr className={styles.activeLine}/>}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
|
||||||
to='/complete-survey'
|
|
||||||
className={`${styles.pageLink} ${isCompleteSurveyActive ? styles.active : ''}`}
|
|
||||||
>
|
|
||||||
Прохождение опроса
|
|
||||||
{isCompleteSurveyActive && <hr className={styles.activeLine}/>}
|
|
||||||
</Link>
|
|
||||||
</nav>
|
</nav>
|
||||||
<Account href={'/profile'} />
|
<Account href={'/profile'} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import {
|
||||||
getAnswerVariants,
|
getAnswerVariants,
|
||||||
updateAnswerVariant
|
updateAnswerVariant
|
||||||
} from "../../api/AnswerVariantsApi.ts";
|
} from "../../api/AnswerVariantsApi.ts";
|
||||||
import {useLocation} from "react-router-dom";
|
|
||||||
import TextareaAutosize from "react-textarea-autosize";
|
import TextareaAutosize from "react-textarea-autosize";
|
||||||
|
import {useRouteReadOnly} from "../../hooks/useRouteReadOnly.ts";
|
||||||
|
|
||||||
interface QuestionItemProps {
|
interface QuestionItemProps {
|
||||||
questionId: number;
|
questionId: number;
|
||||||
|
|
@ -23,7 +23,6 @@ interface QuestionItemProps {
|
||||||
onDeleteQuestion: (index: number) => Promise<void>;
|
onDeleteQuestion: (index: number) => Promise<void>;
|
||||||
initialQuestionType: 'SingleAnswerQuestion' | 'MultipleAnswerQuestion';
|
initialQuestionType: 'SingleAnswerQuestion' | 'MultipleAnswerQuestion';
|
||||||
onQuestionTypeChange: (type: 'SingleAnswerQuestion' | 'MultipleAnswerQuestion') => void;
|
onQuestionTypeChange: (type: 'SingleAnswerQuestion' | 'MultipleAnswerQuestion') => void;
|
||||||
|
|
||||||
surveyId?: number;
|
surveyId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,8 +44,7 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
|
||||||
const [questionType, setQuestionType] = useState<'SingleAnswerQuestion' | 'MultipleAnswerQuestion'>(initialQuestionType);
|
const [questionType, setQuestionType] = useState<'SingleAnswerQuestion' | 'MultipleAnswerQuestion'>(initialQuestionType);
|
||||||
const textareaQuestionRef = useRef<HTMLTextAreaElement>(null);
|
const textareaQuestionRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
const location = useLocation();
|
const isReadOnly = useRouteReadOnly();
|
||||||
const isCompleteSurveyActive = location.pathname === '/complete-survey';
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -63,6 +61,8 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddAnswer = async () => {
|
const handleAddAnswer = async () => {
|
||||||
|
if (isReadOnly) return
|
||||||
|
|
||||||
if (!surveyId) {
|
if (!surveyId) {
|
||||||
onAnswerVariantsChange([...initialAnswerVariants, { text: '' }]);
|
onAnswerVariantsChange([...initialAnswerVariants, { text: '' }]);
|
||||||
return;
|
return;
|
||||||
|
|
@ -167,10 +167,8 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
|
||||||
|
|
||||||
const toggleSelect = (index: number) => {
|
const toggleSelect = (index: number) => {
|
||||||
if (initialQuestionType === 'SingleAnswerQuestion') {
|
if (initialQuestionType === 'SingleAnswerQuestion') {
|
||||||
// Для одиночного выбора: заменяем массив одним выбранным индексом
|
|
||||||
setSelectedAnswers([index]);
|
setSelectedAnswers([index]);
|
||||||
} else {
|
} else {
|
||||||
// Для множественного выбора: добавляем/удаляем индекс
|
|
||||||
setSelectedAnswers(prev =>
|
setSelectedAnswers(prev =>
|
||||||
prev.includes(index)
|
prev.includes(index)
|
||||||
? prev.filter(i => i !== index)
|
? prev.filter(i => i !== index)
|
||||||
|
|
@ -181,7 +179,7 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.questionCard}>
|
<div className={styles.questionCard}>
|
||||||
{isCompleteSurveyActive ? (
|
{isReadOnly ? (
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.questionContainer}>
|
<div className={styles.questionContainer}>
|
||||||
<h2 className={styles.textQuestion}>{textQuestion || initialTextQuestion}</h2>
|
<h2 className={styles.textQuestion}>{textQuestion || initialTextQuestion}</h2>
|
||||||
|
|
@ -194,7 +192,6 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
|
||||||
value={answer.text}
|
value={answer.text}
|
||||||
isSelected={selectedAnswers.includes(index)}
|
isSelected={selectedAnswers.includes(index)}
|
||||||
toggleSelect={() => toggleSelect(index)}
|
toggleSelect={() => toggleSelect(index)}
|
||||||
isCompleteSurveyActive={isCompleteSurveyActive}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import QuestionItem from "../QuestionItem/QuestionItem.tsx";
|
||||||
import AddQuestionButton from "../AddQuestionButton/AddQuestionButton.tsx";
|
import AddQuestionButton from "../AddQuestionButton/AddQuestionButton.tsx";
|
||||||
import {addNewQuestion, deleteQuestion, getListQuestions} from "../../api/QuestionApi.ts";
|
import {addNewQuestion, deleteQuestion, getListQuestions} from "../../api/QuestionApi.ts";
|
||||||
import {addNewAnswerVariant} from "../../api/AnswerVariantsApi.ts";
|
import {addNewAnswerVariant} from "../../api/AnswerVariantsApi.ts";
|
||||||
import {useLocation} from "react-router-dom";
|
|
||||||
import styles from './QuestionsList.module.css'
|
import styles from './QuestionsList.module.css'
|
||||||
|
import {useRouteReadOnly} from "../../hooks/useRouteReadOnly.ts";
|
||||||
|
|
||||||
interface QuestionsListProps {
|
interface QuestionsListProps {
|
||||||
questions: Question[];
|
questions: Question[];
|
||||||
|
|
@ -23,8 +23,7 @@ export interface Question {
|
||||||
}
|
}
|
||||||
|
|
||||||
const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, surveyId}) => {
|
const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, surveyId}) => {
|
||||||
const location = useLocation();
|
const isReadOnly = useRouteReadOnly();
|
||||||
const isCompleteSurveyActive = location.pathname === '/complete-survey';
|
|
||||||
|
|
||||||
const handleAddQuestion = async () => {
|
const handleAddQuestion = async () => {
|
||||||
if (!surveyId) {
|
if (!surveyId) {
|
||||||
|
|
@ -128,7 +127,7 @@ const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, s
|
||||||
surveyId={surveyId}
|
surveyId={surveyId}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{!isCompleteSurveyActive ? <AddQuestionButton onClick={handleAddQuestion} /> : (
|
{!isReadOnly ? <AddQuestionButton onClick={handleAddQuestion} /> : (
|
||||||
<button className={styles.departur_button}>Отправить</button>
|
<button className={styles.departur_button}>Отправить</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,19 @@
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyButton {
|
||||||
|
padding: 10px 15px;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyButton:hover {
|
||||||
|
background-color: #45a049;
|
||||||
}
|
}
|
||||||
|
|
@ -18,6 +18,15 @@ const SettingSurvey: React.FC = () => {
|
||||||
const [descriptionSurvey, setDescriptionSurvey] = useState('');
|
const [descriptionSurvey, setDescriptionSurvey] = useState('');
|
||||||
const [titleSurvey, setTitleSurvey] = useState('');
|
const [titleSurvey, setTitleSurvey] = useState('');
|
||||||
|
|
||||||
|
const handleCopyLink = () => {
|
||||||
|
if (!survey?.id)
|
||||||
|
return;
|
||||||
|
const link = `${window.location.origin}/complete-survey/${survey.id}`;
|
||||||
|
navigator.clipboard.writeText(link)
|
||||||
|
.then(() => console.log('Copied!'))
|
||||||
|
.catch(error => console.error(`Не удалось скопировать ссылку: ${error}`));
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.settingSurvey}>
|
<div className={styles.settingSurvey}>
|
||||||
{isSettingCreatePage ? (
|
{isSettingCreatePage ? (
|
||||||
|
|
@ -43,6 +52,7 @@ const SettingSurvey: React.FC = () => {
|
||||||
<h2>Параметры видимости</h2>
|
<h2>Параметры видимости</h2>
|
||||||
</div>
|
</div>
|
||||||
<SaveButton onClick={() => {}}/>
|
<SaveButton onClick={() => {}}/>
|
||||||
|
<button onClick={handleCopyLink} className={styles.copyButton}>Копировать ссылку</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import styles from './SurveyInfo.module.css'
|
||||||
import AddDescripImg from '../../assets/add_circle.svg?react';
|
import AddDescripImg from '../../assets/add_circle.svg?react';
|
||||||
import TextareaAutosize from 'react-textarea-autosize';
|
import TextareaAutosize from 'react-textarea-autosize';
|
||||||
import {useLocation} from "react-router-dom";
|
import {useLocation} from "react-router-dom";
|
||||||
|
import {useRouteReadOnly} from "../../hooks/useRouteReadOnly.ts";
|
||||||
|
|
||||||
|
|
||||||
interface SurveyInfoProps {
|
interface SurveyInfoProps {
|
||||||
|
|
@ -20,10 +21,11 @@ const SurveyInfo: React.FC<SurveyInfoProps> = ({titleSurvey, setDescriptionSurve
|
||||||
const descriptionTextareaRef = useRef<HTMLTextAreaElement>(null);
|
const descriptionTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const isCompleteSurveyActive = location.pathname === '/complete-survey';
|
|
||||||
const isSurveyViewPage = location.pathname.startsWith('/survey/') &&
|
const isSurveyViewPage = location.pathname.startsWith('/survey/') &&
|
||||||
!location.pathname.startsWith('/survey/create');
|
!location.pathname.startsWith('/survey/create');
|
||||||
|
|
||||||
|
const isReadOnly = useRouteReadOnly();
|
||||||
|
|
||||||
const handleDescriptionChange = (descripEvent: React.ChangeEvent<HTMLTextAreaElement>) => {
|
const handleDescriptionChange = (descripEvent: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
setDescriptionSurvey?.(descripEvent.target.value);
|
setDescriptionSurvey?.(descripEvent.target.value);
|
||||||
};
|
};
|
||||||
|
|
@ -88,7 +90,7 @@ const SurveyInfo: React.FC<SurveyInfoProps> = ({titleSurvey, setDescriptionSurve
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderTitle = () => {
|
const renderTitle = () => {
|
||||||
if (isCompleteSurveyActive) {
|
if (isReadOnly) {
|
||||||
return (
|
return (
|
||||||
<button className={styles.titleSurvey}>
|
<button className={styles.titleSurvey}>
|
||||||
<h1>{titleSurvey || 'Название опроса'}</h1>
|
<h1>{titleSurvey || 'Название опроса'}</h1>
|
||||||
|
|
@ -120,7 +122,7 @@ const SurveyInfo: React.FC<SurveyInfoProps> = ({titleSurvey, setDescriptionSurve
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderDescription = () => {
|
const renderDescription = () => {
|
||||||
if (isCompleteSurveyActive) {
|
if (isReadOnly) {
|
||||||
return descriptionSurvey ? (
|
return descriptionSurvey ? (
|
||||||
<p className={styles.desc}>{descriptionSurvey}</p>
|
<p className={styles.desc}>{descriptionSurvey}</p>
|
||||||
) : 'Описание';
|
) : 'Описание';
|
||||||
|
|
@ -167,7 +169,7 @@ const SurveyInfo: React.FC<SurveyInfoProps> = ({titleSurvey, setDescriptionSurve
|
||||||
{renderTitle()}
|
{renderTitle()}
|
||||||
{renderDescription()}
|
{renderDescription()}
|
||||||
|
|
||||||
{(isSurveyViewPage || isCompleteSurveyActive) && createdAt && (
|
{(isSurveyViewPage || isReadOnly) && createdAt && (
|
||||||
<p className={styles.createdAt}>Дата создания: {addDate()}</p>
|
<p className={styles.createdAt}>Дата создания: {addDate()}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -153,11 +153,9 @@ class ActionQueue {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SurveyPage: React.FC = () => {
|
export const SurveyPage: React.FC = () => {
|
||||||
// const [survey, setSurvey] = useState<ISurvey | null>(null);
|
|
||||||
const [questions, setQuestions] = useState<Question[]>([]);
|
const [questions, setQuestions] = useState<Question[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
// const { surveyId } = useParams<{ surveyId: string }>();
|
|
||||||
|
|
||||||
const [description, setDescription] = useState('');
|
const [description, setDescription] = useState('');
|
||||||
const [title, setTitle] = useState('');
|
const [title, setTitle] = useState('');
|
||||||
|
|
@ -173,7 +171,6 @@ export const SurveyPage: React.FC = () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const id = parseInt(survey.id);
|
|
||||||
const id = survey.id;
|
const id = survey.id;
|
||||||
if (isNaN(id)) {
|
if (isNaN(id)) {
|
||||||
console.error('Invalid survey ID');
|
console.error('Invalid survey ID');
|
||||||
|
|
@ -183,7 +180,6 @@ export const SurveyPage: React.FC = () => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
// const surveyData = await getSurveyById(id);
|
|
||||||
setSurvey(survey);
|
setSurvey(survey);
|
||||||
setTitle(survey.title);
|
setTitle(survey.title);
|
||||||
setDescription(survey.description);
|
setDescription(survey.description);
|
||||||
|
|
@ -218,7 +214,6 @@ export const SurveyPage: React.FC = () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setError(null);
|
setError(null);
|
||||||
// const id = parseInt(survey.id);
|
|
||||||
const id = survey.id;
|
const id = survey.id;
|
||||||
const actionQueue = new ActionQueue();
|
const actionQueue = new ActionQueue();
|
||||||
|
|
||||||
|
|
|
||||||
6
SurveyFrontend/src/hooks/useRouteReadOnly.ts
Normal file
6
SurveyFrontend/src/hooks/useRouteReadOnly.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
export const useRouteReadOnly = () => {
|
||||||
|
const location = useLocation();
|
||||||
|
return location.pathname.includes('/complete-survey/');
|
||||||
|
};
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import Header from "../../components/Header/Header.tsx";
|
|
||||||
import styles from './CompleteSurvey.module.css'
|
import styles from './CompleteSurvey.module.css'
|
||||||
import CompletingSurvey from "../../components/CompletingSurvey/CompletingSurvey.tsx";
|
import CompletingSurvey from "../../components/CompletingSurvey/CompletingSurvey.tsx";
|
||||||
|
|
||||||
export const CompleteSurvey = () => {
|
export const CompleteSurvey = () => {
|
||||||
return(
|
return(
|
||||||
<div className={styles.layout}>
|
<div className={styles.layout}>
|
||||||
<Header/>
|
|
||||||
<CompletingSurvey/>
|
<CompletingSurvey/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue