one
This commit is contained in:
		
							
								
								
									
										104
									
								
								src/assets/styles/adminPanel.module.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/assets/styles/adminPanel.module.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| .main { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
| } | ||||
|  | ||||
| .wrapper { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     display: flex; | ||||
|     justify-content: center; | ||||
|     align-items: center; | ||||
| } | ||||
|  | ||||
| .admin { | ||||
|     width: 70%; | ||||
|     height: 70%; | ||||
|     box-shadow: 0 0 5px 1px rgb(200, 200, 200); | ||||
|     padding: 1.5%; | ||||
|     position: relative; | ||||
|     &__linkProfile { | ||||
|         position: absolute; | ||||
|         bottom: 103%; | ||||
|         left: 10px; | ||||
|         cursor: pointer; | ||||
|         span { | ||||
|             font-size: 15px; | ||||
|             font-family: "Montserrat", sans-serif; | ||||
|             color: rgb(100, 100, 100); | ||||
|             &:hover { | ||||
|                 text-decoration: underline; | ||||
|                 color: rgb(66, 68, 189); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     &__wrapper { | ||||
|         &__header { | ||||
|             width: 100%; | ||||
|             height: 15%; | ||||
|             display: flex; | ||||
|             justify-content: space-between; | ||||
|             align-items: center; | ||||
|             margin-bottom: 10px; | ||||
|             h3 { | ||||
|                 font-size: 25px; | ||||
|                 font-family: "Montserrat", sans-serif; | ||||
|                 color: rgb(100, 100, 100); | ||||
|             } | ||||
|         } | ||||
|         &__body { | ||||
|             width: 100%; | ||||
|             height: 85%; | ||||
|             &__columns { | ||||
|                 width: 100%; | ||||
|                 height: 20%; | ||||
|                 border-bottom: 1px solid rgb(200, 200, 200); | ||||
|                 display: flex; | ||||
|                 justify-content: space-between; | ||||
|                 align-items: center; | ||||
|                 &__item { | ||||
|                     font-size: 15px; | ||||
|                     font-family: "Montserrat", sans-serif; | ||||
|                     color: rgb(70, 70, 70); | ||||
|                     width: 33.3%; | ||||
|                     text-align: center; | ||||
|                 } | ||||
|             } | ||||
|             &__users { | ||||
|                 width: 100%; | ||||
|                 height: 80%; | ||||
|                 margin-top: 10px; | ||||
|                 &__item { | ||||
|                     width: 100%; | ||||
|                     height: 20%; | ||||
|                     display: flex; | ||||
|                     justify-content: space-between; | ||||
|                     align-items: center; | ||||
|                     border-bottom: 1px solid rgb(200, 200, 200); | ||||
|                     &__link { | ||||
|                         font-size: 15px; | ||||
|                         font-family: "Montserrat", sans-serif; | ||||
|                         color: rgb(70, 70, 70); | ||||
|                         width: 33.3%; | ||||
|                         text-align: center; | ||||
|                         cursor: pointer; | ||||
|                         &:hover { | ||||
|                             text-decoration: underline; | ||||
|                             color: rgb(66, 68, 189); | ||||
|                         } | ||||
|                     } | ||||
|                     &__info { | ||||
|                         font-size: 15px; | ||||
|                         font-family: "Montserrat", sans-serif; | ||||
|                         color: rgb(100, 100, 100); | ||||
|                         width: 33.3%; | ||||
|                         text-align: center; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             &__item { | ||||
|                 padding: 5px; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -16,6 +16,22 @@ | ||||
|     height: 70%; | ||||
|     box-shadow: 0 0 5px 1px rgb(200, 200, 200); | ||||
|     padding: 1.5%; | ||||
|     position: relative; | ||||
|     &__linkAdmin { | ||||
|         position: absolute; | ||||
|         bottom: 103%; | ||||
|         left: 10px; | ||||
|         span { | ||||
|             font-size: 15px; | ||||
|             font-family: "Montserrat", sans-serif; | ||||
|             color: rgb(100, 100, 100); | ||||
|             cursor: pointer; | ||||
|             &:hover { | ||||
|                 text-decoration: underline; | ||||
|                 color: rgb(66, 68, 189); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     &__wrapper { | ||||
|         &__header { | ||||
|             width: 100%; | ||||
|   | ||||
| @@ -1,7 +1,28 @@ | ||||
| import React, { useState } from "react"; | ||||
| import classes from "../assets/styles/components/navbar.module.scss" | ||||
| import React, { useState, useEffect } from "react"; | ||||
| import { useCookies } from "react-cookie"; | ||||
| import classes from "../assets/styles/components/navbar.module.scss"; | ||||
| import { verifyUserApi } from "../hooks/api/enterAccountApi"; | ||||
|  | ||||
| const NavBar = ({navigate, auth, setAuth}) => { | ||||
|     // const [cookies, _, __] = useCookies(["user"]); | ||||
|  | ||||
|     // useEffect(() => { | ||||
|     //     async function verifyUser() { | ||||
|     //         const response = await verifyUserApi(cookies.token); | ||||
|  | ||||
|     //         if (response) { | ||||
|     //             if (response.status === 200) { | ||||
|     //                 setAuth(response.data); | ||||
|     //             } | ||||
|     //             else { | ||||
|     //                 console.log(response) | ||||
|     //             } | ||||
|     //         } | ||||
|     //     } | ||||
|  | ||||
|     //     verifyUser() | ||||
|     // }, []); | ||||
|  | ||||
|     return ( | ||||
|         <div className={classes.main}> | ||||
|             <div className={classes.wrapper}> | ||||
| @@ -9,7 +30,7 @@ const NavBar = ({navigate, auth, setAuth}) => { | ||||
|                     <div className={classes.menu__authorized}> | ||||
|                         <span onClick={() => navigate("/")}>Главная</span> | ||||
|                         {auth ?  | ||||
|                         <span onClick={() => navigate("/forms")}>Мои формы</span> : | ||||
|                         auth.is_admin ? <span onClick={() => navigate("/forms")}>Мои формы</span> : <span></span> : | ||||
|                         <span></span>} | ||||
|                     </div>                    | ||||
|                 </div> | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import axios from "axios"; | ||||
|  | ||||
| async function logIn(login, password) { | ||||
|     try { | ||||
|         const response = await axios.post("http://localhost:8080/auth/signIn", {"login": login, "password": password}) | ||||
|         const response = await axios.post("https://api.minerva.krbl.ru/auth/signIn", {"login": login, "password": password}) | ||||
|         return response | ||||
|     } | ||||
|     catch (e) { | ||||
| @@ -16,7 +16,10 @@ async function completeRegistration(data) { | ||||
|  | ||||
|     if (validate.status) { | ||||
|         try { | ||||
|             const response = await axios.post("http://localhost:8080/auth/signUp", {"login": data.login, "password": data.password}) | ||||
|             const response = await axios.post("https://api.minerva.krbl.ru/auth/signUp", { | ||||
|                 "login": data.login,  | ||||
|                 "password": data.password, | ||||
|             }) | ||||
|             return response | ||||
|         } | ||||
|         catch (e) { | ||||
| @@ -29,7 +32,7 @@ async function completeRegistration(data) { | ||||
| async function verifyUserApi(token=false) { | ||||
|     if (token) { | ||||
|         try { | ||||
|             const response = await axios.get("http://localhost:8080/auth/me", {  | ||||
|             const response = await axios.get("https://api.minerva.krbl.ru/auth/me", {  | ||||
|                 headers: { | ||||
|                     "Authorization": `Token ${token}`, | ||||
|                 }, | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import axios from "axios"; | ||||
|  | ||||
| async function listFormBlockApi(token, formId) { | ||||
|     try { | ||||
|         const response = await axios.get(`http://localhost:8080/formBuilder/edit/${formId}/list`, | ||||
|         const response = await axios.get(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/list`, | ||||
|         { | ||||
|             headers: { | ||||
|                 "Authorization": `Token ${token}`, | ||||
| @@ -17,7 +17,7 @@ async function listFormBlockApi(token, formId) { | ||||
|  | ||||
| async function addFormBlockApi(token, formId, data) { | ||||
|     try { | ||||
|         const response = await axios.post(`http://localhost:8080/formBuilder/edit/${formId}/add`, | ||||
|         const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/add`, | ||||
|         { | ||||
|             data: data | ||||
|         }, | ||||
| @@ -50,7 +50,7 @@ async function addFormBlockApi(token, formId, data) { | ||||
|  | ||||
| async function updateBlockApi(token, blockId, data) { | ||||
|     try { | ||||
|         const response = await axios.post(`http://localhost:8080/formBuilder/edit/${blockId}/set`, | ||||
|         const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${blockId}/set`, | ||||
|         { | ||||
|             data: data | ||||
|         }, | ||||
| @@ -68,7 +68,7 @@ async function updateBlockApi(token, blockId, data) { | ||||
|  | ||||
| async function updateOrderBlockApi(token, formId, data) { | ||||
|     try { | ||||
|         const response = await axios.post(`http://localhost:8080/formBuilder/edit/${formId}/moveTo`, | ||||
|         const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/moveTo`, | ||||
|         { | ||||
|             "new_order": data.new, | ||||
|             "old_order": data.old | ||||
| @@ -87,7 +87,7 @@ async function updateOrderBlockApi(token, formId, data) { | ||||
|  | ||||
| async function saveFormApi(token) { | ||||
|     try { | ||||
|         const response = await axios.post("http://localhost:8080/formBuilder/new", | ||||
|         const response = await axios.post("https://api.minerva.krbl.ru/formBuilder/new", | ||||
|         { | ||||
|             title: "Новая форма" | ||||
|         }, | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import axios from "axios"; | ||||
|  | ||||
| async function listFormsApi(token) { | ||||
|     try { | ||||
|         const response = await axios.get("http://localhost:8080/formBuilder/list", { | ||||
|         const response = await axios.get("https://api.minerva.krbl.ru/formBuilder/list", { | ||||
|             headers: { | ||||
|                 "Authorization": `Token ${token}`, | ||||
|             } | ||||
| @@ -17,7 +17,7 @@ async function listFormsApi(token) { | ||||
|  | ||||
| async function createFormApi(token) { | ||||
|     try { | ||||
|         const response = await axios.post("http://localhost:8080/formBuilder/new", | ||||
|         const response = await axios.post("https://api.minerva.krbl.ru/formBuilder/new", | ||||
|         { | ||||
|             title: "Новая форма" | ||||
|         }, | ||||
| @@ -35,7 +35,7 @@ async function createFormApi(token) { | ||||
|  | ||||
| async function removeFormApi(token, formId) { | ||||
|     try { | ||||
|         const response = await axios.post(`http://localhost:8080/formBuilder/edit/${formId}/delete`, { | ||||
|         const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/delete`, { | ||||
|             headers: { | ||||
|                 "Authorization": `Token ${token}`, | ||||
|             }, | ||||
| @@ -49,7 +49,7 @@ async function removeFormApi(token, formId) { | ||||
|  | ||||
| async function updateTitleFormApi(token, formId, title) { | ||||
|     try { | ||||
|         const response = await axios.post(`http://localhost:8080/formBuilder/edit/${formId}/setTitle`,  | ||||
|         const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/setTitle`,  | ||||
|         { | ||||
|             title: title | ||||
|         }, | ||||
| @@ -65,4 +65,19 @@ async function updateTitleFormApi(token, formId, title) { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| export { listFormsApi, createFormApi, removeFormApi, updateTitleFormApi }; | ||||
| async function newFormTokenApi(token, formId) { | ||||
|     try { | ||||
|         const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/new`, | ||||
|         { | ||||
|             headers: { | ||||
|                 "Authorization": `Token ${token}` | ||||
|             } | ||||
|         }) | ||||
|         return response | ||||
|     } | ||||
|     catch (e) { | ||||
|         return e | ||||
|     } | ||||
| }; | ||||
|  | ||||
| export { listFormsApi, createFormApi, removeFormApi, updateTitleFormApi, newFormTokenApi }; | ||||
							
								
								
									
										74
									
								
								src/pages/AdminPanel.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/pages/AdminPanel.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| import React, { useState } from "react"; | ||||
| import { useNavigate } from "react-router-dom"; | ||||
| import classes from "../assets/styles/adminPanel.module.scss"; | ||||
|  | ||||
| const AdminPanel = () => { | ||||
|     const [token, setToken] = useState(""); | ||||
|     const navigate = useNavigate(); | ||||
|  | ||||
|     const [users, setUsers] = useState([ | ||||
|         { | ||||
|           "email": "senya.bogachev@mail.ru", | ||||
|           "first_name": "Арсений", | ||||
|           "id": "1", | ||||
|           "is_admin": false, | ||||
|           "last_name": "Богачев", | ||||
|           "login": "Ars", | ||||
|           "phone": "89110128244" | ||||
|         }, | ||||
|         { | ||||
|             "email": "dasha@mail.ru", | ||||
|             "first_name": "Дарья", | ||||
|             "id": "1", | ||||
|             "is_admin": false, | ||||
|             "last_name": "Утешева", | ||||
|             "login": "dasha", | ||||
|             "phone": "89111032339" | ||||
|         }, | ||||
|         { | ||||
|             "email": "kirik@mail.ru", | ||||
|             "first_name": "Кирилл", | ||||
|             "id": "string", | ||||
|             "is_admin": false, | ||||
|             "last_name": "Жердев", | ||||
|             "login": "Kirik", | ||||
|             "phone": "89110045673" | ||||
|         } | ||||
|       ]) | ||||
|  | ||||
|     return ( | ||||
|         <div className={classes.main}> | ||||
|             <div className={classes.wrapper}> | ||||
|                 <div className={classes.admin}> | ||||
|                     <div className={classes.admin__linkProfile}> | ||||
|                         <span onClick={() => navigate("/profile")}>Профиль</span> | ||||
|                     </div> | ||||
|                     <div className={classes.admin__wrapper}> | ||||
|                         <div className={classes.admin__wrapper__header}> | ||||
|                             <h3>Пользователи</h3> | ||||
|                              | ||||
|                         </div> | ||||
|                         <div className={classes.admin__wrapper__body}> | ||||
|                             <div className={classes.admin__wrapper__body__columns}> | ||||
|                                 <div className={classes.admin__wrapper__body__columns__item}>Логин</div> | ||||
|                                 <div className={classes.admin__wrapper__body__columns__item}>Фамилия</div> | ||||
|                                 <div className={classes.admin__wrapper__body__columns__item}>Email</div> | ||||
|                             </div> | ||||
|                             <div className={classes.admin__wrapper__body__users}> | ||||
|                                 {users.map(item =>  | ||||
|                                     <div className={classes.admin__wrapper__body__users__item}> | ||||
|                                         <div className={classes.admin__wrapper__body__users__item__link}>{item.login}</div> | ||||
|                                         <div className={classes.admin__wrapper__body__users__item__info}>{item.last_name}</div> | ||||
|                                         <div className={classes.admin__wrapper__body__users__item__info}>{item.email}</div> | ||||
|                                     </div> | ||||
|                                 )} | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     ) | ||||
| } | ||||
|  | ||||
| export default AdminPanel; | ||||
| @@ -42,8 +42,8 @@ const EnterAccount = () => { | ||||
|             // email: email, | ||||
|             // phone: phone, | ||||
|             login: login, | ||||
|             // surname: surname, | ||||
|             // patronymic: patronymic, | ||||
|             // first_name: surname, | ||||
|             // last_name: patronymic, | ||||
|             password: password, | ||||
|             repiedPassword: repiedPassword | ||||
|         }); | ||||
| @@ -59,7 +59,8 @@ const EnterAccount = () => { | ||||
|             }); | ||||
|             setCookie("token", response.data.token); | ||||
|             cleanState(); | ||||
|             navigate("/"); | ||||
|             window.location.reload(); | ||||
|             // navigate("/"); | ||||
|         } | ||||
|         else { | ||||
|             console.log("Error") | ||||
| @@ -75,7 +76,8 @@ const EnterAccount = () => { | ||||
|             setUser({ | ||||
|                 login: login | ||||
|             }) | ||||
|             navigate("/") | ||||
|             window.location.reload(); | ||||
|             // navigate("/") | ||||
|             // window.location.reload() | ||||
|         } | ||||
|         else { | ||||
| @@ -123,8 +125,8 @@ const EnterAccount = () => { | ||||
|                                 <MyInput placeholder={"Номер телефона"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={phone} change={setPhone}/> | ||||
|                                 <div className={classes.content__wrapper__register__body__fio}> | ||||
|                                     <MyInput placeholder={"Логин"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={login} change={setLogin}/> | ||||
|                                     <MyInput placeholder={"Фамилия"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={surname} change={setSurname}/> | ||||
|                                     <MyInput placeholder={"Отчество (при наличии)"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={patronymic} change={setPatronymic}/> | ||||
|                                     <MyInput placeholder={"Имя"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={surname} change={setSurname}/> | ||||
|                                     <MyInput placeholder={"Фамилия"} otherMainStyle={{width: "32%", height: "100%"}} otherInputStyle={{width: "100%"}} value={patronymic} change={setPatronymic}/> | ||||
|                                 </div>                                 | ||||
|                                 <MyInput type={'password'} placeholder={"Пароль"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={password} change={setPassword}/> | ||||
|                                 <MyInput type={'password'} placeholder={"Повторите пароль"} otherMainStyle={{width: "100%", height: "15%"}} otherInputStyle={{width: "100%"}} value={repiedPassword} change={setRepiedPassword}/> | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import classes from "../assets/styles/forms.module.scss" | ||||
| import MyButton from "../components/MyButton.jsx"; | ||||
| import MyInput from "../components/MyInput.jsx"; | ||||
| import { FormsData, UserData } from "../context"; | ||||
| import { listFormsApi, createFormApi, removeFormApi } from "../hooks/api/listFormsApi.js"; | ||||
| import { listFormsApi, createFormApi, removeFormApi, newFormTokenApi } from "../hooks/api/listFormsApi.js"; | ||||
|  | ||||
| const Forms = () => { | ||||
|     const navigate = useNavigate(); | ||||
| @@ -17,7 +17,7 @@ const Forms = () => { | ||||
|  | ||||
|     useEffect(() => { | ||||
|         async function listForms() { | ||||
|             const response = await listFormsApi(cookies.token) | ||||
|             const response = await listFormsApi(cookies.token); | ||||
|  | ||||
|             if (response.data) { | ||||
|                 setForms(response.data) | ||||
| @@ -35,10 +35,13 @@ const Forms = () => { | ||||
|  | ||||
|     async function createForm() { | ||||
|         setStateLoading(true); | ||||
|         const response = await createFormApi(cookies.token) | ||||
|         const response = await createFormApi(cookies.token); | ||||
|         console.log("response", response) | ||||
|         setStateLoading(false); | ||||
|  | ||||
|         if (response.data) { | ||||
|             const token = await newFormTokenApi(cookies.token, response.data.id) | ||||
|             console.log("token", token) | ||||
|             navigate(`/forms/${response.data.id}/edit`) | ||||
|         } | ||||
|         else { | ||||
|   | ||||
| @@ -65,8 +65,8 @@ const NewForm = () => { | ||||
|                 setTitleForm(responseForms.data.find(item => item.id === formId).title); | ||||
|             } | ||||
|             else { | ||||
|                 console.log(responseBlock); | ||||
|                 console.log(responseForms); | ||||
|                 setListBlock([]) | ||||
|                 setTitleForm("Новыя форма") | ||||
|             } | ||||
|         }; | ||||
|  | ||||
| @@ -308,7 +308,6 @@ const NewForm = () => { | ||||
|                                                 return typeItem.text | ||||
|                                             } | ||||
|                                         })}</span> | ||||
|                                         <span>{item.order}</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> | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import React, { useState, useContext, useEffect } from "react"; | ||||
| import { useNavigate } from "react-router-dom"; | ||||
| import classes from "../assets/styles/profile.module.scss"; | ||||
| import MyButton from "../components/MyButton.jsx"; | ||||
| import { UserData } from "../context"; | ||||
| @@ -9,8 +10,6 @@ const Profile = () => { | ||||
|     const [edit, setEdit] = useState(true); | ||||
|     const {user, setUser} = useContext(UserData); | ||||
|  | ||||
|     console.log(user) | ||||
|  | ||||
|     const [email, setEmail] = useState(""); | ||||
|     const [phone, setPhone] = useState(""); | ||||
|     const [login, setLogin] = useState(""); | ||||
| @@ -18,9 +17,9 @@ const Profile = () => { | ||||
|     const [last_name, setLast_name] = useState(""); | ||||
|  | ||||
|     const [cookies, _, __] = useCookies(["user"]); | ||||
|     const navigate = useNavigate(); | ||||
|  | ||||
|     useEffect(() => { | ||||
|         console.log(1) | ||||
|         async function verifyUser() { | ||||
|             const response = await verifyUserApi(cookies.token); | ||||
|  | ||||
| @@ -78,6 +77,9 @@ const Profile = () => { | ||||
|         <div className={classes.main}> | ||||
|             <div className={classes.wrapper}> | ||||
|                 <div className={classes.profile}> | ||||
|                     <div className={classes.profile__linkAdmin}> | ||||
|                         <span onClick={() => navigate("/admin")}>Админ панель</span> | ||||
|                     </div> | ||||
|                     <div className={classes.profile__wrapper}> | ||||
|                         <div className={classes.profile__wrapper__header}> | ||||
|                             <h3>Ваши данные</h3> | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import Home from "../pages/Home.jsx"; | ||||
| import App from "../App.jsx"; | ||||
| import Profile from "../pages/Profile.jsx"; | ||||
| import ViewForm from "../pages/ViewForm.jsx"; | ||||
| import AdminPanel from '../pages/AdminPanel.jsx'; | ||||
|  | ||||
| const router = createBrowserRouter([ | ||||
|     { | ||||
| @@ -35,6 +36,10 @@ const router = createBrowserRouter([ | ||||
|             { | ||||
|                 path: "/forms/:formId", | ||||
|                 element: <ViewForm/> | ||||
|             }, | ||||
|             { | ||||
|                 path: "/admin", | ||||
|                 element: <AdminPanel/> | ||||
|             } | ||||
|         ] | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user