step 228
This commit is contained in:
		@@ -30,7 +30,10 @@
 | 
			
		||||
    "@fortawesome/fontawesome-svg-core": "^6.5.1",
 | 
			
		||||
    "@fortawesome/free-solid-svg-icons": "^6.5.1",
 | 
			
		||||
    "@fortawesome/react-fontawesome": "^0.2.0",
 | 
			
		||||
    "@popperjs/core": "^2.11.8",
 | 
			
		||||
    "bootstrap": "^5.3.3",
 | 
			
		||||
    "react": "^18.2.0",
 | 
			
		||||
    "react-bootstrap": "^2.10.1",
 | 
			
		||||
    "react-dom": "^18.2.0",
 | 
			
		||||
    "react-router-dom": "^6.22.1"
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,11 @@
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
    <title>Document</title>
 | 
			
		||||
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
 | 
			
		||||
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <div id="root"></div>
 | 
			
		||||
    <div id="root" style="height: 100%; width: 100%;"></div>
 | 
			
		||||
    <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>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										28
									
								
								src/App.jsx
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/App.jsx
									
									
									
									
									
								
							@@ -1,21 +1,31 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
import { RouterProvider } from "react-router-dom";
 | 
			
		||||
import {FormsData} from "./context";
 | 
			
		||||
import router from "./router/router"
 | 
			
		||||
import classes from "./assets/styles/app.module.scss"
 | 
			
		||||
import NavBar from "./components/NavBar.jsx";
 | 
			
		||||
import 'bootstrap/dist/css/bootstrap.min.css';
 | 
			
		||||
 | 
			
		||||
