Skip to content

Commit de57210

Browse files
swoocnsoleil00
authored andcommitted
Merge pull request #256 from map-of-pi/bug/fix-search-filtering
Self approved.
2 parents 5eb57b5 + e504e88 commit de57210

20 files changed

+767
-65
lines changed

package-lock.json

Lines changed: 12 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"cloudinary": "^2.4.0",
2323
"cookie-parser": "^1.4.7",
2424
"cors": "^2.8.5",
25+
"date-fns": "^4.1.0",
2526
"dotenv": "^16.4.5",
2627
"express": "^4.21.2",
2728
"jsonwebtoken": "^9.0.2",
@@ -56,4 +57,4 @@
5657
"ts-node": "^10.9.2",
5758
"typescript": "^5.4.5"
5859
}
59-
}
60+
}

src/controllers/admin/index.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { Request, Response } from "express";
2+
import Admin from "../../models/Admin";
3+
import { decodeAdminToken, generateAdminToken } from "../../helpers/jwt";
4+
5+
export const registerAdmin = async (req: Request, res: Response) => {
6+
const { email, password } = req.body;
7+
8+
try {
9+
const existingAdmin = await Admin.findOne({ email });
10+
if (existingAdmin) {
11+
return res.status(400).json({ message: "Admin already exists." });
12+
}
13+
14+
const newAdmin = await Admin.create({ email, password });
15+
return res.status(201).json({ message: "Admin registered successfully.", admin: newAdmin });
16+
} catch (error) {
17+
return res.status(500).json({ message: "An error occurred.", error });
18+
}
19+
};
20+
21+
export const loginAdmin = async (req: Request, res: Response) => {
22+
const { email, password } = req.body;
23+
24+
try {
25+
const admin = await Admin.findOne({ email });
26+
if (!admin) {
27+
return res.status(404).json({ message: "Admin not found." });
28+
}
29+
30+
const isPasswordMatch = admin.password === password
31+
if (!isPasswordMatch) {
32+
return res.status(401).json({ message: "Invalid credentials." });
33+
}
34+
35+
const token = generateAdminToken(admin)
36+
return res.status(200).json({ message: "Login successful.", token,admin });
37+
} catch (error) {
38+
return res.status(500).json({ message: "An error occurred.", error });
39+
}
40+
};
41+
42+
export const deactivateAdmin = async (req: Request, res: Response) => {
43+
const { id } = req.params;
44+
try {
45+
const admin = await Admin.findByIdAndUpdate(id, { isActive: false }, { new: true });
46+
if (!admin) {
47+
return res.status(404).json({ message: "Admin not found." });
48+
}
49+
50+
return res.status(200).json({ message: "Admin deactivated successfully.", admin });
51+
} catch (error) {
52+
return res.status(500).json({ message: "An error occurred.", error });
53+
}
54+
};
55+
56+
export const activateAdmin = async (req: Request, res: Response) => {
57+
const { id } = req.params;
58+
59+
try {
60+
const admin = await Admin.findByIdAndUpdate(id, { isActive: true }, { new: true });
61+
if (!admin) {
62+
return res.status(404).json({ message: "Admin not found." });
63+
}
64+
65+
return res.status(200).json({ message: "Admin activated successfully.", admin });
66+
} catch (error) {
67+
return res.status(500).json({ message: "An error occurred.", error });
68+
}
69+
};
70+
71+
export const getAdminInfo = async (req: Request, res: Response) => {
72+
const token = req.headers.authorization?.split(" ")[1];
73+
74+
if (!token) {
75+
return res.status(401).json({ message: "Authorization token missing." });
76+
}
77+
78+
try {
79+
const admin = await decodeAdminToken(token)
80+
81+
if (!admin) {
82+
return res.status(404).json({ message: "Admin not found." });
83+
}
84+
85+
return res.status(200).json(admin);
86+
} catch (error) {
87+
return res.status(401).json({ message: "Invalid or expired token.", error });
88+
}
89+
};

