Compare commits

..

No commits in common. "209c2e0a701637d62be02cfb19b91f0973e61b3c" and "0b48eb739e98d3fa3093124efdd859f782cf9bc0" have entirely different histories.

21 changed files with 287 additions and 456 deletions

View File

@ -1,56 +0,0 @@
name: publish-main
on:
push
jobs:
release-image:
runs-on: ubuntu-latest
container:
image: catthehacker/ubuntu:act-latest
env:
DOCKER_ORG: krbl
RUNNER_TOOL_CACHE: /toolcache
IMAGE_NAME: minerva-frontend
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker BuildX
uses: docker/setup-buildx-action@v2
with:
config-inline: |
[registry."gitea.unprism.ru"]
- name: Login to DockerHub
uses: docker/login-action@v2
with:
registry: gitea.unprism.ru
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Get Meta
id: meta
run: |
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}') >> $GITHUB_OUTPUT
echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT
- name: Extract branch name
shell: bash
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
id: extract_branch
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
platforms: |
linux/amd64
linux/arm64
push: true
tags: |
gitea.unprism.ru/${{ env.DOCKER_ORG }}/${{ env.IMAGE_NAME }}:${{ steps.extract_branch.outputs.branch }}

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
dist/ dist/
node_modules/ node_modules/
package-lock.json package-lock.json
.DS_Store

View File

@ -1,12 +0,0 @@
{
"schemaVersion": 2,
"dockerfileLines": [
"FROM node",
"WORKDIR /app",
"COPY package*.json ./",
"RUN npm install",
"COPY . .",
"EXPOSE 3000",
"CMD [\"npm\", \"run\", \"start:dev\"]"
]
}

View File

@ -3,13 +3,13 @@ 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";
import { globalRender } from "./router/protectedRouting.js"; import { globalRender } from "./router/protectedRouting.js";
import { verifyUserApi } from "./hooks/api/enterAccountApi.js"; import { verifyUserApi } from "./hooks/api/enterAccountApi.js"
import classes from "./assets/styles/app.module.scss"; import classes from "./assets/styles/app.module.scss"
import NavBar from "./components/NavBar.jsx"; import NavBar from "./components/NavBar.jsx";
import "bootstrap/dist/css/bootstrap.min.css"; import 'bootstrap/dist/css/bootstrap.min.css';
import InputText from "./components/typeAnswer/InputText.jsx"; import InputText from "./components/typeAnswer/InputText.jsx";
import TextArea from "./components/typeAnswer/TextArea.jsx"; import TextArea from "./components/typeAnswer/TextArea.jsx";
import YesNo from "./components/typeAnswer/YesNo.jsx"; import YesNo from "./components/typeAnswer/YesNo.jsx"
import InputDate from "./components/typeAnswer/InputDate.jsx"; import InputDate from "./components/typeAnswer/InputDate.jsx";
import InputMultipleRadio from "./components/typeAnswer/InputMultipleRadio.jsx"; import InputMultipleRadio from "./components/typeAnswer/InputMultipleRadio.jsx";
import InputRadio from "./components/typeAnswer/InputRadio.jsx"; import InputRadio from "./components/typeAnswer/InputRadio.jsx";
@ -28,52 +28,51 @@ const App = () => {
{id: 4, text: 'Множественный выбор', typeTag: InputMultipleRadio}, {id: 4, text: 'Множественный выбор', typeTag: InputMultipleRadio},
{id: 5, text: 'Выпадающий список', typeTag: DropDownList}, {id: 5, text: 'Выпадающий список', typeTag: DropDownList},
{id: 6, text: 'Да/Нет', typeTag: YesNo}, {id: 6, text: 'Да/Нет', typeTag: YesNo},
// {id: 7, text: 'Файл', typeTag: InputFile}, {id: 7, text: 'Файл', typeTag: InputFile},
{id: 8, text: 'Дата', typeTag: InputDate} {id: 8, text: 'Дата', typeTag: InputDate}
]); ]);
// useEffect(() => globalRender(window.location.pathname, user, navigate)); // 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("app", user)
if (response.status === 200) { if (response) {
setUser(response.data); if (response.status === 200) {
globalRender(window.location.pathname, response.data, navigate); setUser(response.data);
} }
else { else {
globalRender(window.location.pathname, false, navigate); console.log(response)
}
} }
} }
verifyUser(); verifyUser();
}, []); }, [])
return ( return (
<UserData.Provider value={{ user, setUser }}> <UserData.Provider value={{ user, setUser }}>
<answersData.Provider value={{ answersList, setAnswersList }}> <answersData.Provider value={{ answersList, setAnswersList }}>
<FormsData.Provider value={{ forms, setForms }}> <FormsData.Provider value={{ forms, setForms }}>
<TypeAnswerData.Provider <TypeAnswerData.Provider value={{ listTypeAnswer, setListTypeAnswer }}>
value={{ listTypeAnswer, setListTypeAnswer }} <div className={classes.main}>
> <div className={classes.container}>
<div className={classes.main}> <div className={classes.header}>
<div className={classes.container}> <NavBar navigate={navigate} auth={user} setAuth={setUser}/>
<div className={classes.header}> </div>
<NavBar navigate={navigate} auth={user} setAuth={setUser} /> <div className={classes.content}>
</div> <Outlet/>
<div className={classes.content}> </div>
<Outlet /> </div>
</div> </div>
</div> </TypeAnswerData.Provider>
</div> </FormsData.Provider>
</TypeAnswerData.Provider> </answersData.Provider>
</FormsData.Provider> </UserData.Provider>
</answersData.Provider> )
</UserData.Provider> }
);
};
export default App; export default App;

