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;