From cf8904d47528963a6f1f25d5c29891805e3d1fc3 Mon Sep 17 00:00:00 2001 From: kuwsh1n Date: Sat, 13 Apr 2024 21:53:36 +0300 Subject: [PATCH] prod 2 --- src/App.jsx | 31 ++--- src/assets/styles/answersForm.module.scss | 107 +++++++++++++++++ src/assets/styles/enterAccount.module.scss | 1 + src/assets/styles/profile.module.scss | 7 ++ src/context/index.js | 4 +- src/hooks/api/adminApi.js | 18 +++ src/hooks/api/formApi.js | 64 +++++++--- src/hooks/api/listFormsApi.js | 21 +++- src/hooks/api/profileApi.js | 31 +++++ src/pages/AnswersForm.jsx | 129 +++++++++++++++++++++ src/pages/EnterAccount.jsx | 21 ++-- src/pages/Forms.jsx | 39 ++++--- src/pages/NewForm.jsx | 38 +++--- src/pages/Profile.jsx | 58 ++++++--- src/pages/ViewForm.jsx | 50 ++++---- src/router/protectedRouting.js | 3 + src/router/router.js | 5 + 17 files changed, 511 insertions(+), 116 deletions(-) create mode 100644 src/assets/styles/answersForm.module.scss create mode 100644 src/hooks/api/adminApi.js create mode 100644 src/hooks/api/profileApi.js create mode 100644 src/pages/AnswersForm.jsx diff --git a/src/App.jsx b/src/App.jsx index 3582df4..6a2e781 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useLayoutEffect } from "react"; import { Outlet, useNavigate } from "react-router-dom"; -import { FormsData, UserData, TypeAnswerData } from "./context"; +import { FormsData, UserData, TypeAnswerData, answersData } from "./context"; import { useCookies } from "react-cookie"; import { globalRender } from "./router/protectedRouting.js"; import { verifyUserApi } from "./hooks/api/enterAccountApi.js" @@ -20,6 +20,7 @@ const App = () => { const navigate = useNavigate(); const [forms, setForms] = useState([]); const [user, setUser] = useState(false); + const [answersList, setAnswersList] = useState([]); const [listTypeAnswer, setListTypeAnswer] = useState([ {id: 1, text: 'Краткий ответ', typeTag: InputText}, {id: 2, text: 'Расширенный ответ', typeTag: TextArea}, @@ -48,25 +49,27 @@ const App = () => { } } - verifyUser() + verifyUser(); }, []) return ( - - -
-
-
- -
-
- + + + +
+
+
+ +
+
+ +
-
- - + + + ) } diff --git a/src/assets/styles/answersForm.module.scss b/src/assets/styles/answersForm.module.scss new file mode 100644 index 0000000..62a00f9 --- /dev/null +++ b/src/assets/styles/answersForm.module.scss @@ -0,0 +1,107 @@ +.main { + width: 100%; + height: 100%; +} + +.wrapper { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.answers { + width: 70%; + 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%; + height: 15%; + display: flex; + justify-content: start; + 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%; + &__item { + padding: 5px; + border-bottom: 1px solid rgb(200, 200, 200); + font-size: 15px; + font-family: "Montserrat", sans-serif; + cursor: pointer; + // &__question { + // &__text { + // font-size: 15px; + // font-family: "Montserrat", sans-serif; + // } + // &__comment { + // font-size: 11px; + // font-family: "Montserrat", sans-serif; + // font-style: italic; + // color: rgb(200, 200, 200); + // } + // } + // &__answer { + // &__text { + // font-size: 15px; + // font-family: "Montserrat", sans-serif; + // } + // } + } + } + } +} + +.myModal { + &__item { + padding: 5px; + border-bottom: 1px solid rgb(200, 200, 200); + font-size: 15px; + font-family: "Montserrat", sans-serif; + cursor: pointer; + &__question { + &__text { + font-size: 15px; + font-family: "Montserrat", sans-serif; + } + &__comment { + font-size: 11px; + font-family: "Montserrat", sans-serif; + font-style: italic; + color: rgb(200, 200, 200); + } + } + &__answer { + &__text { + font-size: 15px; + font-family: "Montserrat", sans-serif; + } + } + } +} \ No newline at end of file diff --git a/src/assets/styles/enterAccount.module.scss b/src/assets/styles/enterAccount.module.scss index 2bf26ad..4ed78a8 100644 --- a/src/assets/styles/enterAccount.module.scss +++ b/src/assets/styles/enterAccount.module.scss @@ -87,6 +87,7 @@ justify-content: space-around; flex-direction: column; padding-bottom: 5px; + &__fio { height: 15%; display: flex; diff --git a/src/assets/styles/profile.module.scss b/src/assets/styles/profile.module.scss index c7069ab..32a942c 100644 --- a/src/assets/styles/profile.module.scss +++ b/src/assets/styles/profile.module.scss @@ -40,6 +40,13 @@ justify-content: space-between; align-items: center; margin-bottom: 10px; + &__btn { + height: 100%; + width: 35%; + display: flex; + justify-content: space-between; + align-items: center; + } h3 { font-size: 25px; font-family: "Montserrat", sans-serif; diff --git a/src/context/index.js b/src/context/index.js index 4a7a9c8..a6d92fa 100644 --- a/src/context/index.js +++ b/src/context/index.js @@ -4,4 +4,6 @@ export const FormsData = createContext([]); export const UserData = createContext(false); -export const TypeAnswerData = createContext(); \ No newline at end of file +export const TypeAnswerData = createContext(); + +export const answersData = createContext(); \ No newline at end of file diff --git a/src/hooks/api/adminApi.js b/src/hooks/api/adminApi.js new file mode 100644 index 0000000..027cfa4 --- /dev/null +++ b/src/hooks/api/adminApi.js @@ -0,0 +1,18 @@ +import axios from "axios"; + +async function listUsersApi(token) { + try { + const response = await axios.get(`https://api.minerva.krbl.ru/auth/manage/users`, + { + headers: { + "Authorization": `Token ${token}` + } + }) + return response + } + catch (e) { + return e + } +}; + +export {listUsersApi} \ No newline at end of file diff --git a/src/hooks/api/formApi.js b/src/hooks/api/formApi.js index efb3814..1ecffb3 100644 --- a/src/hooks/api/formApi.js +++ b/src/hooks/api/formApi.js @@ -33,26 +33,11 @@ async function addFormBlockApi(token, formId, data) { } }; -// function removeFormApi(id) { -// return new Promise((resolve, reject) => { -// setTimeout(() => { -// if (true) { -// resolve({ -// id: id -// }) -// } -// else { -// reject("Error") -// } -// }, 200) -// }) -// }; - async function updateBlockApi(token, blockId, data) { try { const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${blockId}/set`, { - data: data + "data": data }, { headers: { @@ -103,4 +88,49 @@ async function saveFormApi(token) { } }; -export { addFormBlockApi, listFormBlockApi, saveFormApi, updateBlockApi, updateOrderBlockApi } \ No newline at end of file +async function listFormBlockByTokenApi(token, formToken) { + try { + const response = await axios.get(`https://api.minerva.krbl.ru/form/${formToken}/get`, + { + headers: { + "Authorization": `Token ${token}` + } + }) + return response + } + catch (e) { + return e + } +}; + +async function saveAnswersApi(token, formToken, data) { + try { + const response = await axios.post(`https://api.minerva.krbl.ru/form/${formToken}/submit`, {"data": data}, + { + headers: { + "Authorization": `Token ${token}` + } + }) + return response + } + catch (e) { + return e + } +}; + +async function getAnswersApi(token, formToken) { + try { + const response = await axios.get(`https://api.minerva.krbl.ru/formBuilder/edit/${formToken}/answers`, + { + headers: { + "Authorization": `Token ${token}` + } + }) + return response + } + catch (e) { + return e + } +}; + +export { addFormBlockApi, listFormBlockApi, saveFormApi, updateBlockApi, updateOrderBlockApi, listFormBlockByTokenApi, saveAnswersApi, getAnswersApi } \ No newline at end of file diff --git a/src/hooks/api/listFormsApi.js b/src/hooks/api/listFormsApi.js index 90ff574..4471f63 100644 --- a/src/hooks/api/listFormsApi.js +++ b/src/hooks/api/listFormsApi.js @@ -35,7 +35,7 @@ async function createFormApi(token) { async function removeFormApi(token, formId) { try { - const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/delete`, { + const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/delete`, {}, { headers: { "Authorization": `Token ${token}`, }, @@ -67,7 +67,7 @@ async function updateTitleFormApi(token, formId, title) { async function newFormTokenApi(token, formId) { try { - const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/new`, + const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/new`, {}, { headers: { "Authorization": `Token ${token}` @@ -80,4 +80,19 @@ async function newFormTokenApi(token, formId) { } }; -export { listFormsApi, createFormApi, removeFormApi, updateTitleFormApi, newFormTokenApi }; \ No newline at end of file +async function listFormsByTokenApi(token, formId) { + try { + const response = await axios.get(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/list`, + { + headers: { + "Authorization": `Token ${token}` + } + }) + return response + } + catch (e) { + return e + } +}; + +export { listFormsApi, createFormApi, removeFormApi, updateTitleFormApi, newFormTokenApi, listFormsByTokenApi }; \ No newline at end of file diff --git a/src/hooks/api/profileApi.js b/src/hooks/api/profileApi.js new file mode 100644 index 0000000..68e1e04 --- /dev/null +++ b/src/hooks/api/profileApi.js @@ -0,0 +1,31 @@ +import axios from "axios"; + +async function editUserApi(token, data) { + try { + const response = await axios.post("https://api.minerva.krbl.ru/auth/manage/edit", + { + "email": data.email, + "first_name": data.first_name, + "id": "6617fec3f603c43e1719d3c8", + "is_admin": data.is_admin, + "last_name": data.last_name, + "login": data.login, + "phone": data.phone + }, + { + headers: { + "Authorization": `Token ${token}`, + }, + }) + + console.log(response) + return response + } + catch(e) { + console.log(e) + return e + } + // return false +} + +export {editUserApi} \ No newline at end of file diff --git a/src/pages/AnswersForm.jsx b/src/pages/AnswersForm.jsx new file mode 100644 index 0000000..de58a80 --- /dev/null +++ b/src/pages/AnswersForm.jsx @@ -0,0 +1,129 @@ +import React, { useState, useContext, useEffect } from "react"; +import { useCookies } from "react-cookie"; +import { useNavigate, useParams } from 'react-router-dom'; +import { answersData } from "../context"; +import classes from "../assets/styles/answersForm.module.scss"; +import { responseDataToListBlock } from "../hooks/sundry/parseListBlock"; +import { listFormBlockApi, getAnswersApi } from "../hooks/api/formApi"; +import { listUsersApi } from "../hooks/api/adminApi"; + +const AnswersForm = () => { + const { formId } = useParams(); + const {answersList, setAnswersList} = useContext(answersData); + const [data, setData] = useState(false); + const [cookies, _, __] = useCookies(["user"]); + + useEffect(() => { + async function getForm() { + const result = [] + const responseBlocks = await listFormBlockApi(cookies.token, formId); + const responseAnswers = await getAnswersApi(cookies.token, formId); + const listUsers = await listUsersApi(cookies.token); + console.log("responseBlocks", responseBlocks) + console.log("responseAnswers", responseAnswers) + + if (responseBlocks.status === 200 && responseBlocks.data) { + const listBlocks = responseDataToListBlock(responseBlocks.data); + + if (responseAnswers.data) { + for (let item of responseAnswers.data) { + const blocks = { + user: listUsers.data.find(user => user.id === item.user_id).login, + block: [] + } + + if (item.data) { + for (let i = 0; i < item.data.length; i++) { + blocks.block.push({answers: {id: item.data[i][0].Value, answer: item.data[i][1].Value}, question: listBlocks[i]}) + } + } + else { + for (let i = 0; i < listBlocks.length; i++) { + blocks.block.push({answers: [], question: listBlocks[i]}) + } + } + + result.push(blocks) + } + console.log("result", result) + } + + setData(result) + } + else { + console.log(responseBlocks) + } + }; + + getForm() + }, []); + + return ( +
+
+
+
+
+

Ответы

+
+
+ {data ? + data.map((item, i) => +
+
+ {item.user} +
+ + +
+ ) + :
Ответов нет
} + + + {/* + {data ?
*/} + {/* {data ? + data.map((item, i) => +
+
+

{i + 1}) {item.question.question}

+

{item.question.comment}

+
+
+

Ответ: {item.answers.answer}

+
+
+ ) + :
Ответов нет
} */} +
+ +
+
+
+
+ ) +} + +export default AnswersForm; \ No newline at end of file diff --git a/src/pages/EnterAccount.jsx b/src/pages/EnterAccount.jsx index 80ff43b..0fbc70c 100644 --- a/src/pages/EnterAccount.jsx +++ b/src/pages/EnterAccount.jsx @@ -5,7 +5,7 @@ import classes from "../assets/styles/enterAccount.module.scss"; import MyInput from "../components/MyInput.jsx"; import MyButton from "../components/MyButton.jsx"; import { UserData } from "../context"; -import { logIn, completeRegistration } from "../hooks/api/enterAccountApi.js"; +import { logIn, completeRegistration, verifyUserApi } from "../hooks/api/enterAccountApi.js"; const EnterAccount = () => { const [enter, setEnter] = useState("login"); @@ -39,11 +39,7 @@ const EnterAccount = () => { async function createUser() { const response = await completeRegistration({ - // email: email, - // phone: phone, login: login, - // first_name: surname, - // last_name: patronymic, password: password, repiedPassword: repiedPassword }); @@ -57,7 +53,7 @@ const EnterAccount = () => { patronymic: patronymic, password: password, }); - setCookie("token", response.data.token); + setCookie("token", response.data.token); cleanState(); window.location.reload(); // navigate("/"); @@ -73,9 +69,9 @@ const EnterAccount = () => { if (response.status === 200) { setCookie("token", response.data.token); cleanState(); - setUser({ - login: login - }) + // setUser({ + // login: login + // }) window.location.reload(); // navigate("/") // window.location.reload() @@ -121,6 +117,11 @@ const EnterAccount = () => {

Зарегестрировать учетную запись

+ + + +
+ {/*
@@ -130,7 +131,7 @@ const EnterAccount = () => {
-
+
*/}
createUser()}/>
diff --git a/src/pages/Forms.jsx b/src/pages/Forms.jsx index ed970a0..e05e0df 100644 --- a/src/pages/Forms.jsx +++ b/src/pages/Forms.jsx @@ -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, newFormTokenApi } from "../hooks/api/listFormsApi.js"; +import { listFormsApi, createFormApi, removeFormApi, newFormTokenApi, listFormsByTokenApi } from "../hooks/api/listFormsApi.js"; const Forms = () => { const navigate = useNavigate(); @@ -20,10 +20,10 @@ const Forms = () => { const response = await listFormsApi(cookies.token); if (response.data) { - setForms(response.data) + setForms(response.data); } else if (response.status === 200 && response.data) { - setForms([]) + setForms([]); } else { console.log(response) @@ -41,7 +41,7 @@ const Forms = () => { if (response.data) { const token = await newFormTokenApi(cookies.token, response.data.id) - console.log("token", token) + navigate(`/forms/${response.data.id}/edit`) } else { @@ -54,22 +54,32 @@ const Forms = () => { }; async function removeForm(id) { - setForms([...forms.filter(item => item.id !== id)]); - // const response = await removeFormApi(cookies.token, id) + const response = await removeFormApi(cookies.token, id) - // if (response.status === 200) { - // setForms([...forms.filter(item => item.id !== id)]); - // } - // else { - // console.log(response) - // } + if (response.status === 200) { + setForms([...forms.filter(item => item.id !== id)]); + } + else { + console.log(response) + } }; + async function openFormView(formId) { + const response = await listFormsByTokenApi(cookies.token, formId); + + if (response.status === 200) { + navigate(`/forms/${response.data.tokens[0].id}/`); + } + else { + console.log(response) + } + } + return (
- + {/* */} Загрузка... @@ -90,7 +100,8 @@ const Forms = () => {
{item.update}
*/} diff --git a/src/pages/NewForm.jsx b/src/pages/NewForm.jsx index 1c4b363..6aa4da5 100644 --- a/src/pages/NewForm.jsx +++ b/src/pages/NewForm.jsx @@ -103,26 +103,28 @@ const NewForm = () => { typeAnswer: currentTypeAnswer, } - // const response = await updateBlockApi(cookies.token, stateModal, data); + console.log(stateModal) - // if (response.status === 200) { - // setListBlock(listBlock.map(item => { - // if (item.id === stateModal) { - // item = data - // } - // return item - // })) - // } - // else { - // console.log(response) - // } + const response = await updateBlockApi(cookies.token, stateModal, data); - setListBlock(listBlock.map(item => { - if (item.id === stateModal) { - item = data - } - return item - })) + if (response.status === 200) { + setListBlock(listBlock.map(item => { + if (item.id === stateModal) { + item = data + } + return item + })) + } + else { + console.log(response) + } + + // setListBlock(listBlock.map(item => { + // if (item.id === stateModal) { + // item = data + // } + // return item + // })) cleanStates(); }; diff --git a/src/pages/Profile.jsx b/src/pages/Profile.jsx index 27562c5..9becf6a 100644 --- a/src/pages/Profile.jsx +++ b/src/pages/Profile.jsx @@ -5,6 +5,7 @@ import MyButton from "../components/MyButton.jsx"; import { UserData } from "../context"; import { useCookies } from "react-cookie"; import { verifyUserApi } from "../hooks/api/enterAccountApi.js"; +import { editUserApi } from "../hooks/api/profileApi.js"; const Profile = () => { const [edit, setEdit] = useState(true); @@ -16,7 +17,7 @@ const Profile = () => { const [first_name, setFirst_name] = useState(""); const [last_name, setLast_name] = useState(""); - const [cookies, _, __] = useCookies(["user"]); + const [cookies, setCookies, removeCookies] = useCookies(["user"]); const navigate = useNavigate(); useEffect(() => { @@ -42,7 +43,6 @@ const Profile = () => { }, []) function choiceInput(key) { - console.log(2) switch (key) { case "email": return {get: email, set: setEmail} @@ -57,40 +57,68 @@ const Profile = () => { } } - function editUser() { + async function editUser() { if (edit) { setEdit(!edit) + } else { - setUser({ + const response = await editUserApi(cookies.token, { login: login, first_name: first_name, last_name: last_name, email: email, phone: phone, + is_admin: user.is_admin }) - setEdit(!edit) + + if (response.status === 200) { + setUser({ + login: login, + first_name: first_name, + last_name: last_name, + email: email, + phone: phone, + }) + setEdit(!edit) + } + } + }; + + function exitAccount() { + removeCookies("token"); + setUser(false); + navigate("/"); } return (
-
+ {/* {user.is_admin ?
navigate("/admin")}>Админ панель -
+
:
} */}

Ваши данные

- Редактировать : - Сохранить - } - backgroundColor={edit ? "rgb(200, 200, 200)" : ""} - click={() => editUser()}/> +
+ {user.is_admin ? Редактировать : + Сохранить + } + backgroundColor={edit ? "rgb(200, 200, 200)" : ""} + click={() => editUser()}/> :
Запросите изменение профиля у администратора
} + Выйти + } + backgroundColor={edit ? "rgb(252, 151, 151)" : ""} + click={() => exitAccount()}/> +
+
{Object.keys(user).map(key => key !== "is_admin" ?
diff --git a/src/pages/ViewForm.jsx b/src/pages/ViewForm.jsx index a97e75b..5a34746 100644 --- a/src/pages/ViewForm.jsx +++ b/src/pages/ViewForm.jsx @@ -2,40 +2,41 @@ import React, { useState, useContext, useEffect } from "react"; import { useNavigate, useParams } from "react-router-dom"; import { useCookies } from "react-cookie"; import classes from "../assets/styles/viewForm.module.scss"; -import { FormsData, TypeAnswerData } from "../context"; +import { FormsData, TypeAnswerData, answersData, UserData } from "../context"; import GeneratingFormFields from "../components/GeneratingFormFields.jsx"; import MyButton from "../components/MyButton.jsx"; -import { listFormBlockApi } from "../hooks/api/formApi.js"; +import { listFormBlockApi, listFormBlockByTokenApi, saveAnswersApi } from "../hooks/api/formApi.js"; import { listFormsApi } from "../hooks/api/listFormsApi.js"; import { responseDataToListBlock } from "../hooks/sundry/parseListBlock.js"; const ViewForm = () => { const navigate = useNavigate(); const { formId } = useParams(); + const {user, setUser} = useContext(UserData); const {forms, setForms} = useContext(FormsData); + const {answersList, setAnswersList} = useContext(answersData); const {listTypeAnswer, setListTypeAnswer} = useContext(TypeAnswerData); - const [cookies, _, __] = useCookies(["user"]); + const [cookies, setCookies, __] = useCookies(["user"]); const [questions, setQuestions] = useState([]); const [answers, setAnswers] = useState([]); - const [title, setTitle] = useState(""); - + // const [title, setTitle] = useState(""); useEffect(() => { async function getForm() { - const responseForms = await listFormsApi(cookies.token); - const responseBlocks = await listFormBlockApi(cookies.token, formId); + // const responseForms = await listFormsApi(cookies.token); + const responseBlocks = await listFormBlockByTokenApi(cookies.token, formId); - if (responseBlocks.status === 200 && responseForms.status === 200 && responseBlocks.data) { - const listBlocks = responseDataToListBlock(responseBlocks.data); + if (responseBlocks.status === 200 && responseBlocks.data) { + const listBlocks = responseDataToListBlock(responseBlocks.data.blocks); setQuestions(listBlocks) setAnswers(listBlocks.map(item => ( {id: item.id, answer: []} ))) - setTitle(responseForms.data.find(item => item.id === formId).title) + // setTitle(responseForms.data.find(item => item.id === formId).title) } else { - console.log(responseForms) + // console.log(responseForms) console.log(responseBlocks) } }; @@ -54,16 +55,20 @@ const ViewForm = () => { ) }; - function saveAnswers() { - // saveAnswersApi(formId, answers) - // .then((resolve, _) => { - // console.log(resolve) - // setAnswers([]); - // navigate("/"); - // }) - // .catch((error) => console.log(error)); - setAnswers([]); - navigate("/forms"); + async function saveAnswers() { + const response = await saveAnswersApi(cookies.token, formId, answers); + console.log(response) + + if (response.status === 200) { + setAnswersList([...answersList, { + id: formId, + user: user.login, + answers: answers + }]) + + setAnswers([]); + navigate("/forms"); + } } return ( @@ -72,9 +77,6 @@ const ViewForm = () => {
-
- {title} -
#{formId}
diff --git a/src/router/protectedRouting.js b/src/router/protectedRouting.js index 51b34bc..24f3491 100644 --- a/src/router/protectedRouting.js +++ b/src/router/protectedRouting.js @@ -4,6 +4,9 @@ const protectedUrl = { "/forms/edit", "/profile" ], + Authorized: [ + "enter" + ], notRights: [ ] diff --git a/src/router/router.js b/src/router/router.js index 7864d31..93ceb5a 100644 --- a/src/router/router.js +++ b/src/router/router.js @@ -8,6 +8,7 @@ import App from "../App.jsx"; import Profile from "../pages/Profile.jsx"; import ViewForm from "../pages/ViewForm.jsx"; import AdminPanel from '../pages/AdminPanel.jsx'; +import AnswersForm from '../pages/AnswersForm.jsx'; const router = createBrowserRouter([ { @@ -40,6 +41,10 @@ const router = createBrowserRouter([ { path: "/admin", element: + }, + { + path: "/forms/:formId/answers", + element: } ] }