From 1fe4e486ff8b09b496a652ce4ff16de5a4cfd251 Mon Sep 17 00:00:00 2001 From: meet Date: Fri, 2 Aug 2024 17:07:01 +0530 Subject: [PATCH] Added download report feature in Users, Posts and Contact Messages --- admin/src/pages/ContactMessages.tsx | 29 ++++ admin/src/pages/Posts.tsx | 29 ++++ admin/src/pages/Users.tsx | 29 ++++ backend/src/routes/admin/controller.ts | 184 +++++++++++++++++++++++++ backend/src/routes/admin/route.ts | 8 +- 5 files changed, 278 insertions(+), 1 deletion(-) diff --git a/admin/src/pages/ContactMessages.tsx b/admin/src/pages/ContactMessages.tsx index 66fbf306..9c746629 100644 --- a/admin/src/pages/ContactMessages.tsx +++ b/admin/src/pages/ContactMessages.tsx @@ -8,6 +8,7 @@ import 'react-responsive-modal/styles.css'; import '../styles/Model.css' import { ColorRing } from 'react-loader-spinner'; import { MdMessage } from "react-icons/md"; +import { TbReportAnalytics } from "react-icons/tb"; const ContactMessages = () => { const [contactMessages, setContactMessages] = useState([]); @@ -37,6 +38,27 @@ const ContactMessages = () => { fetchMessages(); }, [token]); + const downloadContactMessagesReport = async () => { + try { + const response = await axios.get('/api/v1/admin/downloadcontactmessagereport', { + headers: { + Authorization: `Bearer ${token}`, + }, + responseType: 'blob', + }); + + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', 'StyleShare_Contact_Messages_Report.pdf'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } catch (error) { + console.error('Error downloading the Contact Messages report:', error); + } + }; + const handleOpenModal = (message: IContactMessage) => { setSelectedMessage(message); setOpen(true); @@ -68,6 +90,7 @@ const ContactMessages = () => { /> : + <>
@@ -112,6 +135,12 @@ const ContactMessages = () => {
+
+ +
+ } diff --git a/admin/src/pages/Posts.tsx b/admin/src/pages/Posts.tsx index 5ed51183..f2cdc2d1 100644 --- a/admin/src/pages/Posts.tsx +++ b/admin/src/pages/Posts.tsx @@ -7,6 +7,7 @@ import toast from "react-hot-toast"; import { Link } from "react-router-dom"; import { ColorRing } from 'react-loader-spinner'; import { BsFillPostcardFill } from "react-icons/bs"; +import { TbReportAnalytics } from "react-icons/tb"; const Posts = () => { const [posts, setPosts] = useState([]); @@ -48,6 +49,27 @@ const Posts = () => { } }; + const downloadPostsReport = async () => { + try { + const response = await axios.get('/api/v1/admin/downloadpostsreport', { + headers: { + Authorization: `Bearer ${token}`, + }, + responseType: 'blob', + }); + + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', 'StyleShare_Posts_Report.pdf'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } catch (error) { + console.error('Error downloading the Posts report:', error); + } + }; + return (
@@ -69,6 +91,7 @@ const Posts = () => { />
: + <>
@@ -107,6 +130,12 @@ const Posts = () => {
+
+ +
+ }
diff --git a/admin/src/pages/Users.tsx b/admin/src/pages/Users.tsx index 431efd13..257e100a 100644 --- a/admin/src/pages/Users.tsx +++ b/admin/src/pages/Users.tsx @@ -6,6 +6,7 @@ import toast from "react-hot-toast"; import { IUser } from "../types"; import { ColorRing } from 'react-loader-spinner'; import { FaUsers } from "react-icons/fa"; +import { TbReportAnalytics } from "react-icons/tb"; const Users = () => { const [allUsers, setAllUsers] = useState([]); @@ -71,6 +72,27 @@ const Users = () => { } }; + const downloadUsersReport = async () => { + try { + const response = await axios.get('/api/v1/admin/downloadusersreport', { + headers: { + Authorization: `Bearer ${token}`, + }, + responseType: 'blob', + }); + + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', 'StyleShare_Users_Report.pdf'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } catch (error) { + console.error('Error downloading the Users report:', error); + } + }; + return (
@@ -92,6 +114,7 @@ const Users = () => { />
: + <>
@@ -135,6 +158,12 @@ const Users = () => {
+
+ +
+ }
diff --git a/backend/src/routes/admin/controller.ts b/backend/src/routes/admin/controller.ts index f4d59bf6..75e3918e 100644 --- a/backend/src/routes/admin/controller.ts +++ b/backend/src/routes/admin/controller.ts @@ -633,6 +633,190 @@ export const downloadReportController = async (req: UserAuthRequest, res: Respon doc.fontSize(12).text(`${index + 1}. ${post.title}`); }); + doc.end(); + } catch (error) { + console.error(error); + res.status(500).json({ + error: "An unexpected exception occurred!", + }); + } +}; + +export const downloadUsersReportController = async (req: Request, res: Response) => { + try { + const currentDate = new Date().toLocaleDateString(); + + const users = await prisma.user.findMany({ + select: { + username: true, + email: true, + createdAt: true, + blocked: true, + }, + }); + + const totalUsers = users.length; + + const doc = new PDFDocument(); + let filename = `StyleShare_Users_Report.pdf`; + filename = encodeURIComponent(filename); + + res.setHeader('Content-disposition', `attachment; filename="${filename}"`); + res.setHeader('Content-type', 'application/pdf'); + + doc.pipe(res); + + doc.fontSize(25).text('StyleShare Users Report', { + align: 'center' + }); + + doc.moveDown(); + doc.fontSize(20).text('Overview', { + align: 'center' + }); + doc.moveDown(); + doc.fontSize(15).text(`Date: ${currentDate}`); + doc.moveDown(); + + doc.fontSize(12).text(`Total Users: ${totalUsers}`); + doc.moveDown(); + + doc.fontSize(15).text('User Details:'); + doc.moveDown(); + + users.forEach(user => { + doc.text(`Username: ${user.username}`); + doc.text(`Email: ${user.email}`); + doc.text(`Created At: ${user.createdAt.toLocaleDateString()}`); + doc.text(`Blocked: ${user.blocked ? 'Yes' : 'No'}`); + doc.moveDown(); + }); + + doc.end(); + } catch (error) { + console.error(error); + res.status(500).json({ + error: "An unexpected exception occurred!", + }); + } +}; + +export const downloadPostsReportController = async (req: Request, res: Response) => { + try { + const currentDate = new Date().toLocaleDateString(); + + const posts = await prisma.post.findMany({ + select: { + title: true, + description: true, + createdAt: true, + author: { + select: { + username: true, + email: true, + }, + }, + }, + }); + + const totalPosts = posts.length; + + const doc = new PDFDocument(); + let filename = `StyleShare_Posts_Report.pdf`; + filename = encodeURIComponent(filename); + + res.setHeader('Content-disposition', `attachment; filename="${filename}"`); + res.setHeader('Content-type', 'application/pdf'); + + doc.pipe(res); + + doc.fontSize(25).text('StyleShare Posts Report', { + align: 'center' + }); + + doc.moveDown(); + doc.fontSize(20).text('Overview', { + align: 'center' + }); + doc.moveDown(); + doc.fontSize(15).text(`Date: ${currentDate}`); + doc.moveDown(); + + doc.fontSize(12).text(`Total Posts: ${totalPosts}`); + doc.moveDown(); + + doc.fontSize(15).text('Post Details:'); + doc.moveDown(); + + posts.forEach(post => { + doc.text(`Title: ${post.title}`); + doc.text(`Description: ${post.description}`); + doc.text(`Created At: ${post.createdAt.toLocaleDateString()}`); + doc.text(`Author: ${post.author.username} (${post.author.email})`); + doc.moveDown(); + }); + + doc.end(); + } catch (error) { + console.error(error); + res.status(500).json({ + error: "An unexpected exception occurred!", + }); + } +}; + +export const downloadContactMessagesReportController = async (req: Request, res: Response) => { + try { + const currentDate = new Date().toLocaleDateString(); + + const contactMessages = await prisma.contactMessage.findMany({ + select: { + name: true, + email: true, + subject: true, + message: true, + createdAt: true, + }, + }); + + const totalContactMessages = contactMessages.length; + + const doc = new PDFDocument(); + let filename = `StyleShare_Contact_Messages_Report.pdf`; + filename = encodeURIComponent(filename); + + res.setHeader('Content-disposition', `attachment; filename="${filename}"`); + res.setHeader('Content-type', 'application/pdf'); + + doc.pipe(res); + + doc.fontSize(25).text('StyleShare Contact Messages Report', { + align: 'center' + }); + + doc.moveDown(); + doc.fontSize(20).text('Overview', { + align: 'center' + }); + doc.moveDown(); + doc.fontSize(15).text(`Date: ${currentDate}`); + doc.moveDown(); + + doc.fontSize(12).text(`Total Contact Messages: ${totalContactMessages}`); + doc.moveDown(); + + doc.fontSize(15).text('Contact Message Details:'); + doc.moveDown(); + + contactMessages.forEach(message => { + doc.text(`Name: ${message.name}`); + doc.text(`Email: ${message.email}`); + doc.text(`Subject: ${message.subject}`); + doc.text(`Message: ${message.message}`); + doc.text(`Created At: ${message.createdAt.toLocaleDateString()}`); + doc.moveDown(); + }); + doc.end(); } catch (error) { console.error(error); diff --git a/backend/src/routes/admin/route.ts b/backend/src/routes/admin/route.ts index 0dbbf246..88fcc792 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, downloadUsersReportController, downloadContactMessagesReportController, downloadPostsReportController } from './controller'; import { isAdmin } from '../../middleware/adminAuth'; const adminRouter = Router(); @@ -38,4 +38,10 @@ adminRouter.get('/favorites', isAdmin, getFavoritesController); adminRouter.get('/downloadReport',isAdmin, downloadReportController); +adminRouter.get('/downloadusersreport',isAdmin, downloadUsersReportController); + +adminRouter.get('/downloadpostsreport',isAdmin, downloadPostsReportController); + +adminRouter.get('/downloadcontactmessagereport',isAdmin, downloadContactMessagesReportController); + export default adminRouter; \ No newline at end of file