This commit is contained in:
kuwsh1n 2024-04-07 00:38:07 +03:00
parent 6817f5bf9b
commit 33f27d2efc
23 changed files with 570 additions and 241 deletions

7
Dockerfile Normal file
View File

@ -0,0 +1,7 @@
FROM node:21-alpine
WORKDIR /frontend
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "start:dev"]

View File

@ -32,9 +32,11 @@
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@popperjs/core": "^2.11.8",
"axios": "^1.6.8",
"bootstrap": "^5.3.3",
"react": "^18.2.0",
"react-bootstrap": "^2.10.1",
"react-cookie": "^7.1.4",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.1"
}

View File

@ -1,7 +1,9 @@
import React, { useState, useEffect, useLayoutEffect } from "react";
import { Outlet, useNavigate } from "react-router-dom";
import { FormsData, UserData, TypeAnswerData } from "./context";
import { useCookies } from "react-cookie";
import { globalRender } from "./router/protectedRouting.js";
import { verifyUserApi } from "./hooks/api/enterAccountApi.js"
import classes from "./assets/styles/app.module.scss"
import NavBar from "./components/NavBar.jsx";
import 'bootstrap/dist/css/bootstrap.min.css';
@ -30,6 +32,24 @@ const App = () => {
]);
// useEffect(() => globalRender(window.location.pathname, user, navigate));
const [cookies, _, __] = useCookies(["user"]);
useEffect(() => {
async function verifyUser() {
const response = await verifyUserApi(cookies.token);
if (response) {
if (response.status === 200) {
setUser(response.data);
}
else {
console.log(response)
}
}
}
verifyUser()
}, [])
return (
<UserData.Provider value={{ user, setUser }}>

View File

@ -12,9 +12,38 @@
.header {
text-align: right;
display: flex;
justify-content: end;
justify-content: space-between;
width: 100%;
height: 8%;
&__date {
width: 30%;
height: 100%;
&__item {
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 {
display: flex;
justify-content: space-between;

View File

@ -5,9 +5,9 @@ import MyButton from "./MyButton.jsx"
const AnswerModal = ({
cleanStates,
currentTypeAnswer,
updateAnswerByForm,
updateBlock,
stateModal,
saveStates,
addFormBlock,
question,
file,
listTypeAnswer,
@ -16,17 +16,14 @@ const AnswerModal = ({
currentOptionAnswer,
setCurrentOptionAnswer,
comment,
datetime,
mandatory,
setMandatory,
addOptionAnswer,
setQuestion,
setComment,
setDatetime,
setCurrentTypeAnswer,
setFile
}) => {
return (
<div class="modal fade myModal" className={classes.myModal} id="answerModal" tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
@ -79,14 +76,10 @@ const AnswerModal = ({
<span className={classes.myModal__dialog__content__body__mandatory__title}>Обязательный вопрос</span>
<input className={classes.myModal__dialog__content__body__mandatory__choice} type="checkbox" checked={mandatory} onChange={() => setMandatory(!mandatory)}/>
</div>
<div className={classes.myModal__dialog__content__body__time}>
<span>Дедлайн выполнения</span>
<input type="datetime-local" value={datetime} onChange={event => setDatetime(event.target.value)}/>
</div>
</div>
<div class="modal-footer myModal__dialog__content__footer" className={classes.myModal__dialog__content__footer}>
<button type="button" class="btn btn-light" data-bs-dismiss="modal" onClick={cleanStates}>Отмена</button>
<button type="button" class="btn" style={{color: 'white', backgroundColor: 'rgb(150, 209, 158)'}} data-bs-dismiss="modal" onClick={stateModal ? updateAnswerByForm : saveStates}>Сохранить</button>
<button type="button" class="btn" style={{color: 'white', backgroundColor: 'rgb(150, 209, 158)'}} data-bs-dismiss="modal" onClick={stateModal ? updateBlock : addFormBlock}>Сохранить</button>
</div>
</div>
</div>

View File

@ -1,9 +1,9 @@
import React, { useState } from "react";
import classes from "../assets/styles/generatingFormFields.module.scss";
const GeneratingFormFields = ({newForm, listTypeAnswer, answers, updateAnswersForm}) => {
const GeneratingFormFields = ({listBlock, listTypeAnswer, answers, updateAnswersForm}) => {
return (
newForm.map((item, i) =>
listBlock.map((item, i) =>
<div className={classes.item} key={i}>
<div className={classes.item__question}>
<p className={classes.item__question__text}>{i + 1}) {item.question}</p>

View File

@ -16,7 +16,7 @@ const NavBar = ({navigate, auth, setAuth}) => {
<div className={classes.profile}>
{auth ?
<div className={classes.profile__authorized}>
<span onClick={() => navigate("/profile")}>Профиль ({auth.name})</span>
<span onClick={() => navigate("/profile")}>Профиль ({auth.login})</span>
</div> :
<div className={classes.profile__nonAuthorized}>
<span onClick={() => navigate("/enter")}>Вход <i class="fa-solid fa-arrow-right-to-bracket"></i></span>

View File

@ -2,7 +2,7 @@ import React from "react";
import classes from "../assets/styles/components/previewModal.module.scss";
import GeneratingFormFields from "./GeneratingFormFields.jsx";
const PreviewModal = ({newForm, listTypeAnswer}) => {
const PreviewModal = ({listBlock, listTypeAnswer}) => {
return (
<div class="modal fade modal-lg" className={classes.myModal} id="previewModal" tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
<div class="modal-dialog" className={classes.myModal__dialog}>
@ -12,7 +12,7 @@ const PreviewModal = ({newForm, listTypeAnswer}) => {
<i class="fa-solid fa-xmark" data-bs-dismiss="modal" aria-label="Close"></i>
</div>
<div class="modal-body" className={classes.myModal__dialog__content__body}>
<GeneratingFormFields newForm={newForm} listTypeAnswer={listTypeAnswer}/>
<GeneratingFormFields listBlock={listBlock} listTypeAnswer={listTypeAnswer}/>
</div>
<div class="modal-footer" className={classes.myModal__dialog__content__footer}>

View File

@ -2,6 +2,7 @@ import React, { useState } from "react";
import classes from "../../assets/styles/components/typeAnswer/dropDownList.module.scss"
const DropDownList = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
console.log(optionAnswer)
return (
<div className={classes.main}>
<select
@ -9,6 +10,7 @@ const DropDownList = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
onChange={updateAnswersForm ? (e) => updateAnswersForm(Number(e.target.value), postfix) : () => {}}
>
{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.id} key={i}>{item.text}</option>
)}
</select>

View File

@ -34,6 +34,7 @@ const InputMultipleRadio = ({postfix, optionAnswer, answers, updateAnswersForm})
checked={answers ? checkRadio(i) : false}
onChange={() => updateStateCheckbox(i)}
/>
{/* <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>
</div>
)}

View File

@ -11,10 +11,11 @@ const InputRadio = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
type="radio"
name={`inputRadio_${postfix}`}
id={`choice_${item.id}`}
value={i}
value={i}
checked={answers ? answers[postfix].answer === i : false}
onChange={updateAnswersForm ? (e) => updateAnswersForm(Number(e.target.value), 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}</label>
</div>
)}

View File

@ -1,43 +1,46 @@
import { totalRegisterValidate } from "../validation/enterAccountValidate.js";
import axios from "axios";
async function logIn(email, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (true) {
resolve({
email: "senya.bogachev@mail.ru",
phone: "89110128244",
name: "Арсений",
surname: "Богачев",
patronymic: "Валерьевич"
})
}
else {
reject("Error")
}
}, 1000)
}).catch((error) => {
console.log(error)
})
async function logIn(login, password) {
try {
const response = await axios.post("http://localhost:8080/auth/signIn", {"login": login, "password": password})
return response
}
catch (e) {
return e
}
};
async function completeRegistration(data) {
const validate = totalRegisterValidate(data)
const validate = totalRegisterValidate(data);
return new Promise((resolve, reject) => {
setTimeout(() => {
if (validate.status) {
console.log("Отправляем данные на бэк ->", data)
resolve({
status: 201,
data: data
})
}
else {
reject(validate.message)
}
}, 1000)
})
if (validate.status) {
try {
const response = await axios.post("http://localhost:8080/auth/signUp", {"login": data.login, "password": data.password})
return response
}
catch (e) {
return e
}
}
return validate.message
};
export { logIn, completeRegistration };
async function verifyUserApi(token=false) {
if (token) {
try {
const response = await axios.get("http://localhost:8080/auth/me", {
headers: {
"Authorization": `Token ${token}`,
},
})
return response
}
catch(e) {
return e
}
}
return false
}
export { logIn, completeRegistration, verifyUserApi };

View File

@ -1,65 +1,87 @@
function saveAnswersApi(id, answers) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (true) {
resolve({
id: id,
answers: answers
})
import axios from "axios";
async function listFormBlockApi(token, formId) {
try {
const response = await axios.get(`http://localhost:8080/formBuilder/edit/${formId}/list`,
{
headers: {
"Authorization": `Token ${token}`,
}
else {
reject("Error")
}
}, 1000)
})
})
return response
}
catch (e) {
return e
}
}
function removeFormApi(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (true) {
resolve({
id: id
})
async function addFormBlockApi(token, formId, data) {
try {
const response = await axios.post(`http://localhost:8080/formBuilder/edit/${formId}/add`,
{
data: data
},
{
headers: {
"Authorization": `Token ${token}`,
}
else {
reject("Error")
}
}, 200)
})
})
return response
}
catch (e) {
return e
}
};
// function removeFormApi(id) {
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// if (true) {
// resolve({
// id: id
// })
// }
// else {
// reject("Error")
// }
// }, 200)
// })
// };
async function updateBlockApi(token, blockId, data) {
try {
const response = await axios.post(`http://localhost:8080/formBuilder/edit/${blockId}/set`,
{
data: data
},
{
headers: {
"Authorization": `Token ${token}`,
}
})
return response
}
catch (e) {
return e
}
}
function updateFormByFormsApi(id, name, questions) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (true) {
resolve({
id: id,
name: name,
questions: questions
})
async function saveFormApi(token) {
try {
const response = await axios.post("http://localhost:8080/formBuilder/new",
{
title: "Новая форма"
},
{
headers: {
"Authorization": `Token ${token}`
}
else {
reject("Error")
}
}, 1000)
})
}
})
return response
}
catch (e) {
return e
}
};
function saveFormApi(name, questions) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (true) {
resolve({
name: name,
questions: questions
})
}
else {
reject("Error")
}
}, 1000)
})
}
export { saveAnswersApi, saveFormApi, updateFormByFormsApi, removeFormApi }
export { addFormBlockApi, listFormBlockApi, saveFormApi, updateBlockApi }

View File

@ -0,0 +1,50 @@
import axios from "axios";
async function listFormsApi(token) {
try {
const response = await axios.get("http://localhost:8080/formBuilder/list", {
headers: {
"Authorization": `Token ${token}`,
}
})
return response
}
catch (e) {
return e
}
};
async function createFormApi(token) {
try {
const response = await axios.post("http://localhost:8080/formBuilder/new",
{
title: "Новая форма"
},
{
headers: {
"Authorization": `Token ${token}`,
}
})
return response
}
catch (e) {
return e
}
};
async function removeFormApi(token, formId) {
try {
const response = await axios.post(`http://localhost:8080/formBuilder/edit/${formId}/delete`, {
headers: {
"Authorization": `Token ${token}`,
},
})
return response
}
catch (e) {
return e
}
};
export { listFormsApi, createFormApi, removeFormApi };

View File

@ -0,0 +1,30 @@
function responseDataToListBlock(data) {
const result = []
for (let block of data) {
const newParam = {
id: block.id,
formId: block.form_id,
order: block.order
}
for (let param of block.data) {
if (Array.isArray(param.Value) && param.Value.length) {
newParam[param.Key] = param.Value.map(item => ({
id: item[0].Value,
text: item[1].Value
}))
}
else {
newParam[param.Key] = param.Value
}
}
result.push(newParam)
}
return result
}
export { responseDataToListBlock }

View File

@ -12,12 +12,12 @@ const constructorAnswerValidate = (state, messageReject = "Ошибка", messag
const totalRegisterValidate = (data) => {
const listValidation = [
constructorAnswerValidate(data.name.length, "Обязательное поле."),
constructorAnswerValidate(data.surname.length, "Обязательное поле."),
constructorAnswerValidate(data.email.length, "Обязательное поле."),
constructorAnswerValidate(data.phone.length, "Обязательное поле."),
constructorAnswerValidate(data.login.length, "Обязательное поле."),
// constructorAnswerValidate(data.surname.length, "Обязательное поле."),
// constructorAnswerValidate(data.email.length, "Обязательное поле."),
// constructorAnswerValidate(data.phone.length, "Обязательное поле."),
constructorAnswerValidate(data.password === data.repiedPassword, "Введенные пароли не совпадают."),
constructorAnswerValidate(data.password < 8, "Пароль должен иметь более 8 символов.")
constructorAnswerValidate(data.password >= 8, "Пароль должен иметь более 8 символов.")
]
for (let value of listValidation) {

View File

@ -1,4 +1,5 @@
import React, { useState, useContext } from "react";
import { useCookies } from "react-cookie";
import { useNavigate } from "react-router-dom";
import classes from "../assets/styles/enterAccount.module.scss";
import MyInput from "../components/MyInput.jsx";
@ -12,18 +13,19 @@ const EnterAccount = () => {
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
const [name, setName] = useState("");
const [login, setLogin] = useState("");
const [surname, setSurname] = useState("");
const [patronymic, setPatronymic] = useState("");
const [password, setPassword] = useState("");
const [repiedPassword, setRepiedPassword] = useState("");
const {user, setUser} = useContext(UserData);
const [cookies, setCookie, removeCookie] = useCookies(["user"]);
function cleanState() {
setEmail("");
setPhone("");
setName("");
setLogin("");
setSurname("");
setPatronymic("");
setPassword("");
@ -35,26 +37,52 @@ const EnterAccount = () => {
cleanState();
};
function createUser() {
completeRegistration({
email: email,
phone: phone,
name: name,
surname: surname,
patronymic: patronymic,
async function createUser() {
const response = await completeRegistration({
// email: email,
// phone: phone,
login: login,
// surname: surname,
// patronymic: patronymic,
password: password,
repiedPassword: repiedPassword
}).then((resolve, reject) => {
if (resolve.status === 201) {
setUser(resolve.data)
cleanState();
navigate("/");
}
}).catch((error) => {
console.log(error)
})
});
if (response.status === 200) {
setUser({
email: email,
phone: phone,
login: login,
surname: surname,
patronymic: patronymic,
password: password,
});
setCookie("token", response.data.token);
cleanState();
navigate("/");
}
else {
console.log("Error")
}
};
async function logInToAccount() {
const response = await logIn(login, password)
if (response.status === 200) {
setCookie("token", response.data.token);
cleanState();
setUser({
login: login
})
navigate("/")
// window.location.reload()
}
else {
console.log(response)
}
}
return (
<div className={classes.main}>
<div className={classes.wrapper}>
@ -75,14 +103,14 @@ const EnterAccount = () => {
<h3>Войти в аккаунт</h3>
</div>
<div className={classes.content__wrapper__login__body}>
<MyInput placeholder={"Email"} otherMainStyle={{width: "100%", height: "20%"}} otherInputStyle={{width: "100%"}} value={email} change={setEmail}/>
<MyInput placeholder={"Логин"} otherMainStyle={{width: "100%", height: "20%"}} otherInputStyle={{width: "100%"}} value={login} change={setLogin}/>
<MyInput type={"password"} placeholder={"Пароль"} otherMainStyle={{width: "100%", height: "20%"}} otherInputStyle={{width: "100%"}} value={password} change={setPassword}/>
</div>
<div className={classes.content__wrapper__login__footer}>
<MyButton
text={"Войти"}
otherStyle={{height: "50%", width: "20%"}}
click={() => logIn(email, password).then((resolve, reject) => setUser(resolve))}
click={logInToAccount}
/>
</div>
</div> :
@ -94,7 +122,7 @@ const EnterAccount = () => {
<MyInput placeholder={"Email"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={email} change={setEmail}/>
<MyInput placeholder={"Номер телефона"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={phone} change={setPhone}/>
<div className={classes.content__wrapper__register__body__fio}>
<MyInput placeholder={"Имя"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={name} change={setName}/>
<MyInput placeholder={"Логин"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={login} change={setLogin}/>
<MyInput placeholder={"Фамилия"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={surname} change={setSurname}/>
<MyInput placeholder={"Отчество (при наличии)"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={patronymic} change={setPatronymic}/>
</div>

View File

@ -1,10 +1,11 @@
import React, { useState, useContext, useEffect } from "react";
import { useCookies } from "react-cookie";
import { useNavigate } from 'react-router-dom';
import classes from "../assets/styles/forms.module.scss"
import MyButton from "../components/MyButton.jsx";
import MyInput from "../components/MyInput.jsx";
import { FormsData, UserData } from "../context";
import { removeFormApi } from "../hooks/api/formApi.js";
import { listFormsApi, createFormApi, removeFormApi } from "../hooks/api/listFormsApi.js";
const Forms = () => {
const navigate = useNavigate();
@ -12,39 +13,53 @@ const Forms = () => {
const {user, setUser} = useContext(UserData);
const [stateLoading, setStateLoading] = useState(false);
const response = ms => {
return new Promise(r => setTimeout(() => r('response end'), ms))
};
const [cookies, _, __] = useCookies(["user"]);
function createForm() {
setStateLoading(true);
response(1000)
.then((r) => {
console.log(r);
setStateLoading(false);
navigate("/forms/edit");
useEffect(() => {
async function listForms() {
const response = await listFormsApi(cookies.token)
if (response.data) {
setForms(response.data)
}
)
else if (response.status === 200 && response.data) {
setForms([])
}
else {
console.log(response)
}
};
listForms();
}, [])
async function createForm() {
setStateLoading(true);
const response = await createFormApi(cookies.token)
setStateLoading(false);
if (response.data) {
navigate(`/forms/${response.data.id}/edit`)
}
else {
console.log(response)
}
};
function editForm(item) {
navigate("/forms/edit", {
state: {
id: item.id,
data: item.questions
}
});
navigate(`/forms/${item.id}/edit`);
};
function removeForm(id) {
removeFormApi(id)
.then((resolve, _) => {
console.log(resolve);
setForms([...forms.filter(item => {
item.id !== id
})]);
})
.catch(error => console.log(error));
async function removeForm(id) {
setForms([...forms.filter(item => item.id !== id)]);
// const response = await removeFormApi(cookies.token, id)
// if (response.status === 200) {
// setForms([...forms.filter(item => item.id !== id)]);
// }
// else {
// console.log(response)
// }
};
return (

View File

@ -1,9 +1,13 @@
import React from "react";
import React, { useState } from "react";
import { useNavigate, useLocation, useParams } from 'react-router-dom';
import classes from "../assets/styles/home.module.scss";
import MyButton from "../components/MyButton.jsx";
import MyInput from "../components/MyInput.jsx";
const Home = () => {
const [token, setToken] = useState("");
const navigate = useNavigate();
return (
<div className={classes.main}>
<div className={classes.wrapper}>
@ -19,12 +23,12 @@ const Home = () => {
</div>
<div className={classes.content__token}>
<div className={classes.content__token__wrapper}>
<MyInput placeholder={"Введите токен формы..."} otherMainStyle={{width: "100%"}} otherInputStyle={{width: "100%"}}/>
<MyInput placeholder={"Введите токен формы..."} otherMainStyle={{width: "100%"}} otherInputStyle={{width: "100%"}} value={token} change={(e) => setToken(e)}/>
</div>
</div>
<div className={classes.content__search}>
<div className={classes.content__search__wrapper}>
<MyButton text={"Найти форму"}/>
<MyButton text={"Найти форму"} click={() => navigate(`/forms/${token}`)}/>
</div>
</div>
</div>

View File

@ -1,17 +1,22 @@
import React, { useState, useContext } from "react";
import { useNavigate, useLocation } from 'react-router-dom';
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/newForm.module.scss";
import MyButton from "../components/MyButton.jsx";
import AnswerModal from "../components/AnswerModal.jsx";
import PreviewModal from "../components/PreviewModal.jsx"
import { FormsData, TypeAnswerData } from "../context";
import { saveFormApi, updateFormByFormsApi } from "../hooks/api/formApi.js";
import { saveFormApi, addFormBlockApi, listFormBlockApi, updateBlockApi } from "../hooks/api/formApi.js";
import { responseDataToListBlock } from "../hooks/sundry/parseListBlock.js";
const NewForm = () => {
const navigate = useNavigate();
const location = useLocation();
const { formId } = useParams();
const [dragElem, setDragElem] = useState(null);
const [dropElem, setDropElem] = useState(null);
const [cookies, _, __] = useCookies(["user"]);
const {forms, setForms} = useContext(FormsData);
const {listTypeAnswer, setListTypeAnswer} = useContext(TypeAnswerData);
@ -21,26 +26,26 @@ const NewForm = () => {
};
const [question, setQuestion] = useState("");
const [comment, setComment] = useState("");
const [datetime, setDatetime] = useState("");
const [mandatory, setMandatory] = useState(false);
const [optionAnswer, setOptionAnswer] = useState([]);
const [file, setFile] = useState([]);
const [currentTypeAnswer, setCurrentTypeAnswer] = useState("");
const [currentOptionAnswer, setCurrentOptionAnswer] = useState("");
const [newForm, setNewForm] = useState(location.state ? location.state.data : []);
const [datetime, setDatetime] = useState("");
const [listBlock, setListBlock] = useState([]);
const [stateModal, setStateModal] = useState(false);
function removeAnswerByForm(id) {
setNewForm([...newForm.filter(item => item.id !== id)]);
setListBlock([...listBlock.filter(item => item.id !== id)]);
};
function cleanStates() {
setStateModal(false)
setQuestion("");
setComment("");
setDatetime("");
setOptionAnswer([])
setFile([]);
setCurrentTypeAnswer("");
@ -48,6 +53,21 @@ const NewForm = () => {
setMandatory(false);
};
useEffect(() => {
async function listFormBlock() {
const response = await listFormBlockApi(cookies.token, formId);
if (response.status === 200 && response.data) {
setListBlock(responseDataToListBlock(response.data));
}
else {
console.log(response);
}
};
listFormBlock();
}, []);
function addOptionAnswer(text) {
setOptionAnswer([...optionAnswer, {
id: nextID(optionAnswer),
@ -57,56 +77,81 @@ const NewForm = () => {
};
function editAnswerByForm(id) {
const obj = newForm.find(item => item.id === id);
const obj = listBlock.find(item => item.id === id);
setQuestion(obj.question);
setComment(obj.comment);
setDatetime(obj.datetime);
setFile(obj.file);
setCurrentTypeAnswer(obj.typeAnswer);
setOptionAnswer(obj.optionAnswer);
setMandatory(obj.mandatory);
setStateModal(id);
setStateModal(obj.id);
};
function updateAnswerByForm() {
setNewForm(newForm.map(item => {
async function updateBlock() {
const data = {
id: stateModal,
question: question,
comment: comment,
file: file,
mandatory: mandatory,
optionAnswer: optionAnswer,
typeAnswer: currentTypeAnswer,
}
// 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.question = question;
item.comment = comment;
item.datetime = datetime;
item.file = file;
item.mandatory = mandatory;
item.optionAnswer = optionAnswer;
item.typeAnswer = currentTypeAnswer;
item = data
}
return item
}))
cleanStates()
cleanStates();
};
function saveStates() {
setNewForm([...newForm, {
id: nextID(newForm),
async function addFormBlock() {
const newBlock = {
question: question,
typeAnswer: currentTypeAnswer,
comment: comment,
datetime: datetime,
mandatory: mandatory,
optionAnswer: optionAnswer,
file: file
}]);
}
const response = await addFormBlockApi(cookies.token, formId, newBlock)
if (response.status === 200) {
setListBlock([...listBlock, newBlock]);
}
else {
console.log(response)
}
cleanStates();
};
function updateFormByForms() {
updateFormByFormsApi(location.state.id, "Новая форма", newForm)
updateFormByFormsApi(location.state.id, "Новая форма", listBlock)
.then((resolve, _) => {
console.log(resolve);
setForms(
forms.map(item => {
if (item.id === location.state.id) {
item.title = "Новая форма",
item.questions = newForm
item.questions = listBlock
}
return item
})
@ -117,14 +162,14 @@ const NewForm = () => {
};
function saveForm() {
saveFormApi("Новая форма", newForm)
saveFormApi("Новая форма", listBlock)
.then((resolve, reject) => {
console.log(resolve);
setForms(
[...forms, {
id: nextID(forms),
title: "Новая форма",
questions: newForm,
questions: listBlock,
answers: []
}]
);
@ -137,7 +182,13 @@ const NewForm = () => {
return (
<div className={classes.main}>
<div className={classes.wrapper}>
<div className={classes.header}>
<div className={classes.header}>
<div className={classes.header__date}>
<div className={classes.header__date__item}>
<span>Дедлайн выполнения</span>
<input type="datetime-local" value={datetime} onChange={event => setDatetime(event.target.value)}/>
</div>
</div>
<div className={classes.header__listBtn}>
<MyButton text={'Предпросмотр'} backgroundColor={'rgb(225, 225, 225)'} toggle={"modal"} target={"#previewModal"}/>
<MyButton text={'Опубликовать'} click={location.state ? updateFormByForms : saveForm}/>
@ -154,7 +205,7 @@ const NewForm = () => {
</div>
</div>
<PreviewModal newForm={newForm} listTypeAnswer={listTypeAnswer}/>
<PreviewModal listBlock={listBlock} listTypeAnswer={listTypeAnswer}/>
<AnswerModal
stateModal={stateModal}
@ -164,20 +215,18 @@ const NewForm = () => {
mandatory={mandatory}
optionAnswer={optionAnswer}
setOptionAnswer={setOptionAnswer}
datetime={datetime}
file={file}
currentOptionAnswer={currentOptionAnswer}
listTypeAnswer={listTypeAnswer}
setQuestion={setQuestion}
setComment={setComment}
setDatetime={setDatetime}
setFile={setFile}
setCurrentOptionAnswer={setCurrentOptionAnswer}
setMandatory={setMandatory}
cleanStates={cleanStates}
saveStates={saveStates}
addFormBlock={addFormBlock}
addOptionAnswer={addOptionAnswer}
updateAnswerByForm={updateAnswerByForm}
updateBlock={updateBlock}
setCurrentTypeAnswer={setCurrentTypeAnswer}/>
<div className={classes.content__newForm}>
@ -185,7 +234,7 @@ const NewForm = () => {
<h3>Новая форма</h3>
</div>
<div className={classes.content__newForm__list}>
{newForm.map((item, i) =>
{listBlock.map((item, i) =>
<div
className={classes.content__newForm__list__item}
key={i}
@ -203,8 +252,8 @@ const NewForm = () => {
}
}}
onDrop={() => {
const currentElem = newForm[dragElem]
const tNewForm = [...newForm]
const currentElem = listBlock[dragElem]
const tNewForm = [...listBlock]
if (dragElem > dropElem) {
tNewForm.splice(dropElem, 0, currentElem)
tNewForm.splice(dragElem + 1, 1)
@ -213,7 +262,7 @@ const NewForm = () => {
tNewForm.splice(dropElem + 1, 0, currentElem)
tNewForm.splice(dragElem, 1)
}
setNewForm(tNewForm)
setListBlock(tNewForm)
}}
>
<div className={classes.content__newForm__list__item__answer}>

View File

@ -1,30 +1,60 @@
import React, { useState, useContext } from "react";
import React, { useState, useContext, useEffect } from "react";
import classes from "../assets/styles/profile.module.scss";
import MyButton from "../components/MyButton.jsx";
import { UserData } from "../context";
import { useCookies } from "react-cookie";
import { verifyUserApi } from "../hooks/api/enterAccountApi.js";
const Profile = () => {
const [edit, setEdit] = useState(true);
const {user, setUser} = useContext(UserData);
const [email, setEmail] = useState(user.email);
const [phone, setPhone] = useState(user.phone);
const [name, setName] = useState(user.name);
const [surname, setSurname] = useState(user.surname);
const [patronymic, setPatronymic] = useState(user.patronymic);
console.log(user)
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
const [login, setLogin] = useState("");
const [first_name, setFirst_name] = useState("");
const [last_name, setLast_name] = useState("");
const [cookies, _, __] = useCookies(["user"]);
useEffect(() => {
console.log(1)
async function verifyUser() {
const response = await verifyUserApi(cookies.token);
if (response) {
if (response.status === 200) {
setUser(response.data);
setEmail(response.data.email);
setPhone(response.data.phone);
setLogin(response.data.login);
setFirst_name(response.data.first_name);
setLast_name(response.data.last_name);
}
else {
console.log(response)
}
}
}
verifyUser()
}, [])
function choiceInput(key) {
console.log(2)
switch (key) {
case "email":
return {get: email, set: setEmail}
case "phone":
return {get: phone, set: setPhone}
case "name":
return {get: name, set: setName}
case "surname":
return {get: surname, set: setSurname}
case "patronymic":
return {get: patronymic, set: setPatronymic}
case "login":
return {get: login, set: setLogin}
case "last_name":
return {get: last_name, set: setLast_name}
case "first_name":
return {get: first_name, set: setFirst_name}
}
}
@ -34,11 +64,11 @@ const Profile = () => {
}
else {
setUser({
login: login,
first_name: first_name,
last_name: last_name,
email: email,
phone: phone,
name: name,
surname: surname,
patronymic: patronymic
})
setEdit(!edit)
}
@ -61,7 +91,7 @@ const Profile = () => {
click={() => editUser()}/>
</div>
<div className={classes.profile__wrapper__body}>
{Object.keys(user).map(key => key !== "password" ? <div className={classes.profile__wrapper__body__item}>
{Object.keys(user).map(key => key !== "is_admin" ? <div className={classes.profile__wrapper__body__item}>
<div class="input-group mb-3">
<span class="input-group-text">{key}</span>
<input

View File

@ -1,26 +1,67 @@
import React, { useState, useContext } from "react";
import React, { useState, useContext, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useCookies } from "react-cookie";
import classes from "../assets/styles/viewForm.module.scss";
import { FormsData, TypeAnswerData } from "../context";
import GeneratingFormFields from "../components/GeneratingFormFields.jsx";
import MyButton from "../components/MyButton.jsx";
import { saveAnswersApi } from "../hooks/api/formApi.js";
import { listFormBlockApi } from "../hooks/api/formApi.js";
import { listFormsApi } from "../hooks/api/listFormsApi.js";
import { responseDataToListBlock } from "../hooks/sundry/parseListBlock.js";
const ViewForm = () => {
const navigate = useNavigate();
const { formId } = useParams();
const {forms, setForms} = useContext(FormsData);
const {listTypeAnswer, setListTypeAnswer} = useContext(TypeAnswerData);
const [cookies, _, __] = useCookies(["user"]);
const [questions, setQuestions] = useState([]);
const [answers, setAnswers] = useState([]);
const [title, setTitle] = useState("");
function newForm() {
return forms.find(item => item.id === Number(formId))
};
useEffect(() => {
async function getForm() {
const responseForms = await listFormsApi(cookies.token);
const responseBlocks = await listFormBlockApi(cookies.token, formId);
const [answers, setAnswers] = useState(
newForm() ? newForm().questions.map(item => (
{id: item.id, answer: []}
)) : []
);
if (responseBlocks.status === 200 && responseForms.status === 200 && responseBlocks.data) {
// let responseToNewForm = {};
// const result = {
// title: responseForms.data.find(item => item.id === formId).title,
// questions: [],
// answers: []
// }
// for (let item of responseBlocks.data) {
// responseToNewForm["id"] = item.id;
// for (let block of item.data) {
// responseToNewForm[block.Key] = block.Value
// };
// result.questions.push(responseToNewForm);
// result.answers.push(
// {id: item.id, answer: []}
// )
// responseToNewForm = {};
// };
const listBlocks = responseDataToListBlock(responseBlocks.data);
setQuestions(listBlocks)
setAnswers(listBlocks.map(item => (
{id: item.id, answer: []}
)))
setTitle(responseForms.data.find(item => item.id === formId).title)
}
else {
console.log(responseForms)
console.log(responseBlocks)
}
};
getForm()
}, []);
function updateAnswersForm(value, id) {
setAnswers(
@ -34,30 +75,32 @@ const ViewForm = () => {
};
function saveAnswers() {
saveAnswersApi(formId, answers)
.then((resolve, _) => {
console.log(resolve)
setAnswers([]);
navigate("/");
})
.catch((error) => console.log(error));
// saveAnswersApi(formId, answers)
// .then((resolve, _) => {
// console.log(resolve)
// setAnswers([]);
// navigate("/");
// })
// .catch((error) => console.log(error));
setAnswers([]);
navigate("/forms");
}
return (
<div className={classes.main}>
{newForm() ?
{questions ?
<div className={classes.wrapper}>
<div className={classes.form}>
<div className={classes.form__header}>
<div className={classes.form__header__title}>
<span>{newForm().title}</span>
<span>{title}</span>
</div>
<div className={classes.form__header__id}>
<span>#{formId}</span>
</div>
</div>
<div className={classes.form__content}>
<GeneratingFormFields newForm={newForm().questions} listTypeAnswer={listTypeAnswer} answers={answers} updateAnswersForm={updateAnswersForm}/>
<GeneratingFormFields listBlock={questions} listTypeAnswer={listTypeAnswer} answers={answers} updateAnswersForm={updateAnswersForm}/>
</div>
</div>
<div className={classes.footer}>

View File

@ -21,7 +21,7 @@ const router = createBrowserRouter([
element: <Forms/>,
},
{
path: "/forms/edit",
path: "/forms/:formId/edit",
element: <NewForm/>
},
{