From bc5fd09d82ec82fe2089b01d92140fbc1617bb26 Mon Sep 17 00:00:00 2001 From: balaharisankar Date: Wed, 7 Aug 2024 01:04:52 +0530 Subject: [PATCH] Feat:UI Enhanced in Manage Q&A Section of Admin Panel --- .../Faq/Q&A/AnswersModel/AnswersModel.jsx | 112 ++++++++++++++++ .../Faq/Q&A/AnswersModel/AnswersModel.scss | 104 +++++++++++++++ .../Components/Faq/Q&A/AnswersModel/index.js | 1 + .../pages/Admin/Components/Faq/Q&A/QandA.jsx | 124 +++--------------- 4 files changed, 237 insertions(+), 104 deletions(-) create mode 100644 frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/AnswersModel.jsx create mode 100644 frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/AnswersModel.scss create mode 100644 frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/index.js diff --git a/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/AnswersModel.jsx b/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/AnswersModel.jsx new file mode 100644 index 00000000..4b67cb17 --- /dev/null +++ b/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/AnswersModel.jsx @@ -0,0 +1,112 @@ +import React, { useEffect, useState } from "react"; +import { Modal, Backdrop, Fade } from '@material-ui/core'; +import { SimpleToast } from "../../../../../../components/util/Toast"; +import { getAnswers, updateAnswerStatus, deleteAnswer } from "../../../../../../service/Faq"; +import style from './AnswersModel.scss' + +export function AnswersModel(props) { + let dark = props.theme + const [answers, setAnswers] = useState([]) + const [toast, setToast] = useState({ + toastStatus: false, + toastType: "", + toastMessage: "", + }); + async function fetchAnswers() { + const data = await getAnswers(props.data._id, setToast) + setAnswers(data) + } + const updateAnswer = async (id, status) => { + setToast({ toastStatus: true, toastMessage: "Loading...", toastType: "info" }) + await updateAnswerStatus(id, status, setToast); + fetchAnswers() + } + const handleDeleteAnswer = async (answerId) => { + setToast({ toastStatus: true, toastMessage: "Loading...", toastType: "info" }) + await deleteAnswer(answerId, setToast) + fetchAnswers() + } + useEffect(() => { + if (props.open) + fetchAnswers() + }, [props]) + function timeStampFormatter(time) { + const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + const messageTime = new Date(time) + return `${String(messageTime.getDate())} ${String(months[messageTime.getMonth()])} ${String(messageTime.getFullYear())}` + } + return ( +
+ {toast.toastStatus && ( + { setToast({ toastMessage: "", toastStatus: false, toastType: "" }) }} + severity={toast.toastType} + /> + )} + + +
+
+ { + setToast({ toastMessage: "", toastStatus: false, toastType: "" }) + props.handleClose(false) + }}> + + +
+ { + answers.length == 0 ? +

No answers found...

+ : +
+ { + answers.map((ans, index) => { + return ( +
+
+
{ans.created_by || "Anonymous"}
+

{timeStampFormatter(ans.created_on)}

+
+

{ans.answer}

+
+ + {ans.isApproved == true && + } +
+
+ ) + }) + } +
+ } +
+
+
+
+ ) +} diff --git a/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/AnswersModel.scss b/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/AnswersModel.scss new file mode 100644 index 00000000..e5ddb69f --- /dev/null +++ b/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/AnswersModel.scss @@ -0,0 +1,104 @@ +:root { + font-family: "Futura LT Book"; +} + +.modal-container { + width: 70%; + height: auto; + background-color: white; + outline: none !important; + padding: 20px 20px; + border-radius: 12px; + + h2 { + margin: 0; + } + + max-height: 100%; + overflow-y: scroll; +} + +.modal { + display: flex; + position: fixed; + align-items: center; + justify-content: center; + align-items: center; + overflow-y: scroll; + outline: none !important; +} + +.close-icon-container { + display: flex; + justify-content: end; +} + +.close-icon { + font-size: 24px; + padding-right: 20px; + cursor: pointer; + color: #243e74; +} + +.answer-container { + width: 100%; + border-bottom: 1px solid #ccc; + padding-bottom: 20px; + margin-top: 20px; + + p { + margin-top: 8px; + margin-bottom: 8px; + font-size: 16px; + } +} + +.button-group { + display: flex; + width: 100%; + align-items: center; + gap: 10px; +} + +.button-approve { + padding: 10px; + border: none; + outline: none; + border-radius: 5px; + background-color: rgb(6, 158, 41); + margin: 5px; + color: #fff; + width: 120px; + font-size: 12px; + font-weight: bold; + transition: background-color 200ms; +} + +.button-delete { + padding: 10px; + border: none; + outline: none; + border-radius: 5px; + background-color: #fc0254; + margin: 5px; + color: #fff; + width: 120px; + font-size: 12px; + font-weight: bold; + transition: background-color 200ms; + text-align: center; +} + +.button-delete:hover { + background-color: #fc3779; +} + +@media screen and (max-width:768px) { + .modal-container { + width: 90%; + } + + .close-icon { + padding-right: 5px; + } +} \ No newline at end of file diff --git a/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/index.js b/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/index.js new file mode 100644 index 00000000..adb6d86f --- /dev/null +++ b/frontend/src/pages/Admin/Components/Faq/Q&A/AnswersModel/index.js @@ -0,0 +1 @@ +export * from './AnswersModel' \ No newline at end of file diff --git a/frontend/src/pages/Admin/Components/Faq/Q&A/QandA.jsx b/frontend/src/pages/Admin/Components/Faq/Q&A/QandA.jsx index 8d4eb61d..54a8dff4 100644 --- a/frontend/src/pages/Admin/Components/Faq/Q&A/QandA.jsx +++ b/frontend/src/pages/Admin/Components/Faq/Q&A/QandA.jsx @@ -2,21 +2,16 @@ import React, { useEffect, useState } from "react"; import style from "./qanda.module.scss"; import { getAllQuestions, - deleteAnswer, deleteQuestion, updateQuestionStatus, - updateAnswerStatus, - getAnswers, } from "../../../../../service/Faq"; import { SimpleToast } from "../../../../../components/util/Toast/Toast"; -import Loader from "../../../../../components/util/Loader"; -import { hideToast, showToast } from "../../../../../service/toastService"; +import { hideToast } from "../../../../../service/toastService"; import Modal from "@material-ui/core/Modal"; import Button from "@material-ui/core/Button"; import Typography from "@material-ui/core/Typography"; import { makeStyles } from "@material-ui/core/styles"; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import ExpandLessIcon from '@material-ui/icons/ExpandLess'; +import { AnswersModel } from "./AnswersModel/AnswersModel"; const useStyles = makeStyles((theme) => ({ modal: { @@ -40,8 +35,8 @@ const useStyles = makeStyles((theme) => ({ export function QandA() { const [cards, setCards] = useState([]); - const [expandedCards, setExpandedCards] = useState({}); - const [isLoaded, setIsLoaded] = useState(false); + const [open, setOpen] = useState(false) + const [currentQuesId, setCurrentQuesId] = useState("") const [toast, setToast] = useState({ toastStatus: false, toastType: "", @@ -52,10 +47,9 @@ export function QandA() { const classes = useStyles(); const getQuestions = async () => { - setIsLoaded(true); + setToast({ toastStatus: true, toastMessage: "Loading...", toastType: "info" }) const data = await getAllQuestions(setToast, toast); setCards(data); - setIsLoaded(false); }; const handleOpenConfirmModal = (id) => { @@ -82,58 +76,11 @@ export function QandA() { await updateQuestionStatus(id, status, setToast); }; - const handleDeleteAnswer = async (answerId) => { - const questionId = Object.keys(expandedCards)[0]; - const prevAnswers = expandedCards[questionId]?.answers || []; - - setExpandedCards((prev) => ({ - ...prev, - [questionId]: { - ...prev[questionId], - answers: prevAnswers.filter(answer => answer._id !== answerId), - }, - })); - - await deleteAnswer(answerId, setToast); - }; - - const updateAnswer = async (id, status) => { - const questionId = Object.keys(expandedCards)[0]; - const prevAnswers = expandedCards[questionId]?.answers || []; - - setExpandedCards((prev) => ({ - ...prev, - [questionId]: { - ...prev[questionId], - answers: prevAnswers.map(answer => - answer._id === id ? { ...answer, isApproved: status } : answer - ), - }, - })); - - await updateAnswerStatus(id, status, setToast); - }; - const handleToggleExpand = async (id) => { - if (expandedCards[id]) { - setExpandedCards((prev) => { - const newExpanded = { ...prev }; - delete newExpanded[id]; - return newExpanded; - }); - } else { - setIsLoaded(true); - const aRes = await getAnswers(id, setToast); - setExpandedCards((prev) => ({ - ...prev, - [id]: { - answers: aRes, - }, - })); - setIsLoaded(false); - } + setCurrentQuesId(id) + setOpen(true) }; - + const handleCloseToast = (event, reason) => { if (reason === "clickaway") { @@ -148,8 +95,8 @@ export function QandA() { return (
+

Manage Q&A

-
{isLoaded && }
{cards?.map((qns, index) => (
@@ -172,55 +119,24 @@ export function QandA() { > {qns?.isApproved ? "Reject" : "Approve"} - + { + qns.isApproved == true && + + }
- {expandedCards[qns._id] && ( -
- {expandedCards[qns._id].answers?.length === 0 ? ( - No answers Found - ) : ( - expandedCards[qns._id].answers.map((a) => ( -
-
-
-

{a.answer}

-
- - -
-
-
-
- )) - )} -
- )}
))}