diff --git a/src/app/api/badge-assignments/[id]/route.ts b/src/app/api/badge-assignments/[id]/route.ts new file mode 100644 index 00000000..70c01bab --- /dev/null +++ b/src/app/api/badge-assignments/[id]/route.ts @@ -0,0 +1,42 @@ +import { NextResponse } from 'next/server'; +import mongoose from 'mongoose'; +import '@/lib/models/badgeSchema'; // <-- Import badgeSchema BEFORE BadgeAssignment +import BadgeAssignment from '@/lib/models/badgeAssignmentSchema'; +import connect from '@/lib/db'; + +export async function GET( + req: Request, + { params }: { params: Promise<{ id: string }> } // ← PROMISE here +): Promise { + const { id: userId } = await params; // ← AWAIT here + + try { + if (!mongoose.Types.ObjectId.isValid(userId)) { + return NextResponse.json({ error: 'Invalid user ID format' }, { status: 400 }); + } + + await connect(); + + const badgeAssignments = await BadgeAssignment.find({ userId }) + .populate('badgeId') + .sort({ assignedAt: -1 }); + + const responseData = badgeAssignments.map((assignment) => ({ + id: assignment._id, + badge: { + id: assignment.badgeId._id, + badgeName: assignment.badgeId.badgeName, + badgeImage: assignment.badgeId.badgeImage, + criteria: assignment.badgeId.criteria, + description: assignment.badgeId.description + }, + assignedAt: assignment.assignedAt, + context: assignment.assignmentContext + })); + + return NextResponse.json(responseData); + } catch (error) { + console.error('Error fetching badge assignments:', error); + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); + } +} diff --git a/src/components/Dashboard/EarnedBadges.tsx b/src/components/Dashboard/EarnedBadges.tsx index 6d219f20..9c491be1 100644 --- a/src/components/Dashboard/EarnedBadges.tsx +++ b/src/components/Dashboard/EarnedBadges.tsx @@ -2,11 +2,14 @@ import React, { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; +import { processAvatarUrl } from '@/utils/imageUtils'; +import Image from 'next/image'; interface Badge { - id: string; - icon: string; // emoji or image - label: string; + _id: string; + badgeImage: string; + badgeName: string; + // Add other badge properties you need } interface Props { @@ -15,25 +18,57 @@ interface Props { export default function EarnedBadges({ userId }: Props) { const [badges, setBadges] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); const router = useRouter(); useEffect(() => { const fetchBadges = async () => { try { - const res = await fetch('/api/badge'); + setLoading(true); + const res = await fetch(`/api/badge-assignments/${userId}`); + + if (!res.ok) { + throw new Error('Failed to fetch badges'); + } + const data = await res.json(); - setBadges(data || []); + + // Transform API response to match your Badge interface + const transformedBadges = data + .filter((assignment: any) => assignment.badge) // Only keep assignments with a populated badge + .map((assignment: any) => ({ + _id: assignment.badge.id, + badgeImage: assignment.badge.badgeImage, // use badgeImage from schema + badgeName: assignment.badge.badgeName // use badgeName from schema + })); + + setBadges(transformedBadges); + setError(null); } catch (err) { console.error('Error fetching badges:', err); + setError('Failed to load badges'); setBadges([]); + } finally { + setLoading(false); } }; - fetchBadges(); + if (userId) { + fetchBadges(); + } }, [userId]); const displayedBadges = badges.slice(0, 5); + if (loading) { + return
Loading badges...
; + } + + if (error) { + return
{error}
; + } + return (
{/* Learn More Button - top right */} @@ -50,11 +85,21 @@ export default function EarnedBadges({ userId }: Props) {
{displayedBadges.length > 0 ? ( displayedBadges.map((badge, idx) => ( -
-
- {badge.icon} +
+
+ {badge.badgeImage ? ( + {badge.badgeName} + ) : ( + ? + )}
- {badge.label} + {badge.badgeName}
)) ) : ( @@ -63,4 +108,4 @@ export default function EarnedBadges({ userId }: Props) {
); -} +} \ No newline at end of file