Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Added download report feature in comments, reactions and favorite in admin panel successfully issue 558 #559

Merged
merged 3 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions admin/src/pages/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { tokenState } from "../store/atoms/auth";
import toast from "react-hot-toast";
import { ColorRing } from 'react-loader-spinner';
import { FaComments } from "react-icons/fa";
import { TbReportAnalytics } from "react-icons/tb";

const Comments = () => {
const [posts, setPosts] = useState<IPost[]>([]);
Expand Down Expand Up @@ -47,6 +48,27 @@ const Comments = () => {
}
};

const downloadUsersCommentsReport = async () => {
try {
const response = await axios.get('/api/v1/admin/downloaduserscommentsreport', {
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_Comments_Report.pdf');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error('Error downloading users comments report:', error);
}
};

return (
<div>
<div className="flex-1 flex flex-col lg:ml-80">
Expand All @@ -68,6 +90,7 @@ const Comments = () => {
/>
</div>
:
<>
<div className="mx-5 lg:mr-11 overflow-x-auto shadow-md rounded-xl mb-5">
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead className="text-xs text-white uppercase bg-sky-500">
Expand Down Expand Up @@ -123,6 +146,12 @@ const Comments = () => {
</tbody>
</table>
</div>
<div className="mx-5 overflow-x-auto rounded-xl mb-5">
<button onClick={downloadUsersCommentsReport} className="flex items-center py-2.5 px-4 rounded-lg transition duration-200 bg-yellow-500 hover:bg-yellow-600 text-gray-100"><TbReportAnalytics size={23} className='mr-3'/>
Download Comments Info
</button>
</div>
</>
}
</div>
</div>
Expand Down
29 changes: 29 additions & 0 deletions admin/src/pages/Favorites.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { tokenState } from "../store/atoms/auth";
import { IFavoritePost } from "../types";
import { ColorRing } from 'react-loader-spinner';
import { RiHeartsFill } from "react-icons/ri";
import { TbReportAnalytics } from "react-icons/tb";

const Favorites = () => {
const [favoritePosts, setFavoritePosts] = useState<IFavoritePost[]>([]);
Expand Down Expand Up @@ -32,6 +33,27 @@ const Favorites = () => {
fetchFavoritePosts();
}, [token]);

const downloadUsersFavoritesReport = async () => {
try {
const response = await axios.get('/api/v1/admin/downloadusersfavoritesreport', {
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_Favorites_Report.pdf');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error('Error downloading users favorites report:', error);
}
};

return (
<div>
<div className="flex-1 flex flex-col lg:ml-80">
Expand All @@ -53,6 +75,7 @@ const Favorites = () => {
/>
</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">
Expand Down Expand Up @@ -82,6 +105,12 @@ const Favorites = () => {
</tbody>
</table>
</div>
<div className="mx-5 overflow-x-auto rounded-xl mb-5">
<button onClick={downloadUsersFavoritesReport} className="flex items-center py-2.5 px-4 rounded-lg transition duration-200 bg-yellow-500 hover:bg-yellow-600 text-gray-100"><TbReportAnalytics size={23} className='mr-3'/>
Download Favorites Info
</button>
</div>
</>
}
</div>
</div>
Expand Down
29 changes: 29 additions & 0 deletions admin/src/pages/Reactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { tokenState } from "../store/atoms/auth";
import { ColorRing } from 'react-loader-spinner';
import { MdAddReaction } from "react-icons/md";
import { IReaction} from "../types";
import { TbReportAnalytics } from "react-icons/tb";

const Reactions = () => {
const [reactions, setReactions] = useState<IReaction[]>([]);
Expand Down Expand Up @@ -32,6 +33,27 @@ const Reactions = () => {
fetchReactions();
}, [token]);

const downloadUsersReactionsReport = async () => {
try {
const response = await axios.get('/api/v1/admin/downloadusersreactionreport', {
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_Reactions_Report.pdf');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error('Error downloading users reactions report:', error);
}
};

return (
<div>
<div className="flex-1 flex flex-col lg:ml-80">
Expand All @@ -53,6 +75,7 @@ const Reactions = () => {
/>
</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">
Expand Down Expand Up @@ -86,6 +109,12 @@ const Reactions = () => {
</tbody>
</table>
</div>
<div className="mx-5 overflow-x-auto rounded-xl mb-5">
<button onClick={downloadUsersReactionsReport} className="flex items-center py-2.5 px-4 rounded-lg transition duration-200 bg-yellow-500 hover:bg-yellow-600 text-gray-100"><TbReportAnalytics size={23} className='mr-3'/>
Download Reactions Info
</button>
</div>
</>
}
</div>
</div>
Expand Down
216 changes: 216 additions & 0 deletions backend/src/routes/admin/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,4 +688,220 @@ export const toggleFeedbackVisibility = async (req: Request, res: Response) => {
console.error('Error toggling feedback visibility:', error);
res.status(500).json({ error: 'An unexpected error occurred!' });
}
};

export const downloadCommentsReportController = async (req: Request, res: Response) => {
try {
const currentDate = new Date().toLocaleDateString();

const comments = await prisma.comment.findMany({
select: {
content: true,
createdAt: true,
user: {
select: {
username: true,
email: true,
},
},
post: {
select: {
title: true,
},
},
},
});

const totalComments = comments.length;

const doc = new PDFDocument();
let filename = `StyleShare_Comments_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 Comments 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 Comments: ${totalComments}`);
doc.moveDown();

doc.fontSize(15).text('Comment Details:');
doc.moveDown();

comments.forEach(comment => {
doc.text(`Content: ${comment.content}`);
doc.text(`Created At: ${comment.createdAt.toLocaleDateString()}`);
doc.text(`User: ${comment.user.username} (${comment.user.email})`);
doc.text(`Post: ${comment.post.title}`);
doc.moveDown();
});

doc.end();
} catch (error) {
console.error(error);
res.status(500).json({
error: "An unexpected exception occurred!",
});
}
};

export const downloadReactionsReportController = async (req: Request, res: Response) => {
try {
const currentDate = new Date().toLocaleDateString();

const reactions = await prisma.reaction.findMany({
select: {
type: true,
createdAt: true,
user: {
select: {
username: true,
email: true,
},
},
post: {
select: {
title: true,
description: true,
author: {
select: {
username: true,
email: true,
},
},
},
},
},
});

const totalReactions = reactions.length;

const doc = new PDFDocument();
let filename = `StyleShare_Reactions_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 Reactions 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 Reactions: ${totalReactions}`);
doc.moveDown();

doc.fontSize(15).text('Reaction Details:');
doc.moveDown();

reactions.forEach(reaction => {
doc.fontSize(12).text(`Type: ${reaction.type}`);
doc.text(`Created At: ${reaction.createdAt.toLocaleDateString()}`);
doc.text(`User: ${reaction.user.username} (${reaction.user.email})`);
doc.text(`Post: ${reaction.post.title}`);
doc.text(`Post Description: ${reaction.post.description}`);
doc.text(`Post Author: ${reaction.post.author.username} (${reaction.post.author.email})`);
doc.moveDown();
});

doc.end();
} catch (error) {
console.error(error);
res.status(500).json({
error: "An unexpected exception occurred!",
});
}
};

export const downloadFavoritesReportController = async (req: Request, res: Response) => {
try {
const currentDate = new Date().toLocaleDateString();

const favorites = await prisma.favorite.findMany({
select: {
createdAt: true,
user: {
select: {
username: true,
email: true
}
},
post: {
select: {
title: true,
description: true
}
}
},
orderBy: {
createdAt: 'desc'
}
});

const totalFavorites = favorites.length;

const doc = new PDFDocument();
let filename = `StyleShare_Favorites_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 Favorites 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 Favorites: ${totalFavorites}`);
doc.moveDown();

doc.fontSize(15).text('Favorite Details:');
doc.moveDown();

favorites.forEach(favorite => {
doc.text(`Created At: ${favorite.createdAt.toLocaleDateString()}`);
doc.text(`User: ${favorite.user.username} (${favorite.user.email})`);
doc.text(`Post: ${favorite.post.title}`);
doc.text(`Post Description: ${favorite.post.description}`);
doc.moveDown();
});

doc.end();
} catch (error) {
console.error(error);
res.status(500).json({
error: "An unexpected exception occurred!",
});
}
};
Loading
Loading