diff --git a/src/app/api/stats/hero/route.ts b/src/app/api/stats/hero/route.ts new file mode 100644 index 0000000..1b74063 --- /dev/null +++ b/src/app/api/stats/hero/route.ts @@ -0,0 +1,52 @@ +import { NextResponse } from 'next/server'; +import dbConnect from '@/lib/db'; +import User from '@/lib/models/userSchema'; +import SkillList from '@/lib/models/skillList'; +import SkillMatch from '@/lib/models/skillMatch'; +import { Feedback } from '@/lib/models/feedbackSchema'; + +export const dynamic = 'force-dynamic'; + +export async function GET() { + try { + await dbConnect(); + + // Active learners + const activeLearners = await User.countDocuments({ isDeleted: { $ne: true }, isBlocked: { $ne: true } }); + + // Skills available (unique skill names across all categories) + const skillLists = await SkillList.find({}).select('skills'); + const skillSet = new Set(); + skillLists.forEach(list => { + list.skills.forEach(skill => { + skillSet.add(skill.name); + }); + }); + const skillsAvailable = skillSet.size; + + // Successful matches and total matches + const successfulMatches = await SkillMatch.countDocuments({ status: 'completed' }); + const totalMatches = await SkillMatch.countDocuments({}); + + // Satisfaction rate (average rating) + const feedbacks = await Feedback.find({ rating: { $exists: true } }).select('rating'); + let satisfactionRate = 0; + if (feedbacks.length > 0) { + const avg = feedbacks.reduce((sum, f) => sum + (f.rating || 0), 0) / feedbacks.length; + satisfactionRate = Math.round(avg * 20); // Convert 1-5 to % + } + + return NextResponse.json({ + success: true, + data: { + activeLearners, + skillsAvailable, + successfulMatches, + totalMatches, + satisfactionRate + } + }); + } catch (error) { + return NextResponse.json({ success: false, message: 'Failed to fetch hero stats' }, { status: 500 }); + } +} diff --git a/src/app/page.tsx b/src/app/page.tsx index d47117a..28784d4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -25,10 +25,24 @@ const EnhancedHeroSection = () => { const router = useRouter(); const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); const [isVisible, setIsVisible] = useState(false); + const [stats, setStats] = useState<{ + activeLearners: number | null; + skillsAvailable: number | null; + successfulMatches: number | null; + totalMatches: number | null; + satisfactionRate: number | null; + }>({ + activeLearners: null, + skillsAvailable: null, + successfulMatches: null, + totalMatches: null, + satisfactionRate: null, + }); + const [loadingStats, setLoadingStats] = useState(true); useEffect(() => { setIsVisible(true); - + const handleMouseMove = (e: MouseEvent) => { setMousePosition({ x: (e.clientX / window.innerWidth) * 100, @@ -40,6 +54,25 @@ const EnhancedHeroSection = () => { return () => window.removeEventListener('mousemove', handleMouseMove); }, []); + useEffect(() => { + // Fetch hero stats from backend + const fetchStats = async () => { + try { + setLoadingStats(true); + const res = await fetch('/api/stats/hero'); + const data = await res.json(); + if (data.success && data.data) { + setStats(data.data); + } + } catch (err) { + // Optionally handle error + } finally { + setLoadingStats(false); + } + }; + fetchStats(); + }, []); + return (
{/* Animated Background Elements */} @@ -144,13 +177,32 @@ const EnhancedHeroSection = () => { {/* Stats */}
{[ - { number: '50K+', label: 'Active Learners', icon: Users }, - { number: '1000+', label: 'Skills Available', icon: BookOpen }, - { number: '25K+', label: 'Successful Matches', icon: Star }, - { number: '95%', label: 'Satisfaction Rate', icon: Award } + { + number: loadingStats || stats.activeLearners === null ? '...' : stats.activeLearners.toLocaleString(), + label: 'Active Learners', + icon: Users + }, + { + number: loadingStats || stats.skillsAvailable === null ? '...' : stats.skillsAvailable.toLocaleString(), + label: 'Skills Available', + icon: BookOpen + }, + { + number: + loadingStats || stats.totalMatches === null + ? '...' + : stats.totalMatches.toLocaleString(), + label: 'Total Matches', + icon: Star + }, + { + number: loadingStats || stats.satisfactionRate === null ? '...' : `${stats.satisfactionRate}%`, + label: 'Satisfaction Rate', + icon: Award + } ].map((stat, index) => ( -