diff --git a/frontend/src/pages/Admin/Admin.jsx b/frontend/src/pages/Admin/Admin.jsx
index 312af9f5..1c649dee 100644
--- a/frontend/src/pages/Admin/Admin.jsx
+++ b/frontend/src/pages/Admin/Admin.jsx
@@ -24,7 +24,6 @@ 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";
import { Testimonial } from "./Components/Testimonial";
import { AddTestimonial } from "./Components/Testimonial/AddTestimonial";
import { ManageTestimonial } from "./Components/Testimonial/ManageTestimonial";
@@ -261,8 +260,6 @@ export const Admin = (props) => {
) : tab === 18 ? (
- ) : tab === 19 ? (
-
) : tab === 20 ? (
) : tab === 21 ? (
diff --git a/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/ManageQ&A.jsx b/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/ManageQ&A.jsx
deleted file mode 100644
index 4ba23be3..00000000
--- a/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/ManageQ&A.jsx
+++ /dev/null
@@ -1,199 +0,0 @@
-import { useEffect, useState } from "react";
-import style from "./manage.module.scss";
-import { makeStyles } from "@material-ui/core/styles";
-import Modal from "@material-ui/core/Modal";
-import Button from "@material-ui/core/Button";
-import Typography from "@material-ui/core/Typography";
-import { AiOutlineArrowLeft } from "react-icons/ai";
-import { SimpleToast } from "../../../../../../components/util/Toast/Toast";
-import Loader from "../../../../../../components/util/Loader";
-import { getQuestionById, deleteAnswer, deleteQuestion, updateQuestionStatus, updateAnswerStatus, getAnswers } from "../../../../../../service/Faq";
-import { hideToast, showToast } from "../../../../../../service/toastService";
-
-const useStyles = makeStyles((theme) => ({
- modal: {
- display: "flex",
- alignItems: "center",
- justifyContent: "center",
- },
- paper: {
- backgroundColor: theme.palette.background.paper,
- border: "2px solid #000",
- boxShadow: theme.shadows[5],
- padding: theme.spacing(2, 4, 3),
- },
- buttons: {
- display: "flex",
- marginTop: "10px",
- justifyContent: "center",
- gap: "10px",
- },
-}));
-
-export function Manageqa({ setTab, qId }) {
- const [ans, setAns] = useState([]);
- const [qns, setQns] = useState();
- const [toggle, setToggle] = useState(false);
- const [isLoaded, setIsLoaded] = useState(false);
- const [toast, setToast] = useState({
- toastStatus: false,
- toastType: "",
- toastMessage: "",
- });
- const [confirmDelete, setConfirmDelete] = useState(false);
- const [questionToDelete, setQuestionToDelete] = useState(null);
- const classes = useStyles();
-
- const getQuestion = async (id) => {
- setIsLoaded(true);
- const qRes = await getQuestionById(id, setToast);
- setQns(qRes);
- setIsLoaded(false);
- };
-
- const handleOpenConfirmModal = (id) => {
- setConfirmDelete(true);
- setQuestionToDelete(id);
- };
-
- const handleCloseConfirmModal = () => {
- setConfirmDelete(false);
- };
-
- const handleDeleteAnswer = async (answerId) => {
- await deleteAnswer(answerId, setToast);
- setToggle(!toggle);
- };
-
- const handleDeleteQuestion = async () => {
- await deleteQuestion(questionToDelete, setToast);
- setConfirmDelete(false);
- setTab(18);
- setToggle(!toggle);
- };
-
- const updateQuestion = async (id, status) => {
- await updateQuestionStatus(id, status, setToast);
- setToggle(!toggle);
- };
-
- const getAnswer = async (questionId) => {
- setIsLoaded(true);
- const aRes = await getAnswers(questionId, setToast);
- setAns(aRes);
- setIsLoaded(false);
- };
-
- const updateAnswer = async (id, status) => {
- await updateAnswerStatus(id, status, setToast);
- setToggle(!toggle);
- };
-
- const handleCloseToast = (event, reason) => {
- if (reason === "clickaway") {
- return;
- }
- hideToast(setToast);
- };
-
- useEffect(() => {
- getQuestion(qId);
- getAnswer(qId);
- }, [toggle]);
-
- return (
-
-
Manage Q&A
-
-
{isLoaded && }
- {!isLoaded && (
- <>
-
Question
-
-
-
-
{qns?.title}
-
-
{qns?.description}
-
-
-
-
-
- {qns?.tags?.map((tag) => (
-
{tag}
- ))}
-
-
-
-
-
- >
- )}
-
Answers
- {ans?.length === 0 ? (
-
No answers Found
- ) : (
-
- {ans?.map((a) => (
-
-
-
-
{a.answer}
-
-
-
-
-
-
-
- ))}
-
- )}
-
-
-
Confirm Delete
-
Are you sure you want to delete this question and all its answers?
-
-
-
-
-
-
- {toast.toastStatus && (
-
- )}
-
- );
-}
diff --git a/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/index.js b/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/index.js
deleted file mode 100644
index 747c2843..00000000
--- a/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./ManageQ&A";
diff --git a/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/manage.module.scss b/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/manage.module.scss
deleted file mode 100644
index 11c431d3..00000000
--- a/frontend/src/pages/Admin/Components/Faq/Q&A/ManageQ&A/manage.module.scss
+++ /dev/null
@@ -1,146 +0,0 @@
-.card-item {
- text-align: center;
- font-size: 1.5rem;
- border-radius: 1em;
- height: auto;
- width: 90%;
- margin: 10px auto 30px auto;
- display: inline-block;
- background-position: left center;
- transition: all 0.5s ease-in;
- background-color: #016795;
- box-shadow: 0.5em 0.5em 0.5em rgb(54, 53, 53);
- max-width: 400px;
-}
-
-.card-title {
- font-size: 1.8rem;
- margin-bottom: 1.5rem;
- line-height: 1.9rem;
- font-weight: bold;
- color: white;
-}
-.question{
- display: flex;
- justify-content: center;
-}
-.card-question {
- font-weight: bold;
- text-align: left;
- font-size: 1.3rem;
- width: 100%;
- margin: 2px;
-}
-
-.card-answer {
- font-weight: 600;
- text-align: left;
- font-size: 1.2rem;
- width: 100%;
- margin: 2px;
-}
-
-.questionBox{
- display: grid;
- justify-content: center;
- margin: 5px;
- gap: 10px;
-}
-
-.answerBox{
- display: grid;
- justify-content: center;
- margin: 5px;
- gap: 10px;
-}
-
-.card-info {
- color: white;
- margin-top: 10px;
- margin-bottom: 20px;
- display: flex;
- flex-direction: column;
- padding: 14px;
-}
-
-.head {
- text-align: center;
-}
-
-.button-group {
- display: flex;
- width: 100%;
- align-items: center;
- justify-content: center;
- gap: 10px;
- margin: 5px 2px 2px 2px;
-}
-
-.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: medium;
- font-weight: bold;
- transition: background-color 200ms;
-}
-
-.answer{
- display: grid;
- grid-template-columns: auto auto;
-}
-
-.button-edit:hover {
- background-color: rgb(10, 205, 53);
-}
-
-.button-delete {
- padding: 10px;
- border: none;
- outline: none;
- border-radius: 5px;
- background-color: #fc0254;
- margin: 5px;
- color: #fff;
- width: 120px;
- font-size: medium;
- font-weight: bold;
- transition: background-color 200ms;
- text-align: center;
-}
-
-.button-delete:hover {
- background-color: #fc3779;
-}
-
-.tags{
- background-color: gray;
- color: black;
- padding: 0px 4px;
- display: flex;
- justify-content: center;
- align-items: center;
- margin: 4px;
- height: 25px;
- margin-top: 0;
- border-radius: 10px;
- font-size: small;
-}
-@media (max-width:"900px") {
- .answerBox{
- display: block;
- }
- .questionBox{
- display: block;
- }
- .answer{
- display: flex;
- justify-content: center;
- flex-direction: column;
- }
-}
\ 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 8df877bb..8d4eb61d 100644
--- a/frontend/src/pages/Admin/Components/Faq/Q&A/QandA.jsx
+++ b/frontend/src/pages/Admin/Components/Faq/Q&A/QandA.jsx
@@ -1,26 +1,140 @@
import React, { useEffect, useState } from "react";
import style from "./qanda.module.scss";
-import { getAllQuestions } from "../../../../../service/Faq";
+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 } from "../../../../../service/toastService";
+import { hideToast, showToast } 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';
-export function QandA({ setTab, setQId, tab }) {
+const useStyles = makeStyles((theme) => ({
+ modal: {
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ paper: {
+ backgroundColor: theme.palette.background.paper,
+ border: "2px solid #000",
+ boxShadow: theme.shadows[5],
+ padding: theme.spacing(2, 4, 3),
+ },
+ buttons: {
+ display: "flex",
+ marginTop: "10px",
+ justifyContent: "center",
+ gap: "10px",
+ },
+}));
+
+export function QandA() {
const [cards, setCards] = useState([]);
+ const [expandedCards, setExpandedCards] = useState({});
const [isLoaded, setIsLoaded] = useState(false);
const [toast, setToast] = useState({
toastStatus: false,
toastType: "",
toastMessage: "",
});
+ const [confirmDelete, setConfirmDelete] = useState(false);
+ const [questionToDelete, setQuestionToDelete] = useState(null);
+ const classes = useStyles();
- const getdata = async () => {
+ const getQuestions = async () => {
setIsLoaded(true);
const data = await getAllQuestions(setToast, toast);
setCards(data);
setIsLoaded(false);
};
+ const handleOpenConfirmModal = (id) => {
+ setConfirmDelete(true);
+ setQuestionToDelete(id);
+ };
+
+ const handleCloseConfirmModal = () => {
+ setConfirmDelete(false);
+ setQuestionToDelete(null);
+ };
+
+ const handleDeleteQuestion = async () => {
+ await deleteQuestion(questionToDelete, setToast);
+ setCards(cards.filter(card => card._id !== questionToDelete));
+ setConfirmDelete(false);
+ };
+
+ const updateQuestion = async (id, status) => {
+ setCards(cards.map(card =>
+ card._id === id ? { ...card, isApproved: status } : card
+ ));
+
+ 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);
+ }
+ };
+
+
const handleCloseToast = (event, reason) => {
if (reason === "clickaway") {
return;
@@ -29,43 +143,97 @@ export function QandA({ setTab, setQId, tab }) {
};
useEffect(() => {
- getdata();
- }, [tab]);
+ getQuestions();
+ }, []);
return (
Manage Q&A
-
{isLoaded ? : null}
+
{isLoaded && }
- {cards?.map((d, index) => (
+ {cards?.map((qns, index) => (
-
{d.title}
-
-
{d.description}
-
+
{qns.title}
-
Status
{`${d.isApproved ? "Approved" : "Not Approved"}`}
+ {qns.description}
- {d.tags.map((tag, idx) => (
-
- {tag.value || tag}
-
- ))}
+
+ {qns?.tags?.map((tag) => (
+
{tag}
+ ))}
+
+
+
+
+
+ {expandedCards[qns._id] && (
+
+ {expandedCards[qns._id].answers?.length === 0 ? (
+
No answers Found
+ ) : (
+ expandedCards[qns._id].answers.map((a) => (
+
+
+
+
{a.answer}
+
+
+
+
+
+
+
+ ))
+ )}
+
+ )}
))}
+
+
+
Confirm Delete
+
Are you sure you want to delete this question and all its answers?
+
+
+
+
+
+
{toast.toastStatus && (
div > .tags {
- background-color: gray;
+.manage {
+ width: 120px;
+ background-color: white;
color: black;
- padding: 0px 4px;
- display: flex;
+ margin-bottom: 20px;
+ margin-top: 15px;
+ padding: 10px;
+ border: none;
+ border-radius: 5px;
+}
+
+.card-item {
+ text-align: center;
+ font-size: 1.5rem;
+ border-radius: 1em;
+ height: auto;
+ width: 90%;
+ margin: 10px auto 30px auto;
+ display: block;
+ background-position: left center;
+ transition: all 0.5s ease-in;
+ background-color: #016795;
+ box-shadow: 0.5em 0.5em 0.5em rgb(54, 53, 53);
+ max-width: 400px;
+}
+
+.card-answer {
+ font-weight: 600;
+ text-align: left;
+ font-size: 1.2rem;
+ width: 100%;
+ margin: 2px;
+}
+
+.questionBox {
+ display: grid;
+ justify-content: center;
+ margin: 5px;
+ gap: 10px;
+}
+
+.answerBox {
+ display: grid;
justify-content: center;
+ margin: 5px;
+ gap: 10px;
+}
+
+.card-info {
+ color: white;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ display: flex;
+ flex-direction: column;
+ padding: 14px;
+}
+
+.button-group {
+ display: flex;
+ width: 100%;
align-items: center;
- margin: 4px;
- height: 18px;
- margin-top: 0;
- border-radius: 10px;
- font-size: x-small;
+ justify-content: center;
+ gap: 10px;
+ margin: 5px 2px 2px 2px;
}
-.manage{
+.button-approve {
+ padding: 10px;
+ border: none;
+ outline: none;
+ border-radius: 5px;
+ background-color: rgb(6, 158, 41);
+ margin: 5px;
+ color: #fff;
width: 120px;
- background-color: white;
- color: black;
- margin-bottom: 20px;
- margin-top: 15px;
+ font-size: medium;
+ 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: medium;
+ font-weight: bold;
+ transition: background-color 200ms;
+ text-align: center;
+}
+
+.button-delete:hover {
+ background-color: #fc3779;
+}
+
+.tags {
+ background-color: gainsboro;
+ color: black;
+ padding: 0px 4px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin: 4px;
+ height: 25px;
+ margin-top: 0;
+ border-radius: 4px;
+ font-size: small;
+}
+
+@media (max-width: 900px) {
+ .answerBox {
+ display: block;
+ }
+ .questionBox {
+ display: block;
+ }
+ .answer {
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ }
}
diff --git a/frontend/src/pages/Q&A/AnswerModel/AnswerModel.jsx b/frontend/src/pages/Q&A/AnswerModel/AnswerModel.jsx
index a0f7bfc4..aaf075af 100644
--- a/frontend/src/pages/Q&A/AnswerModel/AnswerModel.jsx
+++ b/frontend/src/pages/Q&A/AnswerModel/AnswerModel.jsx
@@ -1,16 +1,32 @@
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
import { Modal, Backdrop, Fade } from '@material-ui/core';
import { SimpleToast } from '../../../components/util/Toast'
-import {postAnswer} from '../../../service/Faq'
+import {postAnswer,getAnswers} from '../../../service/Faq'
import style from './AnswerModel.scss'
export function AnswerModel(props) {
const [answer, setAnswer] = useState("")
+ const[answers,setAnswers]=useState([])
const [toast, setToast] = useState({
toastStatus: false,
toastType: "",
toastMessage: "",
});
+ const filterAnswers=(fetchedAnswers)=>{
+ return fetchedAnswers.filter((ans)=>{return ans.isApproved==true})
+ }
+ async function fetchAnswers(){
+ const data=await getAnswers(props.data._id,setToast)
+ setAnswers(filterAnswers(data))
+ }
+ useEffect(()=>{
+ 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())} ${String(messageTime.getHours()%12 || 12).padStart(2,'0')}:${String(messageTime.getMinutes()).padStart(2,'0')} ${messageTime.getHours()>=12?'pm':'am'}`
+ }
const Tags = [
{ value: "ml" },
{ value: "open-source" },
@@ -75,7 +91,7 @@ export function AnswerModel(props) {
props && props.data?.tags?.map((tag, index) => {
if (tag)
return (
- #{Tags[index].value}
+ #{tag}
)
})
}
@@ -84,6 +100,27 @@ export function AnswerModel(props) {
{ setAnswer(e.target.value) }} value={answer} type="text" placeholder="Post your answer" />
+ Answers ({answers.length})
+ {
+ answers.length==0?
+ No answers found...
+ :
+
+ {
+ answers.map((ans,index)=>{
+ return(
+
+
+
{ans.created_by}
+
{timeStampFormatter(ans.created_on)}
+
+
{ans.answer}
+
+ )
+ })
+ }
+
+ }
diff --git a/frontend/src/pages/Q&A/AnswerModel/AnswerModel.scss b/frontend/src/pages/Q&A/AnswerModel/AnswerModel.scss
index a087fd0f..3524d2a8 100644
--- a/frontend/src/pages/Q&A/AnswerModel/AnswerModel.scss
+++ b/frontend/src/pages/Q&A/AnswerModel/AnswerModel.scss
@@ -1,6 +1,7 @@
-:root{
+:root {
font-family: "Futura LT Book";
}
+
.modal-container {
width: 70%;
height: auto;
@@ -8,9 +9,13 @@
outline: none !important;
padding: 20px 20px;
border-radius: 12px;
- h2{
+
+ h2 {
margin: 0;
}
+
+ max-height: 100%;
+ overflow-y: scroll;
}
.modal {
@@ -22,44 +27,52 @@
overflow-y: scroll;
outline: none !important;
}
-.close-icon-container{
+
+.close-icon-container {
display: flex;
justify-content: end;
}
-.close-icon{
+
+.close-icon {
font-size: 24px;
padding-right: 20px;
cursor: pointer;
- color:#243e74;
+ color: #243e74;
}
-.ques-title{
- color:#243e74;
+
+.ques-title {
+ color: #243e74;
}
-.ques-description{
+
+.ques-description {
font-size: 16px;
margin: 10px auto;
}
-.tag-container{
+
+.tag-container {
width: 100%;
display: flex;
gap: 8px;
flex-wrap: wrap;
}
-.answer-form{
+
+.answer-form {
width: 100%;
margin: 14px auto;
display: flex;
justify-content: space-between;
gap: 8px;
}
-.answer-field{
+
+.answer-field {
width: 85%;
padding: 10px 20px;
outline: none;
border: 1px solid #ccc;
border-radius: 8px;
}
-.post-answer-btn{
+
+.post-answer-btn {
width: 15%;
padding: 10px 20px;
background-color: #243e74;
@@ -68,17 +81,52 @@
border-radius: 8px;
outline: none;
}
+
+.answer-title {
+ color: #243e74;
+}
+
+.answer-container {
+ width: 100%;
+ border-bottom: 1px solid #ccc;
+ padding-bottom: 20px;
+ margin-top: 20px;
+
+ p {
+ margin-top: 8px;
+ font-size: 16px;
+ }
+}
+
+.answer-header {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+
+ h5 {
+ margin: 0;
+ }
+
+ p {
+ font-size: 12px;
+ margin: 0;
+ }
+}
+
@media screen and (max-width:768px) {
- .modal-container{
+ .modal-container {
width: 90%;
}
- .close-icon{
+
+ .close-icon {
padding-right: 5px;
}
- .answer-field{
+
+ .answer-field {
width: 70%;
}
- .post-answer-btn{
+
+ .post-answer-btn {
width: 25%;
}
}
\ No newline at end of file