add modal preview
This commit is contained in:
parent
5ceaac5e3d
commit
b18c49628f
@ -6,7 +6,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build:dev": "npx webpack --env mode=development",
|
"build:dev": "npx webpack --env mode=development",
|
||||||
"build:prod": "npx webpack --env mode=production",
|
"build:prod": "npx webpack --env mode=production",
|
||||||
"start": "npx webpack-dev-server"
|
"start:dev": "npx webpack-dev-server --env mode=development",
|
||||||
|
"start:prod": "npx webpack-dev-server --env mode=production"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root" style="height: 100%; width: 100%;"></div>
|
<div id="root" style="height: 100%; width: 100%;"></div>
|
||||||
|
<script src="/dist/bundle.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -50,6 +50,31 @@
|
|||||||
padding: 0 1%;
|
padding: 0 1%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&__answerOptions {
|
||||||
|
margin-top: 5%;
|
||||||
|
&__title {
|
||||||
|
display: block;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
&__list{
|
||||||
|
margin: 5px 0;
|
||||||
|
&__answer {
|
||||||
|
display: block;
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__text {
|
||||||
|
display: block;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
border: 1px solid rgb(200, 200, 200);
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 1%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
&__mandatory {
|
&__mandatory {
|
||||||
margin-top: 5%;
|
margin-top: 5%;
|
||||||
display: flex;
|
display: flex;
|
20
src/assets/styles/components/previewModal.module.scss
Normal file
20
src/assets/styles/components/previewModal.module.scss
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.myModal {
|
||||||
|
&__dialog {
|
||||||
|
&__content {
|
||||||
|
// padding: 2%;
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2%;
|
||||||
|
h5 {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@
|
|||||||
&__listBtn {
|
&__listBtn {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 20%;
|
width: 30%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import classes from "../assets/styles/components/myModal.module.scss";
|
import classes from "../assets/styles/components/answerModal.module.scss";
|
||||||
|
import MyButton from "./MyButton.jsx"
|
||||||
|
|
||||||
const MyModal = ({
|
const AnswerModal = ({
|
||||||
cleanStates,
|
cleanStates,
|
||||||
currentTypeAnswer,
|
currentTypeAnswer,
|
||||||
updateAnswerByForm,
|
updateAnswerByForm,
|
||||||
@ -10,10 +11,15 @@ const MyModal = ({
|
|||||||
answer,
|
answer,
|
||||||
file,
|
file,
|
||||||
listTypeAnswer,
|
listTypeAnswer,
|
||||||
|
optionAnswer,
|
||||||
|
setOptionAnswer,
|
||||||
|
currentOptionAnswer,
|
||||||
|
setCurrentOptionAnswer,
|
||||||
comment,
|
comment,
|
||||||
datetime,
|
datetime,
|
||||||
mandatory,
|
mandatory,
|
||||||
setMandatory,
|
setMandatory,
|
||||||
|
addOptionAnswer,
|
||||||
setAnswer,
|
setAnswer,
|
||||||
setComment,
|
setComment,
|
||||||
setDatetime,
|
setDatetime,
|
||||||
@ -23,7 +29,7 @@ const MyModal = ({
|
|||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="modal fade myModal" className={classes.myModal} id="exampleModal" tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
|
<div class="modal fade myModal" className={classes.myModal} id="answerModal" 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}>
|
||||||
<div class="modal-content" className={classes.myModal__dialog__content}>
|
<div class="modal-content" className={classes.myModal__dialog__content}>
|
||||||
<div class="modal-header" className={classes.myModal__dialog__content__header}>
|
<div class="modal-header" className={classes.myModal__dialog__content__header}>
|
||||||
@ -51,6 +57,24 @@ const MyModal = ({
|
|||||||
<span className={classes.myModal__dialog__content__body__comment__title}>Комментарий</span>
|
<span className={classes.myModal__dialog__content__body__comment__title}>Комментарий</span>
|
||||||
<textarea className={classes.myModal__dialog__content__body__comment__text} value={comment} onChange={event => setComment(event.target.value)}></textarea>
|
<textarea className={classes.myModal__dialog__content__body__comment__text} value={comment} onChange={event => setComment(event.target.value)}></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
{[3, 4, 5].find(item => item === currentTypeAnswer) ? <div className={classes.myModal__dialog__content__body__answerOptions}>
|
||||||
|
<span className={classes.myModal__dialog__content__body__answerOptions__title}>Варианты ответа</span>
|
||||||
|
<div className={classes.myModal__dialog__content__body__answerOptions__list}>
|
||||||
|
{optionAnswer.map((item, i) =>
|
||||||
|
<span key={i} className={classes.myModal__dialog__content__body__answerOptions__list__answer}>{item.id}) {item.text}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className={classes.myModal__dialog__content__body__answerOptions__text}
|
||||||
|
value={currentOptionAnswer}
|
||||||
|
onChange={event => setCurrentOptionAnswer(event.target.value)}/>
|
||||||
|
<MyButton
|
||||||
|
text={'Добавить'}
|
||||||
|
click={addOptionAnswer}
|
||||||
|
backgroundColor={'rgb(200, 200, 200)'}
|
||||||
|
otherStyle={{padding: '1% 2%'}}/>
|
||||||
|
</div> : <div></div>}
|
||||||
<div className={classes.myModal__dialog__content__body__mandatory}>
|
<div className={classes.myModal__dialog__content__body__mandatory}>
|
||||||
<span className={classes.myModal__dialog__content__body__mandatory__title}>Обязательный вопрос</span>
|
<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)}/>
|
<input className={classes.myModal__dialog__content__body__mandatory__choice} type="checkbox" checked={mandatory} onChange={() => setMandatory(!mandatory)}/>
|
||||||
@ -70,4 +94,4 @@ const MyModal = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MyModal;
|
export default AnswerModal;
|
@ -9,6 +9,9 @@ const MyButton = (props) => {
|
|||||||
type="button"
|
type="button"
|
||||||
class={props.class}
|
class={props.class}
|
||||||
onClick={props.click}
|
onClick={props.click}
|
||||||
|
data-bs-target={props.target}
|
||||||
|
data-bs-toggle={props.toggle}
|
||||||
|
data-bs-dismiss={props.dismiss}
|
||||||
style={{backgroundColor: props.backgroundColor, ...props.otherStyle}}>
|
style={{backgroundColor: props.backgroundColor, ...props.otherStyle}}>
|
||||||
{props.text}
|
{props.text}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link, BrowserRouter, useNavigate } from "react-router-dom";
|
||||||
import classes from "../assets/styles/components/navbar.module.scss"
|
import classes from "../assets/styles/components/navbar.module.scss"
|
||||||
|
|
||||||
const NavBar = () => {
|
const NavBar = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.main}>
|
<div className={classes.main}>
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
{/* <Link to={'/new'}>New Form</Link>
|
|
||||||
<Link to={'/forms'}>Forms</Link> */}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
26
src/components/PreviewModal.jsx
Normal file
26
src/components/PreviewModal.jsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import React from "react";
|
||||||
|
import classes from "../assets/styles/components/previewModal.module.scss";
|
||||||
|
// import MyButton from "./MyButton.jsx";
|
||||||
|
|
||||||
|
const PreviewModal = () => {
|
||||||
|
return (
|
||||||
|
<div class="modal fade" 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}>
|
||||||
|
<div class="modal-content" className={classes.myModal__dialog__content}>
|
||||||
|
<div class="modal-header" className={classes.myModal__dialog__content__header}>
|
||||||
|
<h5 class="modal-title" id="exampleModalLabel">Форма</h5>
|
||||||
|
<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}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer" className={classes.myModal__dialog__content__footer}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PreviewModal;
|
@ -21,7 +21,7 @@ const Forms = () => {
|
|||||||
.then((r) => {
|
.then((r) => {
|
||||||
console.log(r);
|
console.log(r);
|
||||||
setStateLoading(false);
|
setStateLoading(false);
|
||||||
navigate("/new");
|
navigate("/forms/edit");
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@ import React, { useState, useContext } from "react";
|
|||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
import classes from "../assets/styles/newForm.module.scss";
|
import classes from "../assets/styles/newForm.module.scss";
|
||||||
import MyButton from "../components/MyButton.jsx";
|
import MyButton from "../components/MyButton.jsx";
|
||||||
import MyModal from "../components/MyModal.jsx";
|
import AnswerModal from "../components/AnswerModal.jsx";
|
||||||
|
import PreviewModal from "../components/PreviewModal.jsx"
|
||||||
import { FormsData } from "../context";
|
import { FormsData } from "../context";
|
||||||
|
|
||||||
const NewForm = () => {
|
const NewForm = () => {
|
||||||
@ -20,8 +21,10 @@ const NewForm = () => {
|
|||||||
const [comment, setComment] = useState("");
|
const [comment, setComment] = useState("");
|
||||||
const [datetime, setDatetime] = useState("");
|
const [datetime, setDatetime] = useState("");
|
||||||
const [mandatory, setMandatory] = useState(false);
|
const [mandatory, setMandatory] = useState(false);
|
||||||
|
const [optionAnswer, setOptionAnswer] = useState([]);
|
||||||
const [file, setFile] = useState([]);
|
const [file, setFile] = useState([]);
|
||||||
const [currentTypeAnswer, setCurrentTypeAnswer] = useState("");
|
const [currentTypeAnswer, setCurrentTypeAnswer] = useState("");
|
||||||
|
const [currentOptionAnswer, setCurrentOptionAnswer] = useState("");
|
||||||
|
|
||||||
const [newForm, setNewForm] = useState(location.state ? location.state.data : []);
|
const [newForm, setNewForm] = useState(location.state ? location.state.data : []);
|
||||||
|
|
||||||
@ -47,11 +50,21 @@ const NewForm = () => {
|
|||||||
setAnswer("");
|
setAnswer("");
|
||||||
setComment("");
|
setComment("");
|
||||||
setDatetime("");
|
setDatetime("");
|
||||||
setFile("");
|
setOptionAnswer([])
|
||||||
|
setFile([]);
|
||||||
setCurrentTypeAnswer("");
|
setCurrentTypeAnswer("");
|
||||||
|
setCurrentOptionAnswer("")
|
||||||
setMandatory(false);
|
setMandatory(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addOptionAnswer(text) {
|
||||||
|
setOptionAnswer([...optionAnswer, {
|
||||||
|
id: nextID(optionAnswer),
|
||||||
|
text: currentOptionAnswer
|
||||||
|
}]);
|
||||||
|
setCurrentOptionAnswer("");
|
||||||
|
}
|
||||||
|
|
||||||
function editAnswerByForm(id) {
|
function editAnswerByForm(id) {
|
||||||
const obj = newForm.find(item => item.id === id);
|
const obj = newForm.find(item => item.id === id);
|
||||||
setAnswer(obj.answer);
|
setAnswer(obj.answer);
|
||||||
@ -59,7 +72,8 @@ const NewForm = () => {
|
|||||||
setDatetime(obj.datetime);
|
setDatetime(obj.datetime);
|
||||||
setFile(obj.file);
|
setFile(obj.file);
|
||||||
setCurrentTypeAnswer(obj.typeAnswer);
|
setCurrentTypeAnswer(obj.typeAnswer);
|
||||||
setMandatory(obj.mandatory)
|
setOptionAnswer(obj.optionAnswer);
|
||||||
|
setMandatory(obj.mandatory);
|
||||||
setStateModal(id);
|
setStateModal(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +85,7 @@ const NewForm = () => {
|
|||||||
item.datetime = datetime;
|
item.datetime = datetime;
|
||||||
item.file = file;
|
item.file = file;
|
||||||
item.mandatory = mandatory;
|
item.mandatory = mandatory;
|
||||||
|
item.optionAnswer = optionAnswer;
|
||||||
item.typeAnswer = currentTypeAnswer;
|
item.typeAnswer = currentTypeAnswer;
|
||||||
}
|
}
|
||||||
return item
|
return item
|
||||||
@ -86,6 +101,7 @@ const NewForm = () => {
|
|||||||
comment: comment,
|
comment: comment,
|
||||||
datetime: datetime,
|
datetime: datetime,
|
||||||
mandatory: mandatory,
|
mandatory: mandatory,
|
||||||
|
optionAnswer: optionAnswer,
|
||||||
file: file
|
file: file
|
||||||
}]);
|
}]);
|
||||||
cleanStates();
|
cleanStates();
|
||||||
@ -126,37 +142,44 @@ const NewForm = () => {
|
|||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
<div className={classes.header}>
|
<div className={classes.header}>
|
||||||
<div className={classes.header__listBtn}>
|
<div className={classes.header__listBtn}>
|
||||||
|
<MyButton text={'Предпросмотр'} backgroundColor={'rgb(225, 225, 225)'} toggle={"modal"} target={"#previewModal"}/>
|
||||||
<MyButton text={'Опубликовать'} click={location.state ? updateFormByForms : saveForm}/>
|
<MyButton text={'Опубликовать'} click={location.state ? updateFormByForms : saveForm}/>
|
||||||
<MyButton text={<i class="fa-solid fa-ellipsis-vertical"></i>} click={() => console.log(newForm)} backgroundColor={'rgb(225, 225, 225)'}/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.content}>
|
<div className={classes.content}>
|
||||||
<div className={classes.content__listQuestion}>
|
<div className={classes.content__listQuestion}>
|
||||||
<div className={classes.content__listQuestion__list}>
|
<div className={classes.content__listQuestion__list}>
|
||||||
{listTypeAnswer.map((item, i) =>
|
{listTypeAnswer.map((item, i) =>
|
||||||
<div className={classes.content__listQuestion__list__item} data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={() => setCurrentTypeAnswer(item.id)} key={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>
|
<span>{item.text}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MyModal
|
<PreviewModal />
|
||||||
|
|
||||||
|
<AnswerModal
|
||||||
stateModal={stateModal}
|
stateModal={stateModal}
|
||||||
currentTypeAnswer={currentTypeAnswer}
|
currentTypeAnswer={currentTypeAnswer}
|
||||||
answer={answer}
|
answer={answer}
|
||||||
comment={comment}
|
comment={comment}
|
||||||
mandatory={mandatory}
|
mandatory={mandatory}
|
||||||
|
optionAnswer={optionAnswer}
|
||||||
|
setOptionAnswer={setOptionAnswer}
|
||||||
datetime={datetime}
|
datetime={datetime}
|
||||||
file={file}
|
file={file}
|
||||||
|
currentOptionAnswer={currentOptionAnswer}
|
||||||
listTypeAnswer={listTypeAnswer}
|
listTypeAnswer={listTypeAnswer}
|
||||||
setAnswer={setAnswer}
|
setAnswer={setAnswer}
|
||||||
setComment={setComment}
|
setComment={setComment}
|
||||||
setDatetime={setDatetime}
|
setDatetime={setDatetime}
|
||||||
setFile={setFile}
|
setFile={setFile}
|
||||||
|
setCurrentOptionAnswer={setCurrentOptionAnswer}
|
||||||
setMandatory={setMandatory}
|
setMandatory={setMandatory}
|
||||||
cleanStates={cleanStates}
|
cleanStates={cleanStates}
|
||||||
saveStates={saveStates}
|
saveStates={saveStates}
|
||||||
|
addOptionAnswer={addOptionAnswer}
|
||||||
updateAnswerByForm={updateAnswerByForm}
|
updateAnswerByForm={updateAnswerByForm}
|
||||||
setCurrentTypeAnswer={setCurrentTypeAnswer}/>
|
setCurrentTypeAnswer={setCurrentTypeAnswer}/>
|
||||||
|
|
||||||
@ -182,7 +205,7 @@ const NewForm = () => {
|
|||||||
setDropElem(Number(event.target.id))
|
setDropElem(Number(event.target.id))
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onDrop={(event) => {
|
onDrop={() => {
|
||||||
const currentElem = newForm[dragElem]
|
const currentElem = newForm[dragElem]
|
||||||
const tNewForm = [...newForm]
|
const tNewForm = [...newForm]
|
||||||
if (dragElem > dropElem) {
|
if (dragElem > dropElem) {
|
||||||
|
@ -14,7 +14,7 @@ const router = createBrowserRouter([
|
|||||||
element: <Forms/>,
|
element: <Forms/>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/new',
|
path: '/forms/edit/',
|
||||||
element: <NewForm/>
|
element: <NewForm/>
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -5,7 +5,6 @@ const path = require('path');
|
|||||||
module.exports = (env) => {
|
module.exports = (env) => {
|
||||||
|
|
||||||
const isDev = env.mode === 'development';
|
const isDev = env.mode === 'development';
|
||||||
console.log(env.mode ?? 'development', isDev ? 'style-loader' : 'Mini')
|
|
||||||
|
|
||||||
const cssLoader = {
|
const cssLoader = {
|
||||||
loader: "css-loader",
|
loader: "css-loader",
|
||||||
@ -18,9 +17,16 @@ module.exports = (env) => {
|
|||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
mode: env.mode ?? 'development',
|
mode: env.mode ?? 'development',
|
||||||
|
performance: {
|
||||||
|
hints: false,
|
||||||
|
maxEntrypointSize: 512000,
|
||||||
|
maxAssetSize: 512000
|
||||||
|
},
|
||||||
entry: './src/index.js',
|
entry: './src/index.js',
|
||||||
output: {
|
output: {
|
||||||
filename: '[name].[contenthash].js',
|
// filename: '[name].[contenthash].js',
|
||||||
|
filename: 'bundle.js',
|
||||||
|
publicPath: '/',
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
clean: true
|
clean: true
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user