1
1
import { cva } from "class-variance-authority" ;
2
2
import { CrownIcon } from "lucide-react" ;
3
+ import Image from "next/image" ;
3
4
import React from "react" ;
4
5
5
6
import { cn } from "@/lib/utils" ;
@@ -11,6 +12,7 @@ interface PodiumProps {
11
12
username : string ;
12
13
value : string ;
13
14
position : number ;
15
+ profilePicture ?: string ;
14
16
}
15
17
16
18
const podiumVariants = cva ( "" , {
@@ -32,7 +34,39 @@ const podiumVariants = cva("", {
32
34
} ,
33
35
} ) ;
34
36
35
- const Podium = ( { username, value, position } : PodiumProps ) => {
37
+ const RankingPosition = ( { position } : { position : number } ) => (
38
+ < div className = "flex items-center justify-center gap-1" >
39
+ < span className = "xs:text-sm text-xs text-neutral-400 dark:text-neutral-600 md:text-lg" >
40
+ #
41
+ </ span >
42
+ < span className = "xs:text-base text-sm font-semibold text-neutral-800 dark:text-neutral-50 md:text-2xl" >
43
+ { position }
44
+ </ span >
45
+ </ div >
46
+ ) ;
47
+
48
+ const ProfilePicture = ( {
49
+ username,
50
+ src,
51
+ } : {
52
+ username ?: string ;
53
+ src ?: string ;
54
+ } ) => {
55
+ return (
56
+ < div className = "relative flex h-12 w-12 items-center justify-center rounded-full bg-neutral-200/40 dark:bg-neutral-800/60 md:h-16 md:w-16" >
57
+ { username ? (
58
+ < Image
59
+ src = { src || "/default-profile-picture.png" }
60
+ fill = { true }
61
+ alt = "Profile picture"
62
+ className = "rounded-full"
63
+ />
64
+ ) : null }
65
+ </ div >
66
+ ) ;
67
+ } ;
68
+
69
+ const Podium = ( { username, value, position, profilePicture } : PodiumProps ) => {
36
70
const variant =
37
71
position === 1 ? "gold" : position === 2 ? "silver" : "bronze" ;
38
72
@@ -60,12 +94,7 @@ const Podium = ({ username, value, position }: PodiumProps) => {
60
94
) }
61
95
/>
62
96
</ div >
63
- < div className = "flex h-12 w-12 items-center justify-center rounded-full bg-neutral-200/40 dark:bg-neutral-800/60 md:h-16 md:w-16" >
64
- < i
65
- className = "fa-regular fa-user text-lg text-neutral-600 dark:text-neutral-50 md:text-2xl"
66
- aria-hidden = "true"
67
- />
68
- </ div >
97
+ < ProfilePicture username = { username } src = { profilePicture } />
69
98
</ div >
70
99
< div className = "flex w-full flex-col items-center gap-0.5 md:gap-0" >
71
100
< span className = "xs:text-sm max-w-[calc(100%-1rem)] overflow-hidden text-ellipsis whitespace-nowrap text-xs font-normal text-neutral-800 dark:text-neutral-50 md:text-lg" >
@@ -78,14 +107,7 @@ const Podium = ({ username, value, position }: PodiumProps) => {
78
107
podiumVariants ( { text : variant } )
79
108
) }
80
109
>
81
- < span className = "whitespace-nowrap" >
82
- < i
83
- className = "fas fa-dice-d8"
84
- aria-hidden = "true"
85
- style = { { scale : "0.6" } }
86
- /> { " " }
87
- { value }
88
- </ span >
110
+ < span className = "whitespace-nowrap" > { value } </ span >
89
111
</ span >
90
112
</ div >
91
113
</ div >
@@ -99,32 +121,24 @@ const Podium = ({ username, value, position }: PodiumProps) => {
99
121
} )
100
122
) }
101
123
>
102
- < div className = "flex items-center justify-center gap-1" >
103
- < span className = "xs:text-sm text-xs text-neutral-400 dark:text-neutral-600 md:text-lg" >
104
- #
105
- </ span >
106
- < span className = "xs:text-base text-sm font-semibold text-neutral-800 dark:text-neutral-50 md:text-2xl" >
107
- { position }
108
- </ span >
109
- </ div >
124
+ < RankingPosition position = { position } />
110
125
</ div >
111
126
</ div >
112
127
</ Link >
113
128
) ;
114
129
} ;
115
130
116
- export const LeaderboardRow = ( { username, value, position } : PodiumProps ) => {
131
+ export const LeaderboardRow = ( {
132
+ username,
133
+ value,
134
+ position,
135
+ profilePicture,
136
+ } : PodiumProps ) => {
117
137
return (
118
138
< li className = "py-3 sm:py-4" >
119
- < div className = "flex items-start space-x-4" >
120
- < div className = "flex items-center justify-center gap-1" >
121
- < span className = "xs:text-sm text-xs text-neutral-400 dark:text-neutral-600 md:text-lg" >
122
- #
123
- </ span >
124
- < span className = "xs:text-base text-sm font-semibold text-neutral-800 dark:text-neutral-50 md:text-2xl" >
125
- { position }
126
- </ span >
127
- </ div >
139
+ < div className = "flex space-x-4" >
140
+ < RankingPosition position = { position } />
141
+ < ProfilePicture username = { username } src = { profilePicture } />
128
142
< div className = "min-w-0 flex-1" >
129
143
< UsernameLink username = { username } />
130
144
{ /* <div className="text-sm text-muted-foreground ">
@@ -146,6 +160,7 @@ interface LeaderboardProps {
146
160
name : string ;
147
161
value : string ;
148
162
position : number ;
163
+ profilePicture : string ;
149
164
} | null > ;
150
165
}
151
166
@@ -157,16 +172,19 @@ export const Leaderboard = ({ entries }: LeaderboardProps) => {
157
172
username = { entries [ 1 ] ?. name || "" }
158
173
value = { entries [ 1 ] ?. value || "" }
159
174
position = { 2 }
175
+ profilePicture = { entries [ 1 ] ?. profilePicture }
160
176
/>
161
177
< Podium
162
178
username = { entries [ 0 ] ?. name || "" }
163
179
value = { entries [ 0 ] ?. value || "" }
164
180
position = { 1 }
181
+ profilePicture = { entries [ 0 ] ?. profilePicture }
165
182
/>
166
183
< Podium
167
184
username = { entries [ 2 ] ?. name || "" }
168
185
value = { entries [ 2 ] ?. value || "" }
169
186
position = { 3 }
187
+ profilePicture = { entries [ 2 ] ?. profilePicture }
170
188
/>
171
189
</ div >
172
190
< ul className = "divide-y divide-gray-200 dark:divide-gray-700" >
@@ -179,6 +197,7 @@ export const Leaderboard = ({ entries }: LeaderboardProps) => {
179
197
username = { entry ?. name }
180
198
position = { entry ?. position }
181
199
value = { entry ?. value }
200
+ profilePicture = { entry . profilePicture }
182
201
/>
183
202
) : null
184
203
) }
0 commit comments