From a1c0a9c8f942d794129bb6ba02d11507594ac3c6 Mon Sep 17 00:00:00 2001 From: meet Date: Fri, 2 Aug 2024 15:53:57 +0530 Subject: [PATCH] Added Testimonial control by the admin --- admin/src/App.tsx | 2 + admin/src/components/SideBar.tsx | 2 + admin/src/pages/UsersFeedbacks.tsx | 117 +++++++++++++++++++++++++ admin/src/types.ts | 11 ++- backend/prisma/schema.prisma | 1 + backend/src/routes/admin/controller.ts | 44 ++++++++++ backend/src/routes/admin/route.ts | 6 +- backend/src/routes/user/controller.ts | 3 + 8 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 admin/src/pages/UsersFeedbacks.tsx diff --git a/admin/src/App.tsx b/admin/src/App.tsx index c7ba29f4..34864931 100644 --- a/admin/src/App.tsx +++ b/admin/src/App.tsx @@ -17,6 +17,7 @@ import Comments from "./pages/Comments"; import Layout from "./components/Layout"; import Favorites from "./pages/Favorites"; import Reactions from "./pages/Reactions"; +import UsersFeedbacks from "./pages/UsersFeedbacks"; // import axios from "axios"; // axios.defaults.baseURL = "http://localhost:3001/"; @@ -43,6 +44,7 @@ function App() { } /> } /> } /> + } /> } /> } /> } /> diff --git a/admin/src/components/SideBar.tsx b/admin/src/components/SideBar.tsx index 30e7b353..eb6b2d0d 100644 --- a/admin/src/components/SideBar.tsx +++ b/admin/src/components/SideBar.tsx @@ -11,6 +11,7 @@ import { FaRegComments } from "react-icons/fa"; import GoogleTranslate from './GoogleTranslate'; import { RiHeartsLine } from "react-icons/ri"; import { VscReactions } from "react-icons/vsc"; +import { VscFeedback } from "react-icons/vsc"; const SideBar = ({ sidebarOpen, toggleSidebar }: { sidebarOpen: boolean, toggleSidebar: () => void }) => { const location = useLocation(); @@ -39,6 +40,7 @@ const SideBar = ({ sidebarOpen, toggleSidebar }: { sidebarOpen: boolean, toggleS Comments Favorites Reactions + Feedbacks Statistics diff --git a/admin/src/pages/UsersFeedbacks.tsx b/admin/src/pages/UsersFeedbacks.tsx new file mode 100644 index 00000000..5811e175 --- /dev/null +++ b/admin/src/pages/UsersFeedbacks.tsx @@ -0,0 +1,117 @@ +import { useState, useEffect } from "react"; +import axios from "axios"; +import { useRecoilValue } from "recoil"; +import { tokenState } from "../store/atoms/auth"; +import { IFeedback } from "../types"; +import { ColorRing } from 'react-loader-spinner'; +import { VscFeedback } from "react-icons/vsc"; +import toast from "react-hot-toast"; + +const GetFeedbacks = () => { + const [feedbacks, setFeedbacks] = useState([]); + const [loading, setLoading] = useState(true); + const token = useRecoilValue(tokenState); + + document.title = "Style Share Admin | Manage Feedbacks 💬" + + useEffect(() => { + const fetchFeedbacks = async () => { + try { + const response = await axios.get("/api/v1/admin/getfeedback", { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + setFeedbacks(response.data); + setLoading(false); + } catch (error) { + console.error("Error fetching feedbacks:", error); + setLoading(true); + } + }; + + fetchFeedbacks(); + }, [token]); + + const handleToggleVisibility = async (feedbackId: string) => { + try { + await axios.patch( + `/api/v1/admin/toggleFeedbackVisibility/${feedbackId}`, + {}, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + toast.success("Feedback visibility updated"); + setFeedbacks(feedbacks.map(feedback => + feedback.id === feedbackId ? { ...feedback, visible: !feedback.visible } : feedback + )); + } catch (error) { + console.error("Error updating feedback visibility:", error); + toast.error("Error updating feedback visibility"); + } + }; + + return ( +
+
+
+ +
+ +
+ All Feedbacks +
+
+ {loading ? +
+ +
+ : +
+ + + + + + + + + + + + {feedbacks.map(feedback => ( + + + + + + + + ))} + +
UserCommentRatingCreated AtAction
+ {feedback.user.username} + {feedback.comment}{feedback.rating}{new Date(feedback.createdAt).toLocaleDateString()} + +
+
+ } +
+
+ ); +}; + +export default GetFeedbacks; diff --git a/admin/src/types.ts b/admin/src/types.ts index 6da377d5..b75de323 100644 --- a/admin/src/types.ts +++ b/admin/src/types.ts @@ -80,4 +80,13 @@ export interface IReaction { createdAt: number; user: IUser; post: IPost; -} \ No newline at end of file +} + +export interface IFeedback { + id: string; + comment: string; + rating: number; + createdAt: string; + user: IUser; + visible: boolean; +} diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 06bbd664..f0134b58 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -43,6 +43,7 @@ model Feedback { rating Int comment String userId String @db.ObjectId + visible Boolean @default(false) user User @relation("userFeedbacks", fields: [userId], references: [id]) createdAt DateTime @default(now()) } diff --git a/backend/src/routes/admin/controller.ts b/backend/src/routes/admin/controller.ts index f4d59bf6..b9f433d7 100644 --- a/backend/src/routes/admin/controller.ts +++ b/backend/src/routes/admin/controller.ts @@ -640,4 +640,48 @@ export const downloadReportController = async (req: UserAuthRequest, res: Respon error: "An unexpected exception occurred!", }); } +}; + +export const getFeedbacks = async (req: Request, res: Response) => { + try { + const feedbacks = await prisma.feedback.findMany({ + include: { + user: { + select: { + id: true, + username: true, + avatar: true, + }, + }, + }, + }); + + res.status(200).json(feedbacks); + } catch (error) { + console.error('Error fetching feedbacks:', error); + res.status(500).json({ error: 'An unexpected error occurred!' }); + } +}; + +export const toggleFeedbackVisibility = async (req: Request, res: Response) => { + const { id } = req.params; + try { + const feedback = await prisma.feedback.findUnique({ + where: { id }, + }); + + if (!feedback) { + return res.status(404).json({ error: 'Feedback not found' }); + } + + const updatedFeedback = await prisma.feedback.update({ + where: { id }, + data: { visible: !feedback.visible }, + }); + + res.status(200).json(updatedFeedback); + } catch (error) { + console.error('Error toggling feedback visibility:', error); + res.status(500).json({ error: 'An unexpected error occurred!' }); + } }; \ No newline at end of file diff --git a/backend/src/routes/admin/route.ts b/backend/src/routes/admin/route.ts index 0dbbf246..29fad702 100644 --- a/backend/src/routes/admin/route.ts +++ b/backend/src/routes/admin/route.ts @@ -1,5 +1,5 @@ import {Router} from 'express'; -import { getPostReactionsController,getFavoritesController,adminLoginController, adminProfileController, allUserForAdmin, blockUserController, unblockUserController, getAdminPostsController, getAdminTrendingPostsController, getAdminStatsController, getGraphsStatsController, updatePostController, deletePostController, getPostByIdController, getAllContactMessages, deleteCommentController, downloadReportController } from './controller'; +import { getPostReactionsController,getFavoritesController,adminLoginController, adminProfileController, allUserForAdmin, blockUserController, unblockUserController, getAdminPostsController, getAdminTrendingPostsController, getAdminStatsController, getGraphsStatsController, updatePostController, deletePostController, getPostByIdController, getAllContactMessages, deleteCommentController, downloadReportController, getFeedbacks, toggleFeedbackVisibility } from './controller'; import { isAdmin } from '../../middleware/adminAuth'; const adminRouter = Router(); @@ -38,4 +38,8 @@ adminRouter.get('/favorites', isAdmin, getFavoritesController); adminRouter.get('/downloadReport',isAdmin, downloadReportController); +adminRouter.get('/getfeedback',isAdmin, getFeedbacks); + +adminRouter.patch('/toggleFeedbackVisibility/:id', isAdmin, toggleFeedbackVisibility); + export default adminRouter; \ No newline at end of file diff --git a/backend/src/routes/user/controller.ts b/backend/src/routes/user/controller.ts index 5e9798b2..524593d8 100644 --- a/backend/src/routes/user/controller.ts +++ b/backend/src/routes/user/controller.ts @@ -671,6 +671,9 @@ export const createFeedback = async (req: UserAuthRequest, res: Response) => { export const getFeedbacks = async (req: Request, res: Response) => { try { const feedbacks = await prisma.feedback.findMany({ + where:{ + visible:true + }, include: { user: { select: {