src/controllers/sellerController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ export const fetchSellersByCriteria = async (req: Request, res: Response) => {
1212
const sellers = await sellerService.getAllSellers(bounds, search_query, userId);
1313

1414
if (!sellers || sellers.length === 0) {
15-
logger.warn(`No sellers found within bounds (${bounds?.sw_lat}, ${bounds?.sw_lng}) to (${bounds?.ne_lat}, ${bounds?.ne_lng}) with "${search_query ?? 'undefined'}"`);
15+
logger.warn(`No sellers found within bounds (${bounds?.sw_lat}, ${bounds?.sw_lng}) to (${bounds?.ne_lat}, ${bounds?.ne_lng}) with ${search_query}`);
1616
return res.status(204).json({ message: "Sellers not found" });
1717
}
18-
logger.info(`Fetched ${sellers.length} sellers within bounds (${bounds?.sw_lat}, ${bounds?.sw_lng}) to (${bounds?.ne_lat}, ${bounds?.ne_lng}) with "${search_query ?? 'undefined'}"`);
18+
logger.info(`Fetched ${sellers.length} sellers within bounds (${bounds?.sw_lat}, ${bounds?.sw_lng}) to (${bounds?.ne_lat}, ${bounds?.ne_lng}) with ${search_query}`);
1919
return res.status(200).json(sellers);
2020
} catch (error) {
2121
logger.error('Failed to fetch sellers by criteria:', error);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Request, Response } from "express";
2+
import SanctionedRegion from "../../models/misc/SanctionedRegion";
3+
4+
5+
export const getRestrictedAreaStats = async (req: Request, res: Response) => {
6+
try {
7+
const restrictedAreas = await SanctionedRegion.find()
8+
return res.status(200).json({
9+
restrictedAreas
10+
});
11+
} catch (error) {
12+
return res.status(500).json({
13+
success: false,
14+
message: "Error fetching restricted areas",
15+
error: error
16+
});
17+
}
18+
}
19+
20+
export const createSanctionedRegion = async (req: Request, res: Response) => {
21+
try {
22+
const { location, boundary } = req.body;
23+
24+
const newSanctionedRegion = await SanctionedRegion.create({
25+
location,
26+
boundary: {
27+
type: "Polygon",
28+
coordinates: boundary
29+
}
30+
});
31+
32+
return res.status(201).json({
33+
success: true,
34+
message: "Sanctioned region created successfully",
35+
data: newSanctionedRegion
36+
});
37+
} catch (error) {
38+
return res.status(500).json({
39+
success: false,
40+
message: "Error creating sanctioned region",
41+
error: error
42+
});
43+
}
44+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { Request, Response } from "express";
2+
import ReviewFeedback from "../../models/ReviewFeedback";
3+
import User from "../../models/User";
4+
5+
export const getReviewStatistics = async (req: Request, res: Response) => {
6+
try {
7+
const page = parseInt(req.query.page as string) || 1;
8+
const limit = parseInt(req.query.limit as string) || 20;
9+
10+
const skip = (page - 1) * limit;
11+
const totalReviews = await ReviewFeedback.countDocuments();
12+
const reviews = await ReviewFeedback.find()
13+
.sort({ createdAt: -1 })
14+
.skip(skip)
15+
.limit(limit);
16+
17+
const totalPages = Math.ceil(totalReviews / limit);
18+
const hasNextPage = page < totalPages;
19+
const hasPrevPage = page > 1;
20+
21+
const mappedReviews = await Promise.all(
22+
reviews.map(async (review) => {
23+
const reviewerUser = await User.findOne({ pi_uid: review.review_giver_id });
24+
const sellerUser = await User.findOne({ pi_uid: review.review_receiver_id });
25+
26+
return {
27+
id: review._id,
28+
reviewer: reviewerUser?.pi_username ||review.review_giver_id,
29+
seller: sellerUser?.pi_username || review.review_receiver_id ,
30+
rating: review.rating,
31+
comment: review.comment,
32+
date: review.review_date.toISOString().split("T")[0],
33+
};
34+
})
35+
);
36+
37+
38+
const mostReviewedUser = await ReviewFeedback.aggregate([
39+
{ $group: { _id: "$review_receiver_id", count: { $sum: 1 } } },
40+
{ $sort: { count: -1 } },
41+
{ $limit: 1 },
42+
]);
43+
44+
const user = await User.findOne({
45+
pi_uid: mostReviewedUser[0]?._id,
46+
});
47+
48+
49+
const now = new Date();
50+
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
51+
const startOfNextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);
52+
53+
const currentMonthReviews = await ReviewFeedback.countDocuments({
54+
review_date: { $gte: startOfMonth, $lt: startOfNextMonth },
55+
});
56+
57+
const currentMonthReviewPercentage =
58+
totalReviews > 0
59+
? ((currentMonthReviews / totalReviews) * 100).toFixed(2)
60+
: "0.00";
61+
62+
res.status(200).json({
63+
reviews:mappedReviews,
64+
totalReviews,
65+
mostReviewedUser: {
66+
user: user || null,
67+
count: mostReviewedUser[0]?.count || 0,
68+
},
69+
currentMonthReviews,
70+
currentMonthReviewPercentage: `${currentMonthReviewPercentage}`,
71+
pagination: {
72+
currentPage: page,
73+
totalPages,
74+
hasNextPage,
75+
hasPrevPage,
76+
totalReviews
77+
},
78+
});
79+
} catch (error) {
80+
res.status(500).json({ message: "Failed to fetch review statistics", error });
81+
}
82+
};
83+

0 commit comments

Comments
 (0)