corrected components
This commit is contained in:
parent
a27087d681
commit
1bc96d830e
33 changed files with 618 additions and 247 deletions
|
|
@ -1,42 +1,3 @@
|
|||
#root {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: filter 300ms;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.react:hover {
|
||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
||||
}
|
||||
|
||||
@keyframes logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
a:nth-of-type(2) .logo {
|
||||
animation: logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
body{
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -1,35 +1,11 @@
|
|||
import { useState } from 'react'
|
||||
import reactLogo from './assets/react.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
// import { useState } from 'react'
|
||||
import './App.css'
|
||||
import Questions from "./pages/Questions.tsx";
|
||||
|
||||
function App() {
|
||||
const [count, setCount] = useState(0)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<a href="https://vite.dev" target="_blank">
|
||||
<img src={viteLogo} className="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://react.dev" target="_blank">
|
||||
<img src={reactLogo} className="logo react" alt="React logo" />
|
||||
</a>
|
||||
</div>
|
||||
<h1>Vite + React</h1>
|
||||
<div className="card">
|
||||
<button onClick={() => setCount((count) => count + 1)}>
|
||||
count is {count}
|
||||
</button>
|
||||
<p>
|
||||
Edit <code>src/App.tsx</code> and save to test HMR
|
||||
</p>
|
||||
</div>
|
||||
<p className="read-the-docs">
|
||||
Click on the Vite and React logos to learn more
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
const App: React.FC = () => {
|
||||
return (
|
||||
<Questions />
|
||||
);
|
||||
}
|
||||
|
||||
export default App
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
/*Account.module.css*/
|
||||
|
||||
.account {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
margin: 31px 39px 25px 0;
|
||||
}
|
||||
|
||||
.accountImg{
|
||||
width: 55px;
|
||||
}
|
||||
|
|
@ -1,15 +1,21 @@
|
|||
/// <reference types="vite-plugin-svgr/client" />
|
||||
import React from 'react';
|
||||
import styles from './Account.module.css'
|
||||
import AccountSvg from '../../../public/account.svg?react'
|
||||
|
||||
interface AccountProps {
|
||||
href: string
|
||||
href: string;
|
||||
user: string;
|
||||
}
|
||||
|
||||
const Account: React.FC<AccountProps> = ({href}) => {
|
||||
const Account: React.FC<AccountProps> = ({href, user}) => {
|
||||
return (
|
||||
<a className={styles.account} href={href}>
|
||||
<img src='../../../public/account.svg' alt='Личный кабинет'/>
|
||||
</a>
|
||||
<div>
|
||||
<a className={styles.account} href={href}>
|
||||
<AccountSvg className={styles.accountImg}/>
|
||||
{user}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import React from "react";
|
||||
import styles from './AddAnswerButton.module.css'
|
||||
|
||||
import AddAnswerSvg from '../../../public/add_answer.svg?react'
|
||||
|
||||
interface AddAnswerButtonProps {
|
||||
onClick(): void;
|
||||
}
|
||||
|
|
@ -9,7 +11,7 @@ const AddAnswerButton: React.FC<AddAnswerButtonProps> = ({onClick}) => {
|
|||
return (
|
||||
<button className={styles.answerButton} onClick={onClick}>
|
||||
Добавить вариант ответа
|
||||
<img className={styles.addAnswerImg} src='../../../public/add_answer.svg' alt=''/>
|
||||
<AddAnswerSvg className={styles.addAnswerImg} />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React from "react";
|
||||
import styles from './AddQuestionButton.module.css'
|
||||
import AddQuestionSvg from '../../../public/add_question.svg?react'
|
||||
|
||||
interface AddQuestionButtonProps {
|
||||
onClick: () => void;
|
||||
|
|
@ -8,7 +9,7 @@ interface AddQuestionButtonProps {
|
|||
const AddQuestionButton: React.FC<AddQuestionButtonProps> = ({onClick}) => {
|
||||
return (
|
||||
<button className={styles.questionButton} onClick={onClick}>
|
||||
<img className={styles.questionButtonImg} src='../../../public/add_question.svg' alt=''/>
|
||||
<AddQuestionSvg className={styles.questionButtonImg} />
|
||||
Добавить вопрос
|
||||
</button>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({src, index, value, onChange}
|
|||
|
||||
return (
|
||||
<div className={styles.answer}>
|
||||
{/*<div className={styles.answerIconContainer}> <Icon className={styles.answerIcon}/></div>*/}
|
||||
<img className={styles.answerIcon} src={src} alt="" />
|
||||
{isEditing ? (
|
||||
<textarea className={styles.answerInput}
|
||||
|
|
@ -61,9 +62,9 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({src, index, value, onChange}
|
|||
placeholder={`Ответ ${index}`}
|
||||
/>
|
||||
) : (
|
||||
<span className={styles.textAnswer} onClick={handleSpanClick}>
|
||||
{currentValue || `Ответ ${index}`}
|
||||
</span>
|
||||
<button className={styles.textAnswer} onClick={handleSpanClick}>
|
||||
{currentValue || `Ответ ${index}`}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,5 +5,4 @@
|
|||
padding: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
/*justify-content: space-between;*/
|
||||
}
|
||||
|
|
@ -20,7 +20,10 @@ const Header: React.FC<HeaderProps> = () => {
|
|||
activePage={activePage}
|
||||
onPageClick = {handlePageClick}
|
||||
/>
|
||||
<Account href='' />
|
||||
<Account
|
||||
href=''
|
||||
user='Иванов Иван'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
/*Logo.module.css*/
|
||||
|
||||
.logo {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 52px;
|
||||
width: 52px;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React from "react";
|
||||
import styles from './Logo.module.css'
|
||||
import LogoSvg from '../../../public/logo.svg?react'
|
||||
|
||||
interface LogoProps {
|
||||
href: string;
|
||||
|
|
@ -8,7 +9,7 @@ interface LogoProps {
|
|||
const Logo: React.FC<LogoProps> = ({href}) => {
|
||||
return (
|
||||
<a className={styles.logo} href={href}>
|
||||
<img src='../../../public/logo.svg' alt='Логотип'/>
|
||||
<LogoSvg />
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
.active{
|
||||
text-decoration: underline 2px #556FB7;
|
||||
color: #000000;;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.navItem:last-child{
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ interface NavigationItemProps{
|
|||
const NavigationItem: React.FC<NavigationItemProps> = ({title, onClick, isActive}) => {
|
||||
return (
|
||||
<li className={styles.navItem}>
|
||||
<a className={`${styles.page} ${isActive ? styles.active : ''}`} onClick={onClick}>
|
||||
<button className={`${styles.page} ${isActive ? styles.active : ''}`} onClick={onClick}>
|
||||
{title}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,28 +9,4 @@
|
|||
text-decoration: underline;
|
||||
text-decoration-color: #3881C8;
|
||||
|
||||
}
|
||||
|
||||
/*.pagesSurveyItem {*/
|
||||
/* font-size: 24px;*/
|
||||
/* font-weight: 600;*/
|
||||
/* color: #2A6DAE;*/
|
||||
/* position: relative; !* Necessary for positioning the underline *!*/
|
||||
/* display: inline-block; !* Makes the width only as wide as the content *!*/
|
||||
/*}*/
|
||||
|
||||
/*.active {*/
|
||||
/* color: #000000;*/
|
||||
/*}*/
|
||||
|
||||
/*.active::after {*/
|
||||
/* content: "";*/
|
||||
/* display: block; !* Makes it a block element for width/height control *!*/
|
||||
/* width: 96px;*/
|
||||
/* height: 2px; !* Adjust as needed for the thickness of the underline *!*/
|
||||
/* background-color: #3881C8;*/
|
||||
/* position: absolute;*/
|
||||
/* left: 50%; !* Center horizontally *!*/
|
||||
/* transform: translateX(-50%); !* Corrects the centering *!*/
|
||||
/* bottom: -5px; !* Position 5px below the text *!*/
|
||||
/*}*/
|
||||
}
|
||||
|
|
@ -10,9 +10,9 @@ interface PageSurveyProps{
|
|||
const PageSurvey: React.FC<PageSurveyProps> = ({name, isActive, onClick}) => {
|
||||
return (
|
||||
<li className={styles.pagesSurveyItem}>
|
||||
<a className={`${styles.pageSurvey} ${isActive ? styles.active : ''}`} onClick={onClick}>
|
||||
<button className={`${styles.pageSurvey} ${isActive ? styles.active : ''}`} onClick={onClick}>
|
||||
{name}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,3 @@
|
|||
.questionCard:last-child{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.questionContainer{
|
||||
|
||||
}
|
||||
|
|
@ -4,8 +4,9 @@ import AddAnswerButton from "../AddAnswerButton/AddAnswerButton.tsx";
|
|||
import TypeDropdown from "../TypeDropdown/TypeDropdown.tsx";
|
||||
import styles from './QuestionItem.module.css'
|
||||
|
||||
import singleChoiceIcon from '../../../public/radio_button_checked.svg'
|
||||
import multiplyChoiceIcon from '../../../public/check_box.svg'
|
||||
import SingleChoiceIcon from '../../../public/radio_button_checked.svg?react';
|
||||
import MultiplyChoiceIcon from '../../../public/check_box.svg?react';
|
||||
|
||||
|
||||
interface QuestionItemProps {
|
||||
indexQuestion: number;
|
||||
|
|
@ -21,10 +22,6 @@ const QuestionItem: React.FC<QuestionItemProps> = ({indexQuestion, initialTextQu
|
|||
setAnswerOption([...answerOption, '']);
|
||||
};
|
||||
|
||||
// const handleTypeChange = (type: string) => {
|
||||
// setQuestionType(type);
|
||||
// }
|
||||
|
||||
const handleAnswerChange = (index: number, value: string) => {
|
||||
const newAnswerOption = [...answerOption];
|
||||
newAnswerOption[index] = value;
|
||||
|
|
@ -47,9 +44,9 @@ const QuestionItem: React.FC<QuestionItemProps> = ({indexQuestion, initialTextQu
|
|||
{answerOption.map((answerText, index) => (
|
||||
<AnswerOption
|
||||
key={index}
|
||||
src={questionType === "single" ? <SingleChoiceIcon /> : <MultiplyChoiceIcon />}
|
||||
index={index + 1} // Индекс ответа
|
||||
value={answerText}
|
||||
src={questionType === "single" ? singleChoiceIcon : multiplyChoiceIcon}
|
||||
onChange={(value) => handleAnswerChange(index, value)}
|
||||
/>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
/*SaveButton.module.css*/
|
||||
|
||||
.createSurveyButton {
|
||||
/*width: 15%;*/
|
||||
margin-left: 40px;
|
||||
padding: 25px 50.5px;
|
||||
border: none;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ interface CreateSurveyButtonProps {
|
|||
// onClick(): void;
|
||||
}
|
||||
|
||||
const SaveButton: React.FC<CreateSurveyButtonProps> = ({}) => {
|
||||
const SaveButton: React.FC<CreateSurveyButtonProps> = () => {
|
||||
return (
|
||||
<button className={styles.createSurveyButton}>
|
||||
Сохранить
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
.blockInfo{
|
||||
background-color: #ffffff;
|
||||
/*margin: 0;*/
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
margin-top: 34px;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, {useState} from "react";
|
||||
import styles from './SurveyInfo.module.css'
|
||||
import DescripButtonSvg from '../../../public/add_circle.svg?react'
|
||||
|
||||
interface SurveyInfoProps {}
|
||||
|
||||
|
|
@ -44,6 +45,37 @@ const SurveyInfo: React.FC<SurveyInfoProps> = () => {
|
|||
setShowDescriptionField(true);
|
||||
}
|
||||
|
||||
const renderDescription = ()=> {
|
||||
if (descriptionSurvey && !showDescriptionField) {
|
||||
return (
|
||||
<button className={styles.description} onClick={handleParagraphClick}>
|
||||
<p>{descriptionSurvey}</p>
|
||||
</button>
|
||||
);
|
||||
} else if (showDescriptionField) {
|
||||
return (
|
||||
<p className={styles.description}>
|
||||
<textarea
|
||||
className={styles.textareaDescrip}
|
||||
value={descriptionSurvey}
|
||||
onChange={handleDescriptionChange}
|
||||
onKeyDown={handleDescriptionKeyDown}
|
||||
/>
|
||||
</p>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<button
|
||||
className={styles.descripButton}
|
||||
onClick={handleAddDescriptionClick}
|
||||
>
|
||||
<span className={styles.textButton}>Добавить описание</span>
|
||||
<DescripButtonSvg className={styles.descButtonImg}/>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.blockInfo}>
|
||||
<div className={styles.info}>
|
||||
|
|
@ -57,28 +89,14 @@ const SurveyInfo: React.FC<SurveyInfoProps> = () => {
|
|||
/>
|
||||
</h1>
|
||||
) : (
|
||||
<h1 className={styles.titleSurvey} onClick={handleAddNewTitleClick}>{titleSurvey}</h1>
|
||||
<button className={styles.titleSurvey} onClick={handleAddNewTitleClick}>
|
||||
<h1>{titleSurvey}</h1>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
{descriptionSurvey && !showDescriptionField ? (
|
||||
<p className={styles.description} onClick={handleParagraphClick}>{descriptionSurvey}</p>
|
||||
) : showDescriptionField ? (
|
||||
<p className={styles.description}>
|
||||
<textarea className={styles.textareaDescrip}
|
||||
value={descriptionSurvey}
|
||||
onChange={handleDescriptionChange}
|
||||
onKeyDown={handleDescriptionKeyDown}
|
||||
/>
|
||||
</p>
|
||||
) : (
|
||||
<button
|
||||
className={styles.descripButton}
|
||||
onClick={handleAddDescriptionClick}>
|
||||
<span className={styles.textButton}>Добавить описание</span>
|
||||
<img className={styles.descButtonImg} src='../../../public/add_circle.svg'/>
|
||||
</button>
|
||||
)}
|
||||
{renderDescription()}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
border-radius: 5px;
|
||||
padding: 5px 0;
|
||||
list-style: none;
|
||||
/*margin: 0;*/
|
||||
z-index: 1; /* Убедитесь, что список отображается поверх других элементов */
|
||||
width: 100%; /* Занимает всю ширину контейнера */
|
||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const TypeDropdown: React.FC = () => {
|
|||
};
|
||||
}, [dropdownRef]);
|
||||
|
||||
const getImage = (typeValue: string, isSelected: boolean): string => {
|
||||
const getImage = (typeValue: string): string => {
|
||||
if (typeValue === 'multiply') {
|
||||
return multiple_selected;
|
||||
} else {
|
||||
|
|
@ -45,7 +45,7 @@ const TypeDropdown: React.FC = () => {
|
|||
<div className={styles.dropdownContainer} ref={dropdownRef}>
|
||||
<button className={styles.dropdownButton} onClick={handleToggle}>
|
||||
<img
|
||||
src={getImage(selectedType, true)}
|
||||
src={getImage(selectedType)}
|
||||
alt={selectedType === "single" ? "Одиночный выбор" : "Множественный выбор"}
|
||||
className={styles.selectedTypeIcon}
|
||||
/>
|
||||
|
|
@ -55,27 +55,26 @@ const TypeDropdown: React.FC = () => {
|
|||
|
||||
{isOpen && (
|
||||
<ul className={styles.dropdownList}>
|
||||
<li
|
||||
className={styles.dropdownItem}
|
||||
onClick={() => handleSelect("single")}
|
||||
>
|
||||
<li>
|
||||
<button onClick={() => handleSelect("single")}
|
||||
className={styles.dropdownItem}>
|
||||
<img
|
||||
src={getImage("single", selectedType === "single")}
|
||||
alt="Одиночный выбор"
|
||||
className={styles.dropdownItemIcon}
|
||||
/>
|
||||
src={getImage("single")}
|
||||
alt=""/>{' '}
|
||||
Одиночный выбор
|
||||
</button>
|
||||
</li>
|
||||
<li
|
||||
className={styles.dropdownItem}
|
||||
onClick={() => handleSelect("multiply")}
|
||||
>
|
||||
<img
|
||||
src={getImage("multiply", selectedType === "multiply")}
|
||||
alt="Множественный выбор"
|
||||
className={styles.dropdownItemIcon}
|
||||
/>
|
||||
Множественный выбор
|
||||
<li>
|
||||
<button className={styles.dropdownItem}
|
||||
onClick={() => handleSelect("multiply")}>
|
||||
<img
|
||||
src={getImage("multiply")}
|
||||
alt="Множественный выбор"
|
||||
className={styles.dropdownItemIcon}
|
||||
/>{' '}
|
||||
Множественный выбор
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
:root {
|
||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
5
SurveyFrontend/src/svg.d.ts
vendored
Normal file
5
SurveyFrontend/src/svg.d.ts
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
declare module "*.svg" {
|
||||
import React from 'react';
|
||||
const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
|
||||
export default ReactComponent;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue