diff --git a/frontend/src/pages/Admin/Components/Faq/AddFaq/AddFaq.jsx b/frontend/src/pages/Admin/Components/Faq/AddFaq/AddFaq.jsx index b9941f29..edf536f7 100644 --- a/frontend/src/pages/Admin/Components/Faq/AddFaq/AddFaq.jsx +++ b/frontend/src/pages/Admin/Components/Faq/AddFaq/AddFaq.jsx @@ -2,19 +2,24 @@ import React, { useRef, useState } from "react"; import styles from "./add-faq.module.scss"; import { Button2 } from "../../../../../components/util/Button/index"; import { SimpleToast } from "../../../../../components/util/Toast/Toast"; -import { END_POINT } from "../../../../../config/api"; +import { postFaq } from "../../../../../service/Faq"; export function AddFaq() { const tagRef = useRef(); const [tags, setTags] = useState([]); const [formData, setFormData] = useState({ question: "", answer: "", tags: [] }); const [errorObj, setErrorObj] = useState({}); - const [successToast, setSuccessToast] = useState(false); - const [errorToast, setErrorToast] = useState(false); + const [toast, setToast] = useState({ + toastMessage: "", + toastStatus: false, + toastType: "success", + }); const handleCloseToast = () => { - setSuccessToast(false); - setErrorToast(false); + setToast({ + ...toast, + toastStatus: false, + }); }; const handleValidation = () => { @@ -72,25 +77,10 @@ export function AddFaq() { const handleSubmit = async (e) => { e.preventDefault(); if (handleValidation()) { - try { - const response = await fetch(`${END_POINT}/faq/postFaq`, { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("token")}`, - }, - body: JSON.stringify(formData), - }); - - if (response.status === 200) { - setSuccessToast(true); - setFormData({ question: "", answer: "", tags: [] }); - setTags([]); - } else { - setErrorToast(true); - } - } catch (error) { - setErrorToast(true); + const { success } = await postFaq(formData, setToast, toast); + if (success) { + setFormData({ question: "", answer: "", tags: [] }); + setTags([]); } } }; @@ -193,16 +183,10 @@ export function AddFaq() { - ); diff --git a/frontend/src/pages/Admin/Components/Faq/ManageFaq/ManageFaq.jsx b/frontend/src/pages/Admin/Components/Faq/ManageFaq/ManageFaq.jsx index d63e5d37..89104325 100644 --- a/frontend/src/pages/Admin/Components/Faq/ManageFaq/ManageFaq.jsx +++ b/frontend/src/pages/Admin/Components/Faq/ManageFaq/ManageFaq.jsx @@ -6,29 +6,32 @@ import Typography from "@material-ui/core/Typography"; import Button from "@material-ui/core/Button"; import { Edit, Delete } from "@material-ui/icons"; import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; -import { END_POINT } from "../../../../../config/api"; +import { getFaq, deleteFaq, updateFaq } from "../../../../../service/Faq"; import Loader from "../../../../../components/util/Loader"; import style from "./manage-faq.module.scss"; -import { SimpleToast } from "../../../../../components/util/Toast"; import { Button2 } from "../../../../../components/util/Button/index"; +import { SimpleToast } from "../../../../../components/util/Toast"; export function ManageFaq() { const [faqs, setFaqs] = useState([]); const [expanded, setExpanded] = useState(false); const [isFetching, setIsFetching] = useState(true); - const [open, setOpenToast] = useState(false); - const [toastMessage, setToastMessage] = useState(""); - const [severity, setSeverity] = useState("success"); const [reload, setReload] = useState(false); const [faqObject, setFaqObject] = useState({}); const [openEditDialog, setOpenEditDialog] = useState(false); const [formErrors, setFormErrors] = useState({}); + const [toast, setToast] = useState({ + open: false, + message: "", + severity: "success", + }); - const handleCloseToast = useCallback(() => { - setTimeout(() => { - setOpenToast(false); - }, 500); - }, []); + const handleCloseToast = () => { + setToast({ + ...toast, + toastStatus: false, + }); + }; const handleChange = (panel) => (event, isExpanded) => { setExpanded(isExpanded ? panel : false); @@ -37,72 +40,21 @@ export function ManageFaq() { const fetchAllFaq = useCallback(async () => { setIsFetching(true); try { - const response = await fetch(`${END_POINT}/faq/getFaq`); - const data = await response.json(); - setFaqs(data.Faq); + const faqsData = await getFaq(); + setFaqs(faqsData); setIsFetching(false); - } catch (err) { - console.log(err.message); - setIsFetching(false); - } - }, []); - - const deleteFaq = async (faqId) => { - setIsFetching(true); - const url = `${END_POINT}/faq/deleteFaq`; - const body = { faqId: faqId }; - const headers = { - "Content-Type": "application/json", - authorization: `Bearer ${localStorage.getItem("token")}`, - }; - try { - const response = await fetch(url, { - method: "PUT", - headers: headers, - body: JSON.stringify(body), - }); - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - const data = await response.json(); - setToastMessage(data.message); - setOpenToast(true); - setSeverity("success"); - setReload(!reload); } catch (error) { - setToastMessage("Failed to delete Faq"); - setOpenToast(true); - setSeverity("error"); - } finally { + console.error("Failed to fetch FAQs:", error.message); setIsFetching(false); } - }; + }, [reload]); - const updateFaq = async (faqId, updatedFaqDetails) => { + const handleDelete = async (faqId) => { try { - const response = await fetch(`${END_POINT}/faq/updateFaq`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - authorization: `Bearer ${localStorage.getItem("token")}`, - }, - body: JSON.stringify({ faqId, ...updatedFaqDetails }), - }); - - if (!response.ok) { - throw new Error("Failed to update FAQ"); - } - - const data = await response.json(); - setToastMessage(data.message); - setOpenToast(true); - setSeverity("success"); + await deleteFaq(faqId, setToast, toast); setReload((prev) => !prev); } catch (error) { - console.error("Failed to update FAQ:", error.message); - setToastMessage("Failed to update FAQ"); - setOpenToast(true); - setSeverity("error"); + console.error("Failed to delete FAQ:", error.message); } }; @@ -114,8 +66,14 @@ export function ManageFaq() { const handleSaveEdit = () => { if (validateForm()) { - updateFaq(faqObject._id, faqObject); - setOpenEditDialog(false); + updateFaq(faqObject._id, faqObject, setToast, toast) + .then(() => { + setReload((prev) => !prev); + setOpenEditDialog(false); + }) + .catch((error) => { + console.error("Failed to update FAQ:", error.message); + }); } }; @@ -159,11 +117,7 @@ export function ManageFaq() { > - } + expandIcon={} aria-controls="panel1a-content" id="panel1a-header" > @@ -176,18 +130,12 @@ export function ManageFaq() { }} >

- -    {faq.question} +   {faq.question}

- - {faq.answer} - + {faq.answer}
@@ -263,7 +211,7 @@ export function ManageFaq() { onChange={(e) => setFaqObject({ ...faqObject, - tags: e.target.value.split(",").map(tag => tag.trim()), + tags: e.target.value.split(",").map((tag) => tag.trim()), }) } className={style["faq-input"]} @@ -290,9 +238,9 @@ export function ManageFaq() {
)} 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 index 3a125f80..4ba23be3 100644 --- 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 @@ -1,5 +1,4 @@ import { useEffect, useState } from "react"; -import { END_POINT } from "../../../../../../config/api"; import style from "./manage.module.scss"; import { makeStyles } from "@material-ui/core/styles"; import Modal from "@material-ui/core/Modal"; @@ -8,6 +7,8 @@ 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: { @@ -32,7 +33,7 @@ const useStyles = makeStyles((theme) => ({ export function Manageqa({ setTab, qId }) { const [ans, setAns] = useState([]); const [qns, setQns] = useState(); - const [toogle, setToogle] = useState(false); + const [toggle, setToggle] = useState(false); const [isLoaded, setIsLoaded] = useState(false); const [toast, setToast] = useState({ toastStatus: false, @@ -42,29 +43,12 @@ export function Manageqa({ setTab, qId }) { const [confirmDelete, setConfirmDelete] = useState(false); const [questionToDelete, setQuestionToDelete] = useState(null); const classes = useStyles(); + 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 qRes = await getQuestionById(id, setToast); + setQns(qRes); + setIsLoaded(false); }; const handleOpenConfirmModal = (id) => { @@ -77,290 +61,131 @@ export function Manageqa({ setTab, qId }) { }; const handleDeleteAnswer = async (answerId) => { - try { - const url = `${END_POINT}/answers/deleteanswer`; - const response = await fetch(url, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("token")}`, - }, - body: JSON.stringify({ answerId }), - }); - - const data = await response.json(); - setToast({ - ...toast, - toastMessage: "Successfully deleted answer", - toastStatus: true, - toastType: "success", - }); - setToogle(!toogle); - } catch (error) { - console.log(error); - setToast({ - ...toast, - toastMessage: "Unable to delete answer", - toastStatus: true, - toastType: "error", - }); - } + await deleteAnswer(answerId, setToast); + setToggle(!toggle); }; const handleDeleteQuestion = async () => { - try { - const url = `${END_POINT}/question/deletequestion`; - const response = await fetch(url, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("token")}`, - }, - body: JSON.stringify({ questionId: questionToDelete }), - }); - - const data = await response.json(); - setToast({ - ...toast, - toastMessage: "Successfully deleted question", - toastStatus: true, - toastType: "success", - }); - setTab(18); - setToogle(!toogle); - } catch (error) { - console.log(error); - setToast({ - ...toast, - toastMessage: "Unable to delete question", - toastStatus: true, - toastType: "error", - }); - } + await deleteQuestion(questionToDelete, setToast); + setConfirmDelete(false); + setTab(18); + setToggle(!toggle); }; 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", - }); - } + await updateQuestionStatus(id, status, setToast); + setToggle(!toggle); }; 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", - }); - } + setIsLoaded(true); + const aRes = await getAnswers(questionId, setToast); + setAns(aRes); + setIsLoaded(false); }; 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", - }); - } + await updateAnswerStatus(id, status, setToast); + setToggle(!toggle); }; const handleCloseToast = (event, reason) => { if (reason === "clickaway") { return; } - setToast({ ...toast, toastStatus: false }); + hideToast(setToast); }; useEffect(() => { getQuestion(qId); getAnswer(qId); - }, [toogle]); + }, [toggle]); return (

Manage Q&A

-
+
setTab(18)} />
-
{isLoaded ? : null}
- {isLoaded || ( +
{isLoaded && }
+ {!isLoaded && ( <> -

Question

+

Question

-
-
-

{qns?.title}

-
-

{qns?.description}

-
- - +
+
+

{qns?.title}

+
+

{qns?.description}

+
+ + +
+
+ {qns?.tags?.map((tag) => ( +

{tag}

+ ))} +
-
- {qns?.tags?.map((tag) => ( -

{tag}

- ))} -
-
-
-

Answers

- - {ans?.length === 0 ? ( - No answers Found - ) : ( -
- {ans?.map((a) => ( -
-
-
-

{a.answer}

-
- - -
+ + )} +

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? - -
- - -
+ +
+ Confirm Delete + Are you sure you want to delete this question and all its answers? +
+ +
- - } +
+
{toast.toastStatus && ( { - setIsLoaded(true) - try { - const url = `${END_POINT}/question/getallquestions`; - const response = await fetch(url); - const res = await response.json(); - setCards(res); - } catch (error) { - console.log(error); - setToast({ - ...toast, - toastMessage: "Check network failed to fetch", - toastStatus: true, - toastType: "error", - }); - - } - setIsLoaded(false) + setIsLoaded(true); + const data = await getAllQuestions(setToast, toast); + setCards(data); + setIsLoaded(false); }; + const handleCloseToast = (event, reason) => { if (reason === "clickaway") { return; } - setToast({ ...toast, toastStatus: false }); + hideToast(setToast); }; + useEffect(() => { getdata(); }, [tab]); + return (

Manage Q&A

diff --git a/frontend/src/pages/Faq/Faq.jsx b/frontend/src/pages/Faq/Faq.jsx index 2006e6b3..3ddc82d5 100644 --- a/frontend/src/pages/Faq/Faq.jsx +++ b/frontend/src/pages/Faq/Faq.jsx @@ -6,7 +6,7 @@ import AccordionSummary from "@material-ui/core/AccordionSummary"; import Typography from "@material-ui/core/Typography"; import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; import style from "./faq.module.scss"; -import { END_POINT } from "../../config/api"; +import { getFaq } from "../../service/Faq"; import { SimpleToast } from "../../components/util/Toast"; import Loader from "../../components/util/Loader"; @@ -55,31 +55,16 @@ export function Faq(props) { setError(false); }; - const fetchFaqs = () => { - fetch(`${END_POINT}/faq/getFaq`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }) - .then((response) => - response.json().then((res) => { - if (response.status === 200) { - setFaqs(res.Faq); - setIsFetching(false); - } else { - setFaqs([]); - setIsFetching(false); - setError(true); - } - }) - ) - .catch((err) => { - setFaqs([]); - setIsFetching(false); - setError(true); - console.error("Unexpected Error occured: ", err); - }); + const fetchFaqs = async () => { + try { + const faqs = await getFaq(); + setFaqs(faqs); + setIsFetching(false); + } catch (error) { + setFaqs([]); + setError(true); + setIsFetching(false); + } }; useEffect(() => { diff --git a/frontend/src/pages/Q&A/Q&A.jsx b/frontend/src/pages/Q&A/Q&A.jsx index ad86635e..8a4262f8 100644 --- a/frontend/src/pages/Q&A/Q&A.jsx +++ b/frontend/src/pages/Q&A/Q&A.jsx @@ -1,68 +1,41 @@ -import React, { useEffect } from "react"; -import { Button2, Button1 } from "../../components/util/Button"; +import React, { useEffect, useState } from "react"; +import { Button2 } from "../../components/util/Button"; import style from "../Resources/components/ResourceSharingForm/resource-sharing-form.module.scss"; import "./Ques.scss"; -import { useState } from "react"; import Joi from "joi-browser"; import Loader from "../../components/util/Loader/index"; import { SimpleToast } from "../../components/util/Toast"; -import { END_POINT } from "../../config/api"; -import { - AirplayTwoTone, - ErrorSharp, - SettingsBluetoothSharp, -} from "@material-ui/icons"; +import { getAllQuestion, uploadData, upvote, downvote } from "../../service/Faq"; +import { showToast, hideToast } from "../../service/toastService"; function Ques(props) { let dark = props.theme; const Tags = [ - { - value: "ml", - }, - { - value: "open-source", - }, - { - value: "deap-learning", - }, - { - value: "cp", - }, - { - value: "block-chain", - }, - { - value: "mern", - }, - { - value: "android", - }, - { - value: "mean", - }, - { - value: "javascript", - }, - { - value: "java", - }, - { - value: "c++", - }, - { - value: "python", - }, + { value: "ml" }, + { value: "open-source" }, + { value: "deap-learning" }, + { value: "cp" }, + { value: "block-chain" }, + { value: "mern" }, + { value: "android" }, + { value: "mean" }, + { value: "javascript" }, + { value: "java" }, + { value: "c++" }, + { value: "python" }, ]; const [isUploadingData, setIsUploadingData] = useState(false); - const [open, setOpenToast] = useState(false); - const [toastMessage, setToastMessage] = useState(""); - const [severity, setSeverity] = useState("success"); const [isButtonPressed, setButtonPressed] = useState(false); const [checkedState, setCheckedState] = useState( new Array(Tags.length).fill(false) ); + const [toast, setToast] = useState({ + toastStatus: false, + toastType: "", + toastMessage: "", + }); const [loading, setLoading] = useState(true); const [formdata, setFormData] = useState({ @@ -71,11 +44,10 @@ function Ques(props) { tags: [], }); - const handleCloseToast = (event, reason) => { - setTimeout(() => { - setOpenToast(false); - }, 500); + const handleCloseToast = () => { + hideToast(setToast); }; + const handleOnChange = (position) => { const updatedCheckedState = checkedState.map((item, index) => index === position ? !item : item @@ -113,42 +85,6 @@ function Ques(props) { setFormErrors({}); }; - const uploadData = async (formdata) => { - try { - const url = `${END_POINT}/question`; - const response = await fetch(url, { - method: "POST", - headers: { - "content-type": "application/json", - }, - body: JSON.stringify(formdata), - }); - const data = await response.json(); - if (data.errStack) { - setToastMessage(`${data.errStack}`); - setOpenToast(true); - setSeverity("error"); - } else { - setToastMessage("Q&A added successfully!"); - setOpenToast(true); - setSeverity("success"); - } - setIsUploadingData(false); - - setFormData({ - title: "", - description: "", - tags: [], - }); - setFormErrors({}); - setCheckedState(new Array(Tags.length).fill(false)); - } catch (err) { - setIsUploadingData(false); - setToastMessage("Something went wrong!"); - setOpenToast(true); - setSeverity("error"); - } - }; const handleSubmit = (e) => { e.preventDefault(); let isValid = true; @@ -163,80 +99,44 @@ function Ques(props) { }); if (isValid && formdata.tags.length !== 0) { setIsUploadingData(true); - uploadData(formdata); + uploadData(formdata, setToast) + .then(() => { + setIsUploadingData(false); + setFormData({ + title: "", + description: "", + tags: [], + }); + setFormErrors({}); + setCheckedState(new Array(Tags.length).fill(false)); + }) + .catch(() => { + setIsUploadingData(false); + }); } }; - function ActiveButton() { - setButtonPressed(!isButtonPressed); - } - function DeactiveButton() { - setButtonPressed(!isButtonPressed); - } const [getQuestions, setQuestions] = useState([]); - function getQues() { - fetch(`${END_POINT}/question/getallquestions`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }) - .then((res) => res.json()) - .then((data) => { - setLoading(false); - setQuestions(data); - // console.log(data); - }); - } - - const upvote = async (questionId) => { - const response = await fetch(`${END_POINT}/question/upvote`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ questionId }), + const fetchQuestions = () => { + getAllQuestion(setToast).then((data) => { + setLoading(false); + setQuestions(data); }); - - if (!response.ok) { - setToastMessage("Failed to upvote question"); - setOpenToast(true); - setSeverity("error"); - throw new Error("Failed to upvote question"); - } - // const data = await response.json(); - getQues(); - setToastMessage("Upvote Successfully"); - setOpenToast(true); - setSeverity("success"); }; - const downvote = async (questionId) => { - const response = await fetch(`${END_POINT}/question/downvote`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ questionId }), - }); - - if (!response.ok) { - setToastMessage("Failed to downvote question"); - setOpenToast(true); - setSeverity("error"); - throw new Error("Failed to downvote question"); - } - // const data = await response.json(); - // console.log(data); - getQues(); - setToastMessage("Downvote Successfully"); - setOpenToast(true); - setSeverity("success"); + const handleUpvote = async (questionId) => { + await upvote(questionId, setToast); + fetchQuestions(); + }; + + const handleDownvote = async (questionId) => { + await downvote(questionId, setToast); + fetchQuestions(); }; useEffect(() => { - getQues(); + fetchQuestions(); }, []); return ( @@ -245,7 +145,7 @@ function Ques(props) { style={{ background: dark ? "#171717" : "white" }} > {getQuestions.length <= 0 ? ( - + ) : (
{getQuestions.map((item, key) => ( @@ -264,12 +164,12 @@ function Ques(props) {

Created At {new Date(item.createdAt).toLocaleString()}

- @@ -280,12 +180,14 @@ function Ques(props) {
)} - + {toast.toastStatus && ( + + )} {isButtonPressed ? (
-

@@ -313,7 +215,7 @@ function Ques(props) {
@@ -326,9 +228,7 @@ function Ques(props) { onChange={handleChange} /> -
+
{formerrors["title"] ? (
* {formerrors["title"]}
) : ( @@ -342,7 +242,7 @@ function Ques(props) {
@@ -354,13 +254,8 @@ function Ques(props) { value={formdata.description} onChange={handleChange} /> - -
+ +
{formerrors["body"] ? (
* {formerrors["body"]}
) : ( @@ -374,7 +269,7 @@ function Ques(props) {
@@ -427,10 +322,7 @@ function Ques(props) {
-
+
{isUploadingData ? ( @@ -466,14 +358,14 @@ function Ques(props) {

@@ -486,7 +378,7 @@ function Ques(props) { className={style["Ask-div-button"]} label="Ask Question" style={{ width: 200 }} - onClick={ActiveButton} + onClick={() => setButtonPressed(true)} />

diff --git a/frontend/src/service/Faq.jsx b/frontend/src/service/Faq.jsx new file mode 100644 index 00000000..f23e7c8b --- /dev/null +++ b/frontend/src/service/Faq.jsx @@ -0,0 +1,326 @@ +import { END_POINT } from "../config/api"; +import { showToast } from "./toastService"; + +export async function postFaq(formData, setToast, toast) { + try { + const response = await fetch(`${END_POINT}/faq/postFaq`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + body: JSON.stringify(formData), + }); + + if (response.ok) { + setToast({ + ...toast, + toastMessage: "FAQ has been added", + toastStatus: true, + toastType: "success", + }); + return { success: true }; + } else { + setToast({ + ...toast, + toastMessage: "Database Error", + toastStatus: true, + toastType: "error", + }); + return { success: false, error: "Database Error" }; + } + } catch (error) { + setToast({ + ...toast, + toastMessage: "Network Error", + toastStatus: true, + toastType: "error", + }); + return { success: false, error: "Network Error" }; + } + } + +export async function getFaq() { + try { + const response = await fetch(`${END_POINT}/faq/getFaq`); + if (!response.ok) { + throw new Error("Failed to fetch FAQs"); + } + const data = await response.json(); + return data.Faq; + } catch (error) { + console.error("Failed to fetch FAQs:", error.message); + throw new Error("Failed to fetch FAQs"); + } +} + +export const deleteFaq = async (faqId, setToast, toast) => { + const url = `${END_POINT}/faq/deleteFaq`; + const body = { faqId: faqId }; + const headers = { + "Content-Type": "application/json", + authorization: `Bearer ${localStorage.getItem("token")}`, + }; + try { + const response = await fetch(url, { + method: "PUT", + headers: headers, + body: JSON.stringify(body), + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + setToast({ + ...toast, + toastMessage: data.message, + toastStatus: true, + toastType: "success", + }); + return data.message; + } catch (error) { + console.error("Failed to delete FAQ:", error.message); + setToast({ + ...toast, + toastMessage: "Failed to delete FAQ", + toastStatus: true, + toastType: "error", + }); + throw new Error("Failed to delete FAQ"); + } +}; + +export const updateFaq = async (faqId, updatedFaqDetails, setToast, toast) => { + try { + const response = await fetch(`${END_POINT}/faq/updateFaq`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + authorization: `Bearer ${localStorage.getItem("token")}`, + }, + body: JSON.stringify({ faqId, ...updatedFaqDetails }), + }); + + if (!response.ok) { + throw new Error("Failed to update FAQ"); + } + + const data = await response.json(); + setToast({ + ...toast, + toastMessage: data.message, + toastStatus: true, + toastType: "success", + }); + return data.message; + } catch (error) { + console.error("Failed to update FAQ:", error.message); + setToast({ + ...toast, + toastMessage: "Failed to update FAQ", + toastStatus: true, + toastType: "error", + }); + throw new Error("Failed to update FAQ"); + } +}; + +export const getAllQuestions = async (setToast, toast) => { + try { + const response = await fetch(`${END_POINT}/question/getallquestions`); + if (!response.ok) { + throw new Error("Failed to fetch questions"); + } + const data = await response.json(); + return data; + } catch (error) { + console.error("Failed to fetch questions:", error.message); + showToast(setToast, "Check network failed to fetch", "error"); + return []; + } +}; + +export async function getQuestionById(id, setToast) { + const qUrl = `${END_POINT}/question/getQuestionById/${id}`; + try { + const qResponse = await fetch(qUrl); + const qRes = await qResponse.json(); + return qRes; + } catch (error) { + console.log(error); + showToast(setToast, "Failed to fetch question", "error"); + throw new Error("Failed to fetch question"); + } +} + +export async function deleteAnswer(answerId, setToast) { + const url = `${END_POINT}/answers/deleteanswer`; + try { + const response = await fetch(url, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + body: JSON.stringify({ answerId }), + }); + const data = await response.json(); + showToast(setToast, "Successfully deleted answer"); + return data; + } catch (error) { + console.log(error); + showToast(setToast, "Failed to delete answer", "error"); + throw new Error("Failed to delete answer"); + } +} + +export async function deleteQuestion(questionId, setToast) { + const url = `${END_POINT}/question/deletequestion`; + try { + const response = await fetch(url, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + body: JSON.stringify({ questionId }), + }); + const data = await response.json(); + showToast(setToast, "Successfully deleted question"); + return data; + } catch (error) { + console.log(error); + showToast(setToast, "Failed to delete question", "error"); + throw new Error("Failed to delete question"); + } +} + +export async function updateQuestionStatus(id, status, setToast) { + const qUrl = `${END_POINT}/question/updateStatus`; + try { + const qResponse = await fetch(qUrl, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + body: JSON.stringify({ id, status }), + }); + const qRes = await qResponse.json(); + showToast(setToast, "Question status updated successfully"); + return qRes; + } catch (error) { + console.log(error); + showToast(setToast, "Failed to update question status", "error"); + throw new Error("Failed to update question status"); + } +} + +export async function updateAnswerStatus(id, status, setToast) { + const aUrl = `${END_POINT}/answers/updateStatus`; + try { + const aResponse = await fetch(aUrl, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + body: JSON.stringify({ id, status }), + }); + const aRes = await aResponse.json(); + showToast(setToast, "Answer status updated successfully"); + return aRes; + } catch (error) { + console.log(error); + showToast(setToast, "Failed to update answer status", "error"); + throw new Error("Failed to update answer status"); + } +} + +export async function getAnswers(questionId, setToast) { + const aUrl = `${END_POINT}/answers/${questionId}`; + try { + const aResponse = await fetch(aUrl); + const aRes = await aResponse.json(); + return aRes.data; + } catch (error) { + console.log(error); + showToast(setToast, "Failed to fetch answers", "error"); + throw new Error("Failed to fetch answers"); + } +} + +export const getAllQuestion = async (handleToast) => { + try { + const response = await fetch(`${END_POINT}/question/getallquestions`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + const data = await response.json(); + return data; + } catch (error) { + showToast(handleToast, "Failed to fetch questions", "error"); + throw new Error("Failed to fetch questions"); + } +}; + +export const uploadData = async (formData, handleToast) => { + try { + const url = `${END_POINT}/question`; + const response = await fetch(url, { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(formData), + }); + const data = await response.json(); + showToast(handleToast, "Q&A added successfully"); + return data; + } catch (error) { + showToast(handleToast, "Failed to add Q&A", "error"); + throw new Error("Failed to add Q&A"); + } +}; + +export const upvote = async (questionId, handleToast) => { + try { + const response = await fetch(`${END_POINT}/question/upvote`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ questionId }), + }); + if (!response.ok) { + throw new Error("Failed to upvote question"); + } + showToast(handleToast, "Upvote Successfully"); + return response.json(); + } catch (error) { + showToast(handleToast, "Failed to upvote question", "error"); + throw new Error("Failed to upvote question"); + } +}; + +export const downvote = async (questionId, handleToast) => { + try { + const response = await fetch(`${END_POINT}/question/downvote`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ questionId }), + }); + if (!response.ok) { + throw new Error("Failed to downvote question"); + } + showToast(handleToast, "Downvote Successfully"); + return response.json(); + } catch (error) { + showToast(handleToast, "Failed to downvote question", "error"); + throw new Error("Failed to downvote question"); + } +}; \ No newline at end of file diff --git a/frontend/src/service/toastService.jsx b/frontend/src/service/toastService.jsx new file mode 100644 index 00000000..fe7f56ee --- /dev/null +++ b/frontend/src/service/toastService.jsx @@ -0,0 +1,16 @@ + +export const showToast = (setToast, message, type = "success") => { + setToast({ + toastStatus: true, + toastType: type, + toastMessage: message, + }); + }; + +export const hideToast = (setToast) => { + setToast({ + toastStatus: false, + toastType: "", + toastMessage: "", + }); +}; \ No newline at end of file