471 lines
13 KiB
JavaScript
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;
|