View File

@ -11,26 +11,12 @@
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); box-shadow: 0 0 5px 1px rgb(200, 200, 200);
padding: 1.5%; padding: 1.5%;
position: relative;
&__linkAdmin { &__linkAdmin {
position: absolute; position: absolute;
bottom: 103%; bottom: 103%;
@ -47,8 +33,6 @@
} }
} }
&__wrapper { &__wrapper {
width: 100%;
height: 100%;
&__header { &__header {
width: 100%; width: 100%;
height: 15%; height: 15%;
@ -56,7 +40,6 @@
justify-content: start; justify-content: start;
align-items: center; align-items: center;
margin-bottom: 10px; margin-bottom: 10px;
// border-bottom: 1px solid rgb(200, 200, 200);
h3 { h3 {
font-size: 25px; font-size: 25px;
font-family: "Montserrat", sans-serif; font-family: "Montserrat", sans-serif;
@ -66,45 +49,30 @@
&__body { &__body {
width: 100%; width: 100%;
height: 85%; height: 85%;
overflow-y: auto; &__item {
border-bottom: 1px solid rgb(200, 200, 200);
&::-webkit-scrollbar {
width: 7px;
}
&::-webkit-scrollbar-thumb {
background-color: rgb(200, 200, 200);
}
&__column {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 15px;
font-family: "Montserrat", sans-serif;
padding: 5px; padding: 5px;
border-bottom: 1px solid rgb(200, 200, 200); border-bottom: 1px solid rgb(200, 200, 200);
}
&__item {
padding: 0 5px;
// border-bottom: 1px solid rgb(200, 200, 200);
font-size: 15px; font-size: 15px;
font-family: "Montserrat", sans-serif; font-family: "Montserrat", sans-serif;
display: flex; cursor: pointer;
justify-content: space-between; // &__question {
align-items: center; // &__text {
height: 20%; // font-size: 15px;
width: 100%; // font-family: "Montserrat", sans-serif;
&:hover { // }
background-color: rgba(230, 230, 230, 0.6); // &__comment {
} // font-size: 11px;
&__user { // font-family: "Montserrat", sans-serif;
cursor: pointer; // font-style: italic;
&:hover { // color: rgb(200, 200, 200);
text-decoration: underline; // }
} // }
} // &__answer {
&__date { // &__text {
// font-size: 15px;
} // font-family: "Montserrat", sans-serif;
// }
// }
} }
} }
} }

View File

@ -28,6 +28,7 @@
.content { .content {
width: 100%; width: 100%;
height: 100%; height: 100%;
// box-shadow: 0 3px 5px 1px rgb(200, 200, 200);
border: 1px solid rgb(220, 220, 220); border: 1px solid rgb(220, 220, 220);
border-top: none; border-top: none;
&__wrapper { &__wrapper {
@ -57,15 +58,6 @@
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
flex-direction: column; flex-direction: column;
position: relative;
&__error {
position: absolute;
font-size: 13px;
font-family: "Montserrat", sans-serif;
top: 0;
left: 10px;
color: rgb(224, 75, 75);
}
} }
&__footer { &__footer {
width: 100%; width: 100%;
@ -95,15 +87,7 @@
justify-content: space-around; justify-content: space-around;
flex-direction: column; flex-direction: column;
padding-bottom: 5px; padding-bottom: 5px;
position: relative;
&__error {
position: absolute;
font-size: 13px;
font-family: "Montserrat", sans-serif;
top: 0;
left: 10px;
color: rgb(224, 75, 75);
}
&__fio { &__fio {
height: 15%; height: 15%;
display: flex; display: flex;

View File

@ -4,6 +4,10 @@ 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(() => {
console.log("nav", auth)
})
return ( return (
<div className={classes.main}> <div className={classes.main}>
<div className={classes.wrapper}> <div className={classes.wrapper}>
@ -26,7 +30,7 @@ const NavBar = ({navigate, auth, setAuth}) => {
</div> </div>
</div> </div>
</div> </div>
); )
}; }
export default NavBar; export default NavBar;

View File

@ -7,11 +7,11 @@ const DropDownList = ({postfix, optionAnswer, answers, updateAnswersForm}) => {
<div className={classes.main}> <div className={classes.main}>
<select <select
value={answers ? answers[postfix].answer : ""} value={answers ? answers[postfix].answer : ""}
onChange={updateAnswersForm ? (e) => updateAnswersForm(e.target.value, postfix) : () => {}} onChange={updateAnswersForm ? (e) => updateAnswersForm(Number(e.target.value), postfix) : () => {}}
> >
<option selected disabled></option>
{optionAnswer.map((item, i) => {optionAnswer.map((item, i) =>
<option value={item.text} key={i}>{item.text}</option> // <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> </select>
</div> </div>

View File

@ -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(value) { function checkRadio(i) {
if (answers[postfix].answer) { if (answers[postfix].answer) {
return answers[postfix].answer.some(item => item === value) return answers[postfix].answer.some(item => item === Number(i))
} }
return false return false
} }
function updateStateCheckbox(value) { function updateStateCheckbox(i) {
if (updateAnswersForm) { if (updateAnswersForm) {
if (answers[postfix].answer.some((item) => item === value)) { if (answers[postfix].answer.some((item) => item === Number(i))) {
answers[postfix].answer.splice(answers[postfix].answer.indexOf(value), 1) answers[postfix].answer.splice(answers[postfix].answer.indexOf(i), 1)
} }
else { else {
answers[postfix].answer.push(value) answers[postfix].answer.push(i)
} }
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={item.text} value={i}
checked={answers ? checkRadio(item.text) : false} checked={answers ? checkRadio(i) : false}
onChange={() => updateStateCheckbox(item.text)} 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 ? 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>

View File

@ -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={item.text} value={i}
checked={answers ? answers[postfix].answer === item.text : false} checked={answers ? answers[postfix].answer === i : false}
onChange={updateAnswersForm ? (e) => updateAnswersForm(item.text, postfix) : () => {}} 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 ? 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>

View File

@ -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 === "Да" : false} checked={answers ? answers[postfix].answer === "1" : false}
onChange={updateAnswersForm ? () => updateAnswersForm("Да", postfix) : () => {}} onChange={updateAnswersForm ? () => updateAnswersForm("1", 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 === "Нет" : false} checked={answers ? answers[postfix].answer === "2" : false}
onChange={updateAnswersForm ? () => updateAnswersForm("Нет", postfix) : () => {}} onChange={updateAnswersForm ? () => updateAnswersForm("2", postfix) : () => {}}
/> />
<label class="form-check-label" for="choiceNo">Нет</label> <label class="form-check-label" for="choiceNo">Нет</label>
</div> </div>

View File

@ -23,7 +23,7 @@ async function completeRegistration(data) {
return response return response
} }
catch (e) { catch (e) {
return "Ошибка. Проверте корректность введенных данных." return e
} }
} }
return validate.message return validate.message

View File

@ -31,22 +31,4 @@ function responseDataToListBlock(data) {
return result.sort((itemOne, itemTwo) => itemOne.order - itemTwo.order) return result.sort((itemOne, itemTwo) => itemOne.order - itemTwo.order)
}; };
function dateTimeParse(date) { export { responseDataToListBlock }
let newDate = "";
for (let symbol of date) {
if (symbol === "T") {
newDate += " ";
}
else if (symbol === ".") {
break;
}
else {
newDate += symbol;
}
}
return newDate
}
export { responseDataToListBlock, dateTimeParse }

View File

@ -1,24 +1,18 @@
const constructorAnswerValidate = ( const constructorAnswerValidate = (state, messageReject = "Ошибка", messageResolve = undefined) => {
state, return state ?
messageReject = "Ошибка", {
messageResolve = undefined status: true,
) => { message: messageResolve
return state } :
? { {
status: true, status: false,
message: messageResolve, message: messageReject
} }
: { }
status: false,
message: messageReject,
};
};
const totalRegisterValidate = (data) => { const totalRegisterValidate = (data) => {
const listValidation = [ const listValidation = [
constructorAnswerValidate(data.login.length, "Введите логин."), constructorAnswerValidate(data.login.length, "Обязательное поле."),
constructorAnswerValidate(data.password.length, "Введите пароль."),
constructorAnswerValidate(data.repiedPassword.length, "Введите повторно пароль."),
// constructorAnswerValidate(data.surname.length, "Обязательное поле."), // constructorAnswerValidate(data.surname.length, "Обязательное поле."),
// constructorAnswerValidate(data.email.length, "Обязательное поле."), // constructorAnswerValidate(data.email.length, "Обязательное поле."),
// constructorAnswerValidate(data.phone.length, "Обязательное поле."), // constructorAnswerValidate(data.phone.length, "Обязательное поле."),
@ -26,12 +20,12 @@ const totalRegisterValidate = (data) => {
// 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) {
return value; return value
}
} }
} return { status: true }
return { status: true }; }
};
export { totalRegisterValidate, constructorAnswerValidate }; export { totalRegisterValidate, constructorAnswerValidate }

View File

@ -3,7 +3,7 @@ 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, dateTimeParse } from "../hooks/sundry/parseListBlock"; import { responseDataToListBlock } from "../hooks/sundry/parseListBlock";
import { listFormBlockApi, getAnswersApi } from "../hooks/api/formApi"; import { listFormBlockApi, getAnswersApi } from "../hooks/api/formApi";
import { listUsersApi } from "../hooks/api/adminApi"; import { listUsersApi } from "../hooks/api/adminApi";
@ -29,7 +29,6 @@ const AnswersForm = () => {
for (let item of responseAnswers.data) { for (let item of responseAnswers.data) {
const blocks = { const blocks = {
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: []
} }
@ -68,20 +67,12 @@ const AnswersForm = () => {
<h3>Ответы</h3> <h3>Ответы</h3>
</div> </div>
<div className={classes.answers__wrapper__body}> <div className={classes.answers__wrapper__body}>
<div className={classes.answers__wrapper__body__column}>
<div>Логин</div>
<div>Дата</div>
</div>
{data ? {data ?
data.map((item, i) => data.map((item, i) =>
<div className={classes.answers__wrapper__body__item} key={i}> <div className={classes.answers__wrapper__body__item} key={i}>
<div className={classes.answers__wrapper__body__item__user} data-bs-toggle={"modal"} data-bs-target={`#answersModal${i}`}> <div className={classes.answers__wrapper__body__item__user} data-bs-toggle={"modal"} data-bs-target={`#answersModal${i}`}>
{item.user} {item.user}
</div> </div>
<div className={classes.answers__wrapper__body__item__date}>
{item.date}
</div>
<div class="modal fade myModal" className={classes.myModal} id={`answersModal${i}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true"> <div class="modal fade myModal" className={classes.myModal} id={`answersModal${i}`} 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}>
@ -96,11 +87,7 @@ const AnswersForm = () => {
<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}>Ответ: { <p className={classes.myModal__item__question__text}>Ответ: {block.answers.answer}</p>
Array.isArray(block.answers.answer) ?
block.answers.answer.map(item => <span>{item}; </span>) :
block.answers.answer
}</p>
</div> </div>
</div>)} </div>)}
</div> </div>
@ -112,13 +99,26 @@ const AnswersForm = () => {
</div> </div>
</div> </div>
) )
: : <div>Ответов нет</div>}
<div className={classes.loading__wrapper}>
<div class="spinner-border text-dark" className={classes.loading__wrapper__body} role="status">
<span class="visually-hidden">Загрузка...</span> {/* <MyButton text={'Предпросмотр'} backgroundColor={'rgb(225, 225, 225)'} toggle={"modal"} target={"#previewModal"}/>
</div> {data ? <div className={classes.answers__wrapper__body__item}></div> */}
</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> </div>

View File

@ -5,51 +5,44 @@ import classes from "../assets/styles/enterAccount.module.scss";
import MyInput from "../components/MyInput.jsx"; import MyInput from "../components/MyInput.jsx";
import MyButton from "../components/MyButton.jsx"; import MyButton from "../components/MyButton.jsx";
import { UserData } from "../context"; import { UserData } from "../context";
import { import { logIn, completeRegistration, verifyUserApi } from "../hooks/api/enterAccountApi.js";
logIn,
completeRegistration,
verifyUserApi,
} from "../hooks/api/enterAccountApi.js";
const EnterAccount = () => { const EnterAccount = () => {
const [enter, setEnter] = useState("login"); const [enter, setEnter] = useState("login");
const navigate = useNavigate(); const navigate = useNavigate();
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
const [phone, setPhone] = useState(""); const [phone, setPhone] = useState("");
const [login, setLogin] = useState(""); const [login, setLogin] = useState("");
const [surname, setSurname] = useState(""); const [surname, setSurname] = useState("");
const [patronymic, setPatronymic] = useState(""); const [patronymic, setPatronymic] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [repiedPassword, setRepiedPassword] = useState(""); const [repiedPassword, setRepiedPassword] = useState("");
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); function cleanState() {
const [regsterError, setRegsterError] = useState(false); setEmail("");
setPhone("");
setLogin("");
setSurname("");
setPatronymic("");
setPassword("");
setRepiedPassword("");
};
function cleanState() { function selectTag(tag) {
setEmail(""); setEnter(tag);
setPhone(""); cleanState();
setLogin(""); };
setSurname("");
setPatronymic("");
setPassword("");
setRepiedPassword("");
}
function selectTag(tag) { async function createUser() {
setEnter(tag); const response = await completeRegistration({
cleanState(); login: login,
} password: password,
repiedPassword: repiedPassword
async function createUser() { });
const response = await completeRegistration({
login: login,
password: password,
repiedPassword: repiedPassword,
});
if (response.status === 200) { if (response.status === 200) {
const responseMe = await verifyUserApi(response.data.token) const responseMe = await verifyUserApi(response.data.token)
@ -59,12 +52,12 @@ const EnterAccount = () => {
navigate("/"); navigate("/");
} }
else { else {
setRegsterError(response) console.log("Error")
} }
}; };
async function logInToAccount() { async function logInToAccount() {
const response = await logIn(login, password); const response = await logIn(login, password)
if (response.status === 200) { if (response.status === 200) {
setCookie("token", response.data.token); setCookie("token", response.data.token);
@ -75,7 +68,7 @@ const EnterAccount = () => {
navigate("/") navigate("/")
} }
else { else {
setLoginError(true); console.log(response)
} }
} }
@ -99,9 +92,6 @@ 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 placeholder={"Логин"} otherMainStyle={{width: "100%", height: "20%"}} otherInputStyle={{width: "100%"}} value={login} change={setLogin}/> <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}/> <MyInput type={"password"} placeholder={"Пароль"} otherMainStyle={{width: "100%", height: "20%"}} otherInputStyle={{width: "100%"}} value={password} change={setPassword}/>
</div> </div>
@ -115,12 +105,9 @@ const EnterAccount = () => {
</div> : </div> :
<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 placeholder={"Логин"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={login} change={setLogin}/> <MyInput placeholder={"Логин"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={login} change={setLogin}/>
<MyInput type={"password"} placeholder={"Пароль"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={password} change={setPassword}/> <MyInput type={"password"} placeholder={"Пароль"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={password} change={setPassword}/>
<MyInput type={'password'} placeholder={"Повторите пароль"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={repiedPassword} change={setRepiedPassword}/> <MyInput type={'password'} placeholder={"Повторите пароль"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={repiedPassword} change={setRepiedPassword}/>
@ -137,19 +124,14 @@ const EnterAccount = () => {
<MyInput type={'password'} placeholder={"Повторите пароль"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={repiedPassword} change={setRepiedPassword}/> <MyInput type={'password'} placeholder={"Повторите пароль"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={repiedPassword} change={setRepiedPassword}/>
</div> */} </div> */}
<div className={classes.content__wrapper__register__footer}> <div className={classes.content__wrapper__register__footer}>
<MyButton <MyButton text={"Создать"} otherStyle={{height: "100%", width: "20%"}} click={() => createUser()}/>
text={"Создать"}
otherStyle={{ height: "100%", width: "20%" }}
click={() => createUser()}
/>
</div> </div>
</div> </div>}
}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
); )
}; }
export default EnterAccount; export default EnterAccount;

View File

@ -1,54 +1,40 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useNavigate, useLocation, useParams } from "react-router-dom"; import { useNavigate, useLocation, useParams } from 'react-router-dom';
import classes from "../assets/styles/home.module.scss"; import classes from "../assets/styles/home.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";
const Home = () => { const Home = () => {
const [token, setToken] = useState(""); const [token, setToken] = useState("");
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<div className={classes.main}> <div className={classes.main}>
<div className={classes.wrapper}> <div className={classes.wrapper}>
<div className={classes.header}> <div className={classes.header}>
<div className={classes.header__top}> <div className={classes.header__top}>Кажется вы попали на общую страницу.</div>
Кажется вы попали на общую страницу. <div className={classes.header__bottom}>Чтобы перейти к форме ввелите токен ниже или снова перейдите по ссылке.</div>
</div> </div>
<div className={classes.header__bottom}> <div className={classes.content}>
Чтобы перейти к форме введите токен ниже или снова перейдите по <div className={classes.content__title}>
ссылке. <div className={classes.content__title__wrapper}>
</div> <h3>Перейти к нужной форме</h3>
</div>
</div>
<div className={classes.content__token}>
<div className={classes.content__token__wrapper}>
<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={"Найти форму"} click={() => navigate(`/forms/${token}`)}/>
</div>
</div>
</div>
</div>
</div> </div>
<div className={classes.content}> )
<div className={classes.content__title}> }
<div className={classes.content__title__wrapper}>
<h3>Перейти к нужной форме</h3>
</div>
</div>
<div className={classes.content__token}>
<div className={classes.content__token__wrapper}>
<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={"Найти форму"}
click={() => navigate(`/forms/${token}`)}
/>
</div>
</div>
</div>
</div>
</div>
);
};
export default Home; export default Home;

View File

@ -119,6 +119,13 @@ const NewForm = () => {
console.log(response) console.log(response)
} }
// setListBlock(listBlock.map(item => {
// if (item.id === stateModal) {
// item = data
// }
// return item
// }))
cleanStates(); cleanStates();
}; };

View File

@ -19,9 +19,11 @@ 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("");
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) {
@ -31,8 +33,10 @@ const ViewForm = () => {
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 { else {
// console.log(responseForms)
console.log(responseBlocks) console.log(responseBlocks)
} }
}; };
@ -41,7 +45,6 @@ const ViewForm = () => {
}, []); }, []);
function updateAnswersForm(value, id) { function updateAnswersForm(value, id) {
console.log(value)
setAnswers( setAnswers(
answers.map((item, i) => { answers.map((item, i) => {
if (id === i) { if (id === i) {
@ -53,8 +56,8 @@ const ViewForm = () => {
}; };
async function saveAnswers() { async function saveAnswers() {
console.log(answers)
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, {

View File

@ -5,10 +5,10 @@ const protectedUrl = {
"/profile" "/profile"
], ],
Authorized: [ Authorized: [
"/enter" "enter"
], ],
notRights: [ notRights: [
"/forms"
] ]
} }
@ -16,14 +16,6 @@ function globalRender(url, user, navigate) {
if (!user && protectedUrl.notAuthorized.some(item => item === url)) { if (!user && protectedUrl.notAuthorized.some(item => item === url)) {
navigate("/enter") navigate("/enter")
} }
else if (user && protectedUrl.Authorized.some(item => item === url)) {
navigate("/")
}
else if (user && protectedUrl.notRights.some(item => item === url)) {
if (!user.is_admin) {
navigate("/")
}
}
} }
export { globalRender } export { globalRender }

View File

@ -1,74 +1,73 @@
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 path = require("path"); const path = require('path');
module.exports = (env) => { module.exports = (env) => {
const isDev = env.mode === "development";
const cssLoader = { const isDev = env.mode === 'development';
loader: "css-loader",
options: {
modules: {
localIdentName: isDev ? "[path][name]__[local]" : "[hash:base64:8]",
},
},
};
const config = { const cssLoader = {
mode: env.mode ?? "development", loader: "css-loader",
performance: { options: {
hints: false, modules: {
maxEntrypointSize: 512000, localIdentName: isDev ? '[path][name]__[local]' : '[hash:base64:8]'
maxAssetSize: 512000,
},
entry: "./src/index.js",
output: {
// filename: '[name].[contenthash].js',
filename: "bundle.js",
publicPath: "/",
path: path.resolve(__dirname, "dist"),
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "public", "index.html"),
}),
isDev
? undefined
: new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:8].css",
chunkFilename: "css/[name].[contenthash:8].css",
}),
],
module: {
rules: [
{
test: /\.(scss|css)$/,
use: [
isDev ? "style-loader" : MiniCssExtractPlugin.loader,
cssLoader,
"sass-loader",
],
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
}, },
},
}, },
], }
},
devServer: {
port: env.port ?? 3000,
historyApiFallback: true,
host: "0.0.0.0",
allowedHosts: "all",
},
};
return config; const config = {
}; mode: env.mode ?? 'development',
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000
},
entry: './src/index.js',
output: {
// filename: '[name].[contenthash].js',
filename: 'bundle.js',
publicPath: '/',
path: path.resolve(__dirname, 'dist'),
clean: true
},
plugins: [
new HtmlWebpackPlugin({template: path.resolve(__dirname, 'public', 'index.html')}),
isDev ? undefined : new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
chunkFilename: 'css/[name].[contenthash:8].css'
})
],
module: {
rules: [
{
test: /\.(scss|css)$/,
use: [
isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
cssLoader,
'sass-loader'
],
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
}
}
}
]
},
devServer: {
port: env.port ?? 3000,
open: true,
historyApiFallback: true
}
};
return config
}