diff --git a/frontend/src/pages/Q&A/AnswerModel/AnswerModel.jsx b/frontend/src/pages/Q&A/AnswerModel/AnswerModel.jsx
index aaf075af..f7d087e4 100644
--- a/frontend/src/pages/Q&A/AnswerModel/AnswerModel.jsx
+++ b/frontend/src/pages/Q&A/AnswerModel/AnswerModel.jsx
@@ -1,31 +1,34 @@
import React, { useEffect, useState } from "react";
import { Modal, Backdrop, Fade } from '@material-ui/core';
import { SimpleToast } from '../../../components/util/Toast'
-import {postAnswer,getAnswers} from '../../../service/Faq'
+import { postAnswer, getAnswers,upvoteAnswer,downvoteAnswer } from '../../../service/Faq'
import style from './AnswerModel.scss'
export function AnswerModel(props) {
+ let dark=props.theme
const [answer, setAnswer] = useState("")
- const[answers,setAnswers]=useState([])
+ const [author, setAuthor] = useState("")
+ const [answers, setAnswers] = useState([])
const [toast, setToast] = useState({
toastStatus: false,
toastType: "",
toastMessage: "",
});
- const filterAnswers=(fetchedAnswers)=>{
- return fetchedAnswers.filter((ans)=>{return ans.isApproved==true})
+ const filterAnswers = (fetchedAnswers) => {
+ return fetchedAnswers.filter((ans) => { return ans.isApproved == true })
}
- async function fetchAnswers(){
- const data=await getAnswers(props.data._id,setToast)
+ 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'}`
+ 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())} ${String(messageTime.getHours() % 12 || 12).padStart(2, '0')}:${String(messageTime.getMinutes()).padStart(2, '0')} ${messageTime.getHours() >= 12 ? 'pm' : 'am'}`
}
const Tags = [
{ value: "ml" },
@@ -43,22 +46,31 @@ export function AnswerModel(props) {
];
function handleSubmit(e) {
e.preventDefault()
- if(answer!=""){
- let data={question_id:props.data._id,answer,created_on:new Date(),created_by:"Anonymous"}
- postAnswer(data,setToast)
+ if (answer != "" && author != "") {
+ let data = { question_id: props.data._id, answer, created_on: new Date(), created_by: author }
+ postAnswer(data, setToast)
setAnswer("")
+ setAuthor("")
props.handleClose(false)
- }else{
- setToast({toastStatus:true,toastMessage:"Please enter your answer",toastType:"error"})
+ } else {
+ setToast({ toastStatus: true, toastMessage: "Please fill both the fields", toastType: "error" })
}
}
+ const handleUpvote=async(answerId)=>{
+ await upvoteAnswer(answerId,setToast)
+ fetchAnswers()
+ }
+ const handleDownvote=async(answerId)=>{
+ await downvoteAnswer(answerId,setToast)
+ fetchAnswers()
+ }
return (
{toast.toastStatus && (
{setToast({toastMessage:"",toastStatus:false,toastType:""})}}
+ handleCloseToast={() => { setToast({ toastMessage: "", toastStatus: false, toastType: "" }) }}
severity={toast.toastType}
/>
)}
@@ -75,18 +87,18 @@ export function AnswerModel(props) {
}}
>
-
+
- {
+ {
setAnswer("")
props.handleClose(false)
- }}>
-
+ }}>
+
-
{props.data?.title}
-
{props.data?.description}
-
+
{props.data?.title}
+
{props.data?.description}
+
{
props && props.data?.tags?.map((tag, index) => {
if (tag)
@@ -97,29 +109,44 @@ export function AnswerModel(props) {
}
-
Answers ({answers.length})
+
Answers ({answers.length})
{
- answers.length==0?
-
No answers found...
- :
-
- {
- answers.map((ans,index)=>{
- return(
-
-
-
{ans.created_by}
-
{timeStampFormatter(ans.created_on)}
+ answers.length == 0 ?
+
No answers found...
+ :
+
+ {
+ answers.map((ans, index) => {
+ return (
+
+
+
{ans.created_by || "Anonymous"}
+
{timeStampFormatter(ans.created_on)}
+
+
{ans.answer}
+
+
+
+
-
{ans.answer}
-
- )
- })
- }
-
+ )
+ })
+ }
+
}
diff --git a/frontend/src/pages/Q&A/AnswerModel/AnswerModel.scss b/frontend/src/pages/Q&A/AnswerModel/AnswerModel.scss
index 3524d2a8..0f486d26 100644
--- a/frontend/src/pages/Q&A/AnswerModel/AnswerModel.scss
+++ b/frontend/src/pages/Q&A/AnswerModel/AnswerModel.scss
@@ -94,6 +94,7 @@
p {
margin-top: 8px;
+ margin-bottom: 8px;
font-size: 16px;
}
}
@@ -112,6 +113,17 @@
margin: 0;
}
}
+.vote-btn {
+ background-color: #69a9dd;
+ outline: 1px solid white;
+ color: white;
+ border: none;
+ border-radius: 5px;
+ padding: 5px;
+ margin: 5px;
+ cursor: pointer;
+ }
+
@media screen and (max-width:768px) {
.modal-container {
@@ -127,6 +139,12 @@
}
.post-answer-btn {
- width: 25%;
+ width: 100%;
+ }
+ .answer-form{
+ flex-direction: column;
+ }
+ .answer-field{
+ width: 100%;
}
}
\ No newline at end of file
diff --git a/frontend/src/pages/Q&A/Q&A.jsx b/frontend/src/pages/Q&A/Q&A.jsx
index 26698e49..6b6cae33 100644
--- a/frontend/src/pages/Q&A/Q&A.jsx
+++ b/frontend/src/pages/Q&A/Q&A.jsx
@@ -50,6 +50,7 @@ function Ques(props) {
title: "",
description: "",
tags: [],
+ created_by:""
});
const handleCloseToast = () => {
@@ -79,6 +80,7 @@ function Ques(props) {
title: Joi.string().required(),
body: Joi.string().required(),
tags: Joi.required(),
+ created_by:Joi.string().required()
};
const validate = () => {
@@ -188,6 +190,9 @@ function Ques(props) {
))}
+
+
- {item?.created_by||"Anonymous"}
+
@@ -214,7 +219,7 @@ function Ques(props) {
}}>Answers
)
- )};
+ )}
}
{toast.toastStatus && (
@@ -251,6 +256,34 @@ function Ques(props) {
+
+
+
+
+
+ {formerrors["title"] ? (
+
* {formerrors["title"]}
+ ) : (
+
+ )}
+
+
+
{
export const postAnswer = async (data, setToast) => {
try {
- showToast(setToast,"Posting...","info")
+ showToast(setToast, "Posting...", "info")
const url = `${END_POINT}/answers/`;
const response = await fetch(url, {
method: "POST",
@@ -339,8 +339,8 @@ export const postAnswer = async (data, setToast) => {
body: JSON.stringify(data),
});
const res = await response.json();
- if(response.status==200)
- showToast(setToast, "Thanks for answering, it has been sent to admins for review and will appear here on approval","success");
+ if (response.status == 200)
+ showToast(setToast, "Thanks for answering, it has been sent to admins for review and will appear here on approval", "success");
else
showToast(setToast, "Failed to Post Answer", "error");
return res;
@@ -349,3 +349,45 @@ export const postAnswer = async (data, setToast) => {
throw new Error("Failed to post answer");
}
}
+
+export const upvoteAnswer = async (answerId, handleToast) => {
+ try {
+ const response = await fetch(`${END_POINT}/answers/upvote`, {
+ method: "PATCH",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ credentials: "include",
+ body: JSON.stringify({ answerId }),
+ });
+ if (!response.ok) {
+ throw new Error("Failed to upvote question");
+ }
+ showToast(handleToast, "Upvote Successfully");
+ return response.json();
+ } catch (error) {
+ showToast(handleToast, "You have already voted", "error");
+ throw new Error("Failed to upvote answer");
+ }
+}
+
+export const downvoteAnswer = async(answerId, handleToast) => {
+ try {
+ const response = await fetch(`${END_POINT}/answers/downvote`, {
+ method: "PATCH",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ credentials: "include",
+ body: JSON.stringify({ answerId }),
+ });
+ if (!response.ok) {
+ throw new Error("Failed to downvote question");
+ }
+ showToast(handleToast, "Downvote Successfully");
+ return response.json();
+ } catch (error) {
+ showToast(handleToast, "You have already voted", "error");
+ throw new Error("Failed to downvote answer");
+ }
+}
\ No newline at end of file