Skip to content

Commit

Permalink
🍁 [Frontend] Add Q&A section in admin panel (#901)
Browse files Browse the repository at this point in the history
* Frontend Admin Q&A completed

* changes

* changed as per guidence

* changed as per guidence

* back

* toast
  • Loading branch information
Hemu21 authored May 17, 2024
1 parent 4f2f984 commit 24a9f89
Show file tree
Hide file tree
Showing 9 changed files with 556 additions and 4 deletions.
2 changes: 1 addition & 1 deletion backend/app/routes/Q&A/answers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const updateAnswerStatus = require('./updateAnswerStatus');
router.post('/', validation(answerValidationSchema), postAnswer);

// GET API FOR ANSWERS
router.get('/:questionId', validation(getAnswerValidationSchema), getAnswers);
router.get('/:questionId', getAnswers);

// INCREASE UPVOTE FOR ANSWERS
router.patch('/upvote', upvoteAnswer);
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/pages/Admin/Admin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@ import axios from "axios";
import { END_POINT } from "../../config/api";
import { useDispatch } from "react-redux";
import { ManageFaq } from "./Components/Faq/ManageFaq";
import { QandA } from "./Components/Faq/Q&A/QandA";
import { Manageqa } from "./Components/Faq/Q&A/ManageQ&A/ManageQ&A";

export const Admin = (props) => {
const [tab, setTab] = useState(1);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const toggleNav = () => setIsMenuOpen(!isMenuOpen);
const closeMobileMenu = () => setIsMenuOpen(false);
const dispatch = useDispatch();
const firstName = localStorage.getItem("firstName");
const [qId,setQId] = useState("")
const [adminData, setAdminData] = useState({});
const FetchAdminData = async () => {
try {
Expand All @@ -50,7 +54,6 @@ export const Admin = (props) => {
console.error("There was a problem with the fetch operation:", error);
}
};

useEffect(() => {
const token = localStorage.getItem("token");
try {
Expand Down Expand Up @@ -174,7 +177,7 @@ export const Admin = (props) => {
className="fas fa-question fa-fw fa-lg"
aria-hidden="true"
></i>
<div className={style["span"]}>FAQs</div>
<div className={style["span"]}>FAQs and Q&As</div>
</div>
</li>
<li onClick={closeMobileMenu}>
Expand Down Expand Up @@ -244,6 +247,10 @@ export const Admin = (props) => {
<ResetPassword />
) : tab === 16 ? (
<ManageBroadcasts />
) : tab === 18 ? (
<QandA setQId={setQId} setTab={setTab} tab={tab} />
) : tab === 19 ? (
<Manageqa qId={qId} setTab={setTab} />
) : null}
</div>
</div>
Expand Down
15 changes: 14 additions & 1 deletion frontend/src/pages/Admin/Components/Faq/Faq.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Link } from "react-router-dom";
export function Faq(props) {
return (
<div className={style["faq"]}>
<h1 style={{ textAlign: "center" }}> FAQS </h1>
<h1 style={{ textAlign: "center" }}> FAQs and Q&As </h1>
<div className={style["cards"]}>
<div className={style["card-item"]}>
<div className={style["clickable-card"]}>
Expand Down Expand Up @@ -40,6 +40,19 @@ export function Faq(props) {
</div>
</div>
</div>
<div className={style["card-item"]}>
<div className={style["clickable-card"]}>
<div className={style["card-title"]}>
MANAGE Q&A
<AiFillEdit className={style["editt"]} />
</div>
<div className={style["card-content"]}>
<div onClick={()=>props.setTab(18)} className={style["main-btn"]}>
Manage here
</div>
</div>
</div>
</div>
</div>
</div>
);
Expand Down
213 changes: 213 additions & 0 deletions frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/ManageQ&A.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import { useEffect, useState } from "react";
import { END_POINT } from "../../../../../../config/api";
import style from "./manage.module.scss";
import { AiOutlineArrowLeft } from "react-icons/ai";
import { SimpleToast } from "../../../../../../components/util/Toast/Toast";
import Loader from "../../../../../../components/util/Loader";

export function Manageqa({ setTab, qId }) {
const [ans, setAns] = useState([]);
const [qns, setQns] = useState();
const [toogle, setToogle] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);
const [toast, setToast] = useState({
toastStatus: false,
toastType: "",
toastMessage: "",
});
const getQuestion = async (id) => {
setIsLoaded(true);
try {
const qUrl = `${END_POINT}/question/getQuestionById/${id}`;
const qResponse = await fetch(qUrl);
const qRes = await qResponse.json();
setQns(qRes);
setToast({
...toast,
toastMessage: "Successfully get Question",
toastStatus: true,
toastType: "success",
});
} catch (error) {
console.log(error);
setIsLoaded(false);
setToast({
...toast,
toastMessage: "Check network failed to fetch",
toastStatus: true,
toastType: "error",
});
}
};
const updateQuestion = async (id, status) => {
try {
const qUrl = `${END_POINT}/question/updateStatus`;
const qResponse = await fetch(qUrl, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
body: JSON.stringify({ id: id, status: status }),
});
const qRes = await qResponse.json();
setToogle(!toogle);
setToast({
...toast,
toastMessage: "Updated Successfully!",
toastStatus: true,
toastType: "success",
});
} catch (error) {
console.log(error);
setToast({
...toast,
toastMessage: "Check network failed to update",
toastStatus: true,
toastType: "error",
});
}
};
const getAnswer = async (questionId) => {
try {
const aUrl = `${END_POINT}/answers/${questionId}`;
const aResponse = await fetch(aUrl);
const aRes = await aResponse.json();
setAns(aRes.data);
setIsLoaded(false);
setToast({
...toast,
toastMessage: "Successfully get answers",
toastStatus: true,
toastType: "success",
});
} catch (error) {
console.log(error);
setIsLoaded(false);
setToast({
...toast,
toastMessage: "Check network failed to fetch",
toastStatus: true,
toastType: "error",
});
}
};
const updateAnswer = async (id, status) => {
try {
const aUrl = `${END_POINT}/answers/updateStatus`;
const aResponse = await fetch(aUrl, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
body: JSON.stringify({ id: id, status: status }),
});
const aRes = await aResponse.json();
setToogle(!toogle);
setToast({
...toast,
toastMessage: "Updated successfully",
toastStatus: true,
toastType: "success",
});
} catch (error) {
console.log(error);
setToast({
...toast,
toastMessage: "Check network failed to Update",
toastStatus: true,
toastType: "error",
});
}
};
const handleCloseToast = (event, reason) => {
if (reason === "clickaway") {
return;
}
setToast({ ...toast, toastStatus: false });
};
useEffect(() => {
getQuestion(qId);
getAnswer(qId);
}, [toogle]);
return (
<div>
<h1 className={style["head"]}>Manage Q&A</h1>
<div className={style["back"]}>
<AiOutlineArrowLeft size={"35px"} onClick={() => setTab(18)} />
</div>
<div className={style["data-loader"]}>{isLoaded ? <Loader /> : null}</div>
{isLoaded || (
<div className={style["card-item"]}>
<div className={style["card-info"]}>
<h1>{qns?.title}</h1>
<h2>Question</h2>
<div className={style["questionBox"]}>
<h3 className={style["card-question"]}>{qns?.description}</h3>
<div className={style["button-group"]}>
<button
className={
qns?.isApproved
? style["button-delete"]
: style["button-approve"]
}
id={`${qns?._id}`}
onClick={(e) => {
updateQuestion(e.currentTarget.id, !qns?.isApproved);
}}
>
{qns?.isApproved ? "DisApprove" : "Approve"}
</button>
<button className={style["button-delete"]}>Delete</button>
</div>
</div>

{ans?.length !== 0 ? (
<span>No answers Found</span>
) : (
ans?.map((a) => (
<>
<h2>Answers</h2>
<div className={style["answerBox"]}>
<h3 className={style["card-answer"]}>{a.answer}</h3>
<div className={style["button-group"]}>
<button
className={
a?.isApproved
? style["button-delete"]
: style["button-approve"]
}
id={`${a._id}`}
onClick={(e) => {
updateAnswer(e.currentTarget.id, !a?.isApproved);
}}
>
{a?.isApproved ? "DisApprove" : "Approve"}
</button>
<button className={style["button-delete"]}>Delete</button>
</div>
</div>
</>
))
)}

<div style={{ display: "flex", padding: "10px 30px 10px 30px" }}>
{qns?.tags?.map((tag) => (
<p className={style["tags"]}>{tag}</p>
))}
</div>
</div>
</div>
)}
{toast.toastStatus && (
<SimpleToast
open={toast.toastStatus}
message={toast.toastMessage}
handleCloseToast={handleCloseToast}
severity={toast.toastType}
/>
)}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./ManageQ&A";
Loading

0 comments on commit 24a9f89

Please sign in to comment.