diff --git a/admin/src/pages/Users.tsx b/admin/src/pages/Users.tsx index 34ae33a3..94f5e1a6 100644 --- a/admin/src/pages/Users.tsx +++ b/admin/src/pages/Users.tsx @@ -1,184 +1,138 @@ -import { useState } from "react"; -import Navbar from "../components/Navbar" +import { useState, useEffect } from "react"; +import axios from "axios"; +import Navbar from "../components/Navbar"; import SideBar from "../components/SideBar"; +import { useRecoilValue } from "recoil"; +import { tokenState } from "../store/atoms/auth"; +import toast from "react-hot-toast"; + +export interface IUser { + id: string; + username: string; + email: string; + verified: boolean; + blocked: boolean; + createdAt: string; + comments:[]; + posts: []; + following: []; +} const Users = () => { const [sidebarOpen, setSidebarOpen] = useState(false); + const [allUsers, setAllUsers] = useState([]); + const token = useRecoilValue(tokenState); const toggleSidebar = () => { setSidebarOpen(!sidebarOpen); }; + useEffect(() => { + const fetchUsers = async () => { + try { + const response = await axios.get("/api/v1/admin/allUsers", { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + setAllUsers(response.data.allUsers.reverse()); + } catch (error) { + console.error("Error fetching users:", error); + } + }; + + fetchUsers(); + }, [token]); + + const handleBlock = async (userId: string) => { + try { + const response = await axios.patch( + `/api/v1/admin/block/${userId}`, + {}, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + toast.success(response.data.message); + setAllUsers(allUsers.map(user => user.id === userId ? { ...user, blocked: true } : user)); + } catch (error) { + console.error("Error blocking user:", error); + toast.error("Error blocking user"); + } + }; + + const handleUnblock = async (userId: string) => { + try { + const response = await axios.patch( + `/api/v1/admin/unblock/${userId}`, + {}, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + toast.success(response.data.message); + setAllUsers(allUsers.map(user => user.id === userId ? { ...user, blocked: false } : user)); + } catch (error) { + console.error("Error unblocking user:", error); + toast.error("Error unblocking user"); + } + }; + return (
- +
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Name - - Posts - - followers - - Action -
- profile-pic -
-
Neil Sims
-
neil.sims@flowbite.com
-
-
- 10 - - 7 - - -
- profile-pic -
-
Neil Sims
-
neil.sims@flowbite.com
-
-
- 10 - - 7 - - -
- profile-pic -
-
Neil Sims
-
neil.sims@flowbite.com
-
-
- 10 - - 7 - - -
- profile-pic -
-
Neil Sims
-
neil.sims@flowbite.com
-
-
- 10 - - 7 - - -
- profile-pic -
-
Neil Sims
-
neil.sims@flowbite.com
-
-
- 10 - - 7 - - -
- profile-pic -
-
Neil Sims
-
neil.sims@flowbite.com
-
-
- 10 - - 7 - - -
- profile-pic -
-
Neil Sims
-
neil.sims@flowbite.com
-
-
- 10 - - 7 - - -
-
+ +
+ + + + + + + + + + + + + + {allUsers.map(user => ( + + + + + + + + + + ))} + +
PhotoNamesignup AtPostsFollowersCommentsAction
profile-pic +
+ {user.username} + {user.email} +
+
{new Date(user.createdAt).toLocaleDateString()}{user.posts.length}{user.following.length}{user.comments.length} + {user.blocked ? ( + + ) : ( + + )} +
+
- ) -} + ); +}; -export default Users +export default Users; diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 1f114466..baa0228c 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -19,6 +19,7 @@ model User { email String passwordHash String verified Boolean @default(false) + blocked Boolean @default(false) otp Int? isAdmin Boolean @default(false) posts Post[] @relation("authorPosts") diff --git a/backend/src/routes/admin/controller.ts b/backend/src/routes/admin/controller.ts index 7a0b7322..496e6fe7 100644 --- a/backend/src/routes/admin/controller.ts +++ b/backend/src/routes/admin/controller.ts @@ -75,4 +75,74 @@ export const adminProfileController = async (req: UserAuthRequest, res: Response res.status(200).json({ user, }); -}; \ No newline at end of file +}; + +export const blockUserController = async (req: Request, res: Response) => { + const { userId } = req.params; + + try { + const user = await prisma.user.update({ + where: { id: userId }, + data: { blocked: true }, + }); + + res.status(200).json({ + message: `User ${user.username} has been blocked.`, + }); + } catch (error) { + res.status(500).json({ + error: "An unexpected exception occurred!", + }); + } +}; + +export const unblockUserController = async (req: Request, res: Response) => { + const { userId } = req.params; + + try { + const user = await prisma.user.update({ + where: { id: userId }, + data: { blocked: false }, + }); + + res.status(200).json({ + message: `User ${user.username} has been unblocked.`, + }); + } catch (error) { + res.status(500).json({ + error: "An unexpected exception occurred!", + }); + } +}; + +export const allUserForAdmin = async (req: Request, res:Response) => { + try{ + const allUsers = await prisma.user.findMany({ + where: { + isAdmin:false + }, + select: { + id:true, + username:true, + email:true, + blocked:true, + posts:true, + createdAt:true, + comments:true, + following: { + select: { + id: true + } + } + }, + }); + res.status(200).json({ + message: "Successfully fetched All Users!", + allUsers, + }); + }catch(error){ + res.status(500).json({ + error: "An unexpected exception occurred!", + }); + } +} \ No newline at end of file diff --git a/backend/src/routes/admin/route.ts b/backend/src/routes/admin/route.ts index 123a94d7..4fb10648 100644 --- a/backend/src/routes/admin/route.ts +++ b/backend/src/routes/admin/route.ts @@ -1,5 +1,5 @@ import {Router} from 'express'; -import { adminLoginController, adminProfileController } from './controller'; +import { adminLoginController, adminProfileController, allUserForAdmin, blockUserController, unblockUserController } from './controller'; import { isAdmin } from '../../middleware/adminAuth'; const adminRouter = Router(); @@ -8,4 +8,10 @@ adminRouter.post("/login", adminLoginController); adminRouter.get("/me", isAdmin,adminProfileController ); +adminRouter.patch('/block/:userId', isAdmin, blockUserController); + +adminRouter.patch('/unblock/:userId', isAdmin, unblockUserController); + +adminRouter.get('/allUsers',isAdmin,allUserForAdmin); + export default adminRouter; \ No newline at end of file