MinervaFrontend/src/pages/NewForm.jsx
kuwsh1n 0e1dc49f59
Some checks failed
publish-main / release-image (push) Has been cancelled
ticket 16, 4, 18, 19, 20, 21, 22
2024-07-03 16:26:24 +03:00

471 lines
13 KiB
JavaScript

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 Loading from "../components/Loading.jsx";
import { FormsData, TypeAnswerData } from "../context";
import { listFormsApi, updateTitleFormApi } from "../hooks/api/listFormsApi.js";
import { UserData } from "../context";
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 navigate = useNavigate();
const location = useLocation();
const { formId } = useParams();
const {user, setUser} = useContext(UserData);
const [dragElem, setDragElem] = useState(null);
const [dropElem, setDropElem] = useState(null);
const [loading, setLoading] = useState(false);
const [cookies, _, __] = useCookies(["user"]);
const { forms, setForms } = useContext(FormsData);
const { listTypeAnswer, setListTypeAnswer } = useContext(TypeAnswerData);
const nextID = (list, param) => {
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 [datetime, setDatetime] = useState("");
const [newTitleForm, setNewTitleForm] = useState("");
const [oldTitleFrom, setOldTitleForm] = useState("");
const [listBlock, setListBlock] = useState([]);
const [stateModal, setStateModal] = useState(false);
function cleanStates() {
setStateModal(false);
setQuestion("");
setComment("");
setOptionAnswer([]);
setFile([]);
setVideo("");
setCurrentTypeAnswer("");
setCurrentOptionAnswer("");
setMandatory(false);
}
useEffect(() => {
async function totalData() {
const responseForms = await listFormsApi(cookies.token);
const responseBlock = await listFormBlockApi(cookies.token, formId);
if (
responseBlock.status === 200 &&
responseBlock.data &&
responseForms.status === 200
) {
console.log(responseDataToListBlock(responseBlock.data))
setListBlock(responseDataToListBlock(responseBlock.data));
const title = responseForms.data.find(
(item) => item.id === formId
).title;
setNewTitleForm(title);
setOldTitleForm(title);
}
else if (responseForms.status === 401 || responseBlock.status === 401) {
// navigate("/enter")
setUser(false)
}
else {
setListBlock([]);
setNewTitleForm("Новыя форма");
setOldTitleForm("Новыя форма");
}
setLoading(true);
}
totalData();
}, []);
function addOptionAnswer() {
setOptionAnswer(
numberingBlocks(
[
...optionAnswer,
{
id: nextID(optionAnswer, "id"),
text: currentOptionAnswer,
},
],
"id",
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,
};
const response = await updateBlockApi(
cookies.token,
formId,
data,
listBlock.find((item) => item.id === stateModal).order
);
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 removeBlock(order) {
const response = await removeBlockApi(cookies.token, formId, order);
if (response.status === 200) {
setListBlock([...listBlock.filter((item) => item.order !== order)]);
}
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
}
async function addFiles(newFile) {
const fileData = []
for (let item of newFile) {
let binary = ""
const buff = await item.arrayBuffer()
const bytesArray = new Uint8Array(buff)
let len = bytesArray.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode( bytesArray[ i ] );
}
fileData.push({
name: item.name,
type: item.type,
binary: btoa(binary)
})
setFile([...file, ...fileData])
}
}
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 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 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} />
<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;