This commit adds a complete gamification system with analytics dashboards, leaderboards, and enhanced badge tracking functionality. Backend Features: - Analytics API with overview, user stats, activity trends, top contributors, and street statistics endpoints - Leaderboard API supporting global, weekly, monthly, and friends views - Profile API for viewing and managing user profiles - Enhanced gamification service with badge progress tracking and user stats - Comprehensive test coverage for analytics and leaderboard endpoints - Profile validation middleware for secure profile updates Frontend Features: - Analytics dashboard with multiple tabs (Overview, Activity, Personal Stats) - Interactive charts for activity trends and street statistics - Leaderboard component with pagination and timeframe filtering - Badge collection display with progress tracking - Personal stats component showing user achievements - Contributors list for top performing users - Profile management components (View/Edit) - Toast notifications integrated throughout - Comprehensive test coverage for Leaderboard component Enhancements: - User model enhanced with stats tracking and badge management - Fixed express.Router() capitalization bug in users route - Badge service improvements for better criteria matching - Removed unused imports in Profile component This feature enables users to track their contributions, view community analytics, compete on leaderboards, and earn badges for achievements. 🤖 Generated with OpenCode Co-Authored-By: AI Assistant <noreply@opencode.ai>
48 lines
1.3 KiB
JavaScript
48 lines
1.3 KiB
JavaScript
const express = require("express");
|
|
const User = require("../models/User");
|
|
const Street = require("../models/Street");
|
|
const auth = require("../middleware/auth");
|
|
const { asyncHandler } = require("../middleware/errorHandler");
|
|
const { userIdValidation } = require("../middleware/validators/userValidator");
|
|
|
|
const router = express.Router();
|
|
|
|
// Get user by ID
|
|
router.get(
|
|
"/:id",
|
|
auth,
|
|
userIdValidation,
|
|
asyncHandler(async (req, res) => {
|
|
const user = await User.findById(req.params.id);
|
|
if (!user) {
|
|
return res.status(404).json({ msg: "User not found" });
|
|
}
|
|
|
|
// Get adopted streets data
|
|
let adoptedStreets = [];
|
|
if (user.adoptedStreets && user.adoptedStreets.length > 0) {
|
|
adoptedStreets = await Promise.all(
|
|
user.adoptedStreets.map(async (streetId) => {
|
|
const street = await Street.findById(streetId);
|
|
return street ? {
|
|
_id: street._id,
|
|
name: street.name,
|
|
location: street.location,
|
|
status: street.status,
|
|
} : null;
|
|
})
|
|
);
|
|
adoptedStreets = adoptedStreets.filter(Boolean);
|
|
}
|
|
|
|
const userWithStreets = {
|
|
...user.toSafeObject(),
|
|
adoptedStreets,
|
|
};
|
|
|
|
res.json(userWithStreets);
|
|
}),
|
|
);
|
|
|
|
module.exports = router;
|