Merge branch 'creating_components' into 'unstable'
Change components and styles See merge request internship-2025/survey-webapp/survey-webapp!2
|
|
@ -2,9 +2,12 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + React + TS</title>
|
<title>Survey</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
|
||||||
16
SurveyFrontend/package-lock.json
generated
|
|
@ -9,7 +9,8 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0",
|
||||||
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
|
|
@ -2876,6 +2877,19 @@
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "11.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
|
||||||
|
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/esm/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.2.2",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0",
|
||||||
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
|
|
|
||||||
4
SurveyFrontend/public/add_answer.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="15" height="16" viewBox="0 0 15 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7.1579 1.5V14.5" stroke="#3788D6" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M14 8L1 8" stroke="#3788D6" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 268 B |
21
SurveyFrontend/public/add_question.svg
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<svg width="91" height="90" viewBox="0 0 91 90" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_d_3_6)">
|
||||||
|
<circle cx="45.5" cy="45" r="27" fill="#3788D6"/>
|
||||||
|
</g>
|
||||||
|
<path d="M45.5 26V64" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M65.5 45L27.5 45" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M45.5 26V64" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M65.5 45L27.5 45" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d_3_6" x="0.6" y="0.1" width="89.8" height="89.8" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset/>
|
||||||
|
<feGaussianBlur stdDeviation="8.95"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.310533 0 0 0 0 0.630263 0 0 0 0 0.938151 0 0 0 1 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3_6"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3_6" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
3
SurveyFrontend/public/arrow_drop_down.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12 15L7 10H17L12 15Z" fill="#1D1B20"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 152 B |
3
SurveyFrontend/public/arrow_drop_up.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7 14L12 9L17 14H7Z" fill="#1D1B20"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 150 B |
3
SurveyFrontend/public/check_box.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7.06667 10.8L11.7667 6.1L10.8333 5.16667L7.06667 8.93333L5.16667 7.03333L4.23333 7.96667L7.06667 10.8ZM3.33333 14C2.96667 14 2.65278 13.8694 2.39167 13.6083C2.13056 13.3472 2 13.0333 2 12.6667V3.33333C2 2.96667 2.13056 2.65278 2.39167 2.39167C2.65278 2.13056 2.96667 2 3.33333 2H12.6667C13.0333 2 13.3472 2.13056 13.6083 2.39167C13.8694 2.65278 14 2.96667 14 3.33333V12.6667C14 13.0333 13.8694 13.3472 13.6083 13.6083C13.3472 13.8694 13.0333 14 12.6667 14H3.33333Z" fill="#1D1B20"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 596 B |
3
SurveyFrontend/public/radio_button_checked.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8.00004 11.3333C8.92226 11.3333 9.70837 11.0083 10.3584 10.3583C11.0084 9.70834 11.3334 8.92223 11.3334 8.00001C11.3334 7.07779 11.0084 6.29168 10.3584 5.64168C9.70837 4.99168 8.92226 4.66668 8.00004 4.66668C7.07782 4.66668 6.29171 4.99168 5.64171 5.64168C4.99171 6.29168 4.66671 7.07779 4.66671 8.00001C4.66671 8.92223 4.99171 9.70834 5.64171 10.3583C6.29171 11.0083 7.07782 11.3333 8.00004 11.3333ZM8.00004 14.6667C7.07782 14.6667 6.21115 14.4917 5.40004 14.1417C4.58893 13.7917 3.88337 13.3167 3.28337 12.7167C2.68337 12.1167 2.20837 11.4111 1.85837 10.6C1.50837 9.7889 1.33337 8.92223 1.33337 8.00001C1.33337 7.07779 1.50837 6.21112 1.85837 5.40001C2.20837 4.5889 2.68337 3.88334 3.28337 3.28334C3.88337 2.68334 4.58893 2.20834 5.40004 1.85834C6.21115 1.50834 7.07782 1.33334 8.00004 1.33334C8.92226 1.33334 9.78893 1.50834 10.6 1.85834C11.4112 2.20834 12.1167 2.68334 12.7167 3.28334C13.3167 3.88334 13.7917 4.5889 14.1417 5.40001C14.4917 6.21112 14.6667 7.07779 14.6667 8.00001C14.6667 8.92223 14.4917 9.7889 14.1417 10.6C13.7917 11.4111 13.3167 12.1167 12.7167 12.7167C12.1167 13.3167 11.4112 13.7917 10.6 14.1417C9.78893 14.4917 8.92226 14.6667 8.00004 14.6667ZM8.00004 13.3333C9.48893 13.3333 10.75 12.8167 11.7834 11.7833C12.8167 10.75 13.3334 9.4889 13.3334 8.00001C13.3334 6.51112 12.8167 5.25001 11.7834 4.21668C10.75 3.18334 9.48893 2.66668 8.00004 2.66668C6.51115 2.66668 5.25004 3.18334 4.21671 4.21668C3.18337 5.25001 2.66671 6.51112 2.66671 8.00001C2.66671 9.4889 3.18337 10.75 4.21671 11.7833C5.25004 12.8167 6.51115 13.3333 8.00004 13.3333Z" fill="#1D1B20"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
3
SurveyFrontend/public/radio_button_unchecked.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M9.99999 18.3333C8.84721 18.3333 7.76388 18.1146 6.74999 17.6771C5.7361 17.2396 4.85416 16.6458 4.10416 15.8958C3.35416 15.1458 2.76041 14.2639 2.32291 13.25C1.88541 12.2361 1.66666 11.1528 1.66666 9.99999C1.66666 8.84721 1.88541 7.76388 2.32291 6.74999C2.76041 5.7361 3.35416 4.85416 4.10416 4.10416C4.85416 3.35416 5.7361 2.76041 6.74999 2.32291C7.76388 1.88541 8.84721 1.66666 9.99999 1.66666C11.1528 1.66666 12.2361 1.88541 13.25 2.32291C14.2639 2.76041 15.1458 3.35416 15.8958 4.10416C16.6458 4.85416 17.2396 5.7361 17.6771 6.74999C18.1146 7.76388 18.3333 8.84721 18.3333 9.99999C18.3333 11.1528 18.1146 12.2361 17.6771 13.25C17.2396 14.2639 16.6458 15.1458 15.8958 15.8958C15.1458 16.6458 14.2639 17.2396 13.25 17.6771C12.2361 18.1146 11.1528 18.3333 9.99999 18.3333ZM9.99999 16.6667C11.8611 16.6667 13.4375 16.0208 14.7292 14.7292C16.0208 13.4375 16.6667 11.8611 16.6667 9.99999C16.6667 8.13888 16.0208 6.56249 14.7292 5.27082C13.4375 3.97916 11.8611 3.33332 9.99999 3.33332C8.13888 3.33332 6.56249 3.97916 5.27082 5.27082C3.97916 6.56249 3.33332 8.13888 3.33332 9.99999C3.33332 11.8611 3.97916 13.4375 5.27082 14.7292C6.56249 16.0208 8.13888 16.6667 9.99999 16.6667Z" fill="#1D1B20"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -1,42 +1,3 @@
|
||||||
#root {
|
#root {
|
||||||
max-width: 1280px;
|
width: 100%;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,35 +1,12 @@
|
||||||
import { useState } from 'react'
|
import React from 'react';
|
||||||
import reactLogo from './assets/react.svg'
|
|
||||||
import viteLogo from '/vite.svg'
|
|
||||||
import './App.css'
|
import './App.css'
|
||||||
|
import Questions from './pages/Questions.tsx'
|
||||||
|
|
||||||
function App() {
|
const App: React.FC = () => {
|
||||||
const [count, setCount] = useState(0)
|
return (
|
||||||
|
<Questions />
|
||||||
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>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default App
|
export default App
|
||||||
|
|
@ -1,9 +1,24 @@
|
||||||
/*Account.module.css*/
|
/*Account.module.css*/
|
||||||
|
|
||||||
.account {
|
.account {
|
||||||
margin: 0;
|
width: 15%;
|
||||||
padding: 0;
|
background-color: #F3F3F3;
|
||||||
width: 52px;
|
border-radius: 40px;
|
||||||
height: 52px;
|
align-items: center;
|
||||||
margin: 31px 39px 25px 0;
|
padding: 4.58px 13px 4.58px 4.58px;
|
||||||
|
margin: 26px 33px 27px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accountText{
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: black;
|
||||||
|
width: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accountImg{
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 55px;
|
||||||
|
margin-right: 9px;
|
||||||
}
|
}
|
||||||
|
|
@ -2,14 +2,18 @@ import React from 'react';
|
||||||
import styles from './Account.module.css'
|
import styles from './Account.module.css'
|
||||||
|
|
||||||
interface AccountProps {
|
interface AccountProps {
|
||||||
href: string
|
href: string;
|
||||||
|
user: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Account: React.FC<AccountProps> = ({href}) => {
|
const Account: React.FC<AccountProps> = ({href, user}) => {
|
||||||
return (
|
return (
|
||||||
<a className={styles.account} href={href}>
|
<div className={styles.account}>
|
||||||
<img src='../../../public/account.svg' alt='Личный кабинет'/>
|
<a className={styles.accountText} href={href}>
|
||||||
</a>
|
<img src='../../../public/account.svg' className={styles.accountImg} alt='account'/>
|
||||||
|
{user}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
/*AddAnswerButton.module.css*/
|
/*AddAnswerButton.module.css*/
|
||||||
|
|
||||||
.answerButton {
|
.answerButton {
|
||||||
|
margin-top: 18px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styles from './AddAnswerButton.module.css'
|
import styles from './AddAnswerButton.module.css'
|
||||||
|
|
||||||
|
|
||||||
interface AddAnswerButtonProps {
|
interface AddAnswerButtonProps {
|
||||||
onClick(): void;
|
onClick(): void;
|
||||||
}
|
}
|
||||||
|
|
@ -8,8 +9,8 @@ interface AddAnswerButtonProps {
|
||||||
const AddAnswerButton: React.FC<AddAnswerButtonProps> = ({onClick}) => {
|
const AddAnswerButton: React.FC<AddAnswerButtonProps> = ({onClick}) => {
|
||||||
return (
|
return (
|
||||||
<button className={styles.answerButton} onClick={onClick}>
|
<button className={styles.answerButton} onClick={onClick}>
|
||||||
Добавить вариант ответа
|
Добавить вариант ответа {' '}
|
||||||
<img className={styles.addAnswerImg} src='../../../public/add_answer.svg' alt=''/>
|
<img src='../../../public/add_answer.svg' className={styles.addAnswerImg} alt="add answer"/>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,24 @@
|
||||||
/*AddQuestionButton.module.css*/
|
/*AddQuestionButton.module.css*/
|
||||||
|
|
||||||
.questionButton{
|
.questionButton{
|
||||||
background-color: #F6F6F6;
|
display: block;
|
||||||
font-size: 24px;
|
margin: 0 auto;
|
||||||
font-weight: 600;
|
|
||||||
border: none;
|
|
||||||
margin: 104px auto 80px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
margin-bottom: 80px;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #F6F6F6;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.questionButtonImg{
|
.questionButtonImg{
|
||||||
vertical-align: middle;
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
width: 54px;
|
width: 54px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textButton{
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
@ -8,8 +8,8 @@ interface AddQuestionButtonProps {
|
||||||
const AddQuestionButton: React.FC<AddQuestionButtonProps> = ({onClick}) => {
|
const AddQuestionButton: React.FC<AddQuestionButtonProps> = ({onClick}) => {
|
||||||
return (
|
return (
|
||||||
<button className={styles.questionButton} onClick={onClick}>
|
<button className={styles.questionButton} onClick={onClick}>
|
||||||
<img className={styles.questionButtonImg} src='../../../public/add_question.svg' alt=''/>
|
<img src='../../../public/add_question.svg' className={styles.questionButtonImg} alt='add question' />
|
||||||
Добавить вопрос
|
<span className={styles.textButton}>Добавить вопрос</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.textAnswer{
|
.textAnswer{
|
||||||
|
border: none;
|
||||||
|
background-color: #ffffff;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.answerIcon{
|
.answerIcon{
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
width: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answerInput{
|
.answerInput{
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
resize: none;
|
resize: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
@ -1,16 +1,21 @@
|
||||||
import React, {useState, useRef, useEffect} from "react";
|
import React, {useState, useRef, useEffect} from "react";
|
||||||
import styles from'./AnswerOption.module.css';
|
import styles from'./AnswerOption.module.css';
|
||||||
|
|
||||||
|
const single_selected_response = '../../../public/radio_button_checked.svg';
|
||||||
|
const multiple_selected_response = '../../../public/check_box.svg';
|
||||||
|
// const single_response =
|
||||||
|
// const multiple_response =
|
||||||
|
|
||||||
interface AnswerOptionProps{
|
interface AnswerOptionProps{
|
||||||
src: string;
|
|
||||||
index: number;
|
index: number;
|
||||||
value: string;
|
value: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
|
selectedType: 'single' | 'multiply';
|
||||||
}
|
}
|
||||||
|
|
||||||
const AnswerOption: React.FC<AnswerOptionProps> = ({src, index, value, onChange}) => {
|
const AnswerOption: React.FC<AnswerOptionProps> = ({index, value, onChange, selectedType}) => {
|
||||||
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);
|
||||||
|
|
||||||
|
|
@ -48,22 +53,30 @@ const AnswerOption: React.FC<AnswerOptionProps> = ({src, index, value, onChange}
|
||||||
}
|
}
|
||||||
}, [isEditing]);
|
}, [isEditing]);
|
||||||
|
|
||||||
|
const getImage = (typeValue: string): string => {
|
||||||
|
if (typeValue === 'multiply') {
|
||||||
|
return multiple_selected_response;
|
||||||
|
} else {
|
||||||
|
return single_selected_response;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.answer}>
|
<div className={styles.answer}>
|
||||||
<img className={styles.answerIcon} src={src} alt="" />
|
<img className={styles.answerIcon} src={getImage(selectedType)} alt="" />
|
||||||
{isEditing ? (
|
{isEditing ? (
|
||||||
<textarea className={styles.answerInput}
|
<textarea className={styles.answerInput}
|
||||||
ref={textAreaRef}
|
ref={textAreaRef}
|
||||||
value={currentValue}
|
value={currentValue}
|
||||||
onChange={handleTextareaChange}
|
onChange={handleTextareaChange}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
placeholder={`Ответ ${index}`}
|
placeholder={`Ответ ${index}`}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span className={styles.textAnswer} onClick={handleSpanClick}>
|
<button className={styles.textAnswer} onClick={handleSpanClick}>
|
||||||
{currentValue || `Ответ ${index}`}
|
{currentValue || `Ответ ${index}`}
|
||||||
</span>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,4 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
/*justify-content: space-between;*/
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,9 +4,7 @@ import Account from "../Account/Account.tsx";
|
||||||
import styles from './Header.module.css'
|
import styles from './Header.module.css'
|
||||||
import SurveyPagesList from "../SurveyPagesList/SurveyPagesList.tsx";
|
import SurveyPagesList from "../SurveyPagesList/SurveyPagesList.tsx";
|
||||||
|
|
||||||
interface HeaderProps {}
|
const Header: React.FC = () => {
|
||||||
|
|
||||||
const Header: React.FC<HeaderProps> = () => {
|
|
||||||
const [activePage, setActivePage] = useState('Создать опрос');
|
const [activePage, setActivePage] = useState('Создать опрос');
|
||||||
|
|
||||||
const handlePageClick = (name: string)=> {
|
const handlePageClick = (name: string)=> {
|
||||||
|
|
@ -20,7 +18,10 @@ const Header: React.FC<HeaderProps> = () => {
|
||||||
activePage={activePage}
|
activePage={activePage}
|
||||||
onPageClick = {handlePageClick}
|
onPageClick = {handlePageClick}
|
||||||
/>
|
/>
|
||||||
<Account href='' />
|
<Account
|
||||||
|
href=''
|
||||||
|
user='Иванов Иван'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
/*Logo.module.css*/
|
/*Logo.module.css*/
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 52px;
|
height: 52px;
|
||||||
width: 52px;
|
width: 52px;
|
||||||
margin: 31px auto 25px 40px;
|
margin: 31px 77px 25px 40px;
|
||||||
}
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ interface LogoProps {
|
||||||
const Logo: React.FC<LogoProps> = ({href}) => {
|
const Logo: React.FC<LogoProps> = ({href}) => {
|
||||||
return (
|
return (
|
||||||
<a className={styles.logo} href={href}>
|
<a className={styles.logo} href={href}>
|
||||||
<img src='../../../public/logo.svg' alt='Логотип'/>
|
<img src='../../../public/logo.svg' alt="" />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
/*MainComponent.module.css*/
|
||||||
|
|
||||||
.mainPage{
|
.mainPage{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
/*Navigation.module.css*/
|
/*Navigation.module.css*/
|
||||||
|
|
||||||
|
.navContainer{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.nav{
|
.nav{
|
||||||
margin: 34px 0 48px 40px;
|
margin: 34px 0 48px 40px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const Navigation: React.FC<NavigationProps> = ({onNavigationClick, activePage})
|
||||||
const items: string[] = ['Вопросы', 'Настройки', 'Результаты']
|
const items: string[] = ['Вопросы', 'Настройки', 'Результаты']
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={styles.navContainer}>
|
||||||
<nav className={styles.nav}>
|
<nav className={styles.nav}>
|
||||||
<ul className={styles.navList}>
|
<ul className={styles.navList}>
|
||||||
{items.map(item => (
|
{items.map(item => (
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,21 @@
|
||||||
/*NavigationItem.module.css*/
|
/*NavigationItem.module.css*/
|
||||||
|
|
||||||
.navItem{
|
.navItem{
|
||||||
font-weight: 600;
|
padding: 0;
|
||||||
font-size: 24px;
|
|
||||||
color: #AFAFAF;
|
|
||||||
margin-bottom: 42px;
|
margin-bottom: 42px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page{
|
||||||
|
background-color: white;
|
||||||
|
border: none;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #AFAFAF;
|
||||||
|
}
|
||||||
|
|
||||||
.active{
|
.active{
|
||||||
text-decoration: underline 2px #556FB7;
|
text-decoration: underline 2px #556FB7;
|
||||||
color: #000000;;
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navItem:last-child{
|
.navItem:last-child{
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ interface NavigationItemProps{
|
||||||
const NavigationItem: React.FC<NavigationItemProps> = ({title, onClick, isActive}) => {
|
const NavigationItem: React.FC<NavigationItemProps> = ({title, onClick, isActive}) => {
|
||||||
return (
|
return (
|
||||||
<li className={styles.navItem}>
|
<li className={styles.navItem}>
|
||||||
<a className={`${styles.page} ${isActive ? styles.active : ''}`} onClick={onClick}>
|
<button className={`${styles.page} ${isActive ? styles.active : ''}`} onClick={onClick}>
|
||||||
{title}
|
{title}
|
||||||
</a>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,22 @@
|
||||||
|
/*PageSurvey.module.css*/
|
||||||
|
|
||||||
.pagesSurveyItem{
|
.pagesSurveyItem{
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSurvey{
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #2A6DAE;
|
color: #2A6DAE;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.active{
|
.active{
|
||||||
color: #000000;
|
color: #000000;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-decoration-color: #3881C8;
|
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}) => {
|
const PageSurvey: React.FC<PageSurveyProps> = ({name, isActive, onClick}) => {
|
||||||
return (
|
return (
|
||||||
<li className={styles.pagesSurveyItem}>
|
<li className={styles.pagesSurveyItem}>
|
||||||
<a className={`${styles.pageSurvey} ${isActive ? styles.active : ''}`} onClick={onClick}>
|
<button className={`${styles.pageSurvey} ${isActive ? styles.active : ''}`} onClick={onClick}>
|
||||||
{name}
|
{name}
|
||||||
</a>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,40 @@
|
||||||
/*QuestionItem.module.css*/
|
/*QuestionItem.module.css*/
|
||||||
|
|
||||||
.questionCard{
|
.questionCard{
|
||||||
width: 100%;
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
margin-bottom: 34px;
|
margin-bottom: 34px;
|
||||||
padding: 27px 29px 26px 36px;
|
padding: 27px 29px 26px 36px;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.questionCard:last-child{
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.questionContainer{
|
.questionContainer{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.questionTextarea{
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
resize: none;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonQuestion{
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textQuestion{
|
||||||
|
margin-top: 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 35px;
|
||||||
|
text-align: start;
|
||||||
}
|
}
|
||||||
|
|
@ -1,29 +1,63 @@
|
||||||
import React, {useState} from "react";
|
import React, {useState, useRef, useEffect} from "react";
|
||||||
import AnswerOption from '../AnswerOption/AnswerOption';
|
import AnswerOption from '../AnswerOption/AnswerOption';
|
||||||
import AddAnswerButton from "../AddAnswerButton/AddAnswerButton.tsx";
|
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 singleChoiceIcon from '../../../public/radio_button_checked.svg'
|
|
||||||
import multiplyChoiceIcon from '../../../public/check_box.svg'
|
|
||||||
|
|
||||||
interface QuestionItemProps {
|
interface QuestionItemProps {
|
||||||
indexQuestion: number;
|
indexQuestion: number;
|
||||||
initialTextQuestion?: string;
|
initialTextQuestion?: string;
|
||||||
|
valueQuestion: string;
|
||||||
|
onChangeQuestion: (valueQuestion: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QuestionItem: React.FC<QuestionItemProps> = ({indexQuestion, initialTextQuestion = `Вопрос ${indexQuestion}`}) => {
|
const QuestionItem: React.FC<QuestionItemProps> = ({indexQuestion, initialTextQuestion = `Вопрос ${indexQuestion}`,
|
||||||
|
valueQuestion, onChangeQuestion}) => {
|
||||||
|
const [selectedType, setSelectedType] = useState<'single' | 'multiply'>('single');
|
||||||
const [answerOption, setAnswerOption] = useState(['']);
|
const [answerOption, setAnswerOption] = useState(['']);
|
||||||
const [questionType] = useState('single');
|
|
||||||
const [textQuestion, setTextQuestion] = useState(initialTextQuestion);
|
const [textQuestion, setTextQuestion] = useState(initialTextQuestion);
|
||||||
|
const [isEditingQuestion, setIsEditingQuestion] = useState(false);
|
||||||
|
|
||||||
|
const textareaQuestionRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
|
const handleTypeChange = (type: 'single' | 'multiply') => {
|
||||||
|
setSelectedType(type);
|
||||||
|
}
|
||||||
|
|
||||||
const handleAddAnswer = () => {
|
const handleAddAnswer = () => {
|
||||||
setAnswerOption([...answerOption, '']);
|
setAnswerOption([...answerOption, '']);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const handleTypeChange = (type: string) => {
|
const handleQuestionClick = () => {
|
||||||
// setQuestionType(type);
|
setIsEditingQuestion(true);
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
const handleTextareaQuestionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
setTextQuestion(event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSaveQuestion = () => {
|
||||||
|
setIsEditingQuestion(false);
|
||||||
|
onChangeQuestion(textQuestion);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleQuestionKeyDown = (keyDownEvent: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
|
if (keyDownEvent.key === 'Enter') {
|
||||||
|
keyDownEvent.preventDefault();
|
||||||
|
handleSaveQuestion()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleQuestionBlur = () => {
|
||||||
|
handleSaveQuestion()
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isEditingQuestion && textareaQuestionRef.current) {
|
||||||
|
textareaQuestionRef.current.focus();
|
||||||
|
}
|
||||||
|
}, [isEditingQuestion]);
|
||||||
|
|
||||||
const handleAnswerChange = (index: number, value: string) => {
|
const handleAnswerChange = (index: number, value: string) => {
|
||||||
const newAnswerOption = [...answerOption];
|
const newAnswerOption = [...answerOption];
|
||||||
|
|
@ -31,25 +65,34 @@ const QuestionItem: React.FC<QuestionItemProps> = ({indexQuestion, initialTextQu
|
||||||
setAnswerOption(newAnswerOption);
|
setAnswerOption(newAnswerOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleQuestionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
useEffect(() => {
|
||||||
setTextQuestion(event.target.value);
|
setTextQuestion(valueQuestion);
|
||||||
};
|
}, [valueQuestion]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.questionCard}>
|
<div className={styles.questionCard}>
|
||||||
<div className={styles.questionContainer}>
|
<div className={styles.questionContainer}>
|
||||||
<h2>
|
{isEditingQuestion ? (
|
||||||
<textarea
|
<textarea
|
||||||
value={textQuestion}
|
className={styles.questionTextarea}
|
||||||
onChange={handleQuestionChange}
|
ref={textareaQuestionRef}
|
||||||
/>
|
value={textQuestion === initialTextQuestion ? '' : textQuestion}
|
||||||
</h2>
|
onChange={handleTextareaQuestionChange}
|
||||||
|
onKeyDown={handleQuestionKeyDown}
|
||||||
|
onBlur={handleQuestionBlur}
|
||||||
|
placeholder={initialTextQuestion}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<button className={styles.buttonQuestion} onClick={handleQuestionClick}>
|
||||||
|
<h2 className={styles.textQuestion}>{textQuestion || initialTextQuestion}</h2>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
{answerOption.map((answerText, index) => (
|
{answerOption.map((answerText, index) => (
|
||||||
<AnswerOption
|
<AnswerOption
|
||||||
key={index}
|
key={index}
|
||||||
|
selectedType={selectedType}
|
||||||
index={index + 1} // Индекс ответа
|
index={index + 1} // Индекс ответа
|
||||||
value={answerText}
|
value={answerText}
|
||||||
src={questionType === "single" ? singleChoiceIcon : multiplyChoiceIcon}
|
|
||||||
onChange={(value) => handleAnswerChange(index, value)}
|
onChange={(value) => handleAnswerChange(index, value)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
@ -58,7 +101,7 @@ const QuestionItem: React.FC<QuestionItemProps> = ({indexQuestion, initialTextQu
|
||||||
onClick={handleAddAnswer}
|
onClick={handleAddAnswer}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<TypeDropdown/>
|
<TypeDropdown selectedType={selectedType} onTypeChange={handleTypeChange}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,28 @@ interface QuestionsListProps {}
|
||||||
|
|
||||||
interface Question {
|
interface Question {
|
||||||
id: number;
|
id: number;
|
||||||
|
text: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const QuestionsList: React.FC<QuestionsListProps> = () => {
|
const QuestionsList: React.FC<QuestionsListProps> = () => {
|
||||||
const [questions, setQuestions] = useState<Question[]>([
|
const [questions, setQuestions] = useState<Question[]>([
|
||||||
{id: 1},
|
{id: 1, text: ''},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handleAddQuestion = () => {
|
const handleAddQuestion = () => {
|
||||||
// Find the highest ID in the current questions list
|
|
||||||
const maxId = questions.reduce((max, question) => Math.max(max, question.id), 0);
|
const maxId = questions.reduce((max, question) => Math.max(max, question.id), 0);
|
||||||
const newQuestion: Question = {
|
const newQuestion: Question = {
|
||||||
id: maxId + 1, // Increment the ID
|
id: maxId + 1,
|
||||||
|
text: ''
|
||||||
};
|
};
|
||||||
setQuestions([...questions, newQuestion]); // Add the new question to the state
|
setQuestions([...questions, newQuestion]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleQuestionChange = (index: number, value: string) => {
|
||||||
|
const newQuestions = [...questions];
|
||||||
|
newQuestions[index] = {...newQuestions[index], text: value};
|
||||||
|
|
||||||
|
setQuestions(newQuestions);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -28,6 +36,8 @@ const QuestionsList: React.FC<QuestionsListProps> = () => {
|
||||||
<QuestionItem
|
<QuestionItem
|
||||||
key={question.id}
|
key={question.id}
|
||||||
indexQuestion={index + 1}
|
indexQuestion={index + 1}
|
||||||
|
valueQuestion={''}
|
||||||
|
onChangeQuestion={(value) => handleQuestionChange(index, value)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<AddQuestionButton onClick={handleAddQuestion} />
|
<AddQuestionButton onClick={handleAddQuestion} />
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
/*SaveButton.module.css*/
|
/*SaveButton.module.css*/
|
||||||
|
|
||||||
.createSurveyButton {
|
.createSurveyButton {
|
||||||
/*width: 15%;*/
|
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
padding: 25px 50.5px;
|
padding: 25px 50.5px;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
@ -12,4 +11,5 @@
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
box-shadow: 0 0 7.4px 0 rgba(154, 202, 247, 1);
|
box-shadow: 0 0 7.4px 0 rgba(154, 202, 247, 1);
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ interface CreateSurveyButtonProps {
|
||||||
// onClick(): void;
|
// onClick(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SaveButton: React.FC<CreateSurveyButtonProps> = ({}) => {
|
const SaveButton: React.FC<CreateSurveyButtonProps> = () => {
|
||||||
return (
|
return (
|
||||||
<button className={styles.createSurveyButton}>
|
<button className={styles.createSurveyButton}>
|
||||||
Сохранить
|
Сохранить
|
||||||
|
|
|
||||||
|
|
@ -2,55 +2,71 @@
|
||||||
|
|
||||||
.blockInfo{
|
.blockInfo{
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
/*margin: 0;*/
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 34px;
|
margin-top: 34px;
|
||||||
margin-bottom: 49px;
|
margin-bottom: 49px;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
height: 191px;
|
min-height: 191px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info{
|
.info{
|
||||||
|
min-width: 373px;
|
||||||
display: block;
|
display: block;
|
||||||
padding: 35px 0;
|
padding: 35px; /*подумать нужно ли справа слева отступы*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleSurvey{
|
.titleSurvey{
|
||||||
resize: none;
|
display: block;
|
||||||
|
border: none;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0;
|
font-size: 20px;
|
||||||
padding: 0 20px;
|
|
||||||
font-size: 40px;
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 20px;
|
||||||
margin-bottom: 23px;
|
margin-bottom: 23px;
|
||||||
|
word-break: break-word;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textareaTitle{
|
.textareaTitle{
|
||||||
|
margin-top: -17px;
|
||||||
|
width: 80%;
|
||||||
|
padding-top: 35px;
|
||||||
resize: none;
|
resize: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 40px;
|
font-size: 40px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
border: none;
|
border: none;
|
||||||
margin-bottom: 23px;
|
outline: none;
|
||||||
|
line-height: 30px;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.description{
|
.description{
|
||||||
resize: none;
|
border: none;
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 20px;
|
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
background-color: white;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
word-break: break-word;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textareaDescrip{
|
.textareaDescrip{
|
||||||
|
width: 80%;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
resize: none;
|
resize: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0;
|
margin: 0 auto;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
|
font-weight: 500;
|
||||||
|
word-break: break-word;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.descripButton{
|
.descripButton{
|
||||||
|
|
@ -61,11 +77,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.descButtonImg{
|
.descButtonImg{
|
||||||
|
vertical-align: middle;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textButton{
|
.textButton{
|
||||||
vertical-align: center;
|
vertical-align: middle;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #7D7983;
|
color: #7D7983;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
import React, {useState} from "react";
|
import React, {useState, useRef, useEffect} from "react";
|
||||||
import styles from './SurveyInfo.module.css'
|
import styles from './SurveyInfo.module.css'
|
||||||
|
|
||||||
interface SurveyInfoProps {}
|
const SurveyInfo: React.FC = () => {
|
||||||
|
|
||||||
const SurveyInfo: React.FC<SurveyInfoProps> = () => {
|
|
||||||
const [descriptionSurvey, setDescriptionSurvey] = useState('');
|
const [descriptionSurvey, setDescriptionSurvey] = useState('');
|
||||||
const [titleSurvey, setTitleSurvey] = useState('Название опроса');
|
const [titleSurvey, setTitleSurvey] = useState('Название опроса');
|
||||||
const [showDescriptionField, setShowDescriptionField] = useState(false);
|
const [showDescriptionField, setShowDescriptionField] = useState(false);
|
||||||
const [showNewTitleField, setShowNewTitleField] = useState(false);
|
const [showNewTitleField, setShowNewTitleField] = useState(false);
|
||||||
|
const titleTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
const descriptionTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
const handleDescriptionChange = (descripEvent: React.ChangeEvent<HTMLTextAreaElement>) => {
|
const handleDescriptionChange = (descripEvent: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
setDescriptionSurvey(descripEvent.target.value);
|
setDescriptionSurvey(descripEvent.target.value);
|
||||||
|
|
@ -22,10 +21,22 @@ const SurveyInfo: React.FC<SurveyInfoProps> = () => {
|
||||||
setShowNewTitleField(true);
|
setShowNewTitleField(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showNewTitleField && titleTextareaRef.current) {
|
||||||
|
titleTextareaRef.current.focus();
|
||||||
|
}
|
||||||
|
}, [showNewTitleField]);
|
||||||
|
|
||||||
const handleAddDescriptionClick = () => {
|
const handleAddDescriptionClick = () => {
|
||||||
setShowDescriptionField(true);
|
setShowDescriptionField(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showDescriptionField && descriptionTextareaRef.current){
|
||||||
|
descriptionTextareaRef.current.focus();
|
||||||
|
}
|
||||||
|
}, [showDescriptionField]);
|
||||||
|
|
||||||
const handleTitleKeyDown = (titleClickEnter: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const handleTitleKeyDown = (titleClickEnter: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
if (titleClickEnter.key === 'Enter'){
|
if (titleClickEnter.key === 'Enter'){
|
||||||
titleClickEnter.preventDefault();
|
titleClickEnter.preventDefault();
|
||||||
|
|
@ -44,6 +55,49 @@ const SurveyInfo: React.FC<SurveyInfoProps> = () => {
|
||||||
setShowDescriptionField(true);
|
setShowDescriptionField(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleTitleBlur = () => {
|
||||||
|
setShowNewTitleField(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDescriptionBlur = () => {
|
||||||
|
setShowDescriptionField(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const renderDescription = ()=> {
|
||||||
|
if (descriptionSurvey && !showDescriptionField) {
|
||||||
|
return (
|
||||||
|
<button className={styles.description} onClick={handleParagraphClick}>
|
||||||
|
{descriptionSurvey}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
} else if (showDescriptionField) {
|
||||||
|
return (
|
||||||
|
<p className={styles.description}>
|
||||||
|
<textarea
|
||||||
|
ref={descriptionTextareaRef}
|
||||||
|
className={styles.textareaDescrip}
|
||||||
|
value={descriptionSurvey}
|
||||||
|
placeholder={'Добавить описание'}
|
||||||
|
onChange={handleDescriptionChange}
|
||||||
|
onKeyDown={handleDescriptionKeyDown}
|
||||||
|
onBlur={handleDescriptionBlur}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={styles.descripButton}
|
||||||
|
onClick={handleAddDescriptionClick}
|
||||||
|
>
|
||||||
|
<span className={styles.textButton}>Добавить описание</span>
|
||||||
|
<img src='../../../public/add_circle.svg' className={styles.descButtonImg} alt='add circle'/>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.blockInfo}>
|
<div className={styles.blockInfo}>
|
||||||
<div className={styles.info}>
|
<div className={styles.info}>
|
||||||
|
|
@ -51,34 +105,23 @@ const SurveyInfo: React.FC<SurveyInfoProps> = () => {
|
||||||
showNewTitleField ? (
|
showNewTitleField ? (
|
||||||
<h1 className={styles.titleSurvey}>
|
<h1 className={styles.titleSurvey}>
|
||||||
<textarea className={styles.textareaTitle}
|
<textarea className={styles.textareaTitle}
|
||||||
value={titleSurvey}
|
ref={titleTextareaRef}
|
||||||
onChange={handleNewTitleChange}
|
value={titleSurvey === 'Название опроса' ? '' : titleSurvey}
|
||||||
onKeyDown={handleTitleKeyDown}
|
placeholder={'Название опроса'}
|
||||||
|
onChange={handleNewTitleChange}
|
||||||
|
onKeyDown={handleTitleKeyDown}
|
||||||
|
onBlur={handleTitleBlur}
|
||||||
/>
|
/>
|
||||||
</h1>
|
</h1>
|
||||||
) : (
|
) : (
|
||||||
<h1 className={styles.titleSurvey} onClick={handleAddNewTitleClick}>{titleSurvey}</h1>
|
<button className={styles.titleSurvey} onClick={handleAddNewTitleClick}>
|
||||||
|
<h1>{titleSurvey || 'Название опроса'}</h1>
|
||||||
|
</button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
{descriptionSurvey && !showDescriptionField ? (
|
{renderDescription()}
|
||||||
<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>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
|
/*SurveyPagesList.module.css*/
|
||||||
|
|
||||||
.listSurveyPages{
|
.listSurveyPages{
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 61px;
|
gap: 61px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-right: 900px;
|
margin-right: 40%;
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
/*TypeDropdown.module.css*/
|
/*TypeDropdown.module.css*/
|
||||||
|
|
||||||
.dropdownContainer {
|
.dropdownContainer {
|
||||||
width: 22%;
|
width: 23%;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
margin-right: 29px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdownButton {
|
.dropdownButton {
|
||||||
|
|
@ -16,54 +17,52 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
width: 118%;
|
width: 118%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedTypeIcon {
|
.selectedTypeIcon {
|
||||||
margin-right: 5px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdownArrow {
|
.dropdownArrow {
|
||||||
margin-left: 5px;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdownList {
|
.dropdownList {
|
||||||
margin-top: 11px;
|
margin-top: 11px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 5px 0;
|
padding: 12px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
/*margin: 0;*/
|
z-index: 1;
|
||||||
z-index: 1; /* Убедитесь, что список отображается поверх других элементов */
|
width: 100%;
|
||||||
width: 100%; /* Занимает всю ширину контейнера */
|
box-shadow: 0 0 4.7px 0 #00000040;
|
||||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdownItem {
|
.dropdownItem {
|
||||||
padding: 10px 15px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
margin-bottom: 14px;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background-color: #ffffff;
|
||||||
|
|
||||||
.dropdownItem:hover {
|
/*cursor: pointer;*/
|
||||||
background-color: #f0f0f0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdownItemIcon {
|
.dropdownItemIcon {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
width: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedTypeIcon,
|
.selectedTypeIcon,
|
||||||
.dropdownItemIcon {
|
.dropdownItemIcon {
|
||||||
width: 20px; /* Задайте нужную ширину и высоту */
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
vertical-align: middle; /* Выровняйте значок по вертикали */
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,24 @@ import styles from './TypeDropdown.module.css'
|
||||||
const single_selected = '../../../public/radio_button_checked.svg';
|
const single_selected = '../../../public/radio_button_checked.svg';
|
||||||
const multiple_selected = '../../../public/check_box.svg';
|
const multiple_selected = '../../../public/check_box.svg';
|
||||||
|
|
||||||
|
const arrow_drop_down = '../../../public/arrow_drop_down.svg';
|
||||||
|
const arrow_drop_up = '../../../public/arrow_drop_up.svg';
|
||||||
|
|
||||||
const TypeDropdown: React.FC = () => {
|
interface TypeDropdownProps {
|
||||||
|
selectedType: 'single' | 'multiply';
|
||||||
|
onTypeChange: (type: 'single' | 'multiply') => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TypeDropdown: React.FC<TypeDropdownProps> = ({selectedType, onTypeChange}) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [selectedType, setSelectedType] = useState('single');
|
|
||||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const handleToggle = () =>{
|
const handleToggle = () =>{
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSelect = (value: string) => {
|
const handleSelect = (value: 'single' | 'multiply') => {
|
||||||
setSelectedType(value);
|
onTypeChange(value);
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,7 +39,7 @@ const TypeDropdown: React.FC = () => {
|
||||||
};
|
};
|
||||||
}, [dropdownRef]);
|
}, [dropdownRef]);
|
||||||
|
|
||||||
const getImage = (typeValue: string, isSelected: boolean): string => {
|
const getImage = (typeValue: string): string => {
|
||||||
if (typeValue === 'multiply') {
|
if (typeValue === 'multiply') {
|
||||||
return multiple_selected;
|
return multiple_selected;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -45,37 +51,40 @@ const TypeDropdown: React.FC = () => {
|
||||||
<div className={styles.dropdownContainer} ref={dropdownRef}>
|
<div className={styles.dropdownContainer} ref={dropdownRef}>
|
||||||
<button className={styles.dropdownButton} onClick={handleToggle}>
|
<button className={styles.dropdownButton} onClick={handleToggle}>
|
||||||
<img
|
<img
|
||||||
src={getImage(selectedType, true)}
|
src={getImage(selectedType)}
|
||||||
alt={selectedType === "single" ? "Одиночный выбор" : "Множественный выбор"}
|
alt={selectedType === "single" ? "Одиночный выбор" : "Множественный выбор"}
|
||||||
className={styles.selectedTypeIcon}
|
className={styles.selectedTypeIcon}
|
||||||
/>
|
/>
|
||||||
{selectedType === "single" ? "Одиночный выбор" : "Множественный выбор"}
|
{selectedType === "single" ? "Одиночный выбор" : "Множественный выбор"}
|
||||||
<span className={styles.dropdownArrow}>▼</span>
|
<img
|
||||||
|
src={isOpen ? arrow_drop_up : arrow_drop_down}
|
||||||
|
alt={isOpen ? "Закрыть" : "Открыть"}
|
||||||
|
className={styles.dropdownArrow}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<ul className={styles.dropdownList}>
|
<ul className={styles.dropdownList}>
|
||||||
<li
|
<li>
|
||||||
className={styles.dropdownItem}
|
<button onClick={() => handleSelect("single")}
|
||||||
onClick={() => handleSelect("single")}
|
className={styles.dropdownItem}>
|
||||||
>
|
<img
|
||||||
<img
|
className={styles.dropdownItemIcon}
|
||||||
src={getImage("single", selectedType === "single")}
|
src={getImage("single")}
|
||||||
alt="Одиночный выбор"
|
alt=""/>{' '}
|
||||||
className={styles.dropdownItemIcon}
|
Одиночный выбор
|
||||||
/>
|
</button>
|
||||||
Одиночный выбор
|
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li>
|
||||||
className={styles.dropdownItem}
|
<button className={styles.dropdownItem}
|
||||||
onClick={() => handleSelect("multiply")}
|
onClick={() => handleSelect("multiply")}>
|
||||||
>
|
<img
|
||||||
<img
|
src={getImage("multiply")}
|
||||||
src={getImage("multiply", selectedType === "multiply")}
|
alt="Множественный выбор"
|
||||||
alt="Множественный выбор"
|
className={styles.dropdownItemIcon}
|
||||||
className={styles.dropdownItemIcon}
|
/>{' '}
|
||||||
/>
|
Множественный выбор
|
||||||
Множественный выбор
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,68 +1,16 @@
|
||||||
:root {
|
:root {
|
||||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
font-family: Monserrat, sans-serif;
|
||||||
line-height: 1.5;
|
line-height: 100%;
|
||||||
font-weight: 400;
|
font-weight: 600;
|
||||||
|
font-size: 24px;
|
||||||
|
|
||||||
color-scheme: light dark;
|
color: #000000;
|
||||||
color: rgba(255, 255, 255, 0.87);
|
background-color: white;
|
||||||
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 {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
min-width: 320px;
|
width: 100%;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ import './index.css'
|
||||||
import App from './App.tsx'
|
import App from './App.tsx'
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<App />
|
<App />
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
import Header from '../components/Header/Header.tsx'
|
import Header from '../components/Header/Header.tsx'
|
||||||
import MainComponents from '../components/MainComponent/MainComponent.tsx'
|
import MainComponent from "../components/MainComponent/MainComponent.tsx";
|
||||||
|
|
||||||
const Questions = () => {
|
const QuestionsPages: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
<MainComponents />
|
<MainComponent />
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default Questions;
|
export default QuestionsPages;
|
||||||
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;
|
||||||
|
}
|
||||||