const App = () => {
 | 
			
		||||
    const [forms, setForms] = useState([])
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={classes.main}>
 | 
			
		||||
            <div className={classes.container}>
 | 
			
		||||
                <div className={classes.header}>
 | 
			
		||||
                    <NavBar/>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className={classes.content}>
 | 
			
		||||
                    <RouterProvider router={router}/>
 | 
			
		||||
        <FormsData.Provider value={{
 | 
			
		||||
            forms,
 | 
			
		||||
            setForms
 | 
			
		||||
        }}>
 | 
			
		||||
            <div className={classes.main}>
 | 
			
		||||
                <div className={classes.container}>
 | 
			
		||||
                    <div className={classes.header}>
 | 
			
		||||
                        <NavBar/>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className={classes.content}>
 | 
			
		||||
                        <RouterProvider router={router}/>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        </FormsData.Provider>
 | 
			
		||||
        
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
@import url('./base.css');
 | 
			
		||||
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
 | 
			
		||||
 | 
			
		||||
.main {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
@@ -13,7 +14,7 @@
 | 
			
		||||
.header {
 | 
			
		||||
    background-color: rgb(240, 240, 240);
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 50px;
 | 
			
		||||
    height: 10%;
 | 
			
		||||
    box-shadow: 0 0 5px 1px rgb(210, 210, 210);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,12 @@
 | 
			
		||||
.main {
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    button {
 | 
			
		||||
        font-size: 15px;
 | 
			
		||||
        padding: 10%;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        padding: .40em 1.2rem;
 | 
			
		||||
        color: white;
 | 
			
		||||
        background-color: rgb(150, 209, 158);
 | 
			
		||||
        border-radius: 5px;
 | 
			
		||||
        font-family: "Montserrat", sans-serif;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,12 @@
 | 
			
		||||
.main {
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    input {
 | 
			
		||||
        
 | 
			
		||||
        border: 1px solid rgb(180, 180, 180);
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        border-radius: 5px;
 | 
			
		||||
        font-family: "Montserrat", sans-serif;
 | 
			
		||||
        padding: 0 3px;
 | 
			
		||||
        color: rgb(40, 40, 40);
 | 
			
		||||
        font-size: 15px;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								src/assets/styles/components/myModal.module.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/assets/styles/components/myModal.module.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
.myModal {
 | 
			
		||||
    &__dialog {
 | 
			
		||||
        &__content {
 | 
			
		||||
            &__header {
 | 
			
		||||
                display: flex;
 | 
			
		||||
                justify-content: space-between;
 | 
			
		||||
                align-items: center;
 | 
			
		||||
                padding: 3%;
 | 
			
		||||
                h5 {
 | 
			
		||||
                    display: block;
 | 
			
		||||
                }
 | 
			
		||||
                select {
 | 
			
		||||
                    display: block;
 | 
			
		||||
                    font-size: 15px;
 | 
			
		||||
                    font-family: "Montserrat", sans-serif;
 | 
			
		||||
                    border: 1px solid rgb(200, 200, 200);
 | 
			
		||||
                    padding: 5px;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &__body {
 | 
			
		||||
                &__answer {
 | 
			
		||||
                    &__title {
 | 
			
		||||
                        display: block;
 | 
			
		||||
                        font-size: 15px;
 | 
			
		||||
                        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%;
 | 
			
		||||
                    }
 | 
			
		||||
                    &__file {
 | 
			
		||||
                        margin-top: 10px;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                &__comment {
 | 
			
		||||
                    margin-top: 5%;
 | 
			
		||||
                    &__title {
 | 
			
		||||
                        display: block;
 | 
			
		||||
                        font-size: 15px;
 | 
			
		||||
                        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%;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                &__time {
 | 
			
		||||
                    margin-top: 5%;
 | 
			
		||||
                    span {
 | 
			
		||||
                        display: block;
 | 
			
		||||
                        font-size: 15px;
 | 
			
		||||
                        font-family: "Montserrat", sans-serif;
 | 
			
		||||
                    }
 | 
			
		||||
                    input {
 | 
			
		||||
                        display: block;
 | 
			
		||||
                        font-size: 15px;
 | 
			
		||||
                        font-family: "Montserrat", sans-serif;
 | 
			
		||||
                        border: 1px solid rgb(200, 200, 200);
 | 
			
		||||
                        padding: 1%;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -7,17 +7,71 @@
 | 
			
		||||
.wrapper {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    border: 1px solid red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.panel {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 30px;
 | 
			
		||||
    height: 10%;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    padding: 0 5%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.listForms {
 | 
			
		||||
 | 
			
		||||
    box-shadow: 0 0 5px 1px rgb(200, 200, 200);
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    margin-top: 5%;
 | 
			
		||||
    height: 70%;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    &__columns {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        justify-content: space-around;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        height: 15%;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        border-bottom: 1px solid rgb(220, 220, 220);
 | 
			
		||||
        &__item {
 | 
			
		||||
            font-size: 15px;
 | 
			
		||||
            font-family: "Montserrat", sans-serif;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    &__forms {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: 85%;
 | 
			
		||||
        overflow-y: auto;
 | 
			
		||||
        &::-webkit-scrollbar {
 | 
			
		||||
            width: 7px;
 | 
			
		||||
        }
 | 
			
		||||
        &::-webkit-scrollbar-thumb {
 | 
			
		||||
            background-color: rgb(200, 200, 200);
 | 
			
		||||
        }
 | 
			
		||||
        &__item {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            justify-content: space-around;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            height: 25%;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
            font-family: "Montserrat", sans-serif;
 | 
			
		||||
            &:hover {
 | 
			
		||||
                background-color: rgba(240, 240, 240, 0.8);
 | 
			
		||||
            }
 | 
			
		||||
            &__title {
 | 
			
		||||
                width: 33.3%;
 | 
			
		||||
                text-align: center;
 | 
			
		||||
                cursor: pointer;
 | 
			
		||||
                &:hover {
 | 
			
		||||
                    text-decoration: underline;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &__answers  {
 | 
			
		||||
                width: 33.3%;
 | 
			
		||||
                text-align: center;
 | 
			
		||||
            }
 | 
			
		||||
            &__update {
 | 
			
		||||
                width: 33.3%;
 | 
			
		||||
                text-align: center;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										131
									
								
								src/assets/styles/newForm.module.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								src/assets/styles/newForm.module.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
.main {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    padding: 4% 8%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wrapper {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.header {
 | 
			
		||||
    text-align: right;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: end;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 8%;
 | 
			
		||||
    &__listBtn {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
        width: 20%;
 | 
			
		||||
    } 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.content {
 | 
			
		||||
    margin-top: 3%;
 | 
			
		||||
    height: 85%;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
    &__listQuestion {
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        width: 25%;
 | 
			
		||||
        &__list {
 | 
			
		||||
            height: 100%;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
            &__item {
 | 
			
		||||
                height: 12.5%;
 | 
			
		||||
                width: 100%;
 | 
			
		||||
                display: flex;
 | 
			
		||||
                align-items: center;
 | 
			
		||||
                padding: 0 5px;
 | 
			
		||||
                cursor: pointer;
 | 
			
		||||
 | 
			
		||||
                &:hover {
 | 
			
		||||
                    background-color: rgba(230, 230, 230, 0.6);
 | 
			
		||||
                }
 | 
			
		||||
                span {
 | 
			
		||||
                    display: block;
 | 
			
		||||
                    font-size: 15px;
 | 
			
		||||
                    font-family: "Montserrat", sans-serif;
 | 
			
		||||
                }                
 | 
			
		||||
            }
 | 
			
		||||
            &__item:not(:last-child) {
 | 
			
		||||
                border-bottom: 1px solid rgb(220, 220, 220);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    &__newForm {
 | 
			
		||||
        box-shadow: 0 0 5px 1px rgb(220, 220, 220);
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        width: 75%;
 | 
			
		||||
        &__title {
 | 
			
		||||
            padding: 1%;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
            height: 10%;
 | 
			
		||||
            h3 {
 | 
			
		||||
                font-size: 20px;
 | 
			
		||||
                font-family: "Montserrat", sans-serif;
 | 
			
		||||
                color: rgb(80, 80, 80);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        &__list {
 | 
			
		||||
            overflow-y: auto;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
            height: 90%;
 | 
			
		||||
            &::-webkit-scrollbar {
 | 
			
		||||
                width: 7px;
 | 
			
		||||
            }
 | 
			
		||||
            &::-webkit-scrollbar-thumb {
 | 
			
		||||
                background-color: rgb(200, 200, 200);
 | 
			
		||||
            }
 | 
			
		||||
            &__item {
 | 
			
		||||
                padding: 1%;
 | 
			
		||||
                width: 100%;
 | 
			
		||||
                height: 25%;
 | 
			
		||||
                border-bottom: 1px solid rgb(220, 220, 220);
 | 
			
		||||
                display: flex;
 | 
			
		||||
                justify-content: space-between;
 | 
			
		||||
                align-items: center;
 | 
			
		||||
                &:hover {
 | 
			
		||||
                    background-color: rgba(230, 230, 230, 0.6);
 | 
			
		||||
                    cursor: pointer;
 | 
			
		||||
                }
 | 
			
		||||
                &__answer {
 | 
			
		||||
                    width: 90%;
 | 
			
		||||
                    span {
 | 
			
		||||
                        display: block;
 | 
			
		||||
                    }
 | 
			
		||||
                    span:first-child {
 | 
			
		||||
                        font-size: 15px;
 | 
			
		||||
                        font-family: "Montserrat", sans-serif;
 | 
			
		||||
                        color: rgb(80, 80, 80);
 | 
			
		||||
                    }
 | 
			
		||||
                    span:last-child {
 | 
			
		||||
                        font-size: 12px;
 | 
			
		||||
                        font-family: "Montserrat", sans-serif;
 | 
			
		||||
                        color: rgb(180, 180, 180);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                &__btn {
 | 
			
		||||
                    width: 10%;
 | 
			
		||||
                    display: flex;
 | 
			
		||||
                    justify-content: space-around;
 | 
			
		||||
                    align-items: center;
 | 
			
		||||
                    i {
 | 
			
		||||
                        display: block;
 | 
			
		||||
                    }
 | 
			
		||||
                    i:first-child:hover {
 | 
			
		||||
                        color: rgb(42, 64, 187);
 | 
			
		||||
                    }
 | 
			
		||||
                    i:last-child:hover {
 | 
			
		||||
                        color: rgb(199, 73, 73);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,10 +1,17 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import classes from "../assets/styles/components/myButton.module.scss"
 | 
			
		||||
 | 
			
		||||
const MyButton = () => {
 | 
			
		||||
const MyButton = (props) => {
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={classes.main}>
 | 
			
		||||
            <button type="button">Создать</button>
 | 
			
		||||
            <button 
 | 
			
		||||
                type="button"
 | 
			
		||||
                class={props.class} 
 | 
			
		||||
                onClick={props.click}
 | 
			
		||||
                style={{backgroundColor: props.backgroundColor, ...props.otherStyle}}>
 | 
			
		||||
                    {props.text}
 | 
			
		||||
            </button>
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import classes from "../assets/styles/components/myInput.module.scss"
 | 
			
		||||
 | 
			
		||||
const MyInput = () => {
 | 
			
		||||
const MyInput = (props) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={classes.main}>
 | 
			
		||||
            <input type="text" />
 | 
			
		||||
            <input type="text" placeholder={props.placeholder}/>
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										67
									
								
								src/components/MyModal.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/components/MyModal.jsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import classes from "../assets/styles/components/myModal.module.scss";
 | 
			
		||||
 | 
			
		||||
const MyModal = ({
 | 
			
		||||
    cleanStates, 
 | 
			
		||||
    currentTypeAnswer, 
 | 
			
		||||
    updateAnswerByForm,
 | 
			
		||||
    stateModal,
 | 
			
		||||
    saveStates, 
 | 
			
		||||
    answer, 
 | 
			
		||||
    file,
 | 
			
		||||
    listTypeAnswer,
 | 
			
		||||
    comment, 
 | 
			
		||||
    datetime,
 | 
			
		||||
    setAnswer,
 | 
			
		||||
    setComment,
 | 
			
		||||
    setDatetime,
 | 
			
		||||
    setCurrentTypeAnswer,
 | 
			
		||||
    setFile
 | 
			
		||||
    }) => {
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    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-dialog myModal__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>
 | 
			
		||||
                        <select value={currentTypeAnswer} onChange={e => setCurrentTypeAnswer(Number(e.target.value))}>
 | 
			
		||||
                            {listTypeAnswer.map((item, i) => 
 | 
			
		||||
                                <option value={item.id} key={i}>{item.text}</option>
 | 
			
		||||
                            )}
 | 
			
		||||
                        </select>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="modal-body" className={classes.myModal__dialog__content__body}>
 | 
			
		||||
                        <div className={classes.myModal__dialog__content__body__answer}>
 | 
			
		||||
                            <span className={classes.myModal__dialog__content__body__answer__title}>Вопрос</span>
 | 
			
		||||
                            <textarea className={classes.myModal__dialog__content__body__answer__text} value={answer} onChange={event => setAnswer(event.target.value)}></textarea>
 | 
			
		||||
                            <input 
 | 
			
		||||
                                type="file" 
 | 
			
		||||
                                multiple 
 | 
			
		||||
                                accept="image/*,image/jpeg,video/mp4,video/x-m4v,video/*" 
 | 
			
		||||
                                className={classes.myModal__dialog__content__body__answer__file}
 | 
			
		||||
                                value={file}
 | 
			
		||||
                                onChange={event => setFile(event.target.value)}
 | 
			
		||||
                            ></input>                         
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div className={classes.myModal__dialog__content__body__comment}>
 | 
			
		||||
                            <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>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div className={classes.myModal__dialog__content__body__time}>
 | 
			
		||||
                            <span>Дедлайн выполнения</span>
 | 
			
		||||
                            <input type="datetime-local" value={datetime} onChange={event => setDatetime(event.target.value)}/>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="modal-footer myModal__dialog__content__footer" className={classes.myModal__dialog__content__footer}>
 | 
			
		||||
                        <button type="button" class="btn btn-light" data-bs-dismiss="modal" onClick={cleanStates}>Отмена</button>
 | 
			
		||||
                        <button type="button" class="btn" style={{color: 'white', backgroundColor: 'rgb(150, 209, 158)'}} data-bs-dismiss="modal" onClick={stateModal ? updateAnswerByForm : saveStates}>Сохранить</button>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default MyModal;
 | 
			
		||||
@@ -1,13 +1,15 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { Link } from "react-router-dom";
 | 
			
		||||
import classes from "../assets/styles/components/navbar.module.scss"
 | 
			
		||||
 | 
			
		||||
const NavBar = () => {
 | 
			
		||||
    return (
 | 
			
		||||
        <navbar className={classes.main}>
 | 
			
		||||
        <div className={classes.main}>
 | 
			
		||||
            <div className={classes.wrapper}>
 | 
			
		||||
                
 | 
			
		||||
                {/* <Link to={'/new'}>New Form</Link>
 | 
			
		||||
                <Link to={'/forms'}>Forms</Link> */}
 | 
			
		||||
            </div>
 | 
			
		||||
        </navbar>
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								src/context/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/context/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
import { createContext } from "react";
 | 
			
		||||
 | 
			
		||||
export const FormsData = createContext([])
 | 
			
		||||
							
								
								
									
										0
									
								
								src/hooks/dragDrop.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/hooks/dragDrop.js
									
									
									
									
									
										Normal file
									
								
							@@ -1,17 +1,67 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import React, { useState, useContext } from "react";
 | 
			
		||||
import { useNavigate } from 'react-router-dom';
 | 
			
		||||
import classes from "../assets/styles/forms.module.scss"
 | 
			
		||||
import MyButton from "../components/MyButton.jsx";
 | 
			
		||||
import MyInput from "../components/MyInput.jsx";
 | 
			
		||||
import { FormsData } from "../context";
 | 
			
		||||
 | 
			
		||||
const Forms = () => {
 | 
			
		||||
    const navigate = useNavigate()
 | 
			
		||||
    const {forms, setForms} = useContext(FormsData);
 | 
			
		||||
    const [stateLoading, setStateLoading] = useState(false)
 | 
			
		||||
 | 
			
		||||
    const response = ms => {
 | 
			
		||||
        return new Promise(r => setTimeout(() => r('response end'), ms))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createForm() {
 | 
			
		||||
        setStateLoading(true);
 | 
			
		||||
        // Эмуляция пост запроса
 | 
			
		||||
        response(1000)
 | 
			
		||||
            .then((r) => {
 | 
			
		||||
                console.log(r); 
 | 
			
		||||
                setStateLoading(false);
 | 
			
		||||
                navigate("/new");
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function editForm(item) {
 | 
			
		||||
        navigate("/new", { 
 | 
			
		||||
            state: {
 | 
			
		||||
                id: item.id,
 | 
			
		||||
                data: item.listAnswer
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={classes.main}>
 | 
			
		||||
            <div className={classes.wrapper}>
 | 
			
		||||
                <div className={classes.panel}>
 | 
			
		||||
                    <MyInput/>
 | 
			
		||||
                    <MyButton/>
 | 
			
		||||
                    <MyInput placeholder={'Поиск...'}/>
 | 
			
		||||
                    <MyButton click={createForm} otherStyle={{width: '200px'}} text={
 | 
			
		||||
                        stateLoading ? <div class="spinner-border text-light" role="status">
 | 
			
		||||
                            <span class="visually-hidden">Загрузка...</span>
 | 
			
		||||
                        </div> : 'Создать'
 | 
			
		||||
                    }/>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className={classes.listForms}>
 | 
			
		||||
                    <div className={classes.listForms__columns}>
 | 
			
		||||
                        <div className={classes.listForms__columns__item}>Название</div>
 | 
			
		||||
                        <div className={classes.listForms__columns__item}>Ответы</div>
 | 
			
		||||
                        <div className={classes.listForms__columns__item}>Изменения</div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className={classes.listForms__forms}>
 | 
			
		||||
                        {forms.map((item, i) =>
 | 
			
		||||
                            <div className={classes.listForms__forms__item} key={i}>
 | 
			
		||||
                                <div className={classes.listForms__forms__item__title} onClick={() => editForm(item)}>{item.title}</div>
 | 
			
		||||
                                <div className={classes.listForms__forms__item__answers}>{item.answers}</div>
 | 
			
		||||
                                <div className={classes.listForms__forms__item__update}>{item.update}</div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        )}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className={classes.listForms}></div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,213 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import React, { useState, useContext } from "react";
 | 
			
		||||
import { useNavigate, useLocation } from 'react-router-dom';
 | 
			
		||||
import classes from "../assets/styles/newForm.module.scss";
 | 
			
		||||
import MyButton from "../components/MyButton.jsx";
 | 
			
		||||
import MyModal from "../components/MyModal.jsx";
 | 
			
		||||
import { FormsData } from "../context";
 | 
			
		||||
 | 
			
		||||
const NewForm = () => {
 | 
			
		||||
    const navigate = useNavigate();
 | 
			
		||||
    const location = useLocation();
 | 
			
		||||
    const [dragElem, setDragElem] = useState(null);
 | 
			
		||||
    const [dropElem, setDropElem] = useState(null);
 | 
			
		||||
    
 | 
			
		||||
    const {forms, setForms} = useContext(FormsData);
 | 
			
		||||
 | 
			
		||||
    const nextID = (list) => {
 | 
			
		||||
        return list.length ? list.at(-1).id + 1 : 1
 | 
			
		||||
    };
 | 
			
		||||
    const [answer, setAnswer] = useState("");
 | 
			
		||||
    const [comment, setComment] = useState("");
 | 
			
		||||
    const [datetime, setDatetime] = useState("");
 | 
			
		||||
    const [file, setFile] = useState([]);
 | 
			
		||||
    const [currentTypeAnswer, setCurrentTypeAnswer] = useState("");
 | 
			
		||||
 | 
			
		||||
    const [newForm, setNewForm] = useState(location.state ? location.state.data : []);
 | 
			
		||||
 | 
			
		||||
    const [stateModal, setStateModal] = useState(false)
 | 
			
		||||
 | 
			
		||||
    const [listTypeAnswer, setListTypeAnswer] = useState([
 | 
			
		||||
        {id: 1, text: 'Краткий ответ'},
 | 
			
		||||
        {id: 2, text: 'Расширенный ответ'},
 | 
			
		||||
        {id: 3, text: 'Выбор из вариантов'},
 | 
			
		||||
        {id: 4, text: 'Множественный выбор'},
 | 
			
		||||
        {id: 5, text: 'Выпадающий список'},
 | 
			
		||||
        {id: 6, text: 'Да/Нет'},
 | 
			
		||||
        {id: 7, text: 'Файл'},
 | 
			
		||||
        {id: 8, text: 'Дата'}
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    function removeAnswerByForm(id) {
 | 
			
		||||
        setNewForm([...newForm.filter(item => item.id !== id)]); 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function cleanStates() {
 | 
			
		||||
        setStateModal(false)
 | 
			
		||||
        setAnswer("");
 | 
			
		||||
        setComment("");
 | 
			
		||||
        setDatetime("");
 | 
			
		||||
        setFile("");
 | 
			
		||||
        setCurrentTypeAnswer("");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function editAnswerByForm(id) {       
 | 
			
		||||
        const obj = newForm.find(item => item.id === id);
 | 
			
		||||
        setAnswer(obj.answer);
 | 
			
		||||
        setComment(obj.comment);
 | 
			
		||||
        setDatetime(obj.datetime);
 | 
			
		||||
        setFile(obj.file);
 | 
			
		||||
        setCurrentTypeAnswer(obj.typeAnswer);
 | 
			
		||||
        setStateModal(id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateAnswerByForm() {
 | 
			
		||||
        console.log(currentTypeAnswer)
 | 
			
		||||
        setNewForm(newForm.map(item => {
 | 
			
		||||
            if (item.id === stateModal) {
 | 
			
		||||
                item.answer = answer;
 | 
			
		||||
                item.comment = comment;
 | 
			
		||||
                item.datetime = datetime;
 | 
			
		||||
                item.file = file;
 | 
			
		||||
                item.typeAnswer = currentTypeAnswer;
 | 
			
		||||
            }
 | 
			
		||||
            return item
 | 
			
		||||
        }))
 | 
			
		||||
        cleanStates()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function saveStates() {
 | 
			
		||||
        setNewForm([...newForm, {
 | 
			
		||||
            id: nextID(newForm),
 | 
			
		||||
            answer: answer,
 | 
			
		||||
            typeAnswer: currentTypeAnswer,
 | 
			
		||||
            comment: comment,
 | 
			
		||||
            datetime: datetime,
 | 
			
		||||
            file: file
 | 
			
		||||
        }]);
 | 
			
		||||
        cleanStates();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateFormByForms() {
 | 
			
		||||
        setForms(
 | 
			
		||||
            forms.map(item => {
 | 
			
		||||
                if (item.id === location.state.id) {
 | 
			
		||||
                    item.title = 'Новая форма',
 | 
			
		||||
                    item.answers = 'Без изменений',
 | 
			
		||||
                    item.update = '01/01/24',
 | 
			
		||||
                    item.listAnswer = newForm                
 | 
			
		||||
                }
 | 
			
		||||
                return item
 | 
			
		||||
            })
 | 
			
		||||
        )
 | 
			
		||||
        cleanStates();
 | 
			
		||||
        navigate("/forms");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function saveForm() {
 | 
			
		||||
        setForms(
 | 
			
		||||
            [...forms, {
 | 
			
		||||
                id: nextID(forms),
 | 
			
		||||
                title: 'Новая форма',
 | 
			
		||||
                answers: 'Без изменений',
 | 
			
		||||
                update: '01/01/24',
 | 
			
		||||
                listAnswer: newForm
 | 
			
		||||
            }]
 | 
			
		||||
        );
 | 
			
		||||
        cleanStates();
 | 
			
		||||
        navigate("/forms");
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div>
 | 
			
		||||
            NEW
 | 
			
		||||
        <div className={classes.main}>
 | 
			
		||||
            <div className={classes.wrapper}>
 | 
			
		||||
                <div className={classes.header}> 
 | 
			
		||||
                    <div className={classes.header__listBtn}>
 | 
			
		||||
                        <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 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="#exampleModal" onClick={() => setCurrentTypeAnswer(item.id)} key={i}>
 | 
			
		||||
                                    <span>{item.text}</span>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            )}
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <MyModal 
 | 
			
		||||
                        stateModal={stateModal}
 | 
			
		||||
                        currentTypeAnswer={currentTypeAnswer} 
 | 
			
		||||
                        answer={answer}
 | 
			
		||||
                        comment={comment}
 | 
			
		||||
                        datetime={datetime}
 | 
			
		||||
                        file={file}
 | 
			
		||||
                        listTypeAnswer={listTypeAnswer}
 | 
			
		||||
                        setAnswer={setAnswer}
 | 
			
		||||
                        setComment={setComment}
 | 
			
		||||
                        setDatetime={setDatetime}
 | 
			
		||||
                        setFile={setFile}
 | 
			
		||||
                        cleanStates={cleanStates}
 | 
			
		||||
                        saveStates={saveStates}
 | 
			
		||||
                        updateAnswerByForm={updateAnswerByForm}
 | 
			
		||||
                        setCurrentTypeAnswer={setCurrentTypeAnswer}/>
 | 
			
		||||
 | 
			
		||||
                    <div className={classes.content__newForm}>
 | 
			
		||||
                        <div className={classes.content__newForm__title}>
 | 
			
		||||
                            <h3>Новая форма</h3>
 | 
			
		||||
                        </div>                        
 | 
			
		||||
                        <div className={classes.content__newForm__list}>
 | 
			
		||||
                            {newForm.map((item, i) => 
 | 
			
		||||
                                <div 
 | 
			
		||||
                                    className={classes.content__newForm__list__item} 
 | 
			
		||||
                                    key={i} 
 | 
			
		||||
                                    id={i}
 | 
			
		||||
                                    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={(event) => {                                       
 | 
			
		||||
                                        const currentElem = newForm[dragElem]
 | 
			
		||||
                                        const tNewForm = [...newForm]
 | 
			
		||||
                                        if (dragElem > dropElem) {
 | 
			
		||||
                                            tNewForm.splice(dropElem, 0, currentElem)
 | 
			
		||||
                                            tNewForm.splice(dragElem + 1, 1)
 | 
			
		||||
                                        }
 | 
			
		||||
                                        else {
 | 
			
		||||
                                            tNewForm.splice(dropElem + 1, 0, currentElem)
 | 
			
		||||
                                            tNewForm.splice(dragElem, 1)
 | 
			
		||||
                                        }   
 | 
			
		||||
                                        setNewForm(tNewForm)
 | 
			
		||||
                                    }}
 | 
			
		||||
                                >
 | 
			
		||||
                                    <div className={classes.content__newForm__list__item__answer}>
 | 
			
		||||
                                        <span>{item.answer}</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="#exampleModal" onClick={() => {editAnswerByForm(item.id)}}></i>
 | 
			
		||||
                                        <i class="fa-solid fa-trash" onClick={() => removeAnswerByForm(item.id)}></i>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            )}
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>                  
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user