add page completing survey
This commit is contained in:
parent
8182bc1c43
commit
4f1a7cc434
15 changed files with 333 additions and 120 deletions
|
|
@ -8,6 +8,8 @@ import {Results} from "./components/Results/Results.tsx";
|
|||
import {MySurveyList} from "./components/MySurveyList/MySurveyList.tsx";
|
||||
import AuthForm from "./pages/AuthForm/AuthForm.tsx";
|
||||
import {SurveyPage} from "./components/SurveyPage/SurveyPage.tsx";
|
||||
import CompleteSurvey from "./pages/CompleteSurvey/CompleteSurvey.tsx";
|
||||
import CompletingSurvey from "./components/CompletingSurvey/CompletingSurvey.tsx";
|
||||
|
||||
const App = () => {
|
||||
return(
|
||||
|
|
@ -31,6 +33,10 @@ const App = () => {
|
|||
<Route path="results" element={<Results />} />
|
||||
</Route>
|
||||
|
||||
<Route path='/complete-survey' element={<CompleteSurvey/>}>
|
||||
<Route index element={<CompletingSurvey/>}/>
|
||||
</Route>
|
||||
|
||||
<Route path="*" element={<AuthForm />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
|
|
|
|||
|
|
@ -3,17 +3,22 @@ import styles from'./AnswerOption.module.css';
|
|||
import Delete from '../../assets/delete.svg?react';
|
||||
import Single from '../../assets/radio_button_unchecked.svg?react';
|
||||
import Multiple from '../../assets/emptyCheckbox.svg?react';
|
||||
import SelectedSingle from '../../assets/radio_button_checked.svg?react'
|
||||
import SelectedMultiple from '../../assets/check_box.svg?react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
|
||||
interface AnswerOptionProps{
|
||||
index: number;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
onDelete:(index: number) => void;
|
||||
onChange?: (value: string) => void;
|
||||
onDelete?:(index: number) => void;
|
||||
selectedType: 'SingleAnswerQuestion' | 'MultipleAnswerQuestion';
|
||||
toggleSelect: () => void;
|
||||
isSelected?: boolean;
|
||||
toggleSelect?: () => void;
|
||||
isCompleteSurveyActive?: boolean;
|
||||
}
|
||||
|
||||
const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDelete, selectedType, toggleSelect}) => {
|
||||
const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDelete, selectedType, isSelected, toggleSelect, isCompleteSurveyActive = false}) => {
|
||||
const [currentValue, setCurrentValue] = useState(value);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
|
||||
|
|
@ -45,7 +50,7 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDe
|
|||
|
||||
const handleSave = () => {
|
||||
setIsEditing(false);
|
||||
onChange(currentValue);
|
||||
onChange?.(currentValue);
|
||||
};
|
||||
|
||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
|
|
@ -65,16 +70,50 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDe
|
|||
}
|
||||
}, [isEditing]);
|
||||
|
||||
const handleMarkerClick = () => {
|
||||
if (isCompleteSurveyActive && toggleSelect) {
|
||||
toggleSelect();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className={styles.answer}>
|
||||
<button
|
||||
className={`${styles.buttonMarker} ${isEditing ? styles.editing : ''}`}
|
||||
onClick={toggleSelect}
|
||||
>
|
||||
{selectedType === 'SingleAnswerQuestion' ? < Single className={styles.answerIcon} /> : <Multiple className={styles.answerIcon} />}
|
||||
</button>
|
||||
{isEditing ? (
|
||||
<textarea
|
||||
{isCompleteSurveyActive ? (
|
||||
<button
|
||||
className={`${styles.buttonMarker} ${isSelected ? styles.selected : ''}`}
|
||||
onClick={handleMarkerClick}
|
||||
>
|
||||
{selectedType === 'SingleAnswerQuestion' ? (
|
||||
isSelected ? (
|
||||
<SelectedSingle className={styles.answerIcon} />
|
||||
) : (
|
||||
<Single className={styles.answerIcon} />
|
||||
)
|
||||
) : (
|
||||
isSelected ? (
|
||||
<SelectedMultiple className={styles.answerIcon} />
|
||||
) : (
|
||||
<Multiple className={styles.answerIcon} />
|
||||
)
|
||||
)}
|
||||
</button>
|
||||
) : (
|
||||
<button className={styles.buttonMarker}>
|
||||
{selectedType === 'SingleAnswerQuestion' ? (
|
||||
<Single className={styles.answerIcon} />
|
||||
) : (
|
||||
<Multiple className={styles.answerIcon} />
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{isCompleteSurveyActive ? (
|
||||
<button className={styles.textAnswer}>
|
||||
{currentValue || `Ответ ${index}`}
|
||||
</button>
|
||||
) : isEditing ? (
|
||||
<TextareaAutosize
|
||||
className={styles.answerInput}
|
||||
ref={textAreaRef}
|
||||
value={currentValue}
|
||||
|
|
@ -88,12 +127,14 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, onDe
|
|||
{currentValue || `Ответ ${index}`}
|
||||
</button>
|
||||
)}
|
||||
<button className={styles.deleteButton} onClick={() => onDelete(index)}>
|
||||
<Delete />
|
||||
</button>
|
||||
|
||||
{!isCompleteSurveyActive && (
|
||||
<button className={styles.deleteButton} onClick={() => onDelete?.(index)}>
|
||||
<Delete />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
export default AnswerOption;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
.survey{
|
||||
width: 68%;
|
||||
background-color: #F6F6F6;
|
||||
max-width: 100vw;
|
||||
min-height: 100vh;
|
||||
padding: 34px 16%;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import SurveyInfo from "../SurveyInfo/SurveyInfo.tsx";
|
||||
import QuestionsList, {Question} from "../QuestionsList/QuestionsList.tsx";
|
||||
import {useState} from "react";
|
||||
import styles from './CompletingSurvey.module.css'
|
||||
|
||||
export const CompletingSurvey = () => {
|
||||
const [titleSurvey, setTitleSurvey] = useState("Название опроса");
|
||||
const [descriptionSurvey, setDescriptionSurvey] = useState("");
|
||||
const [questions, setQuestions] = useState<Question[]>([
|
||||
{ id: 1, text: 'Вопрос 1', questionType: 'SingleAnswerQuestion', answerVariants: [{ id: 1, text: 'Ответ 1' },
|
||||
{ id: 2, text: 'Ответ 1' }, { id: 3, text: 'Ответ 1' }]},
|
||||
{ id: 2, text: 'Вопрос 2', questionType: 'MultipleAnswerQuestion', answerVariants: [{ id: 1, text: 'Ответ 1' },
|
||||
{ id: 2, text: 'Ответ 1' }, { id: 3, text: 'Ответ 1' }]}
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className={styles.survey}>
|
||||
<SurveyInfo
|
||||
titleSurvey={titleSurvey}
|
||||
descriptionSurvey={descriptionSurvey}
|
||||
setDescriptionSurvey={setDescriptionSurvey}
|
||||
setTitleSurvey={setTitleSurvey}
|
||||
/>
|
||||
<QuestionsList
|
||||
questions={questions}
|
||||
setQuestions={setQuestions}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CompletingSurvey
|
||||
|
|
@ -12,8 +12,7 @@
|
|||
gap: 60px;
|
||||
list-style: none;
|
||||
align-items: center;
|
||||
margin-right: 40%;
|
||||
|
||||
margin-right: 20%;
|
||||
}
|
||||
|
||||
.pageLink{
|
||||
|
|
|
|||
|
|
@ -7,9 +7,13 @@ import {Link, useLocation, useNavigate} from "react-router-dom";
|
|||
const Header: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const isCreateSurveyActive = location.pathname.includes('/survey/create');
|
||||
const isSurveyPage = location.pathname.includes('/survey/') && !location.pathname.includes('/survey/create');
|
||||
const isMySurveysPage = location.pathname === '/my-surveys' || isSurveyPage;
|
||||
|
||||
const isCreateSurveyActive = location.pathname.startsWith('/survey/create');
|
||||
const isMySurveysActive = location.pathname === '/my-surveys';
|
||||
const isCompleteSurveyActive = location.pathname === '/complete-survey';
|
||||
|
||||
const isSurveyViewPage = location.pathname.startsWith('/survey/') &&
|
||||
!location.pathname.startsWith('/survey/create');
|
||||
|
||||
const handleLogoClick = () => {
|
||||
navigate(location.pathname, { replace: true });
|
||||
|
|
@ -19,15 +23,26 @@ const Header: React.FC = () => {
|
|||
<div className={styles.header}>
|
||||
<Logo href={location.pathname} onClick={handleLogoClick} />
|
||||
<nav className={styles.pagesNav}>
|
||||
<Link to='/survey/create/questions'
|
||||
className={`${styles.pageLink} ${isCreateSurveyActive ? styles.active : ''}`}>
|
||||
<Link
|
||||
to='/survey/create/questions'
|
||||
className={`${styles.pageLink} ${isCreateSurveyActive ? styles.active : ''}`}
|
||||
>
|
||||
Создать опрос
|
||||
{isCreateSurveyActive && <hr className={styles.activeLine}/>}
|
||||
</Link>
|
||||
<Link to='/my-surveys'
|
||||
className={`${styles.pageLink} ${isMySurveysPage ? styles.active : ''}`}>
|
||||
<Link
|
||||
to='/my-surveys'
|
||||
className={`${styles.pageLink} ${isMySurveysActive || isSurveyViewPage ? styles.active : ''}`}
|
||||
>
|
||||
Мои опросы
|
||||
{isMySurveysPage && <hr className={styles.activeLine}/>}
|
||||
{(isMySurveysActive || isSurveyViewPage) && <hr className={styles.activeLine}/>}
|
||||
</Link>
|
||||
<Link
|
||||
to='/complete-survey'
|
||||
className={`${styles.pageLink} ${isCompleteSurveyActive ? styles.active : ''}`}
|
||||
>
|
||||
Прохождение опроса
|
||||
{isCompleteSurveyActive && <hr className={styles.activeLine}/>}
|
||||
</Link>
|
||||
</nav>
|
||||
<Account href={'/profile'} />
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
.main {
|
||||
background-color: #F6F6F6;
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
min-height: 100vh;
|
||||
padding: 34px 10%;
|
||||
padding-top: 34px;
|
||||
padding-left: 12%;
|
||||
}
|
||||
|
||||
.survey {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import {
|
|||
getAnswerVariants,
|
||||
updateAnswerVariant
|
||||
} from "../../api/AnswerApi.ts";
|
||||
import {useLocation} from "react-router-dom";
|
||||
import TextareaAutosize from "react-textarea-autosize";
|
||||
|
||||
interface QuestionItemProps {
|
||||
questionId: number;
|
||||
|
|
@ -43,6 +45,10 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
|
|||
const [questionType, setQuestionType] = useState<'SingleAnswerQuestion' | 'MultipleAnswerQuestion'>(initialQuestionType);
|
||||
const textareaQuestionRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const location = useLocation();
|
||||
const isCompleteSurveyActive = location.pathname === '/complete-survey';
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setTextQuestion(valueQuestion);
|
||||
}, [valueQuestion]);
|
||||
|
|
@ -162,62 +168,81 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
|
|||
};
|
||||
|
||||
const toggleSelect = (index: number) => {
|
||||
if (questionType === 'SingleAnswerQuestion') {
|
||||
if (initialQuestionType === 'SingleAnswerQuestion') {
|
||||
// Для одиночного выбора: заменяем массив одним выбранным индексом
|
||||
setSelectedAnswers([index]);
|
||||
} else {
|
||||
setSelectedAnswers((prev) => {
|
||||
if (prev.includes(index)) {
|
||||
return prev.filter((i) => i !== index);
|
||||
} else {
|
||||
return [...prev, index];
|
||||
}
|
||||
});
|
||||
// Для множественного выбора: добавляем/удаляем индекс
|
||||
setSelectedAnswers(prev =>
|
||||
prev.includes(index)
|
||||
? prev.filter(i => i !== index)
|
||||
: [...prev, index]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.questionCard}>
|
||||
<div className={styles.questionContainer}>
|
||||
<div className={styles.question}>
|
||||
{isEditingQuestion ? (
|
||||
<textarea
|
||||
className={styles.questionTextarea}
|
||||
ref={textareaQuestionRef}
|
||||
value={textQuestion === initialTextQuestion ? '' : textQuestion}
|
||||
onChange={handleTextareaQuestionChange}
|
||||
onKeyDown={handleQuestionKeyDown}
|
||||
onBlur={handleQuestionBlur}
|
||||
placeholder={initialTextQuestion}
|
||||
rows={1}
|
||||
{isCompleteSurveyActive ? (
|
||||
<div>
|
||||
<div className={styles.questionContainer}>
|
||||
<h2 className={styles.textQuestion}>{textQuestion || initialTextQuestion}</h2>
|
||||
</div>
|
||||
{initialAnswerVariants.map((answer, index) => (
|
||||
<AnswerOption
|
||||
key={answer.id || index}
|
||||
selectedType={initialQuestionType}
|
||||
index={index + 1}
|
||||
value={answer.text}
|
||||
isSelected={selectedAnswers.includes(index)}
|
||||
toggleSelect={() => toggleSelect(index)}
|
||||
isCompleteSurveyActive={isCompleteSurveyActive}
|
||||
/>
|
||||
) : (
|
||||
<button className={styles.buttonQuestion} onClick={handleQuestionClick}>
|
||||
<h2 className={styles.textQuestion}>{textQuestion || initialTextQuestion}</h2>
|
||||
</button>
|
||||
)}
|
||||
<TypeDropdown selectedType={questionType} onTypeChange={handleTypeChange}/>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.questionContainer}>
|
||||
<div className={styles.question}>
|
||||
{isEditingQuestion ? (
|
||||
<TextareaAutosize
|
||||
className={styles.questionTextarea}
|
||||
ref={textareaQuestionRef}
|
||||
value={textQuestion === initialTextQuestion ? '' : textQuestion}
|
||||
onChange={handleTextareaQuestionChange}
|
||||
onKeyDown={handleQuestionKeyDown}
|
||||
onBlur={handleQuestionBlur}
|
||||
placeholder={initialTextQuestion}
|
||||
rows={1}
|
||||
/>
|
||||
) : (
|
||||
<button className={styles.buttonQuestion} onClick={handleQuestionClick}>
|
||||
<h2 className={styles.textQuestion}>{textQuestion || initialTextQuestion}</h2>
|
||||
</button>
|
||||
)}
|
||||
<TypeDropdown selectedType={questionType} onTypeChange={handleTypeChange}/>
|
||||
</div>
|
||||
|
||||
{initialAnswerVariants.map((answer, index) => (
|
||||
<AnswerOption
|
||||
key={answer.id || index}
|
||||
selectedType={questionType}
|
||||
index={index + 1}
|
||||
value={answer.text}
|
||||
onChange={(value) => handleAnswerChange(index, value)}
|
||||
onDelete={() => handleDeleteAnswer(index)}
|
||||
toggleSelect={() => toggleSelect(index)}
|
||||
/>
|
||||
))}
|
||||
{initialAnswerVariants.map((answer, index) => (
|
||||
<AnswerOption
|
||||
key={answer.id || index}
|
||||
selectedType={questionType}
|
||||
index={index + 1}
|
||||
value={answer.text}
|
||||
onChange={(value) => handleAnswerChange(index, value)}
|
||||
onDelete={() => handleDeleteAnswer(index)}
|
||||
toggleSelect={() => toggleSelect(index)}
|
||||
/>
|
||||
))}
|
||||
|
||||
<div className={styles.questionActions}>
|
||||
<AddAnswerButton onClick={handleAddAnswer} />
|
||||
<button className={styles.deleteQuestionButton} onClick={handleDeleteQuestion}>
|
||||
Удалить
|
||||
<Delete className={styles.basketImg}/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.questionActions}>
|
||||
<AddAnswerButton onClick={handleAddAnswer} />
|
||||
<button className={styles.deleteQuestionButton} onClick={handleDeleteQuestion}>
|
||||
Удалить
|
||||
<Delete className={styles.basketImg}/>
|
||||
</button>
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,2 +1,16 @@
|
|||
/*QuestionsList.module.css*/
|
||||
|
||||
.departur_button{
|
||||
display: block;
|
||||
margin: 10px auto;
|
||||
padding: 25px 50.5px;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
background-color: #3788D6;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
box-shadow: 0 0 7.4px 0 rgba(154, 202, 247, 1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@ import QuestionItem from "../QuestionItem/QuestionItem.tsx";
|
|||
import AddQuestionButton from "../AddQuestionButton/AddQuestionButton.tsx";
|
||||
import {addNewQuestion, deleteQuestion, getListQuestions} from "../../api/QuestionApi.ts";
|
||||
import {addNewAnswerVariant} from "../../api/AnswerApi.ts";
|
||||
import {useLocation} from "react-router-dom";
|
||||
import styles from './QuestionsList.module.css'
|
||||
|
||||
interface QuestionsListProps {
|
||||
questions: Question[];
|
||||
|
|
@ -21,6 +23,9 @@ export interface Question {
|
|||
}
|
||||
|
||||
const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, surveyId}) => {
|
||||
const location = useLocation();
|
||||
const isCompleteSurveyActive = location.pathname === '/complete-survey';
|
||||
|
||||
const handleAddQuestion = async () => {
|
||||
if (!surveyId) {
|
||||
const newQuestion: Question = {
|
||||
|
|
@ -123,7 +128,10 @@ const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, s
|
|||
surveyId={surveyId}
|
||||
/>
|
||||
))}
|
||||
<AddQuestionButton onClick={handleAddQuestion} />
|
||||
{!isCompleteSurveyActive ? <AddQuestionButton onClick={handleAddQuestion} /> : (
|
||||
<button className={styles.departur_button}>Отправить</button>
|
||||
)}
|
||||
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,37 +7,45 @@
|
|||
margin-top: 34px;
|
||||
margin-bottom: 49px;
|
||||
border-radius: 14px;
|
||||
min-height: 191px;
|
||||
/*min-height: 191px;*/
|
||||
/*max-height: 100vh;*/
|
||||
max-height: fit-content;
|
||||
}
|
||||
|
||||
.info{
|
||||
min-width: 373px;
|
||||
display: block;
|
||||
/*display: block;*/
|
||||
padding: 35px;
|
||||
display: flex; /* Добавляем flex */
|
||||
flex-direction: column; /* Элементы в колонку */
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.titleSurvey{
|
||||
width: 80%;
|
||||
display: block;
|
||||
border: none;
|
||||
margin: 0 auto;
|
||||
margin: 0 auto 13px;
|
||||
background-color: white;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 23px;
|
||||
/*margin-bottom: 23px;*/
|
||||
/*margin-bottom: 15px;*/
|
||||
word-break: break-word;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.textareaTitle,
|
||||
.textareaDescrip {
|
||||
width: 100%;
|
||||
width: 80%;
|
||||
max-width: 100%;
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin: 0 auto;
|
||||
background: transparent;
|
||||
display: block;
|
||||
overflow-y: hidden;
|
||||
|
|
@ -48,7 +56,7 @@
|
|||
font-weight: 600;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
min-height: 40px;
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
.textareaDescrip {
|
||||
|
|
@ -67,7 +75,7 @@
|
|||
|
||||
.description {
|
||||
border: none;
|
||||
font-size: 18px;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
|
|
@ -78,6 +86,15 @@
|
|||
word-break: break-word;
|
||||
}
|
||||
|
||||
.desc{
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
background-color: white;
|
||||
max-width: 80%;
|
||||
word-break: break-word;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.descripButton{
|
||||
border: none;
|
||||
|
|
@ -97,4 +114,11 @@
|
|||
font-weight: 500;
|
||||
color: #7D7983;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.createdAt{
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #7D7983;
|
||||
}
|
||||
|
|
@ -2,27 +2,34 @@ import React, {useState, useRef, useEffect} from "react";
|
|||
import styles from './SurveyInfo.module.css'
|
||||
import AddDescripImg from '../../assets/add_circle.svg?react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import {useLocation} from "react-router-dom";
|
||||
|
||||
|
||||
interface SurveyInfoProps {
|
||||
titleSurvey: string;
|
||||
descriptionSurvey: string;
|
||||
setDescriptionSurvey: (text: string) => void;
|
||||
setTitleSurvey: (text: string) => void;
|
||||
setDescriptionSurvey?: (text: string) => void;
|
||||
setTitleSurvey?: (text: string) => void;
|
||||
createdAt?: Date;
|
||||
}
|
||||
|
||||
const SurveyInfo: React.FC<SurveyInfoProps> = ({titleSurvey, setDescriptionSurvey, descriptionSurvey, setTitleSurvey}) => {
|
||||
const SurveyInfo: React.FC<SurveyInfoProps> = ({titleSurvey, setDescriptionSurvey, descriptionSurvey, setTitleSurvey, createdAt = new Date()}) => {
|
||||
const [showDescriptionField, setShowDescriptionField] = useState(false);
|
||||
const [showNewTitleField, setShowNewTitleField] = useState(false);
|
||||
const titleTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const descriptionTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const location = useLocation();
|
||||
const isCompleteSurveyActive = location.pathname === '/complete-survey';
|
||||
const isSurveyViewPage = location.pathname.startsWith('/survey/') &&
|
||||
!location.pathname.startsWith('/survey/create');
|
||||
|
||||
const handleDescriptionChange = (descripEvent: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setDescriptionSurvey(descripEvent.target.value);
|
||||
setDescriptionSurvey?.(descripEvent.target.value);
|
||||
};
|
||||
|
||||
const handleNewTitleChange = (titleEvent: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setTitleSurvey(titleEvent.target.value);
|
||||
setTitleSurvey?.(titleEvent.target.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -72,8 +79,52 @@ const SurveyInfo: React.FC<SurveyInfoProps> = ({titleSurvey, setDescriptionSurve
|
|||
setShowDescriptionField(false);
|
||||
};
|
||||
|
||||
const addDate = () => {
|
||||
const year = createdAt.getFullYear();
|
||||
const month = String(createdAt.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(createdAt.getDate()).padStart(2, '0');
|
||||
return `${day}/${month}/${year}`;
|
||||
}
|
||||
|
||||
const renderTitle = () => {
|
||||
if (isSurveyViewPage || isCompleteSurveyActive) {
|
||||
return (
|
||||
<button className={styles.titleSurvey}>
|
||||
<h1>{titleSurvey || 'Название опроса'}</h1>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
if (showNewTitleField) {
|
||||
return (
|
||||
<h1 className={styles.titleSurvey}>
|
||||
<TextareaAutosize
|
||||
className={styles.textareaTitle}
|
||||
ref={titleTextareaRef}
|
||||
value={titleSurvey === 'Название опроса' ? '' : titleSurvey}
|
||||
placeholder={'Название опроса'}
|
||||
onChange={handleNewTitleChange}
|
||||
onKeyDown={handleTitleKeyDown}
|
||||
onBlur={handleTitleBlur}
|
||||
/>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={styles.titleSurvey} onClick={handleAddNewTitleClick}>
|
||||
<h1>{titleSurvey || 'Название опроса'}</h1>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
const renderDescription = () => {
|
||||
if (isSurveyViewPage || isCompleteSurveyActive) {
|
||||
return descriptionSurvey ? (
|
||||
<p className={styles.desc}>{descriptionSurvey}</p>
|
||||
) : 'Описание';
|
||||
}
|
||||
|
||||
if (descriptionSurvey && !showDescriptionField) {
|
||||
return (
|
||||
<button className={styles.description} onClick={handleParagraphClick}>
|
||||
|
|
@ -106,35 +157,21 @@ const SurveyInfo: React.FC<SurveyInfoProps> = ({titleSurvey, setDescriptionSurve
|
|||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.blockInfo}>
|
||||
<div className={styles.info}>
|
||||
{
|
||||
showNewTitleField ? (
|
||||
<h1 className={styles.titleSurvey}>
|
||||
<TextareaAutosize className={styles.textareaTitle}
|
||||
ref={titleTextareaRef}
|
||||
value={titleSurvey === 'Название опроса' ? '' : titleSurvey}
|
||||
placeholder={'Название опроса'}
|
||||
onChange={handleNewTitleChange}
|
||||
onKeyDown={handleTitleKeyDown}
|
||||
onBlur={handleTitleBlur}
|
||||
/>
|
||||
</h1>
|
||||
) : (
|
||||
<button className={styles.titleSurvey} onClick={handleAddNewTitleClick}>
|
||||
<h1>{titleSurvey || 'Название опроса'}</h1>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
{renderTitle()}
|
||||
{renderDescription()}
|
||||
|
||||
{(isSurveyViewPage || isCompleteSurveyActive) && createdAt && (
|
||||
<p className={styles.createdAt}>Дата создания: {addDate()}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
export default SurveyInfo;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
.layout{
|
||||
width: 100%;
|
||||
}
|
||||
14
SurveyFrontend/src/pages/CompleteSurvey/CompleteSurvey.tsx
Normal file
14
SurveyFrontend/src/pages/CompleteSurvey/CompleteSurvey.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import Header from "../../components/Header/Header.tsx";
|
||||
import styles from './CompleteSurvey.module.css'
|
||||
import CompletingSurvey from "../../components/CompletingSurvey/CompletingSurvey.tsx";
|
||||
|
||||
export const CompleteSurvey = () => {
|
||||
return(
|
||||
<div className={styles.layout}>
|
||||
<Header/>
|
||||
<CompletingSurvey/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CompleteSurvey
|
||||
|
|
@ -2,16 +2,4 @@
|
|||
|
||||
.layout{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main{
|
||||
width: 100%;
|
||||
min-height: 85vh;
|
||||
display: flex;
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
|
||||
.content{
|
||||
width: 100%;
|
||||
margin-left: 8.9%;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue