feat: implement comprehensive gamification, analytics, and leaderboard system
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>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import React, { useState, useEffect, useContext } from \"react\";
|
||||
import { useParams, Link } from \"react-router-dom\";
|
||||
import axios from \"axios\";
|
||||
const { AuthContext } = require(\"../../context/AuthContext\");
|
||||
|
||||
const ProfileView = () => {
|
||||
const { userId } = useParams();
|
||||
const { auth } = useContext(AuthContext);
|
||||
const [profile, setProfile] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchProfile = async () => {
|
||||
try {
|
||||
const res = await axios.get((/api/profile/${userId}`);
|
||||
setProfile(res.data);
|
||||
} catch (err) {
|
||||
setError(err.response?.ager = == auth.user._id;
|
||||
|
||||
return (
|
||||
<div className=\"container mt-5\">
|
||||
<div className=\"row\">
|
||||
<div className=\"col-md-4 text-center\">
|
||||
<img
|
||||
src={`npame"} id: auth.user._id });
|
||||
setProfile(res.data);
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.msg || \"Error fetching profile\");
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
fetchProfile();
|
||||
}, [userId]);
|
||||
|
||||
if (loading) {
|
||||
return <div className=\"container\"><p>Loading profile...</p></div>;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div className=\"container\"><div className=\"alert alert-danger\">{error}</div></div>;
|
||||
}
|
||||
|
||||
if (!profile) {
|
||||
return <div className=\"container\"><p>Profile not found.</p></div>;
|
||||
}
|
||||
|
||||
const { name, avatar, bio, location, website, social, preferences } = profile;
|
||||
const isOwnProfile = auth.isAuthenticated && auth.user._id === userId;
|
||||
|
||||
return (
|
||||
<div className=\"container mt-5\">
|
||||
<div className=\"row\">
|
||||
<div className=\"col-md-4 text-center\">
|
||||
<img
|
||||
src={avatar || \"/logo512.png\"}
|
||||
alt={`${name}\'s avatar`}
|
||||
className=\"img-fluid rounded-circle mb-3\"
|
||||
style={{ width: \"150px\", height: \"150px\" }}
|
||||
/>
|
||||
<h3>{name}</h3>
|
||||
{location && <p className=\"text-muted\">{location}</p>}
|
||||
{isOwnProfile && (
|
||||
<Link to=\"/profile/edit\" className=\"btn btn-primary mb-3\">Edit Profile</Link>
|
||||
)}
|
||||
</div>
|
||||
<div className=\"col-md-8\">
|
||||
<div className=\"card\">
|
||||
<div className=\"card-body\">
|
||||
|
||||
Reference in New Issue
Block a user