Compare commits
25 Commits
695cc690d9
...
main
Author | SHA1 | Date | |
---|---|---|---|
7bccb29aa6
|
|||
2b50f7c332
|
|||
0e1dc49f59 | |||
d25e54f73f | |||
58b6d1387d | |||
0e7f962645 | |||
750b571374
|
|||
133ed782aa | |||
86854956eb | |||
ca131a225c | |||
caf16c4ea9 | |||
e4dba30177 | |||
cdd43807f8 | |||
e3455e3e6d | |||
8f2ae99f76 | |||
2abe6ef765 | |||
749cd56dcf | |||
949a1b7ed5 | |||
cb7d0587e8 | |||
1e1bdceb2c | |||
006c9bc4ea | |||
e02aa76b9a | |||
209c2e0a70 | |||
9a7d71e8fb | |||
0b48eb739e |
@ -28,16 +28,24 @@
|
|||||||
"webpack-dev-server": "^5.0.2"
|
"webpack-dev-server": "^5.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ckeditor/ckeditor5-build-classic": "^41.4.2",
|
||||||
|
"@ckeditor/ckeditor5-react": "^7.0.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
|
"@mdxeditor/editor": "^2.20.7",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
|
"@uiw/react-markdown-editor": "^5.12.1",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"bootstrap": "^5.3.3",
|
"bootstrap": "^5.3.3",
|
||||||
|
"inputmask": "^5.0.9",
|
||||||
|
"primereact": "^10.6.6",
|
||||||
|
"qrcode": "^1.5.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.10.1",
|
"react-bootstrap": "^2.10.1",
|
||||||
"react-cookie": "^7.1.4",
|
"react-cookie": "^7.1.4",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-qr-code": "^2.0.15",
|
||||||
"react-router-dom": "^6.22.1"
|
"react-router-dom": "^6.22.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
54
src/App.jsx
54
src/App.jsx
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect, useLayoutEffect } from "react";
|
import React, { useState, useEffect, useLayoutEffect, useRef } from "react";
|
||||||
import { Outlet, useNavigate } from "react-router-dom";
|
import { Outlet, useNavigate } from "react-router-dom";
|
||||||
import { FormsData, UserData, TypeAnswerData, answersData } from "./context";
|
import { FormsData, UserData, TypeAnswerData, answersData } from "./context";
|
||||||
import { useCookies } from "react-cookie";
|
import { useCookies } from "react-cookie";
|
||||||
@ -17,43 +17,47 @@ import DropDownList from "./components/typeAnswer/DropDownList.jsx";
|
|||||||
import InputFile from "./components/typeAnswer/InputFile.jsx";
|
import InputFile from "./components/typeAnswer/InputFile.jsx";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [forms, setForms] = useState([]);
|
const [forms, setForms] = useState([]);
|
||||||
const [user, setUser] = useState(false);
|
const [user, setUser] = useState(false);
|
||||||
const [answersList, setAnswersList] = useState([]);
|
globalRender(window.location.pathname, user, navigate);
|
||||||
const [listTypeAnswer, setListTypeAnswer] = useState([
|
|
||||||
{ id: 1, text: "Краткий ответ", typeTag: InputText },
|
const userRef = useRef(false)
|
||||||
{ id: 2, text: "Расширенный ответ", typeTag: TextArea },
|
const [answersList, setAnswersList] = useState([]);
|
||||||
{ id: 3, text: "Выбор из вариантов", typeTag: InputRadio },
|
const [listTypeAnswer, setListTypeAnswer] = useState([
|
||||||
{ id: 4, text: "Множественный выбор", typeTag: InputMultipleRadio },
|
{id: 1, text: 'Краткий ответ', typeTag: InputText},
|
||||||
{ id: 5, text: "Выпадающий список", typeTag: DropDownList },
|
{id: 2, text: 'Расширенный ответ', typeTag: TextArea},
|
||||||
{ id: 6, text: "Да/Нет", typeTag: YesNo },
|
{id: 3, text: 'Выбор из вариантов', typeTag: InputRadio},
|
||||||
{ id: 7, text: "Файл", typeTag: InputFile },
|
{id: 4, text: 'Множественный выбор', typeTag: InputMultipleRadio},
|
||||||
{ id: 8, text: "Дата", typeTag: InputDate },
|
{id: 5, text: 'Выпадающий список', typeTag: DropDownList},
|
||||||
]);
|
{id: 6, text: 'Да/Нет', typeTag: YesNo},
|
||||||
|
// {id: 7, text: 'Файл', typeTag: InputFile},
|
||||||
|
{id: 8, text: 'Дата', typeTag: InputDate}
|
||||||
|
]);
|
||||||
|
|
||||||
// useEffect(() => globalRender(window.location.pathname, user, navigate));
|
|
||||||
const [cookies, _, __] = useCookies(["user"]);
|
const [cookies, _, __] = useCookies(["user"]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function verifyUser() {
|
async function verifyUser() {
|
||||||
const response = await verifyUserApi(cookies.token);
|
const response = await verifyUserApi(cookies.token);
|
||||||
console.log("app", user);
|
console.log("verifyUser App")
|
||||||
|
|
||||||
if (response) {
|
if (response.status === 200) {
|
||||||
if (response.status === 200) {
|
setUser(response.data);
|
||||||
setUser(response.data);
|
userRef.current = response.data
|
||||||
} else {
|
// globalRender(window.location.pathname, response.data, navigate);
|
||||||
console.log(response);
|
}
|
||||||
|
else {
|
||||||
|
// globalRender(window.location.pathname, false, navigate);
|
||||||
|
setUser(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyUser();
|
verifyUser();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UserData.Provider value={{ user, setUser }}>
|
<UserData.Provider value={{ user, setUser, userRef }}>
|
||||||
<answersData.Provider value={{ answersList, setAnswersList }}>
|
<answersData.Provider value={{ answersList, setAnswersList }}>
|
||||||
<FormsData.Provider value={{ forms, setForms }}>
|
<FormsData.Provider value={{ forms, setForms }}>
|
||||||
<TypeAnswerData.Provider
|
<TypeAnswerData.Provider
|
||||||
|
@ -1,104 +1,133 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin {
|
.admin {
|
||||||
width: 70%;
|
width: 85%;
|
||||||
height: 70%;
|
height: 80%;
|
||||||
box-shadow: 0 0 5px 1px rgb(200, 200, 200);
|
background: #fff;
|
||||||
padding: 1.5%;
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
position: relative;
|
border-radius: 16px;
|
||||||
&__linkProfile {
|
padding: 1.5%;
|
||||||
position: absolute;
|
position: relative;
|
||||||
bottom: 103%;
|
&__linkProfile {
|
||||||
left: 10px;
|
position: absolute;
|
||||||
cursor: pointer;
|
bottom: 103%;
|
||||||
span {
|
left: 10px;
|
||||||
font-size: 15px;
|
cursor: pointer;
|
||||||
font-family: "Montserrat", sans-serif;
|
span {
|
||||||
color: rgb(100, 100, 100);
|
font-size: 15px;
|
||||||
&:hover {
|
font-family: "Montserrat", sans-serif;
|
||||||
text-decoration: underline;
|
color: rgb(100, 100, 100);
|
||||||
color: rgb(66, 68, 189);
|
&:hover {
|
||||||
}
|
text-decoration: underline;
|
||||||
}
|
color: rgb(66, 68, 189);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__wrapper {
|
}
|
||||||
&__header {
|
&__wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 15%;
|
height: 100%;
|
||||||
|
&__header {
|
||||||
|
width: 100%;
|
||||||
|
height: 15%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
h3 {
|
||||||
|
font-size: 25px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__body {
|
||||||
|
width: 100%;
|
||||||
|
height: 85%;
|
||||||
|
&__columns {
|
||||||
|
width: 100%;
|
||||||
|
height: 20%;
|
||||||
|
border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 95%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
&__item {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(70, 70, 70);
|
||||||
|
width: 33.3%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__users {
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
overflow-y: auto;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
&__item {
|
||||||
|
width: 100%;
|
||||||
|
height: 60px;
|
||||||
|
border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
position: relative;
|
||||||
|
&__wrapper {
|
||||||
|
width: 95%;
|
||||||
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 10px;
|
}
|
||||||
h3 {
|
&__link {
|
||||||
font-size: 25px;
|
font-size: 15px;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
color: rgb(100, 100, 100);
|
color: rgb(70, 70, 70);
|
||||||
}
|
width: 20%;
|
||||||
}
|
text-align: center;
|
||||||
&__body {
|
cursor: pointer;
|
||||||
width: 100%;
|
&:hover {
|
||||||
height: 85%;
|
text-decoration: underline;
|
||||||
&__columns {
|
color: rgb(66, 68, 189);
|
||||||
width: 100%;
|
|
||||||
height: 20%;
|
|
||||||
border-bottom: 1px solid rgb(200, 200, 200);
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
&__item {
|
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(70, 70, 70);
|
|
||||||
width: 33.3%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__users {
|
|
||||||
width: 100%;
|
|
||||||
height: 80%;
|
|
||||||
margin-top: 10px;
|
|
||||||
&__item {
|
|
||||||
width: 100%;
|
|
||||||
height: 20%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid rgb(200, 200, 200);
|
|
||||||
&__link {
|
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(70, 70, 70);
|
|
||||||
width: 33.3%;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
color: rgb(66, 68, 189);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__info {
|
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(100, 100, 100);
|
|
||||||
width: 33.3%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__item {
|
|
||||||
padding: 5px;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
&__info {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
width: 20%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&__remove {
|
||||||
|
position: absolute;
|
||||||
|
right: 2%;
|
||||||
|
cursor: pointer;
|
||||||
|
i {
|
||||||
|
&:hover {
|
||||||
|
color: rgb(199, 73, 73);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
&__item {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,107 +1,156 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
&__body {
|
||||||
|
// margin-top: 100px;
|
||||||
|
span {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.answers {
|
.answers {
|
||||||
width: 70%;
|
width: 70%;
|
||||||
height: 70%;
|
height: 70%;
|
||||||
box-shadow: 0 0 5px 1px rgb(200, 200, 200);
|
background: #fff;
|
||||||
padding: 1.5%;
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
position: relative;
|
border-radius: 16px;
|
||||||
&__linkAdmin {
|
padding: 1.5%;
|
||||||
position: absolute;
|
&__linkAdmin {
|
||||||
bottom: 103%;
|
position: absolute;
|
||||||
left: 10px;
|
bottom: 103%;
|
||||||
span {
|
left: 10px;
|
||||||
font-size: 15px;
|
span {
|
||||||
font-family: "Montserrat", sans-serif;
|
font-size: 15px;
|
||||||
color: rgb(100, 100, 100);
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: rgb(66, 68, 189);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
&__header {
|
||||||
|
width: 100%;
|
||||||
|
height: 15%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
// border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
h3 {
|
||||||
|
font-size: 25px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__body {
|
||||||
|
width: 100%;
|
||||||
|
height: 85%;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
&__column {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
padding: 5px;
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__item {
|
||||||
|
padding: 0 5px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
height: 20%;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(230, 230, 230, 0.6);
|
||||||
|
}
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 95%;
|
||||||
|
&__user {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: rgb(66, 68, 189);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__wrapper {
|
|
||||||
&__header {
|
|
||||||
width: 100%;
|
|
||||||
height: 15%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: start;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
h3 {
|
|
||||||
font-size: 25px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(100, 100, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__body {
|
|
||||||
width: 100%;
|
|
||||||
height: 85%;
|
|
||||||
&__item {
|
|
||||||
padding: 5px;
|
|
||||||
border-bottom: 1px solid rgb(200, 200, 200);
|
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
cursor: pointer;
|
|
||||||
// &__question {
|
|
||||||
// &__text {
|
|
||||||
// font-size: 15px;
|
|
||||||
// font-family: "Montserrat", sans-serif;
|
|
||||||
// }
|
|
||||||
// &__comment {
|
|
||||||
// font-size: 11px;
|
|
||||||
// font-family: "Montserrat", sans-serif;
|
|
||||||
// font-style: italic;
|
|
||||||
// color: rgb(200, 200, 200);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// &__answer {
|
|
||||||
// &__text {
|
|
||||||
// font-size: 15px;
|
|
||||||
// font-family: "Montserrat", sans-serif;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
&__date {
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
font-size: 13px;
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: rgb(199, 73, 73);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.myModal {
|
.myModal {
|
||||||
&__item {
|
&__item {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-bottom: 1px solid rgb(200, 200, 200);
|
border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
cursor: pointer;
|
||||||
|
&__question {
|
||||||
|
&__text {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
cursor: pointer;
|
}
|
||||||
&__question {
|
&__comment {
|
||||||
&__text {
|
font-size: 11px;
|
||||||
font-size: 15px;
|
font-family: "Montserrat", sans-serif;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-style: italic;
|
||||||
}
|
color: rgb(200, 200, 200);
|
||||||
&__comment {
|
}
|
||||||
font-size: 11px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
font-style: italic;
|
|
||||||
color: rgb(200, 200, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__answer {
|
|
||||||
&__text {
|
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
&__answer {
|
||||||
|
&__text {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,24 +1,29 @@
|
|||||||
@import url('./base.css');
|
@import url("./base.css");
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
|
@import url("https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap");
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #9dccf6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
background-color: rgb(240, 240, 240);
|
background-color: #fff;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 10%;
|
height: 50px;
|
||||||
box-shadow: 0 0 5px 1px rgb(210, 210, 210);
|
box-sizing: border-box;
|
||||||
|
// box-shadow: 0 0 5px 1px rgb(210, 210, 210);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 90%;
|
height: 90%;
|
||||||
}
|
}
|
||||||
|
166
src/assets/styles/articles.module.scss
Normal file
166
src/assets/styles/articles.module.scss
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
.main {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
padding: 4% 8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: end;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
gap: 15px;
|
||||||
|
div:first-child {
|
||||||
|
flex-grow: 1;
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.listforms {
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16px;
|
||||||
|
height: 70%;
|
||||||
|
min-height: 700px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
width: 100%;
|
||||||
|
&__columns {
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px 25px;
|
||||||
|
border-bottom: 1px solid rgb(220, 220, 220);
|
||||||
|
&__item {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__forms {
|
||||||
|
min-height: 100%;
|
||||||
|
display: inline;
|
||||||
|
overflow-y: auto;
|
||||||
|
&__item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px 25px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
position: relative;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(240, 240, 240, 0.8);
|
||||||
|
}
|
||||||
|
&__title {
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__answers {
|
||||||
|
width: 33.3%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&__update {
|
||||||
|
width: 33.3%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 15px;
|
||||||
|
right: 30px;
|
||||||
|
top: calc(50% - 7px);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.listArticles {
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16px;
|
||||||
|
height: 70%;
|
||||||
|
min-height: 700px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
width: 100%;
|
||||||
|
&__columns {
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px 25px;
|
||||||
|
border-bottom: 1px solid rgb(220, 220, 220);
|
||||||
|
&__item {
|
||||||
|
width: 33.3%;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__forms {
|
||||||
|
width: 100%;
|
||||||
|
height: 85%;
|
||||||
|
overflow-y: auto;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
&__item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px 25px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
position: relative;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(240, 240, 240, 0.8);
|
||||||
|
}
|
||||||
|
&__title {
|
||||||
|
width: 33.3%;
|
||||||
|
// text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__date {
|
||||||
|
width: 33.3%;
|
||||||
|
// text-align: center;
|
||||||
|
}
|
||||||
|
&__author {
|
||||||
|
width: 33.3%;
|
||||||
|
// text-align: center;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 15px;
|
||||||
|
right: 30px;
|
||||||
|
top: calc(50% - 7px);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,57 +1,88 @@
|
|||||||
* {
|
* {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 0; }
|
border: 0;
|
||||||
|
}
|
||||||
*, *:before, *:after {
|
|
||||||
-moz-box-sizing: border-box;
|
*,
|
||||||
-webkit-box-sizing: border-box;
|
*:before,
|
||||||
box-sizing: border-box; }
|
*:after {
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
:focus, :active {
|
-webkit-box-sizing: border-box;
|
||||||
outline: none; }
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
a:focus, a:active {
|
|
||||||
outline: none; }
|
:focus,
|
||||||
|
:active {
|
||||||
nav, footer, header, aside {
|
outline: none;
|
||||||
display: block; }
|
}
|
||||||
|
|
||||||
html, body {
|
a:focus,
|
||||||
height: 100%;
|
a:active {
|
||||||
width: 100%;
|
outline: none;
|
||||||
font-size: 100%;
|
}
|
||||||
line-height: 1;
|
|
||||||
font-size: 14px;
|
nav,
|
||||||
-ms-text-size-adjust: 100%;
|
footer,
|
||||||
-moz-text-size-adjust: 100%;
|
header,
|
||||||
-webkit-text-size-adjust: 100%; }
|
aside {
|
||||||
|
display: block;
|
||||||
input, button, textarea {
|
}
|
||||||
font-family: inherit; }
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 100%;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 14px;
|
||||||
|
-ms-text-size-adjust: 100%;
|
||||||
|
-moz-text-size-adjust: 100%;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
button,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
input::-ms-clear {
|
input::-ms-clear {
|
||||||
display: none; }
|
display: none;
|
||||||
|
}
|
||||||
button {
|
|
||||||
cursor: pointer; }
|
button {
|
||||||
|
cursor: pointer;
|
||||||
button::-moz-focus-inner {
|
}
|
||||||
padding: 0;
|
|
||||||
border: 0; }
|
button::-moz-focus-inner {
|
||||||
|
padding: 0;
|
||||||
a, a:visited {
|
border: 0;
|
||||||
text-decoration: none; }
|
}
|
||||||
|
|
||||||
a:hover {
|
a,
|
||||||
text-decoration: none; }
|
a:visited {
|
||||||
|
text-decoration: none;
|
||||||
ul li {
|
}
|
||||||
list-style: none; }
|
|
||||||
|
a:hover {
|
||||||
img {
|
text-decoration: none;
|
||||||
vertical-align: top; }
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
ul li {
|
||||||
font-size: inherit;
|
list-style: none;
|
||||||
font-weight: 400; }
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
@ -32,7 +32,27 @@
|
|||||||
padding: 0 1%;
|
padding: 0 1%;
|
||||||
}
|
}
|
||||||
&__file {
|
&__file {
|
||||||
|
// margin-top: 10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&__fileLabel {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
border: 1px solid rgb(100, 100, 100);
|
||||||
|
background-color: rgb(240, 240, 240);
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 1%;
|
||||||
|
transition: 0.3s;
|
||||||
|
&:hover {
|
||||||
|
background-color: rgb(230, 230, 230);
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__listFile {
|
||||||
|
margin-left: 10px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&__comment {
|
&__comment {
|
||||||
@ -50,6 +70,21 @@
|
|||||||
padding: 0 1%;
|
padding: 0 1%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&__video {
|
||||||
|
margin-top: 5%;
|
||||||
|
&__title {
|
||||||
|
display: block;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
&__link {
|
||||||
|
display: block;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
border: 1px solid rgb(200, 200, 200);
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 1%;
|
||||||
|
}
|
||||||
|
}
|
||||||
&__answerOptions {
|
&__answerOptions {
|
||||||
margin-top: 5%;
|
margin-top: 5%;
|
||||||
&__title {
|
&__title {
|
||||||
@ -64,6 +99,17 @@
|
|||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
|
i {
|
||||||
|
display: none;
|
||||||
|
margin-left: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: rgb(230, 80, 80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover i {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&__text {
|
&__text {
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
.main {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 2%;
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
.main {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 3%;
|
||||||
|
&__status {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 5%;
|
||||||
|
&__admin {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(40, 40, 40);
|
||||||
|
font-size: 15px;
|
||||||
|
width: 50%;
|
||||||
|
border: 1px solid rgb(180, 180, 180);
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
border-right: none
|
||||||
|
&__checkbox {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__teacher {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(40, 40, 40);
|
||||||
|
font-size: 15px;
|
||||||
|
align-items: center;
|
||||||
|
width: 50%;
|
||||||
|
border: 1px solid rgb(180, 180, 180);
|
||||||
|
border-radius: 0 5px 5px 0;
|
||||||
|
&__checkbox {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
.main {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2% 0;
|
||||||
|
}
|
0
src/assets/styles/components/checkModal.module.scss
Normal file
0
src/assets/styles/components/checkModal.module.scss
Normal file
7
src/assets/styles/components/defaultModal.module.scss
Normal file
7
src/assets/styles/components/defaultModal.module.scss
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.main {
|
||||||
|
&__dialog {
|
||||||
|
&__content {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/assets/styles/components/loading.module.scss
Normal file
13
src/assets/styles/components/loading.module.scss
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.loading__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
&__body {
|
||||||
|
// margin-top: 100px;
|
||||||
|
span {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
src/assets/styles/components/markDown.module.scss
Normal file
3
src/assets/styles/components/markDown.module.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.main {
|
||||||
|
border: 1px solid rgb(200, 200, 200);
|
||||||
|
}
|
@ -1,12 +1,56 @@
|
|||||||
.main {
|
.main {
|
||||||
|
max-height: 40px;
|
||||||
|
button {
|
||||||
|
font-size: 15px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
button {
|
padding: 0.4em 1.2rem;
|
||||||
font-size: 15px;
|
border-radius: 5px;
|
||||||
height: 100%;
|
font-family: "Montserrat", sans-serif;
|
||||||
padding: .40em 1.2rem;
|
transition: 0.2s;
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__red {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(235, 130, 130);
|
||||||
|
}
|
||||||
|
&__green {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(150, 209, 158);
|
||||||
|
}
|
||||||
|
&__blue {
|
||||||
|
color: white;
|
||||||
|
background-color: #1379c1;
|
||||||
|
}
|
||||||
|
&__white {
|
||||||
|
color: black;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
&__green {
|
||||||
color: white;
|
color: white;
|
||||||
background-color: rgb(150, 209, 158);
|
background-color: rgb(150, 209, 158);
|
||||||
border-radius: 5px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
}
|
}
|
||||||
|
&__white {
|
||||||
|
color: black;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__transparent {
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0);
|
||||||
|
transition: 0.3s;
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(180, 180, 180, 0.5);
|
||||||
|
color: white;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,12 +1,18 @@
|
|||||||
.main {
|
.main {
|
||||||
|
max-height: 40px;
|
||||||
|
input {
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
input {
|
border-radius: 5px;
|
||||||
border: 1px solid rgb(180, 180, 180);
|
font-family: "Montserrat", sans-serif;
|
||||||
height: 100%;
|
box-sizing: border-box;
|
||||||
border-radius: 5px;
|
padding: 8px 8px 8px 10px;
|
||||||
font-family: "Montserrat", sans-serif;
|
color: rgb(40, 40, 40);
|
||||||
padding: 0 3px;
|
font-size: 15px;
|
||||||
color: rgb(40, 40, 40);
|
transition: 0.2s;
|
||||||
font-size: 15px;
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,67 +1,63 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
&__authorized {
|
&__authorized {
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
span {
|
|
||||||
margin-left: 2%;
|
|
||||||
display: block;
|
|
||||||
font-size: 15px;
|
|
||||||
color: rgb(80, 80, 80);
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
color: rgb(66, 68, 189);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile {
|
|
||||||
width: 20%;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
span {
|
||||||
&__authorized {
|
margin-left: 30px;
|
||||||
span {
|
display: block;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
color: rgb(80, 80, 80);
|
color: rgb(80, 80, 80);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: rgb(66, 68, 189);
|
text-decoration: underline;
|
||||||
text-decoration: underline;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&__nonAuthorized {
|
}
|
||||||
span {
|
}
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(80, 80, 80);
|
|
||||||
cursor: pointer;
|
|
||||||
i {
|
|
||||||
|
|
||||||
}
|
.profile {
|
||||||
&:hover {
|
height: 100%;
|
||||||
color: rgb(66, 68, 189);
|
margin-right: 30px;
|
||||||
text-decoration: underline;
|
display: flex;
|
||||||
}
|
align-items: center;
|
||||||
}
|
justify-content: center;
|
||||||
|
&__authorized {
|
||||||
|
span {
|
||||||
|
font-size: 15px;
|
||||||
|
color: rgb(80, 80, 80);
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&__nonAuthorized {
|
||||||
|
span {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(80, 80, 80);
|
||||||
|
cursor: pointer;
|
||||||
|
i {
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,103 +1,135 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 50%;
|
width: 500px;
|
||||||
height: 70%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
ul {
|
ul {
|
||||||
li {
|
li {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
a {
|
a {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
color: #000;
|
||||||
|
&:hover {
|
||||||
|
color: #000;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 100%;
|
width: 500px;
|
||||||
height: 100%;
|
min-height: 320px;
|
||||||
// box-shadow: 0 3px 5px 1px rgb(200, 200, 200);
|
box-sizing: border-box;
|
||||||
border: 1px solid rgb(220, 220, 220);
|
padding: 35px 25px;
|
||||||
border-top: none;
|
background: #fff;
|
||||||
&__wrapper {
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
padding: 2%;
|
border-top: 0;
|
||||||
|
border-radius: 0 0 16px 16px;
|
||||||
|
&__wrapper {
|
||||||
|
&__login {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
&__header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 30%;
|
||||||
&__login {
|
display: flex;
|
||||||
width: 100%;
|
align-items: center;
|
||||||
height: 100%;
|
justify-content: center;
|
||||||
&__header {
|
h3 {
|
||||||
width: 100%;
|
display: block;
|
||||||
height: 30%;
|
font-size: 25px;
|
||||||
display: flex;
|
margin: 0;
|
||||||
align-items: center;
|
font-family: "Montserrat", sans-serif;
|
||||||
justify-content: center;
|
text-align: center;
|
||||||
h3 {
|
color: rgb(100, 100, 100);
|
||||||
display: block;
|
|
||||||
font-size: 25px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
text-align: center;
|
|
||||||
color: rgb(100, 100, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__body {
|
|
||||||
width: 100%;
|
|
||||||
height: 50%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
&__footer {
|
|
||||||
width: 100%;
|
|
||||||
height: 20%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&__register {
|
}
|
||||||
width: 100%;
|
&__body {
|
||||||
height: 100%;
|
width: 100%;
|
||||||
&__header {
|
display: flex;
|
||||||
width: 100%;
|
justify-content: space-around;
|
||||||
height: 15%;
|
flex-direction: column;
|
||||||
display: flex;
|
gap: 15px;
|
||||||
align-items: center;
|
position: relative;
|
||||||
justify-content: center;
|
&__error {
|
||||||
h3 {
|
position: absolute;
|
||||||
display: block;
|
font-size: 13px;
|
||||||
font-size: 25px;
|
font-family: "Montserrat", sans-serif;
|
||||||
font-family: "Montserrat", sans-serif;
|
top: 0;
|
||||||
color: rgb(100, 100, 100);
|
left: 10px;
|
||||||
}
|
color: rgb(224, 75, 75);
|
||||||
}
|
|
||||||
&__body {
|
|
||||||
width: 100%;
|
|
||||||
height: 75%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
flex-direction: column;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
|
|
||||||
&__fio {
|
|
||||||
height: 15%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__footer {
|
|
||||||
width: 100%;
|
|
||||||
height: 10%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
&__footer {
|
||||||
|
div,
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
&__register {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
&__header {
|
||||||
|
width: 100%;
|
||||||
|
height: 15%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
h3 {
|
||||||
|
display: block;
|
||||||
|
font-size: 25px;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__body {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
position: relative;
|
||||||
|
&__error {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
top: 0;
|
||||||
|
left: 10px;
|
||||||
|
color: rgb(224, 75, 75);
|
||||||
|
}
|
||||||
|
&__fio {
|
||||||
|
height: 15%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__footer {
|
||||||
|
div,
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,92 +1,92 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
min-height: 100%;
|
||||||
padding: 4% 8%;
|
padding: 4% 8%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 10%;
|
display: flex;
|
||||||
display: flex;
|
justify-content: space-between;
|
||||||
justify-content: space-between;
|
align-items: end;
|
||||||
align-items: center;
|
margin-bottom: 25px;
|
||||||
padding: 0 5%;
|
gap: 15px;
|
||||||
|
div:first-child {
|
||||||
|
flex-grow: 1;
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.listForms {
|
.listForms {
|
||||||
box-shadow: 0 0 5px 1px rgb(200, 200, 200);
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
border-radius: 5px;
|
background: #fff;
|
||||||
margin-top: 5%;
|
border-radius: 16px;
|
||||||
height: 70%;
|
height: 70%;
|
||||||
width: 100%;
|
min-height: 700px;
|
||||||
&__columns {
|
margin-bottom: 50px;
|
||||||
display: flex;
|
width: 100%;
|
||||||
justify-content: start;
|
&__columns {
|
||||||
align-items: center;
|
display: flex;
|
||||||
padding: 0 2%;
|
justify-content: start;
|
||||||
height: 15%;
|
align-items: center;
|
||||||
width: 100%;
|
padding: 20px 25px;
|
||||||
border-bottom: 1px solid rgb(220, 220, 220);
|
border-bottom: 1px solid rgb(220, 220, 220);
|
||||||
&__item {
|
&__item {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
}
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
&__forms {
|
}
|
||||||
width: 100%;
|
&__forms {
|
||||||
height: 85%;
|
min-height: 100%;
|
||||||
overflow-y: auto;
|
display: inline;
|
||||||
&::-webkit-scrollbar {
|
overflow-y: auto;
|
||||||
width: 7px;
|
&__item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px 25px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
position: relative;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(240, 240, 240, 0.8);
|
||||||
|
}
|
||||||
|
&__title {
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
&::-webkit-scrollbar-thumb {
|
}
|
||||||
background-color: rgb(200, 200, 200);
|
&__answers {
|
||||||
}
|
width: 33.3%;
|
||||||
&__item {
|
text-align: center;
|
||||||
display: flex;
|
}
|
||||||
justify-content: start;
|
&__update {
|
||||||
align-items: center;
|
width: 33.3%;
|
||||||
padding: 0 2%;
|
text-align: center;
|
||||||
height: 25%;
|
}
|
||||||
width: 100%;
|
i {
|
||||||
font-family: "Montserrat", sans-serif;
|
position: absolute;
|
||||||
position: relative;
|
font-size: 15px;
|
||||||
&:hover {
|
right: 30px;
|
||||||
background-color: rgba(240, 240, 240, 0.8);
|
top: calc(50% - 7px);
|
||||||
}
|
cursor: pointer;
|
||||||
&__title {
|
}
|
||||||
// width: 33.3%;
|
ul {
|
||||||
text-align: center;
|
li {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__answers {
|
|
||||||
width: 33.3%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
&__update {
|
|
||||||
width: 33.3%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
i {
|
|
||||||
position: absolute;
|
|
||||||
font-size: 15px;
|
|
||||||
right: 30px;
|
|
||||||
top: calc(50% - 7px);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
li {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -2,18 +2,47 @@
|
|||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border-top: 1px solid rgb(200, 200, 200);
|
border-top: 1px solid rgb(200, 200, 200);
|
||||||
&__question {
|
&__question {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 10px;
|
||||||
&__text {
|
&__text {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
&__comment {
|
&__comment {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
color: rgb(200, 200, 200);
|
color: rgb(200, 200, 200);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
&__video {
|
||||||
|
iframe {
|
||||||
|
|
||||||
|
}
|
||||||
|
&__error {
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgb(220, 105, 105);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
height: 7px;
|
||||||
|
border: 1px solid rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(200, 200, 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&__answer {
|
&__answer {
|
||||||
|
&__file {
|
||||||
|
margin-right: 10px;
|
||||||
|
color: rgb(105, 136, 220);
|
||||||
|
text-decoration: none;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: rgb(53, 88, 182);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,68 +1,83 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
width: 60%;
|
text-align: center;
|
||||||
height: 30%;
|
&__top {
|
||||||
text-align: center;
|
font-size: 24px;
|
||||||
&__top {
|
font-family: "Montserrat", sans-serif;
|
||||||
font-size: 30px;
|
font-weight: bold;
|
||||||
font-family: "Montserrat", sans-serif;
|
color: #000;
|
||||||
color: rgb(100, 100, 100);
|
}
|
||||||
}
|
&__bottom {
|
||||||
&__bottom {
|
margin-top: 25px;
|
||||||
font-size: 30px;
|
font-size: 24px;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
color: rgb(100, 100, 100);
|
font-weight: bold;
|
||||||
}
|
color: #000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 60%;
|
width: 500px;
|
||||||
height: 50%;
|
margin-top: 50px;
|
||||||
box-shadow: 0 0 5px 1px rgb(180, 180, 180);
|
box-sizing: border-box;
|
||||||
padding: 1% 0;
|
padding: 35px 25px;
|
||||||
&__title {
|
background: #fff;
|
||||||
height: 30%;
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
display: flex;
|
border-radius: 16px;
|
||||||
justify-content: center;
|
display: flex;
|
||||||
align-items: center;
|
flex-direction: column;
|
||||||
&__wrapper {
|
gap: 25px;
|
||||||
h3 {
|
&__title {
|
||||||
font-size: 35px;
|
display: flex;
|
||||||
font-family: "Montserrat", sans-serif;
|
justify-content: center;
|
||||||
color: rgb(100, 100, 100);
|
align-items: center;
|
||||||
}
|
&__wrapper {
|
||||||
}
|
h3 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: #000;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__token {
|
}
|
||||||
height: 50%;
|
&__token {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
&__wrapper {
|
&__wrapper {
|
||||||
height: 35%;
|
height: 40px;
|
||||||
width: 80%;
|
width: 100%;
|
||||||
}
|
input {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
input::placeholder {
|
||||||
|
color: rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__search {
|
}
|
||||||
height: 20%;
|
&__search {
|
||||||
display: flex;
|
height: 40px;
|
||||||
justify-content: center;
|
display: flex;
|
||||||
align-items: center;
|
justify-content: center;
|
||||||
&__wrapper {
|
align-items: center;
|
||||||
height: 70%;
|
div,
|
||||||
}
|
button {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
121
src/assets/styles/newArticle.module.scss
Normal file
121
src/assets/styles/newArticle.module.scss
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
.main {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 4% 8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
height: 8%;
|
||||||
|
&__listInput {
|
||||||
|
width: 40%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
&__date {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
position: relative;
|
||||||
|
span {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 8px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
top: -40%;
|
||||||
|
left: 2%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__title {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
position: relative;
|
||||||
|
span {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 8px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
top: -40%;
|
||||||
|
left: 2%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__listBtn {
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
width: 100%;
|
||||||
|
margin: 30px 0;
|
||||||
|
&__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: start;
|
||||||
|
&__input {
|
||||||
|
position: relative;
|
||||||
|
&__title {
|
||||||
|
top: -40%;
|
||||||
|
left: 2px;
|
||||||
|
position: absolute;
|
||||||
|
font-size: 8px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__list {
|
||||||
|
width: 100%;
|
||||||
|
// height: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 5px;
|
||||||
|
&__item {
|
||||||
|
padding: 0 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid rgb(100, 100, 100);
|
||||||
|
margin: 1px 3px;
|
||||||
|
position: relative;
|
||||||
|
span {
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
}
|
||||||
|
&:hover span {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
&:hover i {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: rgb(239, 73, 73);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
|
||||||
|
}
|
@ -1,188 +1,171 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 4% 8%;
|
padding: 4% 8%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
// text-align: right;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
&__listInput {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
align-items: center;
|
||||||
width: 100%;
|
gap: 15px;
|
||||||
height: 8%;
|
&__date {
|
||||||
&__listInput {
|
width: 100%;
|
||||||
width: 40%;
|
display: flex;
|
||||||
height: 100%;
|
justify-content: space-between;
|
||||||
display: flex;
|
position: relative;
|
||||||
justify-content: space-between;
|
span {
|
||||||
align-items: center;
|
position: absolute;
|
||||||
&__date {
|
font-size: 15px;
|
||||||
width: 100%;
|
font-family: "Montserrat", sans-serif;
|
||||||
height: 100%;
|
top: -25px;
|
||||||
display: flex;
|
left: 0;
|
||||||
justify-content: space-between;
|
}
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
span {
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
font-size: 8px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
top: -40%;
|
|
||||||
left: 2%;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
border: 1px solid rgb(200, 200, 200);
|
|
||||||
padding: 1%;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__title {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
span {
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
font-size: 8px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
top: -40%;
|
|
||||||
left: 2%;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
border: 1px solid rgb(200, 200, 200);
|
|
||||||
padding: 1%;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&__listBtn {
|
&__title {
|
||||||
display: flex;
|
width: 100%;
|
||||||
justify-content: space-between;
|
display: flex;
|
||||||
width: 30%;
|
justify-content: space-between;
|
||||||
}
|
position: relative;
|
||||||
|
span {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
top: -25px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__listBtn {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
margin-top: 3%;
|
width: 100%;
|
||||||
height: 85%;
|
height: calc(90% - 100px);
|
||||||
width: 100%;
|
background: #fff;
|
||||||
display: flex;
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
justify-content: space-between;
|
border-radius: 16px;
|
||||||
&__listQuestion {
|
display: flex;
|
||||||
height: 100%;
|
justify-content: space-between;
|
||||||
width: 25%;
|
margin-bottom: 50px;
|
||||||
&__list {
|
&__listQuestion {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 25%;
|
||||||
&__item {
|
&__list {
|
||||||
height: 12.5%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
&__item {
|
||||||
align-items: center;
|
padding: 15px 10px;
|
||||||
padding: 0 5px;
|
width: 100%;
|
||||||
cursor: pointer;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
&:first-child {
|
||||||
|
border-radius: 16px 0 0 0;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(230, 230, 230, 0.6);
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__item:not(:last-child) {
|
||||||
|
border-bottom: 1px solid rgb(220, 220, 220);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__newForm {
|
||||||
|
box-shadow: 0 0 5px 1px rgb(220, 220, 220);
|
||||||
|
min-height: 100%;
|
||||||
|
width: 75%;
|
||||||
|
&__title {
|
||||||
|
padding: 1%;
|
||||||
|
width: 100%;
|
||||||
|
height: 10%;
|
||||||
|
h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(80, 80, 80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&__list {
|
||||||
background-color: rgba(230, 230, 230, 0.6);
|
overflow-y: auto;
|
||||||
}
|
overflow-x: hidden;
|
||||||
span {
|
width: 100%;
|
||||||
display: block;
|
height: 90%;
|
||||||
font-size: 15px;
|
&::-webkit-scrollbar {
|
||||||
font-family: "Montserrat", sans-serif;
|
width: 7px;
|
||||||
}
|
}
|
||||||
}
|
&::-webkit-scrollbar-thumb {
|
||||||
&__item:not(:last-child) {
|
background-color: rgb(200, 200, 200);
|
||||||
border-bottom: 1px solid rgb(220, 220, 220);
|
}
|
||||||
}
|
&__item {
|
||||||
}
|
padding: 1%;
|
||||||
}
|
width: 100%;
|
||||||
&__newForm {
|
border-bottom: 1px solid rgb(220, 220, 220);
|
||||||
box-shadow: 0 0 5px 1px rgb(220, 220, 220);
|
display: flex;
|
||||||
height: 100%;
|
justify-content: space-between;
|
||||||
width: 75%;
|
align-items: center;
|
||||||
&__title {
|
&:hover {
|
||||||
padding: 1%;
|
background-color: rgba(230, 230, 230, 0.6);
|
||||||
width: 100%;
|
cursor: pointer;
|
||||||
height: 10%;
|
|
||||||
h3 {
|
|
||||||
font-size: 20px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(80, 80, 80);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__list {
|
|
||||||
overflow-y: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 90%;
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
width: 7px;
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
background-color: rgb(200, 200, 200);
|
|
||||||
}
|
|
||||||
&__item {
|
|
||||||
padding: 1%;
|
|
||||||
width: 100%;
|
|
||||||
height: 25%;
|
|
||||||
border-bottom: 1px solid rgb(220, 220, 220);
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(230, 230, 230, 0.6);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
&__answer {
|
|
||||||
width: 90%;
|
|
||||||
span {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
span:first-child {
|
|
||||||
font-size: 15px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(80, 80, 80);
|
|
||||||
}
|
|
||||||
span:last-child {
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(180, 180, 180);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__btn {
|
|
||||||
width: 10%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
align-items: center;
|
|
||||||
i {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
i:first-child:hover {
|
|
||||||
color: rgb(42, 64, 187);
|
|
||||||
}
|
|
||||||
i:last-child:hover {
|
|
||||||
color: rgb(199, 73, 73);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
&__answer {
|
||||||
|
width: 90%;
|
||||||
|
overflow-x: auto;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
height: 7px;
|
||||||
|
border: 1px solid rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
span:first-child {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(80, 80, 80);
|
||||||
|
}
|
||||||
|
span:last-child {
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(180, 180, 180);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__btn {
|
||||||
|
width: 10%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
i {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
i:first-child:hover {
|
||||||
|
color: rgb(42, 64, 187);
|
||||||
|
}
|
||||||
|
i:last-child:hover {
|
||||||
|
color: rgb(199, 73, 73);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,64 +1,65 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile {
|
.profile {
|
||||||
width: 70%;
|
width: 70%;
|
||||||
height: 70%;
|
height: 70%;
|
||||||
box-shadow: 0 0 5px 1px rgb(200, 200, 200);
|
background: #fff;
|
||||||
padding: 1.5%;
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
position: relative;
|
border-radius: 16px;
|
||||||
&__linkAdmin {
|
padding: 1.5%;
|
||||||
position: absolute;
|
position: relative;
|
||||||
bottom: 103%;
|
&__linkAdmin {
|
||||||
left: 10px;
|
position: absolute;
|
||||||
span {
|
bottom: 103%;
|
||||||
font-size: 15px;
|
left: 10px;
|
||||||
font-family: "Montserrat", sans-serif;
|
span {
|
||||||
color: rgb(100, 100, 100);
|
font-size: 15px;
|
||||||
cursor: pointer;
|
font-family: "Montserrat", sans-serif;
|
||||||
&:hover {
|
color: rgb(100, 100, 100);
|
||||||
text-decoration: underline;
|
cursor: pointer;
|
||||||
color: rgb(66, 68, 189);
|
&:hover {
|
||||||
}
|
text-decoration: underline;
|
||||||
}
|
color: rgb(66, 68, 189);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__wrapper {
|
}
|
||||||
&__header {
|
&__wrapper {
|
||||||
width: 100%;
|
&__header {
|
||||||
height: 15%;
|
width: 100%;
|
||||||
display: flex;
|
height: 15%;
|
||||||
justify-content: space-between;
|
display: flex;
|
||||||
align-items: center;
|
justify-content: space-between;
|
||||||
margin-bottom: 10px;
|
align-items: center;
|
||||||
&__btn {
|
margin-bottom: 10px;
|
||||||
height: 100%;
|
&__btn {
|
||||||
width: 35%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
align-items: center;
|
||||||
align-items: center;
|
gap: 15px;
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
color: rgb(100, 100, 100);
|
color: rgb(100, 100, 100);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
&__body {
|
|
||||||
width: 100%;
|
|
||||||
height: 85%;
|
|
||||||
&__item {
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
&__body {
|
||||||
|
width: 100%;
|
||||||
|
height: 85%;
|
||||||
|
&__item {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
170
src/assets/styles/tokensForm.module.scss
Normal file
170
src/assets/styles/tokensForm.module.scss
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
.main {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
&__body {
|
||||||
|
// margin-top: 100px;
|
||||||
|
span {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.answers {
|
||||||
|
width: 70%;
|
||||||
|
height: 70%;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 1.5%;
|
||||||
|
&__linkAdmin {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 103%;
|
||||||
|
left: 10px;
|
||||||
|
span {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: rgb(66, 68, 189);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
&__header {
|
||||||
|
width: 100%;
|
||||||
|
height: 15%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
h3 {
|
||||||
|
font-size: 25px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__body {
|
||||||
|
width: 100%;
|
||||||
|
height: 85%;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
&__column {
|
||||||
|
font-size: 15px;
|
||||||
|
width: 100%;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
padding: 5px 30px 5px 5px;
|
||||||
|
border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__item {
|
||||||
|
padding: 0 30px 0 5px;
|
||||||
|
// border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
height: 20%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(230, 230, 230, 0.6);
|
||||||
|
}
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 90%;
|
||||||
|
height: 100%;
|
||||||
|
&__title {
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__token {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__btn {
|
||||||
|
width: 10%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
i {
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
i:first-child:hover {
|
||||||
|
color: rgb(42, 64, 187);
|
||||||
|
}
|
||||||
|
i:last-child:hover {
|
||||||
|
color: rgb(199, 73, 73);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.myModal {
|
||||||
|
&__item {
|
||||||
|
padding: 5px;
|
||||||
|
border-bottom: 1px solid rgb(200, 200, 200);
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
cursor: pointer;
|
||||||
|
&__question {
|
||||||
|
&__text {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
&__comment {
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
font-style: italic;
|
||||||
|
color: rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__answer {
|
||||||
|
&__text {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
159
src/assets/styles/viewArticle.module.scss
Normal file
159
src/assets/styles/viewArticle.module.scss
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
.main {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 90%;
|
||||||
|
height: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
// height: 10%;
|
||||||
|
&__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
border-bottom: none;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
padding: 0 5px;
|
||||||
|
&__article {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
&__title {
|
||||||
|
width: 20%;
|
||||||
|
height: 75%;
|
||||||
|
display: flex;
|
||||||
|
border-right: 1px solid rgb(180, 180, 180);
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
&__name {
|
||||||
|
position: absolute;
|
||||||
|
top: -20%;
|
||||||
|
left: 3px;
|
||||||
|
font-size: 8px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
&__text {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__tags {
|
||||||
|
width: 60%;
|
||||||
|
height: 75%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 5px;
|
||||||
|
position: relative;
|
||||||
|
overflow-y: auto;
|
||||||
|
// &::-webkit-scrollbar {
|
||||||
|
// width: 10px;
|
||||||
|
// }
|
||||||
|
// &::-webkit-scrollbar-thumb {
|
||||||
|
// background-color: rgb(200, 200, 200);
|
||||||
|
// }
|
||||||
|
// &::-webkit-scrollbar-button:single-button {
|
||||||
|
// background-color: #bbbbbb;
|
||||||
|
// display: block;
|
||||||
|
// border-style: solid;
|
||||||
|
// height: 10px;
|
||||||
|
// width: 16px;
|
||||||
|
// }
|
||||||
|
&__item {
|
||||||
|
padding: 0 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid rgb(100, 100, 100);
|
||||||
|
margin: 1px 3px;
|
||||||
|
span {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__owner {
|
||||||
|
width: 20%;
|
||||||
|
height: 75%;
|
||||||
|
border-left: 1px solid rgb(180, 180, 180);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
&__name {
|
||||||
|
position: absolute;
|
||||||
|
top: -20%;
|
||||||
|
right: 3px;
|
||||||
|
font-size: 8px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
&__text {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__tags {
|
||||||
|
width: 100%;
|
||||||
|
height: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
&__item {
|
||||||
|
padding: 0 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid rgb(100, 100, 100);
|
||||||
|
margin: 1px 3px;
|
||||||
|
span {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
width: 100%;
|
||||||
|
height: 90%;
|
||||||
|
&__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
overflow: auto;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
height: 7px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
&__article {
|
||||||
|
max-width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// .image {
|
||||||
|
// width: 400px;
|
||||||
|
// height: 200px;
|
||||||
|
// border: 4px solid red
|
||||||
|
// img {
|
||||||
|
// width: 400px;
|
||||||
|
// height: 200px;
|
||||||
|
// aspect-ratio: 1000/700;
|
||||||
|
// }
|
||||||
|
// }
|
@ -1,74 +1,77 @@
|
|||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form {
|
.form {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
width: 70%;
|
width: 70%;
|
||||||
height: 80%;
|
height: 80%;
|
||||||
border: 2px solid rgb(220, 220, 220);
|
background: #fff;
|
||||||
&::-webkit-scrollbar {
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
width: 7px;
|
border-radius: 16px 16px 0 0;
|
||||||
border-left: 1px solid rgb(200, 200, 200);
|
&::-webkit-scrollbar {
|
||||||
}
|
width: 7px;
|
||||||
&::-webkit-scrollbar-thumb {
|
border-left: 1px solid rgb(200, 200, 200);
|
||||||
background-color: rgb(200, 200, 200);
|
}
|
||||||
}
|
&::-webkit-scrollbar-thumb {
|
||||||
&__header {
|
background-color: rgb(200, 200, 200);
|
||||||
border-bottom: 1px solid rgb(220, 220, 220);
|
}
|
||||||
width: 100%;
|
&__header {
|
||||||
height: 10%;
|
border-bottom: 1px solid rgb(220, 220, 220);
|
||||||
display: flex;
|
width: 100%;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 10px 20px;
|
|
||||||
&__title {
|
|
||||||
font-size: 17px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
color: rgb(100, 100, 100);
|
|
||||||
}
|
|
||||||
&__id {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__content {
|
|
||||||
width: 100%;
|
|
||||||
height: 80%;
|
|
||||||
}
|
|
||||||
&__unexists {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
span {
|
|
||||||
display: block;
|
|
||||||
font-size: 18px;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
|
||||||
font-style: italic;
|
|
||||||
color: rgb(200, 200, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
width: 70%;
|
|
||||||
height: 10%;
|
height: 10%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border: 2px solid rgb(220, 220, 220);
|
&__title {
|
||||||
border-top: none;
|
font-size: 17px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
}
|
||||||
|
&__id {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__content {
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
&__unexists {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
font-size: 18px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
font-style: italic;
|
||||||
|
color: rgb(200, 200, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 0 0 16px 16px;
|
||||||
|
width: 70%;
|
||||||
|
height: 10%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 20px;
|
||||||
|
border-top: none;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import classes from "../assets/styles/components/answerModal.module.scss";
|
import classes from "../assets/styles/components/answerModal.module.scss";
|
||||||
import MyButton from "./MyButton.jsx"
|
import MyButton from "./MyButton.jsx";
|
||||||
|
import MarkDowm from "./MarkDown.jsx";
|
||||||
|
|
||||||
const AnswerModal = ({
|
const AnswerModal = ({
|
||||||
cleanStates,
|
cleanStates,
|
||||||
@ -10,6 +11,8 @@ const AnswerModal = ({
|
|||||||
addFormBlock,
|
addFormBlock,
|
||||||
question,
|
question,
|
||||||
file,
|
file,
|
||||||
|
video,
|
||||||
|
setVideo,
|
||||||
listTypeAnswer,
|
listTypeAnswer,
|
||||||
optionAnswer,
|
optionAnswer,
|
||||||
setOptionAnswer,
|
setOptionAnswer,
|
||||||
@ -22,11 +25,13 @@ const AnswerModal = ({
|
|||||||
setQuestion,
|
setQuestion,
|
||||||
setComment,
|
setComment,
|
||||||
setCurrentTypeAnswer,
|
setCurrentTypeAnswer,
|
||||||
setFile
|
setFile,
|
||||||
|
removeOptionAnswer,
|
||||||
|
addFiles
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="modal fade myModal" className={classes.myModal} id="answerModal" tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
|
<div class="modal fade modal-lg myModal" className={classes.myModal} id="answerModal" tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
|
||||||
<div class="modal-dialog myModal__dialog" className={classes.myModal__dialog}>
|
<div class="modal-dialog myModal__dialog" className={classes.myModal__dialog}>
|
||||||
<div class="modal-content" className={classes.myModal__dialog__content}>
|
<div class="modal-content" className={classes.myModal__dialog__content}>
|
||||||
<div class="modal-header" className={classes.myModal__dialog__content__header}>
|
<div class="modal-header" className={classes.myModal__dialog__content__header}>
|
||||||
@ -40,37 +45,48 @@ const AnswerModal = ({
|
|||||||
<div class="modal-body" className={classes.myModal__dialog__content__body}>
|
<div class="modal-body" className={classes.myModal__dialog__content__body}>
|
||||||
<div className={classes.myModal__dialog__content__body__answer}>
|
<div className={classes.myModal__dialog__content__body__answer}>
|
||||||
<span className={classes.myModal__dialog__content__body__answer__title}>Вопрос</span>
|
<span className={classes.myModal__dialog__content__body__answer__title}>Вопрос</span>
|
||||||
<textarea className={classes.myModal__dialog__content__body__answer__text} value={question} onChange={event => setQuestion(event.target.value)}></textarea>
|
<MarkDowm mkValue={question} setMkValue={setQuestion}></MarkDowm>
|
||||||
|
<label for="fileUpload" className={classes.myModal__dialog__content__body__answer__fileLabel}>Добавить файл</label>
|
||||||
|
<label for="fileUpload" className={classes.myModal__dialog__content__body__answer__listFile}>Файлы : {file ? file.map(item => `${item.name}; `) : Нет}</label>
|
||||||
<input
|
<input
|
||||||
|
id="fileUpload"
|
||||||
type="file"
|
type="file"
|
||||||
multiple
|
multiple
|
||||||
accept="image/*,image/jpeg,video/mp4,video/x-m4v,video/*"
|
accept="image/*,image/jpeg,video/mp4,video/x-m4v,video/*"
|
||||||
className={classes.myModal__dialog__content__body__answer__file}
|
className={classes.myModal__dialog__content__body__answer__file}
|
||||||
value={file}
|
onChange={e => addFiles(e.target.files)}
|
||||||
onChange={event => setFile(event.target.value)}
|
></input>
|
||||||
></input>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.myModal__dialog__content__body__comment}>
|
<div className={classes.myModal__dialog__content__body__comment}>
|
||||||
<span className={classes.myModal__dialog__content__body__comment__title}>Комментарий</span>
|
<span className={classes.myModal__dialog__content__body__comment__title}>Комментарий</span>
|
||||||
<textarea className={classes.myModal__dialog__content__body__comment__text} value={comment} onChange={event => setComment(event.target.value)}></textarea>
|
<textarea className={classes.myModal__dialog__content__body__comment__text} value={comment} onChange={event => setComment(event.target.value)}></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={classes.myModal__dialog__content__body__video}>
|
||||||
|
<span className={classes.myModal__dialog__content__body__video__title}>Видео</span>
|
||||||
|
<input type="text" className={classes.myModal__dialog__content__body__video__link} placeholder="Ссылка на видео" value={video} onChange={(e) => setVideo(e.target.value)}/>
|
||||||
|
</div>
|
||||||
{[3, 4, 5].find(item => item === currentTypeAnswer) ? <div className={classes.myModal__dialog__content__body__answerOptions}>
|
{[3, 4, 5].find(item => item === currentTypeAnswer) ? <div className={classes.myModal__dialog__content__body__answerOptions}>
|
||||||
<span className={classes.myModal__dialog__content__body__answerOptions__title}>Варианты ответа</span>
|
<span className={classes.myModal__dialog__content__body__answerOptions__title}>Варианты ответа</span>
|
||||||
<div className={classes.myModal__dialog__content__body__answerOptions__list}>
|
<div className={classes.myModal__dialog__content__body__answerOptions__list}>
|
||||||
{optionAnswer.map((item, i) =>
|
{optionAnswer.map((item, i) =>
|
||||||
<span key={i} className={classes.myModal__dialog__content__body__answerOptions__list__answer}>{item.id}) {item.text}</span>
|
<span key={i} className={classes.myModal__dialog__content__body__answerOptions__list__answer}>
|
||||||
|
{item.id}) {item.text}
|
||||||
|
<i class="fa-solid fa-xmark" onClick={() => removeOptionAnswer(item.id)}></i>
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className={classes.myModal__dialog__content__body__answerOptions__text}
|
className={classes.myModal__dialog__content__body__answerOptions__text}
|
||||||
value={currentOptionAnswer}
|
value={currentOptionAnswer}
|
||||||
onChange={event => setCurrentOptionAnswer(event.target.value)}/>
|
onChange={event => setCurrentOptionAnswer(event.target.value)}
|
||||||
|
/>
|
||||||
<MyButton
|
<MyButton
|
||||||
text={'Добавить'}
|
text={'Добавить'}
|
||||||
click={addOptionAnswer}
|
click={addOptionAnswer}
|
||||||
backgroundColor={'rgb(200, 200, 200)'}
|
class={"main__white"}
|
||||||
otherStyle={{padding: '1% 2%'}}/>
|
otherStyle={{padding: '1% 2%'}}
|
||||||
|
/>
|
||||||
</div> : <div></div>}
|
</div> : <div></div>}
|
||||||
<div className={classes.myModal__dialog__content__body__mandatory}>
|
<div className={classes.myModal__dialog__content__body__mandatory}>
|
||||||
<span className={classes.myModal__dialog__content__body__mandatory__title}>Обязательный вопрос</span>
|
<span className={classes.myModal__dialog__content__body__mandatory__title}>Обязательный вопрос</span>
|
||||||
|
34
src/components/CheckModal.jsx
Normal file
34
src/components/CheckModal.jsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React from "react";
|
||||||
|
import classes from "../assets/styles/components/checkModal.module.scss";
|
||||||
|
import MyButton from "./MyButton.jsx";
|
||||||
|
|
||||||
|
const CheckModal = ({postfix, message, action}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="modal fade" tabindex="-1" id={`checkModal${postfix}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
{/* <h5 class="modal-title">Modal title</h5> */}
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onClick={action.cancel}></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>{message}</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<MyButton text={"Отмена"} dismiss={"modal"} class={"main__white"} click={action.cancel}/>
|
||||||
|
<MyButton
|
||||||
|
text={"Да, удалить"}
|
||||||
|
backgroundColor={"rgb(229, 87, 87)"}
|
||||||
|
otherStyle={{color: "white"}}
|
||||||
|
dismiss={"modal"}
|
||||||
|
click={action.execute}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CheckModal;
|
28
src/components/DefaultModal.jsx
Normal file
28
src/components/DefaultModal.jsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import React, { useState, useEffect, useContext } from "react";
|
||||||
|
import classes from "../assets/styles/components/defaultModal.module.scss";
|
||||||
|
import MyButton from "./MyButton.jsx";
|
||||||
|
|
||||||
|
|
||||||
|
const DefaultModal = ({
|
||||||
|
name,
|
||||||
|
btn,
|
||||||
|
BodyModal
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="modal fade myModal" className={classes.main} id={`${name}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered myModal__dialog" className={classes.main__dialog}>
|
||||||
|
<div class="modal-content" className={classes.main__dialog__content}>
|
||||||
|
{BodyModal}
|
||||||
|
<div class="modal-footer myModal__dialog__content__footer" className={classes.myModal__dialog__content__footer}>
|
||||||
|
{btn.map(((item, i) =>
|
||||||
|
<MyButton text={item.text} dismiss={item.dismiss} class={item.class} click={item.action} key={i}/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DefaultModal;
|
@ -1,13 +1,44 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import classes from "../assets/styles/generatingFormFields.module.scss";
|
import classes from "../assets/styles/generatingFormFields.module.scss";
|
||||||
|
import MarkdownEditor from "@uiw/react-markdown-editor";
|
||||||
|
import { parseTotalLinkVideo } from "../hooks/sundry/parseLinkVideo";
|
||||||
|
|
||||||
const GeneratingFormFields = ({listBlock, listTypeAnswer, answers, updateAnswersForm}) => {
|
const GeneratingFormFields = ({listBlock, listTypeAnswer, answers, updateAnswersForm}) => {
|
||||||
|
|
||||||
|
const getUint8Array = (binary) => {
|
||||||
|
let bytesArray = []
|
||||||
|
let len = binary.length
|
||||||
|
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
bytesArray.push(binary.charCodeAt(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
return [new Uint8Array(bytesArray)]
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
listBlock.map((item, i) =>
|
listBlock.map((item, i) =>
|
||||||
<div className={classes.item} key={i}>
|
<div className={classes.item} key={i}>
|
||||||
<div className={classes.item__question}>
|
<div className={classes.item__question}>
|
||||||
<p className={classes.item__question__text}>{i + 1}) {item.question}</p>
|
<p className={classes.item__question__text}><MarkdownEditor.Markdown source={`${i + 1}) ${item.question}`}/></p>
|
||||||
<p className={classes.item__question__comment}>{item.comment}</p>
|
<p className={classes.item__question__comment}>{item.comment}</p>
|
||||||
|
<div className={classes.item__question__video}>
|
||||||
|
{item.video ?
|
||||||
|
parseTotalLinkVideo(item.video).check ?
|
||||||
|
<iframe
|
||||||
|
width="300"
|
||||||
|
height="150"
|
||||||
|
src={parseTotalLinkVideo(item.video).parseLink}
|
||||||
|
frameborder="0"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||||
|
referrerpolicy="strict-origin-when-cross-origin"
|
||||||
|
allowfullscreen
|
||||||
|
></iframe> :
|
||||||
|
<span className={classes.item__question__video__error}>
|
||||||
|
Данный сервис неподдерживает использование их видео.
|
||||||
|
</span> :
|
||||||
|
<span></span>}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.item__answer}>
|
<div className={classes.item__answer}>
|
||||||
{
|
{
|
||||||
@ -18,6 +49,13 @@ const GeneratingFormFields = ({listBlock, listTypeAnswer, answers, updateAnswers
|
|||||||
updateAnswersForm: updateAnswersForm ? updateAnswersForm : false
|
updateAnswersForm: updateAnswersForm ? updateAnswersForm : false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
item.file.map(f => <a className={classes.item__answer__file} download={f.name} href={
|
||||||
|
URL.createObjectURL(
|
||||||
|
new Blob(getUint8Array(atob(f.binary)), { type: f.type })
|
||||||
|
)
|
||||||
|
}>{f.name}</a>)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
15
src/components/Loading.jsx
Normal file
15
src/components/Loading.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React from "react";
|
||||||
|
import classes from "../assets/styles/components/loading.module.scss";
|
||||||
|
|
||||||
|
const Loading = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.loading__wrapper}>
|
||||||
|
<div class="spinner-border text-dark" className={classes.loading__wrapper__body} role="status">
|
||||||
|
<span class="visually-hidden">Загрузка...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Loading;
|
19
src/components/MarkDown.jsx
Normal file
19
src/components/MarkDown.jsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import MarkdownEditor from '@uiw/react-markdown-editor';
|
||||||
|
import classes from "../assets/styles/components/markDown.module.scss"
|
||||||
|
import '@mdxeditor/editor/style.css';
|
||||||
|
|
||||||
|
const MarkDown = ({mkValue, setMkValue}) => {
|
||||||
|
return (
|
||||||
|
<div className={classes.main} data-color-mode="light">
|
||||||
|
<MarkdownEditor
|
||||||
|
value={mkValue}
|
||||||
|
onChange={(value, viewUpdate) => setMkValue(value)}
|
||||||
|
enablePreview={false}
|
||||||
|
visibleDragbar={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MarkDown;
|
@ -4,15 +4,16 @@ import classes from "../assets/styles/components/myButton.module.scss"
|
|||||||
const MyButton = (props) => {
|
const MyButton = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.main}>
|
<div className={classes.main} style={props.mainStyle}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class={props.class}
|
className={classes[props.class]}
|
||||||
onClick={props.click}
|
onClick={props.click}
|
||||||
data-bs-target={props.target}
|
data-bs-target={props.target}
|
||||||
data-bs-toggle={props.toggle}
|
data-bs-toggle={props.toggle}
|
||||||
data-bs-dismiss={props.dismiss}
|
data-bs-dismiss={props.dismiss}
|
||||||
style={{backgroundColor: props.backgroundColor, ...props.otherStyle}}>
|
style={{backgroundColor: props.backgroundColor, ...props.otherStyle}}
|
||||||
|
>
|
||||||
{props.text}
|
{props.text}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,16 +1,28 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import classes from "../assets/styles/components/myInput.module.scss"
|
import { InputMask } from "primereact/inputmask";
|
||||||
|
import classes from "../assets/styles/components/myInput.module.scss";
|
||||||
|
|
||||||
const MyInput = (props) => {
|
const MyInput = (props) => {
|
||||||
return (
|
return (
|
||||||
<div className={classes.main} style={{...props.otherMainStyle}}>
|
<div className={classes.main} style={{...props.otherMainStyle}}>
|
||||||
<input
|
{
|
||||||
type={props.type}
|
props.mask ?
|
||||||
placeholder={props.placeholder}
|
<InputMask
|
||||||
style={{...props.otherInputStyle}}
|
type={props.type}
|
||||||
onChange={(e) => props.change(e.target.value)}
|
placeholder={props.placeholder}
|
||||||
value={props.value}
|
style={{...props.otherInputStyle}}
|
||||||
/>
|
onChange={(e) => props.change(e.target.value)}
|
||||||
|
value={props.value}
|
||||||
|
mask={props.mask}
|
||||||
|
/> :
|
||||||
|
<input
|
||||||
|
type={props.type}
|
||||||
|
placeholder={props.placeholder}
|
||||||
|
style={{...props.otherInputStyle}}
|
||||||
|
onChange={(e) => props.change(e.target.value)}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
11
src/components/MyQrCode.jsx
Normal file
11
src/components/MyQrCode.jsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from "react";
|
||||||
|
import QRCode from "react-qr-code";
|
||||||
|
|
||||||
|
|
||||||
|
const MyQrCode = ({value}) => {
|
||||||
|
return (
|
||||||
|
<QRCode value={value}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyQrCode
|
@ -3,46 +3,36 @@ import { useCookies } from "react-cookie";
|
|||||||
import classes from "../assets/styles/components/navbar.module.scss";
|
import classes from "../assets/styles/components/navbar.module.scss";
|
||||||
import { verifyUserApi } from "../hooks/api/enterAccountApi";
|
import { verifyUserApi } from "../hooks/api/enterAccountApi";
|
||||||
|
|
||||||
const NavBar = ({ navigate, auth, setAuth }) => {
|
const NavBar = ({navigate, auth, setAuth}) => {
|
||||||
useEffect(() => {
|
return (
|
||||||
console.log("nav", auth);
|
<div className={classes.main}>
|
||||||
});
|
<div className={classes.wrapper}>
|
||||||
|
<div className={classes.menu}>
|
||||||
return (
|
<div className={classes.menu__authorized}>
|
||||||
<div className={classes.main}>
|
<span onClick={() => navigate("/")}>Главная</span>
|
||||||
<div className={classes.wrapper}>
|
{
|
||||||
<div className={classes.menu}>
|
auth ?
|
||||||
<div className={classes.menu__authorized}>
|
auth.is_admin ?
|
||||||
<span onClick={() => navigate("/")}>Главная</span>
|
<><span onClick={() => navigate("/forms")}>Мои формы</span>
|
||||||
{auth ? (
|
<span onClick={() => navigate("/admin")}>Админ панель</span>
|
||||||
auth.is_admin ? (
|
<span onClick={() => navigate("/articles")}>Мои статьи</span></> :
|
||||||
<span onClick={() => navigate("/forms")}>Мои формы</span>
|
<span></span> :
|
||||||
) : (
|
<span></span>
|
||||||
<span></span>
|
}
|
||||||
)
|
</div>
|
||||||
) : (
|
</div>
|
||||||
<span></span>
|
<div className={classes.profile}>
|
||||||
)}
|
{auth ?
|
||||||
</div>
|
<div className={classes.profile__authorized}>
|
||||||
</div>
|
<span onClick={() => navigate("/profile")}>Профиль ({auth.login})</span>
|
||||||
<div className={classes.profile}>
|
</div> :
|
||||||
{auth ? (
|
<div className={classes.profile__nonAuthorized}>
|
||||||
<div className={classes.profile__authorized}>
|
<span onClick={() => navigate("/enter")}>Вход <i class="fa-solid fa-arrow-right-to-bracket"></i></span>
|
||||||
<span onClick={() => navigate("/profile")}>
|
</div>}
|
||||||
Профиль ({auth.login})
|
</div>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<div className={classes.profile__nonAuthorized}>
|
|
||||||
<span onClick={() => navigate("/enter")}>
|
|
||||||
Вход <i class="fa-solid fa-arrow-right-to-bracket"></i>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NavBar;
|
export default NavBar;
|
||||||
|
57
src/components/TextEditor.jsx
Normal file
57
src/components/TextEditor.jsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { CKEditor } from '@ckeditor/ckeditor5-react';
|
||||||
|
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
|
||||||
|
|
||||||
|
const TextEditor = ({data, setData}) => {
|
||||||
|
|
||||||
|
function uploadAdapter(loader) {
|
||||||
|
return {
|
||||||
|
upload: () => {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const file = await loader.file;
|
||||||
|
const buff = await file.arrayBuffer()
|
||||||
|
const bytesArray = new Uint8Array(buff)
|
||||||
|
const bytesString = btoa(String.fromCharCode.apply(null, bytesArray))
|
||||||
|
resolve({
|
||||||
|
default: `data:image/jpg;base64, ${bytesString}`
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
reject("Hello");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadPlugin(editor) {
|
||||||
|
editor.plugins.get("FileRepository").createUploadAdapter = (loader) => {
|
||||||
|
return uploadAdapter(loader);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="App">
|
||||||
|
<h2>Редактор статьи</h2>
|
||||||
|
<CKEditor
|
||||||
|
editor={ ClassicEditor }
|
||||||
|
data={data}
|
||||||
|
config = {{
|
||||||
|
extraPlugins: [uploadPlugin],
|
||||||
|
mediaEmbed: {previewsInData: true }
|
||||||
|
}}
|
||||||
|
onReady={ editor => {
|
||||||
|
// You can store the "editor" and use when it is needed.
|
||||||
|
console.log( 'Editor is ready to use!', editor );
|
||||||
|
} }
|
||||||
|
onChange={ ( event, editor ) => {
|
||||||
|
setData(editor.getData())
|
||||||
|
}}
|
||||||
|
onBlur={ ( event, editor ) => {}}
|
||||||
|
onFocus={ ( event, editor ) => {}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TextEditor
|
14
src/components/bodyModal/EditToken.jsx
Normal file
14
src/components/bodyModal/EditToken.jsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import React from "react";
|
||||||
|
import classes from "../../assets/styles/components/bodyModal/editToken.module.scss";
|
||||||
|
import MyInput from "../MyInput.jsx";
|
||||||
|
|
||||||
|
|
||||||
|
const EditToken = ({titleToken, setTitleToken}) => {
|
||||||
|
return (
|
||||||
|
<div className={classes.main}>
|
||||||
|
<MyInput type={"text"} value={titleToken} change={setTitleToken} placeholder={"Название"}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditToken
|
142
src/components/bodyModal/EditUserAdminPanel.jsx
Normal file
142
src/components/bodyModal/EditUserAdminPanel.jsx
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import React, {useState, useRef} from "react";
|
||||||
|
import classes from "../../assets/styles/components/bodyModal/editUserAdminPanel.module.scss";
|
||||||
|
import MyInput from "../../components/MyInput.jsx";
|
||||||
|
|
||||||
|
|
||||||
|
const EditUserAdminPanel = ({
|
||||||
|
id,
|
||||||
|
email,
|
||||||
|
firstName,
|
||||||
|
isAdmin,
|
||||||
|
isTeacher,
|
||||||
|
lastName,
|
||||||
|
login,
|
||||||
|
phone,
|
||||||
|
pass,
|
||||||
|
setEmail,
|
||||||
|
setFirstName,
|
||||||
|
setIsAdmin,
|
||||||
|
setIsTeacher,
|
||||||
|
setLastName,
|
||||||
|
setLogin,
|
||||||
|
setPhone,
|
||||||
|
setPass
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.main}>
|
||||||
|
<MyInput
|
||||||
|
type={"text"}
|
||||||
|
value={login}
|
||||||
|
placeholder={"Логин"}
|
||||||
|
change={setLogin}
|
||||||
|
otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}}
|
||||||
|
otherInputStyle={{width: "100%", height: "10%"}}
|
||||||
|
/>
|
||||||
|
<MyInput
|
||||||
|
type={"text"}
|
||||||
|
mask={"9 (999) 999-99-99"}
|
||||||
|
value={phone}
|
||||||
|
placeholder={"Телефон"}
|
||||||
|
change={setPhone}
|
||||||
|
otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}}
|
||||||
|
otherInputStyle={{width: "100%", height: "10%"}}
|
||||||
|
/>
|
||||||
|
<MyInput
|
||||||
|
type={"text"}
|
||||||
|
value={firstName}
|
||||||
|
placeholder={"Имя"}
|
||||||
|
change={setFirstName}
|
||||||
|
otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}}
|
||||||
|
otherInputStyle={{width: "100%", height: "10%"}}
|
||||||
|
/>
|
||||||
|
<MyInput
|
||||||
|
type={"text"}
|
||||||
|
value={lastName}
|
||||||
|
placeholder={"Фамилия"}
|
||||||
|
change={setLastName}
|
||||||
|
otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}}
|
||||||
|
otherInputStyle={{width: "100%", height: "10%"}}
|
||||||
|
/>
|
||||||
|
<MyInput
|
||||||
|
type={"text"}
|
||||||
|
value={email}
|
||||||
|
placeholder={"email"}
|
||||||
|
change={setEmail}
|
||||||
|
otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}}
|
||||||
|
otherInputStyle={{width: "100%", height: "10%"}}
|
||||||
|
/>
|
||||||
|
<MyInput
|
||||||
|
type={"text"}
|
||||||
|
value={pass}
|
||||||
|
placeholder={"Пароль"}
|
||||||
|
change={setPass}
|
||||||
|
otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}}
|
||||||
|
otherInputStyle={{width: "100%", height: "10%"}}
|
||||||
|
/>
|
||||||
|
<div className={classes.main__status}>
|
||||||
|
<div className={classes.main__status__admin}>
|
||||||
|
<div className={classes.main__status__admin__text}>Администратор</div>
|
||||||
|
<div className={classes.main__status__admin__checkbox}>
|
||||||
|
<div class="form-check">
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="admin"
|
||||||
|
id="choiceYes"
|
||||||
|
value="1"
|
||||||
|
checked={isAdmin}
|
||||||
|
onChange={() => setIsAdmin(true)}
|
||||||
|
/>
|
||||||
|
<label class="form-check-label" for="choiceYes">Да</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="admin"
|
||||||
|
id="choiceNo"
|
||||||
|
value="2"
|
||||||
|
checked={!isAdmin}
|
||||||
|
onChange={() => setIsAdmin(false)}
|
||||||
|
/>
|
||||||
|
<label class="form-check-label" for="choiceNo">Нет</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.main__status__teacher}>
|
||||||
|
<div className={classes.main__status__admin__text}>Учитель</div>
|
||||||
|
<div className={classes.main__status__admin__checkbox}>
|
||||||
|
<div class="form-check">
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="teacher"
|
||||||
|
id="choiceYes"
|
||||||
|
value="1"
|
||||||
|
checked={isTeacher}
|
||||||
|
onChange={() => setIsTeacher(true)}
|
||||||
|
/>
|
||||||
|
<label class="form-check-label" for="choiceYes">Да</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="teacher"
|
||||||
|
id="choiceNo"
|
||||||
|
value="2"
|
||||||
|
checked={!isTeacher}
|
||||||
|
onChange={() => setIsTeacher(false)}
|
||||||
|
/>
|
||||||
|
<label class="form-check-label" for="choiceNo">Нет</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditUserAdminPanel;
|
13
src/components/bodyModal/QrCodeToken.jsx
Normal file
13
src/components/bodyModal/QrCodeToken.jsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import React from "react";
|
||||||
|
import classes from "../../assets/styles/components/bodyModal/qrCodeToken.module.scss";
|
||||||
|
import MyQrCode from "../MyQrCode.jsx";
|
||||||
|
|
||||||
|
const QrCodeToken = ({ value }) => {
|
||||||
|
return (
|
||||||
|
<div className={classes.main}>
|
||||||
|
<MyQrCode value={`http://minerva.krbl.ru/forms/${value}`} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default QrCodeToken;
|
@ -2,16 +2,16 @@ import React, { useState } from "react";
|
|||||||
import classes from "../../assets/styles/components/typeAnswer/dropDownList.module.scss"
|
import classes from "../../assets/styles/components/typeAnswer/dropDownList.module.scss"
|
||||||
|
|
||||||
const DropDownList = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
|
const DropDownList = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
|
||||||
console.log(optionAnswer)
|
// console.log(optionAnswer)
|
||||||
return (
|
return (
|
||||||
<div className={classes.main}>
|
<div className={classes.main}>
|
||||||
<select
|
<select
|
||||||
value={answers ? answers[postfix].answer : ""}
|
value={answers ? answers[postfix].answer : ""}
|
||||||
onChange={updateAnswersForm ? (e) => updateAnswersForm(Number(e.target.value), postfix) : () => {}}
|
onChange={updateAnswersForm ? (e) => updateAnswersForm(e.target.value, postfix) : () => {}}
|
||||||
>
|
>
|
||||||
|
<option selected disabled></option>
|
||||||
{optionAnswer.map((item, i) =>
|
{optionAnswer.map((item, i) =>
|
||||||
// <option value={item.id ? item.id : item[0].Value} key={i}>{item.text ? item.text : item[1].Value}</option>
|
<option value={item.text} key={i}>{item.text}</option>
|
||||||
<option value={item.id} key={i}>{item.text}</option>
|
|
||||||
)}
|
)}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,20 +2,20 @@ import React from "react";
|
|||||||
import classes from "../../assets/styles/components/typeAnswer/inputMultiple.module.scss"
|
import classes from "../../assets/styles/components/typeAnswer/inputMultiple.module.scss"
|
||||||
|
|
||||||
const InputMultipleRadio = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
|
const InputMultipleRadio = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
|
||||||
function checkRadio(i) {
|
function checkRadio(value) {
|
||||||
if (answers[postfix].answer) {
|
if (answers[postfix].answer) {
|
||||||
return answers[postfix].answer.some(item => item === Number(i))
|
return answers[postfix].answer.some(item => item === value)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateStateCheckbox(i) {
|
function updateStateCheckbox(value) {
|
||||||
if (updateAnswersForm) {
|
if (updateAnswersForm) {
|
||||||
if (answers[postfix].answer.some((item) => item === Number(i))) {
|
if (answers[postfix].answer.some((item) => item === value)) {
|
||||||
answers[postfix].answer.splice(answers[postfix].answer.indexOf(i), 1)
|
answers[postfix].answer.splice(answers[postfix].answer.indexOf(value), 1)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
answers[postfix].answer.push(i)
|
answers[postfix].answer.push(value)
|
||||||
}
|
}
|
||||||
updateAnswersForm(answers[postfix].answer, postfix)
|
updateAnswersForm(answers[postfix].answer, postfix)
|
||||||
}
|
}
|
||||||
@ -30,9 +30,9 @@ const InputMultipleRadio = ({postfix, optionAnswer, answers, updateAnswersForm})
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
name={`inputMultiple_${postfix}`}
|
name={`inputMultiple_${postfix}`}
|
||||||
id={`inputMultiple_${postfix}`}
|
id={`inputMultiple_${postfix}`}
|
||||||
value={i}
|
value={item.text}
|
||||||
checked={answers ? checkRadio(i) : false}
|
checked={answers ? checkRadio(item.text) : false}
|
||||||
onChange={() => updateStateCheckbox(i)}
|
onChange={() => updateStateCheckbox(item.text)}
|
||||||
/>
|
/>
|
||||||
{/* <label class="form-check-label" for={`inputMultiple_${postfix}`}>{item.text ? item.text : item[1].Value}</label> */}
|
{/* <label class="form-check-label" for={`inputMultiple_${postfix}`}>{item.text ? item.text : item[1].Value}</label> */}
|
||||||
<label class="form-check-label" for={`inputMultiple_${postfix}`}>{item.text}</label>
|
<label class="form-check-label" for={`inputMultiple_${postfix}`}>{item.text}</label>
|
||||||
|
@ -11,9 +11,9 @@ const InputRadio = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
|
|||||||
type="radio"
|
type="radio"
|
||||||
name={`inputRadio_${postfix}`}
|
name={`inputRadio_${postfix}`}
|
||||||
id={`choice_${item.id}`}
|
id={`choice_${item.id}`}
|
||||||
value={i}
|
value={item.text}
|
||||||
checked={answers ? answers[postfix].answer === i : false}
|
checked={answers ? answers[postfix].answer === item.text : false}
|
||||||
onChange={updateAnswersForm ? (e) => updateAnswersForm(Number(e.target.value), postfix) : () => {}}
|
onChange={updateAnswersForm ? (e) => updateAnswersForm(item.text, postfix) : () => {}}
|
||||||
/>
|
/>
|
||||||
{/* <label class="form-check-label" for={`inputRadio_${postfix}`}>{item.text ? item.text : item[1].Value}</label> */}
|
{/* <label class="form-check-label" for={`inputRadio_${postfix}`}>{item.text ? item.text : item[1].Value}</label> */}
|
||||||
<label class="form-check-label" for={`inputRadio_${postfix}`}>{item.text}</label>
|
<label class="form-check-label" for={`inputRadio_${postfix}`}>{item.text}</label>
|
||||||
|
@ -11,8 +11,8 @@ const YesNo = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
|
|||||||
name={`YesOrNo_${postfix}`}
|
name={`YesOrNo_${postfix}`}
|
||||||
id="choiceYes"
|
id="choiceYes"
|
||||||
value="1"
|
value="1"
|
||||||
checked={answers ? answers[postfix].answer === "1" : false}
|
checked={answers ? answers[postfix].answer === "Да" : false}
|
||||||
onChange={updateAnswersForm ? () => updateAnswersForm("1", postfix) : () => {}}
|
onChange={updateAnswersForm ? () => updateAnswersForm("Да", postfix) : () => {}}
|
||||||
/>
|
/>
|
||||||
<label class="form-check-label" for="choiceYes">Да</label>
|
<label class="form-check-label" for="choiceYes">Да</label>
|
||||||
</div>
|
</div>
|
||||||
@ -23,8 +23,8 @@ const YesNo = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
|
|||||||
name={`YesOrNo_${postfix}`}
|
name={`YesOrNo_${postfix}`}
|
||||||
id="choiceNo"
|
id="choiceNo"
|
||||||
value="2"
|
value="2"
|
||||||
checked={answers ? answers[postfix].answer === "2" : false}
|
checked={answers ? answers[postfix].answer === "Нет" : false}
|
||||||
onChange={updateAnswersForm ? () => updateAnswersForm("2", postfix) : () => {}}
|
onChange={updateAnswersForm ? () => updateAnswersForm("Нет", postfix) : () => {}}
|
||||||
/>
|
/>
|
||||||
<label class="form-check-label" for="choiceNo">Нет</label>
|
<label class="form-check-label" for="choiceNo">Нет</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
import axios from "axios";
|
|
||||||
|
|
||||||
async function listUsersApi(token) {
|
|
||||||
try {
|
|
||||||
const response = await axios.get(`https://api.minerva.krbl.ru/auth/manage/users`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"Authorization": `Token ${token}`
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export {listUsersApi}
|
|
36
src/hooks/api/answersApi.js
Normal file
36
src/hooks/api/answersApi.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
async function getAnswersApi(token, formToken) {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`https://api.minerva.krbl.ru/formBuilder/edit/${formToken}/answers`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function removeAnswerFormApi(token, formId, answerId) {
|
||||||
|
try {
|
||||||
|
const response = await axios.delete(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/answers`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
"answer_id": answerId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getAnswersApi, removeAnswerFormApi }
|
144
src/hooks/api/articleApi.js
Normal file
144
src/hooks/api/articleApi.js
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
|
||||||
|
async function createArticleApi(token, data) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/articles/new`,
|
||||||
|
{
|
||||||
|
"tags": [],
|
||||||
|
"title": "Новая статья"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function getListArticlesApi(token) {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`https://api.minerva.krbl.ru/articles/list`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function getArticleApi(token, articleId) {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`https://api.minerva.krbl.ru/articles/${articleId}/view`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function editTagsApi(token, articleId, tags, flag) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/articles/edit/${articleId}/tags`,
|
||||||
|
{
|
||||||
|
"delete_flag": flag,
|
||||||
|
"tags": tags,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function editTitleArticleApi(token, articleId, title) {
|
||||||
|
console.log('set')
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/articles/edit/${articleId}/setTitle`,
|
||||||
|
{
|
||||||
|
"title": title,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function addArticleApi(token, articleId, content) {
|
||||||
|
console.log('add')
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/articles/edit/${articleId}/add`,
|
||||||
|
{
|
||||||
|
"data": content,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function editArticleApi(token, articleId, content) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/articles/edit/${articleId}/set`,
|
||||||
|
{
|
||||||
|
"order": 0,
|
||||||
|
"data": content,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export {
|
||||||
|
createArticleApi,
|
||||||
|
getArticleApi,
|
||||||
|
getListArticlesApi,
|
||||||
|
editTagsApi,
|
||||||
|
editTitleArticleApi,
|
||||||
|
addArticleApi,
|
||||||
|
editArticleApi
|
||||||
|
}
|
@ -7,7 +7,7 @@ async function logIn(login, password) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ async function completeRegistration(data) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return "Ошибка. Проверте корректность введенных данных."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return validate.message
|
return validate.message
|
||||||
@ -32,7 +32,8 @@ async function completeRegistration(data) {
|
|||||||
async function verifyUserApi(token=false) {
|
async function verifyUserApi(token=false) {
|
||||||
if (token) {
|
if (token) {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get("https://api.minerva.krbl.ru/auth/me", {
|
const response = await axios.get("https://api.minerva.krbl.ru/auth/me",
|
||||||
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Token ${token}`,
|
"Authorization": `Token ${token}`,
|
||||||
},
|
},
|
||||||
@ -40,7 +41,7 @@ async function verifyUserApi(token=false) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -11,7 +11,7 @@ async function listFormBlockApi(token, formId) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,15 +29,16 @@ async function addFormBlockApi(token, formId, data) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function updateBlockApi(token, blockId, data) {
|
async function updateBlockApi(token, formId, data, order) {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${blockId}/set`,
|
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/set`,
|
||||||
{
|
{
|
||||||
"data": data
|
order: order,
|
||||||
|
data: data
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
@ -47,7 +48,26 @@ async function updateBlockApi(token, blockId, data) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function removeBlockApi(token, formId, order) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/set`,
|
||||||
|
{
|
||||||
|
order: order,
|
||||||
|
delete_flag: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,7 +86,7 @@ async function updateOrderBlockApi(token, formId, data) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +104,7 @@ async function saveFormApi(token) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,7 +119,7 @@ async function listFormBlockByTokenApi(token, formToken) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -111,16 +131,20 @@ async function saveAnswersApi(token, formToken, data) {
|
|||||||
"Authorization": `Token ${token}`
|
"Authorization": `Token ${token}`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
console.log("saveAnswersApi", response)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getAnswersApi(token, formToken) {
|
async function getBlockApi(token, formId, order) {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`https://api.minerva.krbl.ru/formBuilder/edit/${formToken}/answers`,
|
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/get`,
|
||||||
|
{
|
||||||
|
"order": order
|
||||||
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Token ${token}`
|
"Authorization": `Token ${token}`
|
||||||
@ -129,8 +153,18 @@ async function getAnswersApi(token, formToken) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { addFormBlockApi, listFormBlockApi, saveFormApi, updateBlockApi, updateOrderBlockApi, listFormBlockByTokenApi, saveAnswersApi, getAnswersApi }
|
export {
|
||||||
|
addFormBlockApi,
|
||||||
|
listFormBlockApi,
|
||||||
|
saveFormApi,
|
||||||
|
updateBlockApi,
|
||||||
|
updateOrderBlockApi,
|
||||||
|
listFormBlockByTokenApi,
|
||||||
|
saveAnswersApi,
|
||||||
|
removeBlockApi,
|
||||||
|
getBlockApi
|
||||||
|
}
|
@ -11,7 +11,7 @@ async function listFormsApi(token) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -26,10 +26,11 @@ async function createFormApi(token) {
|
|||||||
"Authorization": `Token ${token}`,
|
"Authorization": `Token ${token}`,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
console.log("createFormApi", response)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ async function removeFormApi(token, formId) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,13 +62,16 @@ async function updateTitleFormApi(token, formId, title) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function newFormTokenApi(token, formId) {
|
async function newFormTokenApi(token, formId, name) {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/new`, {},
|
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/new`,
|
||||||
|
{
|
||||||
|
"name": name
|
||||||
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Token ${token}`
|
"Authorization": `Token ${token}`
|
||||||
@ -76,7 +80,7 @@ async function newFormTokenApi(token, formId) {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,11 +92,59 @@ async function listFormsByTokenApi(token, formId) {
|
|||||||
"Authorization": `Token ${token}`
|
"Authorization": `Token ${token}`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
console.log(response)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return e
|
return e.response
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { listFormsApi, createFormApi, removeFormApi, updateTitleFormApi, newFormTokenApi, listFormsByTokenApi };
|
async function removeTokenFormApi(token, formId, formToken) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/revoke`,
|
||||||
|
{
|
||||||
|
"token_id": formToken
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function editTokenFormApi(token, formId, formToken, name) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/revoke`,
|
||||||
|
{
|
||||||
|
"token_id": formToken,
|
||||||
|
"is_active": true,
|
||||||
|
"name": name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
listFormsApi,
|
||||||
|
createFormApi,
|
||||||
|
removeFormApi,
|
||||||
|
updateTitleFormApi,
|
||||||
|
newFormTokenApi,
|
||||||
|
listFormsByTokenApi,
|
||||||
|
removeTokenFormApi,
|
||||||
|
editTokenFormApi
|
||||||
|
};
|
@ -6,8 +6,9 @@ async function editUserApi(token, data) {
|
|||||||
{
|
{
|
||||||
"email": data.email,
|
"email": data.email,
|
||||||
"first_name": data.first_name,
|
"first_name": data.first_name,
|
||||||
"id": "6617fec3f603c43e1719d3c8",
|
"id": data.id,
|
||||||
"is_admin": data.is_admin,
|
"is_admin": data.is_admin,
|
||||||
|
"is_teacher": data.is_teacher,
|
||||||
"last_name": data.last_name,
|
"last_name": data.last_name,
|
||||||
"login": data.login,
|
"login": data.login,
|
||||||
"phone": data.phone
|
"phone": data.phone
|
||||||
@ -17,15 +18,97 @@ async function editUserApi(token, data) {
|
|||||||
"Authorization": `Token ${token}`,
|
"Authorization": `Token ${token}`,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(response)
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
console.log(e)
|
return e.response
|
||||||
return e
|
}
|
||||||
}
|
};
|
||||||
// return false
|
|
||||||
|
|
||||||
|
async function getListUserApi(token) {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`https://api.minerva.krbl.ru/auth/manage/users`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function addUserApi(token, data) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://api.minerva.krbl.ru/auth/manage/add`,
|
||||||
|
{
|
||||||
|
"email": data.email,
|
||||||
|
"first_name": data.first_name,
|
||||||
|
// "id": data.id,
|
||||||
|
"is_admin": data.is_admin,
|
||||||
|
"is_teacher": data.is_teacher,
|
||||||
|
"last_name": data.last_name,
|
||||||
|
"login": data.login,
|
||||||
|
"phone": data.phone
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function removeUserApi(token, login) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post("https://api.minerva.krbl.ru/auth/manage/delete",
|
||||||
|
{
|
||||||
|
"login": login
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function editUserPass(token, login, pass) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post("https://api.minerva.krbl.ru/auth/manage/updatePassword",
|
||||||
|
{
|
||||||
|
"login": login,
|
||||||
|
"password": pass
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Token ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
return e.response
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {editUserApi}
|
export {
|
||||||
|
editUserApi,
|
||||||
|
getListUserApi,
|
||||||
|
addUserApi,
|
||||||
|
removeUserApi,
|
||||||
|
editUserPass
|
||||||
|
}
|
20
src/hooks/services/profile.js
Normal file
20
src/hooks/services/profile.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { verifyUserApi } from "../api/enterAccountApi";
|
||||||
|
|
||||||
|
|
||||||
|
async function verifyUser(cookies, user, setUser) {
|
||||||
|
const response = await verifyUserApi(cookies.token);
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
if (response.status === 200) {
|
||||||
|
setUser(response.data);
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
verifyUser
|
||||||
|
}
|
75
src/hooks/sundry/parseLinkVideo.js
Normal file
75
src/hooks/sundry/parseLinkVideo.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
const serviceVideo = {
|
||||||
|
"www.youtube.com": parseYTlinkVideo,
|
||||||
|
"youtu.be": parseMobileYTlinkVideo,
|
||||||
|
"vk.com": parseVKlinkVideo,
|
||||||
|
"rutube.ru": parseRTlinkVideo
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseYTlinkVideo(link) {
|
||||||
|
const startIndexIdVideo = link.indexOf("watch?v=") + 8;
|
||||||
|
const endIndexIdVideo = link.indexOf("&");
|
||||||
|
const idVideo = endIndexIdVideo === -1 ?
|
||||||
|
link.slice(startIndexIdVideo) :
|
||||||
|
link.slice(startIndexIdVideo, endIndexIdVideo);
|
||||||
|
|
||||||
|
return `https://www.youtube.com/embed/${idVideo}`
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseMobileYTlinkVideo(link) {
|
||||||
|
const startIndexIdVideo = 17;
|
||||||
|
const endIndexIdVideo = link.indexOf("?");
|
||||||
|
const idVideo = endIndexIdVideo === -1 ?
|
||||||
|
link.slice(startIndexIdVideo) :
|
||||||
|
link.slice(startIndexIdVideo, endIndexIdVideo);
|
||||||
|
|
||||||
|
return `https://www.youtube.com/embed/${idVideo}`
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseVKlinkVideo(link) {
|
||||||
|
let idVideo = "";
|
||||||
|
|
||||||
|
if (link.indexOf("video?z=video") !== -1) {
|
||||||
|
const startIndexIdVideo = link.indexOf("video?z=video") + 13;
|
||||||
|
const endIndexIdVideo = link.lastIndexOf("%");
|
||||||
|
idVideo = link.slice(startIndexIdVideo, endIndexIdVideo);
|
||||||
|
}
|
||||||
|
else if (link.indexOf("video") !== -1) {
|
||||||
|
const startIndexIdVideo = link.indexOf("video") + 5;
|
||||||
|
idVideo = link.slice(startIndexIdVideo)
|
||||||
|
}
|
||||||
|
|
||||||
|
const oid = idVideo.slice(0, idVideo.indexOf("_"));
|
||||||
|
const id = idVideo.slice(idVideo.indexOf("_") + 1);
|
||||||
|
|
||||||
|
return `https://vk.com/video_ext.php?oid=${oid}&id=${id}&hd=2`
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseRTlinkVideo(link) {
|
||||||
|
const startIndexIdVideo = link.indexOf("video/") + 6;
|
||||||
|
const endIndexIdVideo = link.lastIndexOf("?r=a");
|
||||||
|
const idVideo = endIndexIdVideo === -1 ?
|
||||||
|
link.slice(startIndexIdVideo) :
|
||||||
|
link.slice(startIndexIdVideo, endIndexIdVideo);
|
||||||
|
|
||||||
|
return `https://rutube.ru/play/embed/${idVideo}`
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseTotalLinkVideo(link) {
|
||||||
|
const serviceLink = {
|
||||||
|
check: false,
|
||||||
|
parseLink: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
for (let key of Object.keys(serviceVideo)) {
|
||||||
|
if (link.indexOf(key) !== -1) {
|
||||||
|
serviceLink.parseLink = serviceVideo[key](link);
|
||||||
|
serviceLink.check = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return serviceLink
|
||||||
|
};
|
||||||
|
|
||||||
|
export { parseYTlinkVideo, parseVKlinkVideo, parseTotalLinkVideo }
|
@ -13,11 +13,13 @@ function responseDataToListBlock(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let param of block.data) {
|
for (let param of block.data) {
|
||||||
|
|
||||||
if (Array.isArray(param.Value) && param.Value.length) {
|
if (Array.isArray(param.Value) && param.Value.length) {
|
||||||
newParam[param.Key] = param.Value.map(item => ({
|
newParam[param.Key] = param.Value.map(item => ({
|
||||||
id: item[0].Value,
|
id: item.find(obj => obj.Key === "id") ? item.find(obj => obj.Key === "id").Value : null,
|
||||||
text: item[1].Value
|
text: item.find(obj => obj.Key === "text") ? item.find(obj => obj.Key === "text").Value : null,
|
||||||
|
name: item.find(obj => obj.Key === "name") ? item.find(obj => obj.Key === "name").Value : null,
|
||||||
|
type: item.find(obj => obj.Key === "type") ? item.find(obj => obj.Key === "type").Value : null,
|
||||||
|
binary: item.find(obj => obj.Key === "binary") ? item.find(obj => obj.Key === "binary").Value : null,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -31,4 +33,27 @@ function responseDataToListBlock(data) {
|
|||||||
return result.sort((itemOne, itemTwo) => itemOne.order - itemTwo.order)
|
return result.sort((itemOne, itemTwo) => itemOne.order - itemTwo.order)
|
||||||
};
|
};
|
||||||
|
|
||||||
export { responseDataToListBlock }
|
function dateTimeParse(date) {
|
||||||
|
let newDate = "";
|
||||||
|
|
||||||
|
for (let symbol of date) {
|
||||||
|
if (symbol === "T") {
|
||||||
|
newDate += " ";
|
||||||
|
}
|
||||||
|
else if (symbol === ".") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newDate += symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newDate
|
||||||
|
};
|
||||||
|
|
||||||
|
function numberingBlocks(list, key, increase = 0) {
|
||||||
|
list.forEach((value, i) => list[i][key] = i + increase)
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
export { responseDataToListBlock, dateTimeParse, numberingBlocks }
|
@ -15,17 +15,16 @@ const constructorAnswerValidate = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const totalRegisterValidate = (data) => {
|
const totalRegisterValidate = (data) => {
|
||||||
const listValidation = [
|
const listValidation = [
|
||||||
constructorAnswerValidate(data.login.length, "Обязательное поле."),
|
constructorAnswerValidate(data.login.length, "Введите логин."),
|
||||||
// constructorAnswerValidate(data.surname.length, "Обязательное поле."),
|
constructorAnswerValidate(data.password.length, "Введите пароль."),
|
||||||
// constructorAnswerValidate(data.email.length, "Обязательное поле."),
|
constructorAnswerValidate(data.repiedPassword.length, "Введите повторно пароль."),
|
||||||
// constructorAnswerValidate(data.phone.length, "Обязательное поле."),
|
// constructorAnswerValidate(data.surname.length, "Обязательное поле."),
|
||||||
constructorAnswerValidate(
|
// constructorAnswerValidate(data.email.length, "Обязательное поле."),
|
||||||
data.password === data.repiedPassword,
|
// constructorAnswerValidate(data.phone.length, "Обязательное поле."),
|
||||||
"Введенные пароли не совпадают."
|
constructorAnswerValidate(data.password === data.repiedPassword, "Введенные пароли не совпадают."),
|
||||||
),
|
// constructorAnswerValidate(data.password >= 8, "Пароль должен иметь более 8 символов.")
|
||||||
// constructorAnswerValidate(data.password >= 8, "Пароль должен иметь более 8 символов.")
|
]
|
||||||
];
|
|
||||||
|
|
||||||
for (let value of listValidation) {
|
for (let value of listValidation) {
|
||||||
if (!value.status) {
|
if (!value.status) {
|
||||||
|
@ -1,67 +1,258 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useEffect, useContext } from "react";
|
||||||
|
import { useCookies } from "react-cookie";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import classes from "../assets/styles/adminPanel.module.scss";
|
import classes from "../assets/styles/adminPanel.module.scss";
|
||||||
|
import { UserData } from "../context";
|
||||||
|
import { getListUserApi, editUserApi, addUserApi, removeUserApi, editUserPass } from "../hooks/api/profileApi.js";
|
||||||
|
import { verifyUser } from "../hooks/services/profile.js";
|
||||||
|
import DefaultModal from "../components/DefaultModal.jsx";
|
||||||
|
import EditUserAdminPanel from "../components/bodyModal/EditUserAdminPanel.jsx";
|
||||||
|
import MyButton from "../components/MyButton.jsx";
|
||||||
|
import CheckModal from "../components/CheckModal.jsx";
|
||||||
|
|
||||||
|
|
||||||
const AdminPanel = () => {
|
const AdminPanel = () => {
|
||||||
const [token, setToken] = useState("");
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [cookies, setCookies] = useCookies(["user"]);
|
||||||
|
const {user, setUser, userRef} = useContext(UserData);
|
||||||
|
const [listUser, setListUser] = useState([]);
|
||||||
|
|
||||||
const [users, setUsers] = useState([
|
const [email, setEmail] = useState("");
|
||||||
{
|
const [firstName, setFirstName] = useState("");
|
||||||
"email": "senya.bogachev@mail.ru",
|
const [id, setId] = useState(false);
|
||||||
"first_name": "Арсений",
|
const [isAdmin, setIsAdmin] = useState(false);
|
||||||
"id": "1",
|
const [isTeacher, setIsTeacher] = useState(false);
|
||||||
"is_admin": false,
|
const [lastName, setLastName] = useState("");
|
||||||
"last_name": "Богачев",
|
const [login, setLogin] = useState("");
|
||||||
"login": "Ars",
|
const [phone, setPhone] = useState("");
|
||||||
"phone": "89110128244"
|
const [pass, setPass] = useState("");
|
||||||
},
|
|
||||||
{
|
useEffect(() => {
|
||||||
"email": "dasha@mail.ru",
|
async function getListUser() {
|
||||||
"first_name": "Дарья",
|
const responseListUser = await getListUserApi(cookies.token);
|
||||||
"id": "1",
|
|
||||||
"is_admin": false,
|
if (
|
||||||
"last_name": "Утешева",
|
responseListUser.status === 200
|
||||||
"login": "dasha",
|
) {
|
||||||
"phone": "89111032339"
|
setListUser(responseListUser.data)
|
||||||
},
|
}
|
||||||
{
|
else if (
|
||||||
"email": "kirik@mail.ru",
|
responseListUser.status === 401
|
||||||
"first_name": "Кирилл",
|
) {
|
||||||
"id": "string",
|
// navigate("/enter")
|
||||||
"is_admin": false,
|
setUser(false)
|
||||||
"last_name": "Жердев",
|
}
|
||||||
"login": "Kirik",
|
else {
|
||||||
"phone": "89110045673"
|
console.log(responseListUser)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
])
|
|
||||||
|
getListUser()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function clearState() {
|
||||||
|
setEmail("")
|
||||||
|
setFirstName("")
|
||||||
|
setId("")
|
||||||
|
setIsAdmin("")
|
||||||
|
setIsTeacher("")
|
||||||
|
setLastName("")
|
||||||
|
setLogin("")
|
||||||
|
setPhone("")
|
||||||
|
setPass("")
|
||||||
|
};
|
||||||
|
|
||||||
|
async function addUser() {
|
||||||
|
const currentState = {
|
||||||
|
email: email,
|
||||||
|
first_name: firstName,
|
||||||
|
id: id,
|
||||||
|
is_admin: isAdmin,
|
||||||
|
is_teacher: isTeacher,
|
||||||
|
last_name: lastName,
|
||||||
|
login: login,
|
||||||
|
phone: phone
|
||||||
|
}
|
||||||
|
const response = await addUserApi(cookies.token, currentState)
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setListUser([...listUser, currentState])
|
||||||
|
|
||||||
|
if (pass) {
|
||||||
|
await editUserPass(cookies.token, login, pass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
clearState()
|
||||||
|
};
|
||||||
|
|
||||||
|
async function editUser() {
|
||||||
|
const currentState = {
|
||||||
|
email: email,
|
||||||
|
first_name: firstName,
|
||||||
|
id: id,
|
||||||
|
is_admin: isAdmin,
|
||||||
|
is_teacher: isTeacher,
|
||||||
|
last_name: lastName,
|
||||||
|
login: login,
|
||||||
|
phone: phone
|
||||||
|
};
|
||||||
|
const response = await editUserApi(cookies.token, currentState);
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setListUser(listUser.map(item => item.id === id ? currentState : item));
|
||||||
|
|
||||||
|
if (pass) {
|
||||||
|
await editUserPass(cookies.token, login, pass);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
clearState();
|
||||||
|
};
|
||||||
|
|
||||||
|
function openUser(user) {
|
||||||
|
setEmail(user.email)
|
||||||
|
setFirstName(user.first_name)
|
||||||
|
setId(user.id)
|
||||||
|
setIsAdmin(user.is_admin)
|
||||||
|
setIsTeacher(user.is_teacher)
|
||||||
|
setLastName(user.last_name)
|
||||||
|
setLogin(user.login)
|
||||||
|
setPhone(user.phone)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeUser(login) {
|
||||||
|
const response = await removeUserApi(cookies.token, login)
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setListUser(listUser.filter(item => item.login !== login))
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.main}>
|
<div className={classes.main}>
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
<div className={classes.admin}>
|
<div className={classes.admin}>
|
||||||
<div className={classes.admin__linkProfile}>
|
{/* <div className={classes.admin__linkProfile}>
|
||||||
<span onClick={() => navigate("/profile")}>Профиль</span>
|
<span onClick={() => navigate("/profile")}>Профиль</span>
|
||||||
</div>
|
</div> */}
|
||||||
<div className={classes.admin__wrapper}>
|
<div className={classes.admin__wrapper}>
|
||||||
<div className={classes.admin__wrapper__header}>
|
<div className={classes.admin__wrapper__header}>
|
||||||
<h3>Пользователи</h3>
|
<h3>Пользователи</h3>
|
||||||
|
<MyButton
|
||||||
|
text={"Создать пользователя"}
|
||||||
|
class={"main__green"}
|
||||||
|
toggle={"modal"}
|
||||||
|
target={"#adminModal"}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.admin__wrapper__body}>
|
<div className={classes.admin__wrapper__body}>
|
||||||
<div className={classes.admin__wrapper__body__columns}>
|
<div className={classes.admin__wrapper__body__columns}>
|
||||||
<div className={classes.admin__wrapper__body__columns__item}>Логин</div>
|
<div className={classes.admin__wrapper__body__columns__wrapper}>
|
||||||
<div className={classes.admin__wrapper__body__columns__item}>Фамилия</div>
|
<div className={classes.admin__wrapper__body__columns__item}>Логин</div>
|
||||||
<div className={classes.admin__wrapper__body__columns__item}>Email</div>
|
<div className={classes.admin__wrapper__body__columns__item}>Фамилия</div>
|
||||||
|
<div className={classes.admin__wrapper__body__columns__item}>Email</div>
|
||||||
|
<div className={classes.admin__wrapper__body__columns__item}>Учитель</div>
|
||||||
|
<div className={classes.admin__wrapper__body__columns__item}>Администратор</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.admin__wrapper__body__users}>
|
<div className={classes.admin__wrapper__body__users}>
|
||||||
{users.map(item =>
|
{listUser.map(item =>
|
||||||
<div className={classes.admin__wrapper__body__users__item}>
|
<div className={classes.admin__wrapper__body__users__item} key={item.id}>
|
||||||
<div className={classes.admin__wrapper__body__users__item__link}>{item.login}</div>
|
<div className={classes.admin__wrapper__body__users__item__wrapper}>
|
||||||
<div className={classes.admin__wrapper__body__users__item__info}>{item.last_name}</div>
|
<div
|
||||||
<div className={classes.admin__wrapper__body__users__item__info}>{item.email}</div>
|
className={classes.admin__wrapper__body__users__item__link}
|
||||||
|
data-bs-toggle="modal" data-bs-target={`#adminModal`}
|
||||||
|
onClick={() => openUser(item)}
|
||||||
|
>
|
||||||
|
{item.login}
|
||||||
|
</div>
|
||||||
|
<div className={classes.admin__wrapper__body__users__item__info}>
|
||||||
|
{item.last_name ? item.last_name : '-'}
|
||||||
|
</div>
|
||||||
|
<div className={classes.admin__wrapper__body__users__item__info}>
|
||||||
|
{item.email ? item.email : '-'}
|
||||||
|
</div>
|
||||||
|
<div className={classes.admin__wrapper__body__users__item__info}>
|
||||||
|
{
|
||||||
|
item.is_teacher ?
|
||||||
|
<i class="fa-solid fa-circle-check" style={{color: "rgb(150, 209, 158)"}}></i> :
|
||||||
|
<i class="fa-solid fa-circle-xmark" style={{color: "rgb(235, 130, 130)"}}></i>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className={classes.admin__wrapper__body__users__item__info}>
|
||||||
|
{
|
||||||
|
item.is_admin ?
|
||||||
|
<i class="fa-solid fa-circle-check" style={{color: "rgb(150, 209, 158)"}}></i> :
|
||||||
|
<i class="fa-solid fa-circle-xmark" style={{color: "rgb(235, 130, 130)"}}></i>}
|
||||||
|
</div>
|
||||||
|
<div className={classes.admin__wrapper__body__users__item__remove}>
|
||||||
|
<i class="fa-solid fa-trash" data-bs-toggle="modal" data-bs-target={`#checkModal${item.id}`}></i>
|
||||||
|
</div>
|
||||||
|
<CheckModal
|
||||||
|
postfix={item.id}
|
||||||
|
message={`Вы хотетите удалить пользователя <${item.login}>?`}
|
||||||
|
action={{
|
||||||
|
execute: () => removeUser(item.login),
|
||||||
|
cancel: () => {}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<DefaultModal
|
||||||
|
name={"adminModal"}
|
||||||
|
BodyModal={
|
||||||
|
<EditUserAdminPanel
|
||||||
|
id={id}
|
||||||
|
email={email}
|
||||||
|
firstName={firstName}
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
isTeacher={isTeacher}
|
||||||
|
lastName={lastName}
|
||||||
|
login={login}
|
||||||
|
phone={phone}
|
||||||
|
setEmail={setEmail}
|
||||||
|
setFirstName={setFirstName}
|
||||||
|
setIsAdmin={setIsAdmin}
|
||||||
|
setIsTeacher={setIsTeacher}
|
||||||
|
setLastName={setLastName}
|
||||||
|
setLogin={setLogin}
|
||||||
|
setPhone={setPhone}
|
||||||
|
pass={pass}
|
||||||
|
setPass={setPass}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
btn={[
|
||||||
|
{text: id ? "Изменить" : "Сохранить", dismiss: "modal", class: "main__green", action: id ? () => editUser() : () => addUser()},
|
||||||
|
{text: "Отмена", dismiss: "modal", class: "main__white", action: () => clearState()}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,13 +3,18 @@ import { useCookies } from "react-cookie";
|
|||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { answersData } from "../context";
|
import { answersData } from "../context";
|
||||||
import classes from "../assets/styles/answersForm.module.scss";
|
import classes from "../assets/styles/answersForm.module.scss";
|
||||||
import { responseDataToListBlock } from "../hooks/sundry/parseListBlock";
|
import { responseDataToListBlock, dateTimeParse } from "../hooks/sundry/parseListBlock.js";
|
||||||
import { listFormBlockApi, getAnswersApi } from "../hooks/api/formApi";
|
import { listFormBlockApi } from "../hooks/api/formApi.js";
|
||||||
import { listUsersApi } from "../hooks/api/adminApi";
|
import { getListUserApi } from "../hooks/api/profileApi.js";
|
||||||
|
import { removeAnswerFormApi, getAnswersApi } from "../hooks/api/answersApi.js";
|
||||||
|
import Loading from "../components/Loading.jsx";
|
||||||
|
import CheckModal from "../components/CheckModal.jsx";
|
||||||
|
import { UserData } from "../context";
|
||||||
|
|
||||||
const AnswersForm = () => {
|
const AnswersForm = () => {
|
||||||
const { formId } = useParams();
|
const { formId } = useParams();
|
||||||
const {answersList, setAnswersList} = useContext(answersData);
|
const {answersList, setAnswersList} = useContext(answersData);
|
||||||
|
const {user, setUser} = useContext(UserData);
|
||||||
const [data, setData] = useState(false);
|
const [data, setData] = useState(false);
|
||||||
const [cookies, _, __] = useCookies(["user"]);
|
const [cookies, _, __] = useCookies(["user"]);
|
||||||
|
|
||||||
@ -18,9 +23,7 @@ const AnswersForm = () => {
|
|||||||
const result = []
|
const result = []
|
||||||
const responseBlocks = await listFormBlockApi(cookies.token, formId);
|
const responseBlocks = await listFormBlockApi(cookies.token, formId);
|
||||||
const responseAnswers = await getAnswersApi(cookies.token, formId);
|
const responseAnswers = await getAnswersApi(cookies.token, formId);
|
||||||
const listUsers = await listUsersApi(cookies.token);
|
const listUsers = await getListUserApi(cookies.token);
|
||||||
console.log("responseBlocks", responseBlocks)
|
|
||||||
console.log("responseAnswers", responseAnswers)
|
|
||||||
|
|
||||||
if (responseBlocks.status === 200 && responseBlocks.data) {
|
if (responseBlocks.status === 200 && responseBlocks.data) {
|
||||||
const listBlocks = responseDataToListBlock(responseBlocks.data);
|
const listBlocks = responseDataToListBlock(responseBlocks.data);
|
||||||
@ -28,13 +31,18 @@ const AnswersForm = () => {
|
|||||||
if (responseAnswers.data) {
|
if (responseAnswers.data) {
|
||||||
for (let item of responseAnswers.data) {
|
for (let item of responseAnswers.data) {
|
||||||
const blocks = {
|
const blocks = {
|
||||||
|
id: item.id,
|
||||||
user: listUsers.data.find(user => user.id === item.user_id).login,
|
user: listUsers.data.find(user => user.id === item.user_id).login,
|
||||||
|
date: dateTimeParse(item.date),
|
||||||
block: []
|
block: []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.data) {
|
if (item.data) {
|
||||||
for (let i = 0; i < item.data.length; i++) {
|
for (let i = 0; i < item.data.length; i++) {
|
||||||
blocks.block.push({answers: {id: item.data[i][0].Value, answer: item.data[i][1].Value}, question: listBlocks[i]})
|
blocks.block.push({
|
||||||
|
answers: {id: item.data[i].find(obj => obj.Key === "id").Value, answer: item.data[i].find(obj => obj.Key === "answer").Value},
|
||||||
|
question: listBlocks[i]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -44,20 +52,42 @@ const AnswersForm = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.push(blocks)
|
result.push(blocks)
|
||||||
}
|
}
|
||||||
console.log("result", result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setData(result)
|
setData(result)
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
console.log(responseBlocks)
|
console.log(response)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getForm()
|
getForm()
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
async function removeAnswerForm(answerId) {
|
||||||
|
const response = await removeAnswerFormApi(cookies.token, formId, answerId)
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setData([...data].filter(item => item.id !== answerId))
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.main}>
|
<div className={classes.main}>
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
@ -67,27 +97,51 @@ const AnswersForm = () => {
|
|||||||
<h3>Ответы</h3>
|
<h3>Ответы</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.answers__wrapper__body}>
|
<div className={classes.answers__wrapper__body}>
|
||||||
{data ?
|
<div className={classes.answers__wrapper__body__column}>
|
||||||
data.map((item, i) =>
|
<div className={classes.answers__wrapper__body__column__wrapper}>
|
||||||
<div className={classes.answers__wrapper__body__item} key={i}>
|
<div>Логин</div>
|
||||||
<div className={classes.answers__wrapper__body__item__user} data-bs-toggle={"modal"} data-bs-target={`#answersModal${i}`}>
|
<div>Дата</div>
|
||||||
{item.user}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal fade myModal" className={classes.myModal} id={`answersModal${i}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
|
{data ?
|
||||||
|
data.map((item, dataIndex) =>
|
||||||
|
<div className={classes.answers__wrapper__body__item} key={dataIndex}>
|
||||||
|
<div className={classes.answers__wrapper__body__item__wrapper}>
|
||||||
|
<div className={classes.answers__wrapper__body__item__wrapper__user} data-bs-toggle={"modal"} data-bs-target={`#answersModal${dataIndex}`}>
|
||||||
|
{item.user}
|
||||||
|
</div>
|
||||||
|
<div className={classes.answers__wrapper__body__item__wrapper__date}>
|
||||||
|
{item.date}
|
||||||
|
</div>
|
||||||
|
<i class="fa-solid fa-trash" data-bs-toggle="modal" data-bs-target={`#checkModal${item.id}`}></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CheckModal
|
||||||
|
postfix={item.id}
|
||||||
|
message={`Вы хотетите удалить ответы пользователя <${item.user}>?`}
|
||||||
|
action={{
|
||||||
|
execute: () => removeAnswerForm(item.id),
|
||||||
|
cancel: () => {}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="modal fade myModal" className={classes.myModal} id={`answersModal${dataIndex}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
|
||||||
<div class="modal-dialog myModal__dialog" className={classes.myModal__dialog}>
|
<div class="modal-dialog myModal__dialog" className={classes.myModal__dialog}>
|
||||||
<div class="modal-content" className={classes.myModal__dialog__content}>
|
<div class="modal-content" className={classes.myModal__dialog__content}>
|
||||||
<div class="modal-body" className={classes.myModal__dialog__content__body}>
|
<div class="modal-body" className={classes.myModal__dialog__content__body}>
|
||||||
|
{item.block.map((block, blockIndex) =>
|
||||||
|
<div className={classes.myModal__item} key={blockIndex}>
|
||||||
{item.block.map((block, i) =>
|
|
||||||
<div className={classes.myModal__item} key={i}>
|
|
||||||
<div className={classes.myModal__item__question}>
|
<div className={classes.myModal__item__question}>
|
||||||
<p className={classes.myModal__item__question__text}>{block.question.question}</p>
|
<p className={classes.myModal__item__question__text}>{block.question.question}</p>
|
||||||
<p className={classes.myModal__item__question__comment}>{block.question.comment}</p>
|
<p className={classes.myModal__item__question__comment}>{block.question.comment}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.myModal__item__answer}>
|
<div className={classes.myModal__item__answer}>
|
||||||
<p className={classes.myModal__item__question__text}>Ответ: {block.answers.answer}</p>
|
<p className={classes.myModal__item__question__text}>Ответ: {
|
||||||
|
Array.isArray(block.answers.answer) ?
|
||||||
|
block.answers.answer.map((answer, indexAnswer) => <span key={indexAnswer}>{answer}; </span>) :
|
||||||
|
block.answers.answer
|
||||||
|
}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>)}
|
</div>)}
|
||||||
</div>
|
</div>
|
||||||
@ -99,26 +153,9 @@ const AnswersForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
: <div>Ответов нет</div>}
|
:
|
||||||
|
<Loading/>}
|
||||||
|
</div>
|
||||||
{/* <MyButton text={'Предпросмотр'} backgroundColor={'rgb(225, 225, 225)'} toggle={"modal"} target={"#previewModal"}/>
|
|
||||||
{data ? <div className={classes.answers__wrapper__body__item}></div> */}
|
|
||||||
{/* {data ?
|
|
||||||
data.map((item, i) =>
|
|
||||||
<div className={classes.answers__wrapper__body__item} key={i}>
|
|
||||||
<div className={classes.answers__wrapper__body__item__question}>
|
|
||||||
<p className={classes.answers__wrapper__body__item__question__text}>{i + 1}) {item.question.question}</p>
|
|
||||||
<p className={classes.item__question__comment}>{item.question.comment}</p>
|
|
||||||
</div>
|
|
||||||
<div className={classes.answers__wrapper__body__item__answer}>
|
|
||||||
<p className={classes.answers__wrapper__body__item__question__text}>Ответ: {item.answers.answer}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
: <div>Ответов нет</div>} */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
138
src/pages/Articles.jsx
Normal file
138
src/pages/Articles.jsx
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import React, { useState, useContext, useEffect } from "react";
|
||||||
|
import { useCookies } from "react-cookie";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import classes from "../assets/styles/articles.module.scss";
|
||||||
|
import MyButton from "../components/MyButton.jsx";
|
||||||
|
import MyInput from "../components/MyInput.jsx";
|
||||||
|
import { UserData } from "../context";
|
||||||
|
import CheckModal from "../components/CheckModal.jsx";
|
||||||
|
import {
|
||||||
|
createArticleApi,
|
||||||
|
getListArticlesApi,
|
||||||
|
} from "../hooks/api/articleApi.js";
|
||||||
|
|
||||||
|
const Articles = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { user, setUser } = useContext(UserData);
|
||||||
|
const [stateLoading, setStateLoading] = useState(false);
|
||||||
|
|
||||||
|
const [listArticles, setListArticles] = useState([]);
|
||||||
|
|
||||||
|
const [cookies, _, __] = useCookies(["user"]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function getListArticles() {
|
||||||
|
const response = await getListArticlesApi(cookies.token);
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setListArticles(response.data);
|
||||||
|
} else if (response.status === 401) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
|
} else {
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getListArticles();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function createArticle() {
|
||||||
|
const response = await createArticleApi(cookies.token);
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
navigate(`/articles/${response.data.id}/edit`);
|
||||||
|
} else if (response.status === 401) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
|
} else {
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.main}>
|
||||||
|
<div className={classes.wrapper}>
|
||||||
|
<div className={classes.panel}>
|
||||||
|
<MyInput placeholder={"Поиск..."} />
|
||||||
|
<MyButton
|
||||||
|
click={createArticle}
|
||||||
|
class={"main__blue"}
|
||||||
|
otherStyle={{ width: "200px" }}
|
||||||
|
text={
|
||||||
|
stateLoading ? (
|
||||||
|
<div class="spinner-border text-light" role="status">
|
||||||
|
<span class="visually-hidden">Загрузка...</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
"Создать"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.listArticles}>
|
||||||
|
<div className={classes.listArticles__columns}>
|
||||||
|
<div className={classes.listArticles__columns__item}>Название</div>
|
||||||
|
<div className={classes.listArticles__columns__item}>
|
||||||
|
Дата публикации
|
||||||
|
</div>
|
||||||
|
<div className={classes.listArticles__columns__item}>Автор</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.listArticles__forms}>
|
||||||
|
{listArticles.map((item) => (
|
||||||
|
<div className={classes.listArticles__forms__item}>
|
||||||
|
<div
|
||||||
|
className={classes.listArticles__forms__item__title}
|
||||||
|
onClick={() => navigate(`/articles/${item.id}/edit`)}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</div>
|
||||||
|
<div className={classes.listArticles__forms__item__date}>
|
||||||
|
24.06.24
|
||||||
|
</div>
|
||||||
|
<div className={classes.listArticles__forms__item__author}>
|
||||||
|
kuwsh1n
|
||||||
|
</div>
|
||||||
|
<i
|
||||||
|
class="fa-solid fa-ellipsis-vertical"
|
||||||
|
id="action"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
></i>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="action">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
onClick={() => navigate(`/articles/${item.id}/`)}
|
||||||
|
>
|
||||||
|
Открыть
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target={`#checkModaltest`}
|
||||||
|
>
|
||||||
|
Удалить
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<CheckModal
|
||||||
|
postfix={"test"}
|
||||||
|
message={`Вы хотетите удалить статью <Test article>?`}
|
||||||
|
action={{
|
||||||
|
execute: () => {},
|
||||||
|
cancel: () => {},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Articles;
|
@ -26,6 +26,9 @@ const EnterAccount = () => {
|
|||||||
const { user, setUser } = useContext(UserData);
|
const { user, setUser } = useContext(UserData);
|
||||||
const [cookies, setCookie, removeCookie] = useCookies(["user"]);
|
const [cookies, setCookie, removeCookie] = useCookies(["user"]);
|
||||||
|
|
||||||
|
const [loginError, setLoginError] = useState(false);
|
||||||
|
const [regsterError, setRegsterError] = useState(false);
|
||||||
|
|
||||||
function cleanState() {
|
function cleanState() {
|
||||||
setEmail("");
|
setEmail("");
|
||||||
setPhone("");
|
setPhone("");
|
||||||
@ -49,21 +52,13 @@ const EnterAccount = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
// setUser({
|
|
||||||
// email: email,
|
|
||||||
// phone: phone,
|
|
||||||
// login: login,
|
|
||||||
// surname: surname,
|
|
||||||
// patronymic: patronymic,
|
|
||||||
// password: password,
|
|
||||||
// });
|
|
||||||
const responseMe = await verifyUserApi(response.data.token);
|
const responseMe = await verifyUserApi(response.data.token);
|
||||||
setUser(responseMe.data);
|
setUser(responseMe.data);
|
||||||
setCookie("token", response.data.token);
|
setCookie("token", response.data.token);
|
||||||
cleanState();
|
cleanState();
|
||||||
navigate("/");
|
navigate("/");
|
||||||
} else {
|
} else {
|
||||||
console.log("Error");
|
setRegsterError(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,10 +69,11 @@ const EnterAccount = () => {
|
|||||||
setCookie("token", response.data.token);
|
setCookie("token", response.data.token);
|
||||||
const responseMe = await verifyUserApi(response.data.token);
|
const responseMe = await verifyUserApi(response.data.token);
|
||||||
setUser(responseMe.data);
|
setUser(responseMe.data);
|
||||||
|
|
||||||
cleanState();
|
cleanState();
|
||||||
navigate("/");
|
navigate("/");
|
||||||
} else {
|
} else {
|
||||||
console.log(response);
|
setLoginError(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +96,7 @@ const EnterAccount = () => {
|
|||||||
enter === "register" ? "nav-link active" : "nav-link"
|
enter === "register" ? "nav-link active" : "nav-link"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Регистрация
|
Регитрация
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -113,6 +109,17 @@ const EnterAccount = () => {
|
|||||||
<h3>Войти в аккаунт</h3>
|
<h3>Войти в аккаунт</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.content__wrapper__login__body}>
|
<div className={classes.content__wrapper__login__body}>
|
||||||
|
{loginError ? (
|
||||||
|
<span
|
||||||
|
className={classes.content__wrapper__login__body__error}
|
||||||
|
>
|
||||||
|
Ошибка. Проверте корректность ввода логина и пароля.
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
className={classes.content__wrapper__login__body__error}
|
||||||
|
></span>
|
||||||
|
)}
|
||||||
<MyInput
|
<MyInput
|
||||||
placeholder={"Логин"}
|
placeholder={"Логин"}
|
||||||
otherMainStyle={{ width: "100%", height: "20%" }}
|
otherMainStyle={{ width: "100%", height: "20%" }}
|
||||||
@ -132,7 +139,7 @@ const EnterAccount = () => {
|
|||||||
<div className={classes.content__wrapper__login__footer}>
|
<div className={classes.content__wrapper__login__footer}>
|
||||||
<MyButton
|
<MyButton
|
||||||
text={"Войти"}
|
text={"Войти"}
|
||||||
otherStyle={{ height: "50%", width: "20%" }}
|
class={"main__blue"}
|
||||||
click={logInToAccount}
|
click={logInToAccount}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -140,9 +147,24 @@ const EnterAccount = () => {
|
|||||||
) : (
|
) : (
|
||||||
<div className={classes.content__wrapper__register}>
|
<div className={classes.content__wrapper__register}>
|
||||||
<div className={classes.content__wrapper__register__header}>
|
<div className={classes.content__wrapper__register__header}>
|
||||||
<h3>Зарегистрировать учетную запись</h3>
|
<h3>Создать аккаунт</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.content__wrapper__register__body}>
|
<div className={classes.content__wrapper__register__body}>
|
||||||
|
{regsterError ? (
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
classes.content__wrapper__register__body__error
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{regsterError}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
classes.content__wrapper__register__body__error
|
||||||
|
}
|
||||||
|
></span>
|
||||||
|
)}
|
||||||
<MyInput
|
<MyInput
|
||||||
placeholder={"Логин"}
|
placeholder={"Логин"}
|
||||||
otherMainStyle={{ width: "100%", height: "15%" }}
|
otherMainStyle={{ width: "100%", height: "15%" }}
|
||||||
@ -181,7 +203,7 @@ const EnterAccount = () => {
|
|||||||
<div className={classes.content__wrapper__register__footer}>
|
<div className={classes.content__wrapper__register__footer}>
|
||||||
<MyButton
|
<MyButton
|
||||||
text={"Создать"}
|
text={"Создать"}
|
||||||
otherStyle={{ height: "100%", width: "20%" }}
|
class={"main__blue"}
|
||||||
click={() => createUser()}
|
click={() => createUser()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,128 +1,234 @@
|
|||||||
import React, { useState, useContext, useEffect } from "react";
|
import React, { useState, useContext, useEffect } from "react";
|
||||||
import { useCookies } from "react-cookie";
|
import { useCookies } from "react-cookie";
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from "react-router-dom";
|
||||||
import classes from "../assets/styles/forms.module.scss"
|
import classes from "../assets/styles/forms.module.scss";
|
||||||
import MyButton from "../components/MyButton.jsx";
|
import MyButton from "../components/MyButton.jsx";
|
||||||
import MyInput from "../components/MyInput.jsx";
|
import MyInput from "../components/MyInput.jsx";
|
||||||
import { FormsData, UserData } from "../context";
|
import { FormsData, UserData } from "../context";
|
||||||
import { listFormsApi, createFormApi, removeFormApi, newFormTokenApi, listFormsByTokenApi } from "../hooks/api/listFormsApi.js";
|
import CheckModal from "../components/CheckModal.jsx";
|
||||||
|
import { verifyUserApi } from "../hooks/api/enterAccountApi.js";
|
||||||
|
import {
|
||||||
|
listFormsApi,
|
||||||
|
createFormApi,
|
||||||
|
removeFormApi,
|
||||||
|
newFormTokenApi,
|
||||||
|
listFormsByTokenApi,
|
||||||
|
} from "../hooks/api/listFormsApi.js";
|
||||||
|
|
||||||
const Forms = () => {
|
const Forms = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const {forms, setForms} = useContext(FormsData);
|
const { forms, setForms } = useContext(FormsData);
|
||||||
const {user, setUser} = useContext(UserData);
|
const { user, setUser, userRef } = useContext(UserData);
|
||||||
const [stateLoading, setStateLoading] = useState(false);
|
const [stateLoading, setStateLoading] = useState(false);
|
||||||
|
const [searchForm, setSearchForm] = useState("");
|
||||||
|
|
||||||
const [cookies, _, __] = useCookies(["user"]);
|
const [cookies, setCookies, __] = useCookies(["user"]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function listForms() {
|
async function listForms() {
|
||||||
const response = await listFormsApi(cookies.token);
|
const responseForms = await listFormsApi(cookies.token);
|
||||||
|
const responseUser = await verifyUserApi(cookies.token)
|
||||||
|
|
||||||
if (response.data) {
|
if (responseForms.data && responseUser) {
|
||||||
setForms(response.data);
|
setForms(responseForms.data.filter(item => item.owner_id === responseUser.data.id));
|
||||||
}
|
} else if (responseForms.status === 200 && response.data) {
|
||||||
else if (response.status === 200 && response.data) {
|
setForms([]);
|
||||||
setForms([]);
|
} else if (responseForms.status === 401 || responseUser.status === 401) {
|
||||||
}
|
// navigate("/enter")
|
||||||
else {
|
setUser(false)
|
||||||
console.log(response)
|
} else {
|
||||||
}
|
console.log(responseForms);
|
||||||
};
|
console.log(responseUser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
listForms();
|
listForms();
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
async function createForm() {
|
async function createForm() {
|
||||||
setStateLoading(true);
|
setStateLoading(true);
|
||||||
const response = await createFormApi(cookies.token);
|
const response = await createFormApi(cookies.token);
|
||||||
console.log("response", response)
|
setStateLoading(false);
|
||||||
setStateLoading(false);
|
|
||||||
|
|
||||||
if (response.data) {
|
if (response.data && response.status === 200) {
|
||||||
const token = await newFormTokenApi(cookies.token, response.data.id)
|
const token = await newFormTokenApi(cookies.token, response.data.id, "Админ");
|
||||||
|
navigate(`/forms/${response.data.id}/edit`);
|
||||||
|
} else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
navigate(`/forms/${response.data.id}/edit`)
|
function editForm(item) {
|
||||||
}
|
navigate(`/forms/${item.id}/edit`);
|
||||||
else {
|
}
|
||||||
console.log(response)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function editForm(item) {
|
async function removeForm(id) {
|
||||||
navigate(`/forms/${item.id}/edit`);
|
const response = await removeFormApi(cookies.token, id);
|
||||||
};
|
|
||||||
|
|
||||||
async function removeForm(id) {
|
if (response.status === 200) {
|
||||||
const response = await removeFormApi(cookies.token, id)
|
setForms([...forms.filter((item) => item.id !== id)]);
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (response.status === 200) {
|
async function openFormView(formId) {
|
||||||
setForms([...forms.filter(item => item.id !== id)]);
|
const response = await listFormsByTokenApi(cookies.token, formId);
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(response)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async function openFormView(formId) {
|
if (response.status === 200 && response.data.tokens) {
|
||||||
const response = await listFormsByTokenApi(cookies.token, formId);
|
navigate(`/forms/${response.data.tokens[0].id}/`);
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (response.status === 200 && response.data.tokens) {
|
async function copyLinkToFormView(formId) {
|
||||||
navigate(`/forms/${response.data.tokens[0].id}/`);
|
const response = await listFormsByTokenApi(cookies.token, formId);
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(response)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async function copyLinkToFormView(formId) {
|
if (response.status === 200 && response.data.tokens) {
|
||||||
const response = await listFormsByTokenApi(cookies.token, formId);
|
navigator.clipboard.writeText(
|
||||||
|
`${window.location.host}/forms/${response.data.tokens[0].id}/`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (response.status === 200 && response.data.tokens) {
|
const filterFormsBySearch = () =>
|
||||||
navigator.clipboard.writeText(`http://localhost:3000/forms/${response.data.tokens[0].id}/`)
|
[...forms].filter((item) => item.title.toLowerCase().includes(searchForm));
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(response)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.main}>
|
<div className={classes.main}>
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
<div className={classes.panel}>
|
<div className={classes.panel}>
|
||||||
{/* <MyInput placeholder={'Поиск...'}/> */}
|
<MyInput
|
||||||
<MyButton click={createForm} otherStyle={{width: '200px'}} text={
|
placeholder={"Поиск..."}
|
||||||
stateLoading ? <div class="spinner-border text-light" role="status">
|
value={searchForm}
|
||||||
<span class="visually-hidden">Загрузка...</span>
|
change={setSearchForm}
|
||||||
</div> : 'Создать'
|
/>
|
||||||
}/>
|
<MyButton
|
||||||
|
click={createForm}
|
||||||
|
class={"main__blue"}
|
||||||
|
otherStyle={{ width: "200px" }}
|
||||||
|
text={
|
||||||
|
stateLoading ? (
|
||||||
|
<div class="spinner-border text-light" role="status">
|
||||||
|
<span class="visually-hidden">Загрузка...</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.listForms}>
|
) : (
|
||||||
<div className={classes.listForms__columns}>
|
"Создать"
|
||||||
<div className={classes.listForms__columns__item}>Название</div>
|
)
|
||||||
{/* <div className={classes.listForms__columns__item}>Ответы</div>
|
}
|
||||||
<div className={classes.listForms__columns__item}>Изменения</div> */}
|
/>
|
||||||
</div>
|
|
||||||
<div className={classes.listForms__forms}>
|
|
||||||
{forms.map((item, i) =>
|
|
||||||
<div className={classes.listForms__forms__item} key={i}>
|
|
||||||
<div className={classes.listForms__forms__item__title} onClick={() => editForm(item)}>{item.title}</div>
|
|
||||||
{/* <div className={classes.listForms__forms__item__answers}>{item.datetime}</div>
|
|
||||||
<div className={classes.listForms__forms__item__update}>{item.update}</div> */}
|
|
||||||
<i class="fa-solid fa-ellipsis-vertical" id="action" data-bs-toggle="dropdown"></i>
|
|
||||||
<ul class="dropdown-menu" aria-labelledby="action">
|
|
||||||
<li><a class="dropdown-item" onClick={() => openFormView(item.id)}>Открыть</a></li>
|
|
||||||
<li><a class="dropdown-item" onClick={() => navigate(`/forms/${item.id}/answers`)}>Ответы</a></li>
|
|
||||||
<li><a class="dropdown-item" onClick={() => copyLinkToFormView(item.id)}>Скопировать ссылку</a></li>
|
|
||||||
<li><a class="dropdown-item" onClick={() => removeForm(item.id)}>Удалить</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
<div className={classes.listForms}>
|
||||||
}
|
<div className={classes.listForms__columns}>
|
||||||
|
<div className={classes.listForms__columns__item}>Название</div>
|
||||||
|
{/* <div className={classes.listForms__columns__item}>Ответы</div>
|
||||||
|
<div className={classes.listForms__columns__item}>Изменения</div> */}
|
||||||
|
</div>
|
||||||
|
<div className={classes.listForms__forms}>
|
||||||
|
{filterFormsBySearch().map((item, i) => (
|
||||||
|
<div className={classes.listForms__forms__item} key={i}>
|
||||||
|
<div
|
||||||
|
className={classes.listForms__forms__item__title}
|
||||||
|
onClick={() => editForm(item)}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</div>
|
||||||
|
{/* <div className={classes.listForms__forms__item__answers}>{item.datetime}</div>
|
||||||
|
<div className={classes.listForms__forms__item__update}>{item.update}</div> */}
|
||||||
|
<i
|
||||||
|
class="fa-solid fa-ellipsis-vertical"
|
||||||
|
id="action"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
></i>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="action">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
onClick={() => openFormView(item.id)}
|
||||||
|
>
|
||||||
|
Открыть
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
onClick={() => navigate(`/forms/${item.id}/answers`)}
|
||||||
|
>
|
||||||
|
Ответы
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
onClick={() => navigate(`/tokens/${item.id}`)}
|
||||||
|
>
|
||||||
|
Список токенов
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
onClick={() => copyLinkToFormView(item.id)}
|
||||||
|
>
|
||||||
|
Скопировать ссылку
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target={`#checkModal${item.id}`}
|
||||||
|
>
|
||||||
|
Удалить
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
export default Forms;
|
<CheckModal
|
||||||
|
postfix={item.id}
|
||||||
|
message={`Вы хотите удалить форму <${item.title}>?`}
|
||||||
|
action={{
|
||||||
|
execute: () => removeForm(item.id),
|
||||||
|
cancel: () => {},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Forms;
|
||||||
|
@ -16,8 +16,8 @@ const Home = () => {
|
|||||||
Кажется вы попали на общую страницу.
|
Кажется вы попали на общую страницу.
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.header__bottom}>
|
<div className={classes.header__bottom}>
|
||||||
Чтобы перейти к форме введите токен ниже или снова перейдите по
|
Чтобы перейти к форме введите токен ниже <br /> или снова перейдите
|
||||||
ссылке.
|
по ссылке.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.content}>
|
<div className={classes.content}>
|
||||||
@ -41,6 +41,7 @@ const Home = () => {
|
|||||||
<div className={classes.content__search__wrapper}>
|
<div className={classes.content__search__wrapper}>
|
||||||
<MyButton
|
<MyButton
|
||||||
text={"Найти форму"}
|
text={"Найти форму"}
|
||||||
|
class={"main__blue"}
|
||||||
click={() => navigate(`/forms/${token}`)}
|
click={() => navigate(`/forms/${token}`)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
178
src/pages/NewArticle.jsx
Normal file
178
src/pages/NewArticle.jsx
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
import React, { useState, useContext, useEffect } from "react";
|
||||||
|
import { useNavigate, useLocation, useParams } from 'react-router-dom';
|
||||||
|
import { useCookies } from "react-cookie";
|
||||||
|
import classes from "../assets/styles/newArticle.module.scss";
|
||||||
|
import MyButton from "../components/MyButton.jsx";
|
||||||
|
import Loading from "../components/Loading.jsx";
|
||||||
|
import MyInput from "../components/MyInput.jsx";
|
||||||
|
import TextEditor from "../components/TextEditor.jsx";
|
||||||
|
import { UserData } from "../context/index.js";
|
||||||
|
import { getArticleApi, editTagsApi, editTitleArticleApi, editArticleApi, addArticleApi } from "../hooks/api/articleApi.js";
|
||||||
|
|
||||||
|
const NewArticle = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
const { articleId } = useParams();
|
||||||
|
const {user, setUser} = useContext(UserData)
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const [title, setTitle] = useState("");
|
||||||
|
const [tags, setTags] = useState([]);
|
||||||
|
const [newTag, setNewTag] = useState("")
|
||||||
|
const [ownerId, setOwnerId] = useState("");
|
||||||
|
const [contentArticle, setContentArticle] = useState('');
|
||||||
|
const [blocks, setBlocks] = useState('');
|
||||||
|
|
||||||
|
const [cookies, _, __] = useCookies(["user"]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function getArticle() {
|
||||||
|
const response = await getArticleApi(cookies.token, articleId)
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setTitle(response.data.article.title)
|
||||||
|
setTags(response.data.article.tags ? response.data.article.tags : [])
|
||||||
|
setOwnerId(response.data.article.owner_id)
|
||||||
|
setContentArticle(response.data.blocks ? response.data.blocks[0].data : '')
|
||||||
|
setBlocks(response.data.blocks ? response.data.blocks : false)
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getArticle()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
async function addTag() {
|
||||||
|
if (newTag.length > 0 && !tags.find(item => item === newTag)) {
|
||||||
|
const response = await editTagsApi(cookies.token, articleId, [newTag], false)
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setTags([...tags, newTag])
|
||||||
|
setNewTag("")
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeTag(item, index) {
|
||||||
|
const response = await editTagsApi(cookies.token, articleId, [item], true)
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
const cTags = [...tags]
|
||||||
|
cTags.splice(index, 1)
|
||||||
|
setTags(cTags)
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveArticle() {
|
||||||
|
const responseTitle = await editTitleArticleApi(cookies.token, articleId, title)
|
||||||
|
const responseContentArticle = blocks ?
|
||||||
|
await editArticleApi(cookies.token, articleId, contentArticle) :
|
||||||
|
await addArticleApi(cookies.token, articleId, contentArticle)
|
||||||
|
|
||||||
|
if (responseTitle.status === 200 && responseContentArticle.status === 200) {
|
||||||
|
navigate("/articles")
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
responseTitle.status === 401 || responseContentArticle.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(responseTitle)
|
||||||
|
console.log(responseContentArticle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.main}>
|
||||||
|
<div className={classes.wrapper}>
|
||||||
|
<div className={classes.header}>
|
||||||
|
<div className={classes.header__listInput}>
|
||||||
|
<div className={classes.header__listInput__date}>
|
||||||
|
<span>Дата создания</span>
|
||||||
|
<MyInput type={"datetime-local"}/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.header__listInput__title}>
|
||||||
|
<span>Название статьи</span>
|
||||||
|
<MyInput type={"text"} value={title} change={setTitle}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.header__listBtn}>
|
||||||
|
{/* <MyButton text={'Предпросмотр'} class={"main__white"}/> */}
|
||||||
|
<MyButton text={'Опубликовать'} class={"main__green"} click={() => saveArticle()}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.tags}>
|
||||||
|
<div className={classes.tags__wrapper}>
|
||||||
|
<div className={classes.tags__wrapper__input}>
|
||||||
|
<span className={classes.tags__wrapper__input__title}>Добавить тэг</span>
|
||||||
|
<MyInput
|
||||||
|
type={"text"}
|
||||||
|
otherMainStyle={{border: "1px solid rgb(180, 180, 180)", borderRadius: "5px"}}
|
||||||
|
otherInputStyle={{border: "0px solid rgb(180, 180, 180)", width: "85%"}}
|
||||||
|
value={newTag}
|
||||||
|
change={setNewTag}
|
||||||
|
/>
|
||||||
|
<MyButton
|
||||||
|
type={"button"}
|
||||||
|
text={<i class="fa-solid fa-arrow-right"></i>}
|
||||||
|
class={"main__transparent"}
|
||||||
|
mainStyle={
|
||||||
|
{
|
||||||
|
position: "absolute",
|
||||||
|
right: "0",
|
||||||
|
top: "0",
|
||||||
|
height: "100%",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
otherStyle={{borderRadius: "0 5px 5px 0", padding: "3px 7px 0 7px"}}
|
||||||
|
click={() => addTag()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.tags__wrapper__list}>
|
||||||
|
{tags ? tags.map((item, i) =>
|
||||||
|
<div className={classes.tags__wrapper__list__item} key={i}>
|
||||||
|
<span>#{item}</span>
|
||||||
|
<i class="fa-solid fa-circle-xmark" onClick={() => removeTag(item, i)}></i>
|
||||||
|
</div>
|
||||||
|
) : <></>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.content}>
|
||||||
|
<TextEditor data={contentArticle} setData={setContentArticle}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewArticle;
|
@ -1,328 +1,470 @@
|
|||||||
import React, { useState, useContext, useEffect } from "react";
|
import React, { useState, useContext, useEffect } from "react";
|
||||||
import { useNavigate, useLocation, useParams } from 'react-router-dom';
|
import { useNavigate, useLocation, useParams } from "react-router-dom";
|
||||||
import { useCookies } from "react-cookie";
|
import { useCookies } from "react-cookie";
|
||||||
import classes from "../assets/styles/newForm.module.scss";
|
import classes from "../assets/styles/newForm.module.scss";
|
||||||
import MyButton from "../components/MyButton.jsx";
|
import MyButton from "../components/MyButton.jsx";
|
||||||
import AnswerModal from "../components/AnswerModal.jsx";
|
import AnswerModal from "../components/AnswerModal.jsx";
|
||||||
import PreviewModal from "../components/PreviewModal.jsx"
|
import PreviewModal from "../components/PreviewModal.jsx";
|
||||||
|
import Loading from "../components/Loading.jsx";
|
||||||
import { FormsData, TypeAnswerData } from "../context";
|
import { FormsData, TypeAnswerData } from "../context";
|
||||||
import { listFormsApi, updateTitleFormApi } from "../hooks/api/listFormsApi.js";
|
import { listFormsApi, updateTitleFormApi } from "../hooks/api/listFormsApi.js";
|
||||||
import { saveFormApi, addFormBlockApi, listFormBlockApi, updateBlockApi, updateOrderBlockApi } from "../hooks/api/formApi.js";
|
import { UserData } from "../context";
|
||||||
import { responseDataToListBlock } from "../hooks/sundry/parseListBlock.js";
|
import {
|
||||||
|
saveFormApi,
|
||||||
|
addFormBlockApi,
|
||||||
|
listFormBlockApi,
|
||||||
|
updateBlockApi,
|
||||||
|
updateOrderBlockApi,
|
||||||
|
removeBlockApi,
|
||||||
|
getBlockApi,
|
||||||
|
} from "../hooks/api/formApi.js";
|
||||||
|
import {
|
||||||
|
responseDataToListBlock,
|
||||||
|
numberingBlocks,
|
||||||
|
} from "../hooks/sundry/parseListBlock.js";
|
||||||
|
import MyInput from "../components/MyInput.jsx";
|
||||||
|
|
||||||
const NewForm = () => {
|
const NewForm = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { formId } = useParams();
|
const { formId } = useParams();
|
||||||
const [dragElem, setDragElem] = useState(null);
|
const {user, setUser} = useContext(UserData);
|
||||||
const [dropElem, setDropElem] = useState(null);
|
const [dragElem, setDragElem] = useState(null);
|
||||||
|
const [dropElem, setDropElem] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const [cookies, _, __] = useCookies(["user"]);
|
const [cookies, _, __] = useCookies(["user"]);
|
||||||
|
|
||||||
const {forms, setForms} = useContext(FormsData);
|
|
||||||
const {listTypeAnswer, setListTypeAnswer} = useContext(TypeAnswerData);
|
|
||||||
|
|
||||||
const nextID = (list, param) => {
|
const { forms, setForms } = useContext(FormsData);
|
||||||
return list.length ? list.at(-1)[param] + 1 : 1
|
const { listTypeAnswer, setListTypeAnswer } = useContext(TypeAnswerData);
|
||||||
};
|
|
||||||
const [question, setQuestion] = useState("");
|
|
||||||
const [comment, setComment] = useState("");
|
|
||||||
const [mandatory, setMandatory] = useState(false);
|
|
||||||
const [optionAnswer, setOptionAnswer] = useState([]);
|
|
||||||
const [file, setFile] = useState([]);
|
|
||||||
const [currentTypeAnswer, setCurrentTypeAnswer] = useState("");
|
|
||||||
const [currentOptionAnswer, setCurrentOptionAnswer] = useState("");
|
|
||||||
|
|
||||||
const [datetime, setDatetime] = useState("");
|
const nextID = (list, param) => {
|
||||||
const [titleForm, setTitleForm] = useState("");
|
return list.length ? list.at(-1)[param] + 1 : 1;
|
||||||
|
};
|
||||||
|
const [question, setQuestion] = useState("");
|
||||||
|
const [comment, setComment] = useState("");
|
||||||
|
const [mandatory, setMandatory] = useState(false);
|
||||||
|
const [optionAnswer, setOptionAnswer] = useState([]);
|
||||||
|
const [file, setFile] = useState([]);
|
||||||
|
const [video, setVideo] = useState("");
|
||||||
|
const [currentTypeAnswer, setCurrentTypeAnswer] = useState("");
|
||||||
|
const [currentOptionAnswer, setCurrentOptionAnswer] = useState("");
|
||||||
|
|
||||||
const [listBlock, setListBlock] = useState([]);
|
const [datetime, setDatetime] = useState("");
|
||||||
|
const [newTitleForm, setNewTitleForm] = useState("");
|
||||||
|
const [oldTitleFrom, setOldTitleForm] = useState("");
|
||||||
|
|
||||||
const [stateModal, setStateModal] = useState(false);
|
const [listBlock, setListBlock] = useState([]);
|
||||||
|
|
||||||
function removeAnswerByForm(id) {
|
const [stateModal, setStateModal] = useState(false);
|
||||||
setListBlock([...listBlock.filter(item => item.id !== id)]);
|
|
||||||
};
|
|
||||||
|
|
||||||
function cleanStates() {
|
function cleanStates() {
|
||||||
setStateModal(false)
|
setStateModal(false);
|
||||||
setQuestion("");
|
setQuestion("");
|
||||||
setComment("");
|
setComment("");
|
||||||
setOptionAnswer([])
|
setOptionAnswer([]);
|
||||||
setFile([]);
|
setFile([]);
|
||||||
setCurrentTypeAnswer("");
|
setVideo("");
|
||||||
setCurrentOptionAnswer("")
|
setCurrentTypeAnswer("");
|
||||||
setMandatory(false);
|
setCurrentOptionAnswer("");
|
||||||
};
|
setMandatory(false);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function totalData() {
|
async function totalData() {
|
||||||
const responseForms = await listFormsApi(cookies.token);
|
const responseForms = await listFormsApi(cookies.token);
|
||||||
const responseBlock = await listFormBlockApi(cookies.token, formId);
|
const responseBlock = await listFormBlockApi(cookies.token, formId);
|
||||||
|
|
||||||
if (responseBlock.status === 200 && responseBlock.data && responseForms.status === 200) {
|
if (
|
||||||
setListBlock(responseDataToListBlock(responseBlock.data));
|
responseBlock.status === 200 &&
|
||||||
setTitleForm(responseForms.data.find(item => item.id === formId).title);
|
responseBlock.data &&
|
||||||
}
|
responseForms.status === 200
|
||||||
else {
|
) {
|
||||||
setListBlock([])
|
console.log(responseDataToListBlock(responseBlock.data))
|
||||||
setTitleForm("Новыя форма")
|
setListBlock(responseDataToListBlock(responseBlock.data));
|
||||||
}
|
const title = responseForms.data.find(
|
||||||
};
|
(item) => item.id === formId
|
||||||
|
).title;
|
||||||
totalData();
|
setNewTitleForm(title);
|
||||||
}, []);
|
setOldTitleForm(title);
|
||||||
|
}
|
||||||
function addOptionAnswer(text) {
|
else if (responseForms.status === 401 || responseBlock.status === 401) {
|
||||||
setOptionAnswer([...optionAnswer, {
|
// navigate("/enter")
|
||||||
id: nextID(optionAnswer, "id"),
|
setUser(false)
|
||||||
text: currentOptionAnswer
|
}
|
||||||
}]);
|
else {
|
||||||
setCurrentOptionAnswer("");
|
setListBlock([]);
|
||||||
};
|
setNewTitleForm("Новыя форма");
|
||||||
|
setOldTitleForm("Новыя форма");
|
||||||
function editAnswerByForm(id) {
|
}
|
||||||
const obj = listBlock.find(item => item.id === id);
|
setLoading(true);
|
||||||
setQuestion(obj.question);
|
|
||||||
setComment(obj.comment);
|
|
||||||
setFile(obj.file);
|
|
||||||
setCurrentTypeAnswer(obj.typeAnswer);
|
|
||||||
setOptionAnswer(obj.optionAnswer);
|
|
||||||
setMandatory(obj.mandatory);
|
|
||||||
setStateModal(obj.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
async function updateBlock() {
|
|
||||||
const data = {
|
|
||||||
id: stateModal,
|
|
||||||
question: question,
|
|
||||||
comment: comment,
|
|
||||||
file: file,
|
|
||||||
mandatory: mandatory,
|
|
||||||
optionAnswer: optionAnswer,
|
|
||||||
typeAnswer: currentTypeAnswer,
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(stateModal)
|
|
||||||
|
|
||||||
const response = await updateBlockApi(cookies.token, stateModal, data);
|
|
||||||
|
|
||||||
if (response.status === 200) {
|
|
||||||
setListBlock(listBlock.map(item => {
|
|
||||||
if (item.id === stateModal) {
|
|
||||||
item = data
|
|
||||||
}
|
|
||||||
return item
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setListBlock(listBlock.map(item => {
|
|
||||||
// if (item.id === stateModal) {
|
|
||||||
// item = data
|
|
||||||
// }
|
|
||||||
// return item
|
|
||||||
// }))
|
|
||||||
|
|
||||||
cleanStates();
|
|
||||||
};
|
|
||||||
|
|
||||||
async function addFormBlock() {
|
|
||||||
const newBlock = {
|
|
||||||
question: question,
|
|
||||||
typeAnswer: currentTypeAnswer,
|
|
||||||
comment: comment,
|
|
||||||
mandatory: mandatory,
|
|
||||||
optionAnswer: optionAnswer,
|
|
||||||
file: file
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await addFormBlockApi(cookies.token, formId, newBlock)
|
|
||||||
|
|
||||||
if (response.status === 200) {
|
|
||||||
setListBlock([...listBlock, {...newBlock, order: nextID(listBlock, "order")}]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(response)
|
|
||||||
}
|
|
||||||
cleanStates();
|
|
||||||
};
|
|
||||||
|
|
||||||
async function updateTitleForm() {
|
|
||||||
const response = await updateTitleFormApi(cookies.token, formId, titleForm);
|
|
||||||
|
|
||||||
if (response.status === 200) {
|
|
||||||
console.log(response)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(response)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async function updateOrderBlock() {
|
|
||||||
const response = await updateOrderBlockApi(cookies.token, formId, {
|
|
||||||
new: dropElem,
|
|
||||||
old: dragElem
|
|
||||||
})
|
|
||||||
|
|
||||||
if (response.status === 200) {
|
|
||||||
const currentElem = listBlock[dragElem];
|
|
||||||
const tListBlock = [...listBlock];
|
|
||||||
|
|
||||||
if (dragElem > dropElem) {
|
|
||||||
tListBlock.splice(dropElem, 0, currentElem);
|
|
||||||
tListBlock.splice(dragElem + 1, 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tListBlock.splice(dropElem + 1, 0, currentElem);
|
|
||||||
tListBlock.splice(dragElem, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
setListBlock(tListBlock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFormByForms() {
|
totalData();
|
||||||
updateFormByFormsApi(location.state.id, "Новая форма", listBlock)
|
}, []);
|
||||||
.then((resolve, _) => {
|
|
||||||
console.log(resolve);
|
function addOptionAnswer() {
|
||||||
setForms(
|
setOptionAnswer(
|
||||||
forms.map(item => {
|
numberingBlocks(
|
||||||
if (item.id === location.state.id) {
|
[
|
||||||
item.title = "Новая форма",
|
...optionAnswer,
|
||||||
item.questions = listBlock
|
{
|
||||||
}
|
id: nextID(optionAnswer, "id"),
|
||||||
return item
|
text: currentOptionAnswer,
|
||||||
})
|
},
|
||||||
);
|
],
|
||||||
cleanStates();
|
"id",
|
||||||
navigate("/forms");
|
1
|
||||||
})
|
)
|
||||||
|
);
|
||||||
|
setCurrentOptionAnswer("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeOptionAnswer(id) {
|
||||||
|
setOptionAnswer(
|
||||||
|
numberingBlocks(
|
||||||
|
[...optionAnswer].filter((answer) => answer.id !== id),
|
||||||
|
"id",
|
||||||
|
1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editAnswerByForm(id) {
|
||||||
|
const obj = listBlock.find((item) => item.id === id);
|
||||||
|
setQuestion(obj.question);
|
||||||
|
setComment(obj.comment);
|
||||||
|
setFile(obj.file);
|
||||||
|
setVideo(obj.video);
|
||||||
|
setCurrentTypeAnswer(obj.typeAnswer);
|
||||||
|
setOptionAnswer(obj.optionAnswer);
|
||||||
|
setMandatory(obj.mandatory);
|
||||||
|
setStateModal(obj.id);
|
||||||
|
console.log(obj.file.map(item => item.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateBlock() {
|
||||||
|
const data = {
|
||||||
|
question: question,
|
||||||
|
comment: comment,
|
||||||
|
file: file,
|
||||||
|
video: video,
|
||||||
|
mandatory: mandatory,
|
||||||
|
optionAnswer: optionAnswer,
|
||||||
|
typeAnswer: currentTypeAnswer,
|
||||||
};
|
};
|
||||||
|
|
||||||
function saveForm() {
|
const response = await updateBlockApi(
|
||||||
// saveFormApi("Новая форма", listBlock)
|
cookies.token,
|
||||||
// .then((resolve, reject) => {
|
formId,
|
||||||
// console.log(resolve);
|
data,
|
||||||
// setForms(
|
listBlock.find((item) => item.id === stateModal).order
|
||||||
// [...forms, {
|
);
|
||||||
// id: nextID(forms),
|
|
||||||
// title: "Новая форма",
|
|
||||||
// questions: listBlock,
|
|
||||||
// answers: []
|
|
||||||
// }]
|
|
||||||
// );
|
|
||||||
cleanStates();
|
|
||||||
navigate("/forms");
|
|
||||||
// })
|
|
||||||
// .catch(error => console.log(error));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
if (response.status === 200) {
|
||||||
<div className={classes.main}>
|
const responseBlock = await listFormBlockApi(cookies.token, formId);
|
||||||
<div className={classes.wrapper}>
|
|
||||||
<div className={classes.header}>
|
|
||||||
<div className={classes.header__listInput}>
|
|
||||||
<div className={classes.header__listInput__date}>
|
|
||||||
<span>Дедлайн выполнения</span>
|
|
||||||
<input type="datetime-local" value={datetime} onChange={event => setDatetime(event.target.value)}/>
|
|
||||||
</div>
|
|
||||||
<div className={classes.header__listInput__title}>
|
|
||||||
<span>Название формы</span>
|
|
||||||
<input type="text" value={titleForm} onChange={event => setTitleForm(event.target.value)}/>
|
|
||||||
</div>
|
|
||||||
<MyButton
|
|
||||||
text={<i class="fa-solid fa-floppy-disk"></i>}
|
|
||||||
click={() => updateTitleForm()}
|
|
||||||
otherStyle={{paddingLeft: "0.9rem", paddingRight: "0.9rem"}}>
|
|
||||||
</MyButton>
|
|
||||||
</div>
|
|
||||||
<div className={classes.header__listBtn}>
|
|
||||||
<MyButton text={'Предпросмотр'} backgroundColor={'rgb(225, 225, 225)'} toggle={"modal"} target={"#previewModal"}/>
|
|
||||||
<MyButton text={'Опубликовать'} click={location.state ? updateFormByForms : saveForm}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={classes.content}>
|
|
||||||
<div className={classes.content__listQuestion}>
|
|
||||||
<div className={classes.content__listQuestion__list}>
|
|
||||||
{listTypeAnswer.map((item, i) =>
|
|
||||||
<div className={classes.content__listQuestion__list__item} data-bs-toggle="modal" data-bs-target="#answerModal" onClick={() => setCurrentTypeAnswer(item.id)} key={i}>
|
|
||||||
<span>{item.text}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<PreviewModal listBlock={listBlock} listTypeAnswer={listTypeAnswer}/>
|
if (responseBlock.status === 200) {
|
||||||
|
setListBlock(responseDataToListBlock(responseBlock.data));
|
||||||
|
} else {
|
||||||
|
setListBlock([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
|
||||||
<AnswerModal
|
cleanStates();
|
||||||
stateModal={stateModal}
|
}
|
||||||
currentTypeAnswer={currentTypeAnswer}
|
|
||||||
question={question}
|
|
||||||
comment={comment}
|
|
||||||
mandatory={mandatory}
|
|
||||||
optionAnswer={optionAnswer}
|
|
||||||
setOptionAnswer={setOptionAnswer}
|
|
||||||
file={file}
|
|
||||||
currentOptionAnswer={currentOptionAnswer}
|
|
||||||
listTypeAnswer={listTypeAnswer}
|
|
||||||
setQuestion={setQuestion}
|
|
||||||
setComment={setComment}
|
|
||||||
setFile={setFile}
|
|
||||||
setCurrentOptionAnswer={setCurrentOptionAnswer}
|
|
||||||
setMandatory={setMandatory}
|
|
||||||
cleanStates={cleanStates}
|
|
||||||
addFormBlock={addFormBlock}
|
|
||||||
addOptionAnswer={addOptionAnswer}
|
|
||||||
updateBlock={updateBlock}
|
|
||||||
setCurrentTypeAnswer={setCurrentTypeAnswer}/>
|
|
||||||
|
|
||||||
<div className={classes.content__newForm}>
|
async function removeBlock(order) {
|
||||||
<div className={classes.content__newForm__title}>
|
const response = await removeBlockApi(cookies.token, formId, order);
|
||||||
<h3>Новая форма</h3>
|
|
||||||
</div>
|
if (response.status === 200) {
|
||||||
<div className={classes.content__newForm__list}>
|
setListBlock([...listBlock.filter((item) => item.order !== order)]);
|
||||||
{listBlock.map((item, i) =>
|
}
|
||||||
<div
|
else if (
|
||||||
className={classes.content__newForm__list__item}
|
response.status === 401
|
||||||
key={i}
|
) {
|
||||||
id={item.order}
|
// navigate("/enter")
|
||||||
draggable="true"
|
setUser(false)
|
||||||
onDragOver={(event) => {event.preventDefault()}}
|
}
|
||||||
onDragStart={(event) => {
|
else {
|
||||||
if (event.target.id) {
|
console.log(response)
|
||||||
setDragElem(Number(event.target.id))
|
}
|
||||||
}
|
}
|
||||||
}}
|
|
||||||
onDragEnter={(event) => {
|
async function addFiles(newFile) {
|
||||||
if (event.target.id) {
|
const fileData = []
|
||||||
setDropElem(Number(event.target.id))
|
|
||||||
}
|
for (let item of newFile) {
|
||||||
}}
|
let binary = ""
|
||||||
onDrop={() => updateOrderBlock()}
|
const buff = await item.arrayBuffer()
|
||||||
>
|
const bytesArray = new Uint8Array(buff)
|
||||||
<div className={classes.content__newForm__list__item__answer}>
|
let len = bytesArray.byteLength;
|
||||||
<span>{item.question}</span>
|
|
||||||
<span>{listTypeAnswer.map(typeItem => {
|
for (let i = 0; i < len; i++) {
|
||||||
if (typeItem.id === item.typeAnswer) {
|
binary += String.fromCharCode( bytesArray[ i ] );
|
||||||
return typeItem.text
|
}
|
||||||
}
|
|
||||||
})}</span>
|
fileData.push({
|
||||||
</div>
|
name: item.name,
|
||||||
<div className={classes.content__newForm__list__item__btn}>
|
type: item.type,
|
||||||
<i class="fa-solid fa-pen" data-bs-toggle="modal" data-bs-target="#answerModal" onClick={() => {editAnswerByForm(item.id)}}></i>
|
binary: btoa(binary)
|
||||||
<i class="fa-solid fa-trash" onClick={() => removeAnswerByForm(item.id)}></i>
|
})
|
||||||
</div>
|
|
||||||
</div>
|
setFile([...file, ...fileData])
|
||||||
)}
|
}
|
||||||
</div>
|
}
|
||||||
</div>
|
|
||||||
</div>
|
async function addFormBlock() {
|
||||||
|
|
||||||
|
const newBlock = {
|
||||||
|
question: question,
|
||||||
|
typeAnswer: currentTypeAnswer,
|
||||||
|
comment: comment,
|
||||||
|
mandatory: mandatory,
|
||||||
|
optionAnswer: optionAnswer,
|
||||||
|
file: file,
|
||||||
|
video: video,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await addFormBlockApi(cookies.token, formId, newBlock);
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
const responseBlock = await listFormBlockApi(cookies.token, formId);
|
||||||
|
|
||||||
|
if (responseBlock.status === 200) {
|
||||||
|
setListBlock(responseDataToListBlock(responseBlock.data));
|
||||||
|
} else {
|
||||||
|
setListBlock([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
cleanStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
// async function updateTitleForm() {
|
||||||
|
// const response = await updateTitleFormApi(cookies.token, formId, newTitleForm);
|
||||||
|
|
||||||
|
// if (response.status === 200) {
|
||||||
|
// console.log(response)
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// console.log(response)
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
async function updateOrderBlock() {
|
||||||
|
const response = await updateOrderBlockApi(cookies.token, formId, {
|
||||||
|
new: dropElem,
|
||||||
|
old: dragElem,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
const currentElem = listBlock[dragElem];
|
||||||
|
const tListBlock = [...listBlock];
|
||||||
|
|
||||||
|
if (dragElem > dropElem) {
|
||||||
|
tListBlock.splice(dropElem, 0, currentElem);
|
||||||
|
tListBlock.splice(dragElem + 1, 1);
|
||||||
|
} else {
|
||||||
|
tListBlock.splice(dropElem + 1, 0, currentElem);
|
||||||
|
tListBlock.splice(dragElem, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setListBlock(numberingBlocks(tListBlock, "order"));
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveForm() {
|
||||||
|
if (oldTitleFrom !== newTitleForm) {
|
||||||
|
const response = await updateTitleFormApi(cookies.token, formId, newTitleForm);
|
||||||
|
|
||||||
|
if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanStates();
|
||||||
|
navigate("/forms");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.main}>
|
||||||
|
<div className={classes.wrapper}>
|
||||||
|
<div className={classes.header}>
|
||||||
|
<div className={classes.header__listInput}>
|
||||||
|
{/* <div className={classes.header__listInput__date}>
|
||||||
|
<span>Дедлайн выполнения</span>
|
||||||
|
<MyInput
|
||||||
|
type={"datetime-local"}
|
||||||
|
value={datetime}
|
||||||
|
change={setDatetime}
|
||||||
|
/>
|
||||||
|
</div> */}
|
||||||
|
<div className={classes.header__listInput__title}>
|
||||||
|
<span>Название формы</span>
|
||||||
|
<MyInput
|
||||||
|
type={"text"}
|
||||||
|
value={newTitleForm}
|
||||||
|
change={setNewTitleForm}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.header__listBtn}>
|
||||||
|
<MyButton
|
||||||
|
text={"Предпросмотр"}
|
||||||
|
class={"main__white"}
|
||||||
|
toggle={"modal"}
|
||||||
|
target={"#previewModal"}
|
||||||
|
/>
|
||||||
|
<MyButton
|
||||||
|
text={"Опубликовать"}
|
||||||
|
class={"main__blue"}
|
||||||
|
click={location.state ? updateFormByForms : saveForm}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
<div className={classes.content}>
|
||||||
}
|
<div className={classes.content__listQuestion}>
|
||||||
|
<div className={classes.content__listQuestion__list}>
|
||||||
|
{listTypeAnswer.map((item, i) => (
|
||||||
|
<div
|
||||||
|
className={classes.content__listQuestion__list__item}
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#answerModal"
|
||||||
|
onClick={() => setCurrentTypeAnswer(item.id)}
|
||||||
|
key={i}
|
||||||
|
>
|
||||||
|
<span>{item.text}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
export default NewForm;
|
<PreviewModal listBlock={listBlock} listTypeAnswer={listTypeAnswer} />
|
||||||
|
|
||||||
|
<AnswerModal
|
||||||
|
stateModal={stateModal}
|
||||||
|
currentTypeAnswer={currentTypeAnswer}
|
||||||
|
question={question}
|
||||||
|
comment={comment}
|
||||||
|
mandatory={mandatory}
|
||||||
|
optionAnswer={optionAnswer}
|
||||||
|
setOptionAnswer={setOptionAnswer}
|
||||||
|
file={file}
|
||||||
|
video={video}
|
||||||
|
setVideo={setVideo}
|
||||||
|
currentOptionAnswer={currentOptionAnswer}
|
||||||
|
listTypeAnswer={listTypeAnswer}
|
||||||
|
setQuestion={setQuestion}
|
||||||
|
setComment={setComment}
|
||||||
|
setFile={setFile}
|
||||||
|
setCurrentOptionAnswer={setCurrentOptionAnswer}
|
||||||
|
setMandatory={setMandatory}
|
||||||
|
cleanStates={cleanStates}
|
||||||
|
addFormBlock={addFormBlock}
|
||||||
|
addOptionAnswer={addOptionAnswer}
|
||||||
|
updateBlock={updateBlock}
|
||||||
|
setCurrentTypeAnswer={setCurrentTypeAnswer}
|
||||||
|
removeOptionAnswer={removeOptionAnswer}
|
||||||
|
addFiles={addFiles}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className={classes.content__newForm}>
|
||||||
|
<div className={classes.content__newForm__title}>
|
||||||
|
<h3>Новая форма</h3>
|
||||||
|
</div>
|
||||||
|
<div className={classes.content__newForm__list}>
|
||||||
|
{loading ? (
|
||||||
|
listBlock.map((item, i) => (
|
||||||
|
<div
|
||||||
|
className={classes.content__newForm__list__item}
|
||||||
|
key={i}
|
||||||
|
id={item.order}
|
||||||
|
draggable="true"
|
||||||
|
onDragOver={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
onDragStart={(event) => {
|
||||||
|
if (event.target.id) {
|
||||||
|
setDragElem(Number(event.target.id));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onDragEnter={(event) => {
|
||||||
|
if (event.target.id) {
|
||||||
|
setDropElem(Number(event.target.id));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onDrop={() => updateOrderBlock()}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={classes.content__newForm__list__item__answer}
|
||||||
|
>
|
||||||
|
<span>{item.question}</span>
|
||||||
|
<span>
|
||||||
|
{listTypeAnswer.map((typeItem) => {
|
||||||
|
if (typeItem.id === item.typeAnswer) {
|
||||||
|
return typeItem.text;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className={classes.content__newForm__list__item__btn}>
|
||||||
|
<i
|
||||||
|
class="fa-solid fa-pen"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#answerModal"
|
||||||
|
onClick={() => {
|
||||||
|
editAnswerByForm(item.id);
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
<i
|
||||||
|
class="fa-solid fa-trash"
|
||||||
|
onClick={() => removeBlock(item.order)}
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Loading />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NewForm;
|
||||||
|
@ -33,6 +33,12 @@ const Profile = () => {
|
|||||||
setFirst_name(response.data.first_name);
|
setFirst_name(response.data.first_name);
|
||||||
setLast_name(response.data.last_name);
|
setLast_name(response.data.last_name);
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false)
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
console.log(response)
|
console.log(response)
|
||||||
}
|
}
|
||||||
@ -68,7 +74,9 @@ const Profile = () => {
|
|||||||
last_name: last_name,
|
last_name: last_name,
|
||||||
email: email,
|
email: email,
|
||||||
phone: phone,
|
phone: phone,
|
||||||
is_admin: user.is_admin
|
is_admin: user.is_admin,
|
||||||
|
is_teacher: user.is_teacher,
|
||||||
|
id: user.id
|
||||||
})
|
})
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@ -81,7 +89,16 @@ const Profile = () => {
|
|||||||
is_admin: user.is_admin
|
is_admin: user.is_admin
|
||||||
})
|
})
|
||||||
setEdit(!edit)
|
setEdit(!edit)
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,19 +125,19 @@ const Profile = () => {
|
|||||||
<span>Редактировать <i class="fa-solid fa-pen"></i></span> :
|
<span>Редактировать <i class="fa-solid fa-pen"></i></span> :
|
||||||
<span>Сохранить <i class="fa-solid fa-floppy-disk"></i></span>
|
<span>Сохранить <i class="fa-solid fa-floppy-disk"></i></span>
|
||||||
}
|
}
|
||||||
backgroundColor={edit ? "rgb(200, 200, 200)" : ""}
|
class={edit ? "main__white" : "main__green"}
|
||||||
click={() => editUser()}/> : <div>Запросите изменение профиля у администратора</div>}
|
click={() => editUser()}/> : <div>Запросите изменение профиля у администратора</div>}
|
||||||
<MyButton
|
<MyButton
|
||||||
text={
|
text={
|
||||||
<span>Выйти</span>
|
<span>Выйти</span>
|
||||||
}
|
}
|
||||||
backgroundColor={edit ? "rgb(252, 151, 151)" : ""}
|
class={"main__red"}
|
||||||
click={() => exitAccount()}/>
|
click={() => exitAccount()}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.profile__wrapper__body}>
|
<div className={classes.profile__wrapper__body}>
|
||||||
{Object.keys(user).map(key => key !== "is_admin" ? <div className={classes.profile__wrapper__body__item}>
|
{Object.keys(user).map(key => key !== "is_admin" && key !== "is_teacher" && key !== "id" ? <div className={classes.profile__wrapper__body__item}>
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<span class="input-group-text">{key}</span>
|
<span class="input-group-text">{key}</span>
|
||||||
<input
|
<input
|
||||||
|
239
src/pages/TokensForm.jsx
Normal file
239
src/pages/TokensForm.jsx
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
import React, { useState, useEffect, useContext } from "react";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { useCookies } from "react-cookie";
|
||||||
|
import classes from "../assets/styles/tokensForm.module.scss";
|
||||||
|
import {
|
||||||
|
listFormsByTokenApi,
|
||||||
|
newFormTokenApi,
|
||||||
|
removeTokenFormApi,
|
||||||
|
editTokenFormApi,
|
||||||
|
} from "../hooks/api/listFormsApi";
|
||||||
|
import MyButton from "../components/MyButton.jsx";
|
||||||
|
import { UserData } from "../context/index.js";
|
||||||
|
import DefaultModal from "../components/DefaultModal.jsx";
|
||||||
|
import EditToken from "../components/bodyModal/EditToken.jsx";
|
||||||
|
import QrCodeToken from "../components/bodyModal/QrCodeToken.jsx";
|
||||||
|
import QRCode from "qrcode";
|
||||||
|
|
||||||
|
const TokensForm = () => {
|
||||||
|
const { formId } = useParams();
|
||||||
|
const [tokens, setTokens] = useState([]);
|
||||||
|
const [currentIdToken, setCurrentIdToken] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [titleToken, setTitleToken] = useState("");
|
||||||
|
const { user, setUser } = useContext(UserData);
|
||||||
|
const [qrCodeUrl, setQrcodeUrl] = useState("");
|
||||||
|
|
||||||
|
const [cookies, _, __] = useCookies(["user"]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function listFormsByToken() {
|
||||||
|
const response = await listFormsByTokenApi(cookies.token, formId);
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setTokens(
|
||||||
|
response.data.tokens.filter(
|
||||||
|
(item, i) => item.is_active === true && i !== 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setLoading(false);
|
||||||
|
} else if (response.status === 401) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
|
} else {
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listFormsByToken();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function newFormToken() {
|
||||||
|
const response = await newFormTokenApi(cookies.token, formId, titleToken);
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setTokens([...tokens, response.data.token]);
|
||||||
|
} else if (response.status === 401) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
|
} else {
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// async function editTokenForm(tokenForm) {
|
||||||
|
// const response = await editTokenFormApi(cookies.token, formId, tokenForm, titleToken)
|
||||||
|
|
||||||
|
// if (response.status === 200) {
|
||||||
|
// setTokens([])
|
||||||
|
// }
|
||||||
|
// else if (
|
||||||
|
// response.status === 401
|
||||||
|
// ) {
|
||||||
|
// // navigate("/enter")
|
||||||
|
// setUser(false);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// console.log(response)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
async function removeTokenForm(tokenForm) {
|
||||||
|
const response = await removeTokenFormApi(cookies.token, formId, tokenForm);
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setTokens(tokens.filter((item) => item.id !== tokenForm));
|
||||||
|
} else if (response.status === 401) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
|
} else {
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.main}>
|
||||||
|
<div className={classes.wrapper}>
|
||||||
|
<div className={classes.answers}>
|
||||||
|
<div className={classes.answers__wrapper}>
|
||||||
|
<div className={classes.answers__wrapper__header}>
|
||||||
|
<h3>Токены формы</h3>
|
||||||
|
<MyButton
|
||||||
|
text={"Создать"}
|
||||||
|
class={"main__green"}
|
||||||
|
click={() => {
|
||||||
|
setTitleToken("");
|
||||||
|
setCurrentIdToken(false);
|
||||||
|
}}
|
||||||
|
target={"#tokenModal"}
|
||||||
|
toggle={"modal"}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.answers__wrapper__body}>
|
||||||
|
<div className={classes.answers__wrapper__body__column}>
|
||||||
|
<div
|
||||||
|
className={classes.answers__wrapper__body__column__wrapper}
|
||||||
|
>
|
||||||
|
<div>Название</div>
|
||||||
|
<div>Токен</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{tokens ? (
|
||||||
|
tokens.map((item, i) => (
|
||||||
|
<div className={classes.answers__wrapper__body__item} key={i}>
|
||||||
|
<div
|
||||||
|
className={classes.answers__wrapper__body__item__wrapper}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
classes.answers__wrapper__body__item__wrapper__title
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
classes.answers__wrapper__body__item__wrapper__token
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.id}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.answers__wrapper__body__item__btn}>
|
||||||
|
{/* <i
|
||||||
|
class="fa-solid fa-pen"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target={`#tokenModal`}
|
||||||
|
onClick={() => {
|
||||||
|
setTitleToken(item.name)
|
||||||
|
setCurrentIdToken(item.id)
|
||||||
|
}}>
|
||||||
|
</i> */}
|
||||||
|
<i
|
||||||
|
class="fa-solid fa-qrcode"
|
||||||
|
onClick={() => {
|
||||||
|
QRCode.toDataURL(
|
||||||
|
`http://minerva.krbl.ru/forms/${item.id}`,
|
||||||
|
{},
|
||||||
|
(err, url) => {
|
||||||
|
setQrcodeUrl(url);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target={`#qrModal`}
|
||||||
|
></i>
|
||||||
|
<i
|
||||||
|
class="fa-solid fa-trash"
|
||||||
|
onClick={() => removeTokenForm(item.id)}
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
<DefaultModal
|
||||||
|
name={"qrModal"}
|
||||||
|
btn={[
|
||||||
|
{
|
||||||
|
text: "Скачать",
|
||||||
|
class: "main__green",
|
||||||
|
dismiss: "modal",
|
||||||
|
action: () => {
|
||||||
|
const aElem = document.createElement("a");
|
||||||
|
aElem.href = qrCodeUrl;
|
||||||
|
aElem.download = `${item.name}.png`;
|
||||||
|
aElem.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Отмена",
|
||||||
|
class: "main__white",
|
||||||
|
dismiss: "modal",
|
||||||
|
action: () => {},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
BodyModal={<QrCodeToken value={item.id} />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div className={classes.loading__wrapper}>
|
||||||
|
<div
|
||||||
|
class="spinner-border text-dark"
|
||||||
|
className={classes.loading__wrapper__body}
|
||||||
|
role="status"
|
||||||
|
>
|
||||||
|
<span class="visually-hidden">Загрузка...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<DefaultModal
|
||||||
|
name={"tokenModal"}
|
||||||
|
btn={[
|
||||||
|
{
|
||||||
|
text: "Сохранить",
|
||||||
|
class: "main__green",
|
||||||
|
dismiss: "modal",
|
||||||
|
action: () => newFormToken(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Отмена",
|
||||||
|
class: "main__white",
|
||||||
|
dismiss: "modal",
|
||||||
|
action: () => {},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
BodyModal={
|
||||||
|
<EditToken
|
||||||
|
titleToken={titleToken}
|
||||||
|
setTitleToken={setTitleToken}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TokensForm;
|
87
src/pages/ViewArticle.jsx
Normal file
87
src/pages/ViewArticle.jsx
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import React, { useState, useContext, useEffect, useLocation } from "react";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { useCookies } from "react-cookie";
|
||||||
|
import classes from "../assets/styles/viewArticle.module.scss";
|
||||||
|
import { FormsData, TypeAnswerData, answersData, UserData } from "../context";
|
||||||
|
import MyButton from "../components/MyButton.jsx";
|
||||||
|
import { getArticleApi } from "../hooks/api/articleApi.js";
|
||||||
|
import { getListUserApi } from "../hooks/api/profileApi.js";
|
||||||
|
|
||||||
|
|
||||||
|
const ViewArticle = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
// const location = useLocation();
|
||||||
|
const { articleId } = useParams();
|
||||||
|
const {user, setUser} = useContext(UserData)
|
||||||
|
|
||||||
|
const [title, setTitle] = useState("");
|
||||||
|
const [tags, setTags] = useState([]);
|
||||||
|
const [newTag, setNewTag] = useState("")
|
||||||
|
const [owner, setOwner] = useState("");
|
||||||
|
|
||||||
|
const [contentArticle, setContentArticle] = useState('');
|
||||||
|
|
||||||
|
const [cookies, _, __] = useCookies(["user"]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function getArticle() {
|
||||||
|
const response = await getArticleApi(cookies.token, articleId)
|
||||||
|
const responseUser = await getListUserApi(cookies.token)
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
setTitle(response.data.article.title)
|
||||||
|
setTags(response.data.article.tags ? response.data.article.tags : [])
|
||||||
|
setOwner(responseUser.status === 200 ? responseUser.data.find(item => item.id === response.data.article.owner_id).login : response.data.article.owner_id)
|
||||||
|
setContentArticle(response.data.blocks ? response.data.blocks[0].data : '')
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getArticle()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.main}>
|
||||||
|
<div className={classes.wrapper}>
|
||||||
|
<div className={classes.header}>
|
||||||
|
<div className={classes.header__wrapper}>
|
||||||
|
<div className={classes.header__wrapper__article}>
|
||||||
|
<div className={classes.header__wrapper__article__title}>
|
||||||
|
<span className={classes.header__wrapper__article__title__name}>Название</span>
|
||||||
|
<span className={classes.header__wrapper__article__title__text}>{title}</span>
|
||||||
|
</div>
|
||||||
|
<div className={classes.header__wrapper__article__tags}>
|
||||||
|
{/* <span className={classes.header__wrapper__article__tags__name}>Тэги</span> */}
|
||||||
|
{tags.map(item => <div className={classes.header__wrapper__tags__item}>
|
||||||
|
<span>#{item}</span>
|
||||||
|
</div>)}
|
||||||
|
</div>
|
||||||
|
<div className={classes.header__wrapper__article__owner}>
|
||||||
|
<span className={classes.header__wrapper__article__owner__name}>Автор</span>
|
||||||
|
<span className={classes.header__wrapper__article__owner__text}>{owner}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.content}>
|
||||||
|
<div className={classes.content__wrapper}>
|
||||||
|
<div className="classes.content__wrapper__article" dangerouslySetInnerHTML={{__html: contentArticle}}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default ViewArticle
|
@ -5,8 +5,7 @@ import classes from "../assets/styles/viewForm.module.scss";
|
|||||||
import { FormsData, TypeAnswerData, answersData, UserData } from "../context";
|
import { FormsData, TypeAnswerData, answersData, UserData } from "../context";
|
||||||
import GeneratingFormFields from "../components/GeneratingFormFields.jsx";
|
import GeneratingFormFields from "../components/GeneratingFormFields.jsx";
|
||||||
import MyButton from "../components/MyButton.jsx";
|
import MyButton from "../components/MyButton.jsx";
|
||||||
import { listFormBlockApi, listFormBlockByTokenApi, saveAnswersApi } from "../hooks/api/formApi.js";
|
import { listFormBlockByTokenApi, saveAnswersApi } from "../hooks/api/formApi.js";
|
||||||
import { listFormsApi } from "../hooks/api/listFormsApi.js";
|
|
||||||
import { responseDataToListBlock } from "../hooks/sundry/parseListBlock.js";
|
import { responseDataToListBlock } from "../hooks/sundry/parseListBlock.js";
|
||||||
|
|
||||||
const ViewForm = () => {
|
const ViewForm = () => {
|
||||||
@ -19,25 +18,28 @@ const ViewForm = () => {
|
|||||||
const [cookies, setCookies, __] = useCookies(["user"]);
|
const [cookies, setCookies, __] = useCookies(["user"]);
|
||||||
const [questions, setQuestions] = useState([]);
|
const [questions, setQuestions] = useState([]);
|
||||||
const [answers, setAnswers] = useState([]);
|
const [answers, setAnswers] = useState([]);
|
||||||
// const [title, setTitle] = useState("");
|
const [responseStatus, setResponseStatus] = useState(200);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function getForm() {
|
async function getForm() {
|
||||||
// const responseForms = await listFormsApi(cookies.token);
|
|
||||||
const responseBlocks = await listFormBlockByTokenApi(cookies.token, formId);
|
const responseBlocks = await listFormBlockByTokenApi(cookies.token, formId);
|
||||||
|
|
||||||
if (responseBlocks.status === 200 && responseBlocks.data) {
|
if (responseBlocks.status === 200 && responseBlocks.data.blocks) {
|
||||||
const listBlocks = responseDataToListBlock(responseBlocks.data.blocks);
|
const listBlocks = responseDataToListBlock(responseBlocks.data.blocks);
|
||||||
|
|
||||||
setQuestions(listBlocks)
|
setQuestions(listBlocks);
|
||||||
setAnswers(listBlocks.map(item => (
|
setAnswers(listBlocks.map(item => (
|
||||||
{id: item.id, answer: []}
|
{id: item.id, answer: []}
|
||||||
)))
|
)));
|
||||||
// setTitle(responseForms.data.find(item => item.id === formId).title)
|
}
|
||||||
|
else if (
|
||||||
|
responseBlocks.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// console.log(responseForms)
|
setResponseStatus(responseBlocks.status)
|
||||||
console.log(responseBlocks)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,7 +59,6 @@ const ViewForm = () => {
|
|||||||
|
|
||||||
async function saveAnswers() {
|
async function saveAnswers() {
|
||||||
const response = await saveAnswersApi(cookies.token, formId, answers);
|
const response = await saveAnswersApi(cookies.token, formId, answers);
|
||||||
console.log(response)
|
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setAnswersList([...answersList, {
|
setAnswersList([...answersList, {
|
||||||
@ -69,11 +70,20 @@ const ViewForm = () => {
|
|||||||
setAnswers([]);
|
setAnswers([]);
|
||||||
navigate("/forms");
|
navigate("/forms");
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
response.status === 401
|
||||||
|
) {
|
||||||
|
// navigate("/enter")
|
||||||
|
setUser(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.main}>
|
<div className={classes.main}>
|
||||||
{questions ?
|
{questions.length ?
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
<div className={classes.form}>
|
<div className={classes.form}>
|
||||||
<div className={classes.form__header}>
|
<div className={classes.form__header}>
|
||||||
@ -86,8 +96,8 @@ const ViewForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.footer}>
|
<div className={classes.footer}>
|
||||||
<MyButton text={"Отправить"} click={saveAnswers}/>
|
<MyButton text={"Отправить"} class={"main__green"} click={saveAnswers}/>
|
||||||
<MyButton text={"Отмена"} backgroundColor={"rgb(180, 180, 180)"} click={() => {
|
<MyButton text={"Отмена"} class={"main__white"} click={() => {
|
||||||
setAnswers([]);
|
setAnswers([]);
|
||||||
navigate("/");
|
navigate("/");
|
||||||
}}/>
|
}}/>
|
||||||
@ -96,7 +106,11 @@ const ViewForm = () => {
|
|||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
<div className={classes.form}>
|
<div className={classes.form}>
|
||||||
<div className={classes.form__unexists}>
|
<div className={classes.form__unexists}>
|
||||||
<span>Форма с идентификатором #{formId} отсутствует.</span>
|
<span>
|
||||||
|
{responseStatus === 200 ?
|
||||||
|
`Форма с идентификатором #${formId} пустая.` :
|
||||||
|
`Форма с идентификатором #${formId} отсутствует.`}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
|
@ -1,21 +1,40 @@
|
|||||||
const protectedUrl = {
|
const protectedUrl = {
|
||||||
notAuthorized: [
|
notAuthorized: [
|
||||||
"/forms",
|
new RegExp("/forms"),
|
||||||
"/forms/edit",
|
new RegExp("/forms/\\w+/edit"),
|
||||||
"/profile"
|
new RegExp("/profile"),
|
||||||
|
new RegExp("/forms/\\w+/answers"),
|
||||||
|
new RegExp("/tokens/\\w+"),
|
||||||
|
new RegExp("/admin"),
|
||||||
|
new RegExp("/articles"),
|
||||||
|
new RegExp("/articles/\\w+/edit"),
|
||||||
],
|
],
|
||||||
Authorized: [
|
Authorized: [
|
||||||
"enter"
|
"/enter"
|
||||||
],
|
],
|
||||||
notRights: [
|
notRights: [
|
||||||
|
new RegExp("/forms"),
|
||||||
|
new RegExp("/forms/\\w+/edit"),
|
||||||
|
new RegExp("/forms/\\w+/answers"),
|
||||||
|
new RegExp("/tokens/\\w+"),
|
||||||
|
new RegExp("/admin"),
|
||||||
|
new RegExp("/articles"),
|
||||||
|
new RegExp("/articles/\\w+/edit"),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function globalRender(url, user, navigate) {
|
function globalRender(url, user, navigate) {
|
||||||
if (!user && protectedUrl.notAuthorized.some(item => item === url)) {
|
if (!user && protectedUrl.notAuthorized.some(item => url.match(item) ? url.match(item)[0] === url : false)) {
|
||||||
navigate("/enter")
|
navigate("/enter")
|
||||||
}
|
}
|
||||||
|
else if (user && protectedUrl.Authorized.some(item => item === url)) {
|
||||||
|
navigate("/")
|
||||||
|
}
|
||||||
|
else if (user && protectedUrl.notRights.some(item => url.match(item) ? url.match(item)[0] === url : false)) {
|
||||||
|
if (!user.is_admin) {
|
||||||
|
navigate("/")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { globalRender }
|
export { globalRender }
|
@ -9,6 +9,10 @@ import Profile from "../pages/Profile.jsx";
|
|||||||
import ViewForm from "../pages/ViewForm.jsx";
|
import ViewForm from "../pages/ViewForm.jsx";
|
||||||
import AdminPanel from '../pages/AdminPanel.jsx';
|
import AdminPanel from '../pages/AdminPanel.jsx';
|
||||||
import AnswersForm from '../pages/AnswersForm.jsx';
|
import AnswersForm from '../pages/AnswersForm.jsx';
|
||||||
|
import TokensForm from '../pages/TokensForm.jsx';
|
||||||
|
import Articles from '../pages/Articles.jsx';
|
||||||
|
import NewArticle from '../pages/NewArticle.jsx';
|
||||||
|
import ViewArticle from '../pages/ViewArticle.jsx';
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@ -45,6 +49,22 @@ const router = createBrowserRouter([
|
|||||||
{
|
{
|
||||||
path: "/forms/:formId/answers",
|
path: "/forms/:formId/answers",
|
||||||
element: <AnswersForm/>
|
element: <AnswersForm/>
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/tokens/:formId",
|
||||||
|
element: <TokensForm/>
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/articles",
|
||||||
|
element: <Articles/>
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/articles/:articleId/edit",
|
||||||
|
element: <NewArticle/>
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/articles/:articleId/",
|
||||||
|
element: <ViewArticle/>
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||||
|
// const Inputmask = require('inputmask');
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
module.exports = (env) => {
|
module.exports = (env) => {
|
||||||
|
Reference in New Issue
Block a user