22
33import React , { useEffect , useState } from 'react' ;
44import { useRouter } from 'next/navigation' ;
5+ import { processAvatarUrl } from '@/utils/imageUtils' ;
6+ import Image from 'next/image' ;
57
68interface Badge {
7- id : string ;
8- icon : string ; // emoji or image
9- label : string ;
9+ _id : string ;
10+ badgeImage : string ;
11+ badgeName : string ;
12+ // Add other badge properties you need
1013}
1114
1215interface Props {
@@ -15,25 +18,57 @@ interface Props {
1518
1619export default function EarnedBadges ( { userId } : Props ) {
1720 const [ badges , setBadges ] = useState < Badge [ ] > ( [ ] ) ;
21+ const [ loading , setLoading ] = useState ( true ) ;
22+ const [ error , setError ] = useState < string | null > ( null ) ;
1823 const router = useRouter ( ) ;
1924
2025 useEffect ( ( ) => {
2126 const fetchBadges = async ( ) => {
2227 try {
23- const res = await fetch ( '/api/badge' ) ;
28+ setLoading ( true ) ;
29+ const res = await fetch ( `/api/badge-assignments/${ userId } ` ) ;
30+
31+ if ( ! res . ok ) {
32+ throw new Error ( 'Failed to fetch badges' ) ;
33+ }
34+
2435 const data = await res . json ( ) ;
25- setBadges ( data || [ ] ) ;
36+
37+ // Transform API response to match your Badge interface
38+ const transformedBadges = data
39+ . filter ( ( assignment : any ) => assignment . badge ) // Only keep assignments with a populated badge
40+ . map ( ( assignment : any ) => ( {
41+ _id : assignment . badge . id ,
42+ badgeImage : assignment . badge . badgeImage , // use badgeImage from schema
43+ badgeName : assignment . badge . badgeName // use badgeName from schema
44+ } ) ) ;
45+
46+ setBadges ( transformedBadges ) ;
47+ setError ( null ) ;
2648 } catch ( err ) {
2749 console . error ( 'Error fetching badges:' , err ) ;
50+ setError ( 'Failed to load badges' ) ;
2851 setBadges ( [ ] ) ;
52+ } finally {
53+ setLoading ( false ) ;
2954 }
3055 } ;
3156
32- fetchBadges ( ) ;
57+ if ( userId ) {
58+ fetchBadges ( ) ;
59+ }
3360 } , [ userId ] ) ;
3461
3562 const displayedBadges = badges . slice ( 0 , 5 ) ;
3663
64+ if ( loading ) {
65+ return < div className = "text-sm text-gray-500" > Loading badges...</ div > ;
66+ }
67+
68+ if ( error ) {
69+ return < div className = "text-sm text-red-500" > { error } </ div > ;
70+ }
71+
3772 return (
3873 < div className = "relative" >
3974 { /* Learn More Button - top right */ }
@@ -50,11 +85,21 @@ export default function EarnedBadges({ userId }: Props) {
5085 < div className = "flex flex-wrap gap-6 pt-6" >
5186 { displayedBadges . length > 0 ? (
5287 displayedBadges . map ( ( badge , idx ) => (
53- < div key = { badge . id || idx } className = "flex flex-col items-center" >
54- < div className = "w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mb-2 text-lg" >
55- { badge . icon }
88+ < div key = { badge . _id || idx } className = "flex flex-col items-center" >
89+ < div className = "w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mb-2 text-lg overflow-hidden" >
90+ { badge . badgeImage ? (
91+ < Image
92+ src = { processAvatarUrl ( badge . badgeImage ) || '/placeholder-badge.png' }
93+ alt = { badge . badgeName }
94+ width = { 48 }
95+ height = { 48 }
96+ className = "object-contain w-full h-full"
97+ />
98+ ) : (
99+ < span className = "text-gray-400" > ?</ span >
100+ ) }
56101 </ div >
57- < span className = "text-xs text-center" > { badge . label } </ span >
102+ < span className = "text-xs text-center" > { badge . badgeName } </ span >
58103 </ div >
59104 ) )
60105 ) : (
@@ -63,4 +108,4 @@ export default function EarnedBadges({ userId }: Props) {
63108 </ div >
64109 </ div >
65110 ) ;
66- }
111+ }
0 commit comments