Skip to content

Commit

Permalink
Merge pull request #509 from MeetDOD/issue-499
Browse files Browse the repository at this point in the history
Feat: Added showing admin which user reacted to which post successfully issue 499
  • Loading branch information
akbatra567 authored Jul 26, 2024
2 parents ed55bcc + 1fd7499 commit 7178ca3
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 1 deletion.
2 changes: 2 additions & 0 deletions admin/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Graphs from "./pages/Graphs";
import ContactMessages from "./pages/ContactMessages";
import Comments from "./pages/Comments";
import Layout from "./components/Layout";
import Reactions from "./pages/Reactions";
// import axios from "axios";
// axios.defaults.baseURL = "http://localhost:3001/";

Expand Down Expand Up @@ -46,6 +47,7 @@ function App() {
<Route path="statistics" element={<Graphs />} />
<Route path="contactmessages" element={<ContactMessages />} />
<Route path="comments" element={<Comments />} />
<Route path="reactions" element={<Reactions />} />
<Route path="*" element={<PageNotFound />} />
</Routes>
</AuthenticatedRoute>
Expand Down
2 changes: 2 additions & 0 deletions admin/src/components/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { VscGraphScatter } from "react-icons/vsc";
import { MdOutlineAttachEmail } from "react-icons/md";
import { FaRegComments } from "react-icons/fa";
import GoogleTranslate from './GoogleTranslate';
import { VscReactions } from "react-icons/vsc";

const SideBar = ({ sidebarOpen, toggleSidebar }: { sidebarOpen: boolean, toggleSidebar: () => void }) => {
const location = useLocation();
Expand All @@ -35,6 +36,7 @@ const SideBar = ({ sidebarOpen, toggleSidebar }: { sidebarOpen: boolean, toggleS
<Link to="/admin/posts" className={linkClasses('/admin/posts')}><IoNewspaperOutline size={23} className='mr-3'/>All Posts</Link>
<Link to="/admin/contactmessages" className={linkClasses('/admin/contactmessages')}><MdOutlineAttachEmail size={23} className='mr-3'/>Messages</Link>
<Link to="/admin/comments" className={linkClasses('/admin/comments')}><FaRegComments size={23} className='mr-3'/>Comments</Link>
<Link to="/admin/reactions" className={linkClasses('/admin/reactions')}><VscReactions size={23} className='mr-3'/>Reactions</Link>
<Link to="/admin/statistics" className={linkClasses('/admin/statistics')}><VscGraphScatter size={23} className='mr-3'/>Statistics</Link>
</nav>
</div>
Expand Down
95 changes: 95 additions & 0 deletions admin/src/pages/Reactions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { useState, useEffect } from "react";
import axios from "axios";
import { useRecoilValue } from "recoil";
import { tokenState } from "../store/atoms/auth";
import { ColorRing } from 'react-loader-spinner';
import { MdAddReaction } from "react-icons/md";
import { IReaction} from "../types";

const Reactions = () => {
const [reactions, setReactions] = useState<IReaction[]>([]);
const [loading, setLoading] = useState(true);
const token = useRecoilValue(tokenState);

document.title = "Style Share Admin | Manage Reactions 📊"

useEffect(() => {
const fetchReactions = async () => {
try {
const response = await axios.get("/api/v1/admin/getreactions", {
headers: {
Authorization: `Bearer ${token}`,
},
});
setReactions(response.data.reactions.reverse());
setLoading(false);
} catch (error) {
console.error("Error fetching reactions:", error);
setLoading(true);
}
};

fetchReactions();
}, [token]);

return (
<div>
<div className="flex-1 flex flex-col lg:ml-80">
<div className="mx-5 mb-5">
<span className="flex items-center text-xl font-bold decoration-sky-500 decoration-dotted underline">
<div className='inline-block p-2 text-white bg-[#000435] rounded-lg mr-2'>
<MdAddReaction size={23} />
</div>
All Reactions
</span>
</div>
{loading ?
<div className="flex justify-center items-center h-80">
<ColorRing
visible={true}
height="100"
width="100"
colors={['#000435', 'rgb(14 165 233)', 'rgb(243 244 246)','#000435','rgb(14 165 233)']}
/>
</div>
:
<div className="mx-5 lg:mr-11 overflow-x-auto shadow-md rounded-xl mb-5">
<table className="w-full rtl:text-right text-gray-500 dark:text-gray-400">
<thead className="text-xs md:text-sm text-white uppercase bg-sky-500 text-center">
<tr>
<th scope="col" className="px-5 py-3">Photo</th>
<th scope="col" className="px-6 py-3 text-left">User</th>
<th scope="col" className="px-9 py-3">Reaction Type</th>
<th scope="col" className="px-6 py-3 ">Post Title</th>
<th scope="col" className="px-6 py-3">Author</th>
<th scope="col" className="px-6 py-3">Reacted At</th>
</tr>
</thead>
<tbody>
{reactions.map(reaction => (
<tr key={reaction.user.id + reaction.post.id + reaction.type} className="text-xs md:text-sm text-center border-b bg-[#000435] border-sky-500 hover:bg-blue-950 hover:text-white">
<td className="pl-7">
<img className="h-10 w-10 rounded-full" src={`https://ui-avatars.com/api/?name=${reaction.user?.username}&background=0ea5e9&color=fff&rounded=true&bold=true`} alt="profile-pic" />
</td>
<td className="px-6 py-4 font-semibold">
<div className="flex flex-col items-start">
<span className="font-bold">{reaction.user.username}</span>
<span className="font-thin text-gray-300">{reaction.user.email}</span>
</div>
</td>
<td className="py-4 font-semibold">{reaction.type}</td>
<td className="px-8 py-4 font-semibold">{reaction.post.title}</td>
<td className="px-8 py-4 font-semibold">{reaction.post.author.username}</td>
<td className="px-8 py-4 font-semibold">{new Date(reaction.createdAt).toLocaleDateString()}</td>
</tr>
))}
</tbody>
</table>
</div>
}
</div>
</div>
);
};

export default Reactions;
8 changes: 8 additions & 0 deletions admin/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface IPost {
comments:[];
following: [];
isFollowing: boolean;
avatar?:string;
}

export interface IStats {
Expand All @@ -55,4 +56,11 @@ export interface IContactMessage{
subject:string,
message:string,
createdAt:number
}

export interface IReaction {
type: 'Like' | 'Celebrate' | 'Support' | 'Love' | 'Insightful' | 'Funny';
createdAt: number;
user: IUser;
post: IPost;
}
42 changes: 42 additions & 0 deletions backend/src/routes/admin/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,4 +472,46 @@ export const deleteCommentController = async (req: UserAuthRequest, res: Respons
error: "An unexpected exception occurred!",
});
}
};

export const getPostReactionsController = async (req: Request, res: Response) => {
try {
const reactions = await prisma.reaction.findMany({
select: {
type: true,
createdAt: true,
user: {
select: {
id: true,
username: true,
email: true,
},
},
post: {
select: {
id: true,
title: true,
description: true,
author: {
select: {
id: true,
username: true,
email: true,
},
},
},
},
},
});

res.status(200).json({
message: "Successfully fetched all reactions!",
reactions,
});
} catch (error) {
console.error(error);
res.status(500).json({
error: "An unexpected exception occurred!",
});
}
};
4 changes: 3 additions & 1 deletion backend/src/routes/admin/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Router} from 'express';
import { adminLoginController, adminProfileController, allUserForAdmin, blockUserController, unblockUserController, getAdminPostsController, getAdminTrendingPostsController, getAdminStatsController, getGraphsStatsController, updatePostController, deletePostController, getPostByIdController, getAllContactMessages, deleteCommentController } from './controller';
import { getPostReactionsController,adminLoginController, adminProfileController, allUserForAdmin, blockUserController, unblockUserController, getAdminPostsController, getAdminTrendingPostsController, getAdminStatsController, getGraphsStatsController, updatePostController, deletePostController, getPostByIdController, getAllContactMessages, deleteCommentController } from './controller';
import { isAdmin } from '../../middleware/adminAuth';

const adminRouter = Router();
Expand Down Expand Up @@ -32,4 +32,6 @@ adminRouter.get("/geallcontactmessages", isAdmin,getAllContactMessages);

adminRouter.delete('/comments/delete/:commentId', isAdmin, deleteCommentController);

adminRouter.get('/getreactions', isAdmin, getPostReactionsController);

export default adminRouter;

0 comments on commit 7178ca3

Please sign in to comment.