@@ -5,12 +5,28 @@ import { useLeetcodeStore } from "@/store/LeetcodeStore/useLeetcodeStore";
5
5
import { Badge } from "@/components/ui/badge" ;
6
6
import { Card , CardContent , CardHeader , CardTitle } from "@/components/ui/card" ;
7
7
import { Skeleton } from "@/components/ui/skeleton" ;
8
- import { Github , Linkedin , Twitter , Award , Book , Star } from "lucide-react" ;
8
+ import {
9
+ Github ,
10
+ Linkedin ,
11
+ Twitter ,
12
+ Award ,
13
+ Book ,
14
+ Star ,
15
+ Target ,
16
+ Timer ,
17
+ Trophy ,
18
+ TrendingUp ,
19
+ CheckCircle ,
20
+ XCircle ,
21
+ Calendar
22
+ } from "lucide-react" ;
23
+
9
24
export default function Dashboard ( ) {
10
25
const { fetchLeetcodeUserProfile, leetcodeUserProfile } = useLeetcodeStore ( ) ;
11
26
React . useEffect ( ( ) => {
12
27
fetchLeetcodeUserProfile ( ) ;
13
28
} , [ fetchLeetcodeUserProfile ] ) ;
29
+
14
30
if ( ! leetcodeUserProfile ) {
15
31
return < DashboardSkeleton /> ;
16
32
}
@@ -48,46 +64,98 @@ export default function Dashboard() {
48
64
</ div >
49
65
</ CardHeader >
50
66
< CardContent className = "pt-6" >
51
- < div className = "grid gap-6 md:grid-cols-2" >
52
- < div className = "space-y-4" >
53
- < h3 className = "text-xl font-semibold mb-3" > Statistics</ h3 >
54
- < div className = "grid grid-cols-2 gap-4" >
55
- < StatItem
56
- icon = { < Book className = "w-5 h-5" /> }
57
- value = {
58
- leetcodeUserProfile . submitStats . acSubmissionNum [ 0 ] . count ||
59
- 0
60
- }
61
- label = "Problems Solved"
62
- />
63
- < StatItem
64
- icon = { < Award className = "w-5 h-5" /> }
65
- value = { leetcodeUserProfile . contributions . points }
66
- label = "Contribution Points"
67
- />
68
- < StatItem
69
- icon = { < Star className = "w-5 h-5" /> }
70
- value = { leetcodeUserProfile . profile . starRating }
71
- label = "Star Rating"
72
- />
73
- < StatItem
74
- icon = { < Award className = "w-5 h-5" /> }
75
- value = { leetcodeUserProfile . profile . ranking }
76
- label = "Global Ranking"
77
- />
67
+ { /* New Additional Dashboard Sections */ }
68
+ < div className = "mt-8" >
69
+ < div className = "grid gap-6 md:grid-cols-2" >
70
+ < div className = "space-y-4" >
71
+ < h3 className = "text-xl font-semibold mb-3 flex items-center" >
72
+ < Trophy className = "w-5 h-5 mr-2 text-primary" />
73
+ Solving Statistics
74
+ </ h3 >
75
+ < div className = "grid grid-cols-2 gap-4" >
76
+ < StatItem
77
+ icon = { < Book className = "w-5 h-5 text-blue-500" /> }
78
+ value = {
79
+ leetcodeUserProfile . submitStats . acSubmissionNum [ 0 ] . count ||
80
+ 0
81
+ }
82
+ label = "Total Solved"
83
+ subtitle = { `${ (
84
+ ( leetcodeUserProfile . submitStats . acSubmissionNum [ 0 ] . count /
85
+ leetcodeUserProfile . submitStats . totalSubmissionNum [ 0 ] . count ) *
86
+ 100
87
+ ) . toFixed ( 1 ) } % success rate`}
88
+ />
89
+ < StatItem
90
+ icon = { < Target className = "w-5 h-5 text-green-500" /> }
91
+ value = {
92
+ leetcodeUserProfile . submitStats . acSubmissionNum [ 1 ] . count ||
93
+ 0
94
+ }
95
+ label = "Easy Problems"
96
+ subtitle = { `${ leetcodeUserProfile . submitStats . acSubmissionNum [ 1 ] . submissions } submissions` }
97
+ />
98
+ < StatItem
99
+ icon = { < Target className = "w-5 h-5 text-yellow-500" /> }
100
+ value = {
101
+ leetcodeUserProfile . submitStats . acSubmissionNum [ 2 ] . count ||
102
+ 0
103
+ }
104
+ label = "Medium Problems"
105
+ subtitle = { `${ leetcodeUserProfile . submitStats . acSubmissionNum [ 2 ] . submissions } submissions` }
106
+ />
107
+ < StatItem
108
+ icon = { < Target className = "w-5 h-5 text-red-500" /> }
109
+ value = {
110
+ leetcodeUserProfile . submitStats . acSubmissionNum [ 3 ] . count ||
111
+ 0
112
+ }
113
+ label = "Hard Problems"
114
+ subtitle = { `${ leetcodeUserProfile . submitStats . acSubmissionNum [ 3 ] . submissions } submissions` }
115
+ />
116
+ </ div >
117
+ </ div >
118
+ < div className = "space-y-4" >
119
+ < h3 className = "text-xl font-semibold mb-3 flex items-center" >
120
+ < Award className = "w-5 h-5 mr-2 text-primary" />
121
+ Performance Metrics
122
+ </ h3 >
123
+ < div className = "grid grid-cols-2 gap-4" >
124
+ < StatItem
125
+ icon = { < TrendingUp className = "w-5 h-5 text-purple-500" /> }
126
+ value = { leetcodeUserProfile . profile . ranking }
127
+ label = "Global Ranking"
128
+ subtitle = "Current Position"
129
+ />
130
+ < StatItem
131
+ icon = { < Star className = "w-5 h-5 text-yellow-500" /> }
132
+ value = { leetcodeUserProfile . profile . starRating }
133
+ label = "Contest Rating"
134
+ subtitle = { `Level ${ Math . floor ( leetcodeUserProfile . profile . starRating / 500 ) + 1 } ` }
135
+ />
136
+ < StatItem
137
+ icon = { < CheckCircle className = "w-5 h-5 text-green-500" /> }
138
+ value = { leetcodeUserProfile . contributions . points }
139
+ label = "Contribution Points"
140
+ subtitle = "Community Impact"
141
+ />
142
+ </ div >
78
143
</ div >
79
144
</ div >
145
+ < br > </ br >
146
+ { /* Original Badges */ }
147
+ < div className = "grid gap-6 md:grid-cols-3" >
80
148
< div className = "space-y-4" >
81
- < h3 className = "text-xl font-semibold mb-3 " > Recent Badges</ h3 >
149
+ < h3 className = "text-xl font-semibold mb-6 " > Recent Badges</ h3 >
82
150
< div className = "grid grid-cols-2 sm:grid-cols-3 gap-3" >
83
- { leetcodeUserProfile . badges . slice ( 0 , 6 ) . map ( ( badge ) => (
151
+ { leetcodeUserProfile . badges . slice ( 0 , 5 ) . map ( ( badge ) => (
84
152
< div
85
153
key = { badge . id }
86
154
className = "flex flex-col items-center p-2 bg-secondary rounded-lg"
87
155
>
88
156
< div className = "relative w-12 h-12 mb-2" >
89
157
< Image
90
- src = { badge . icon || "/placeholder.svg" }
158
+ src = { badge . icon }
91
159
alt = { badge . displayName }
92
160
fill
93
161
className = "object-contain"
@@ -101,6 +169,25 @@ export default function Dashboard() {
101
169
</ div >
102
170
</ div >
103
171
</ div >
172
+ { /* Submission Timeline */ }
173
+ < div className = "mt-8" >
174
+ < h3 className = "text-xl font-semibold mb-4 flex items-center" >
175
+ < Timer className = "w-5 h-5 mr-2 text-primary" />
176
+ Submission Timeline
177
+ </ h3 >
178
+ < div className = "bg-secondary/30 rounded-lg p-4" >
179
+ < div className = "grid grid-cols-2 md:grid-cols-4 gap-4" >
180
+ < TimelineStat
181
+ label = "All Time"
182
+ value = { leetcodeUserProfile . submitStats . totalSubmissionNum [ 0 ] . count }
183
+ total = { leetcodeUserProfile . submitStats . totalSubmissionNum [ 0 ] . count }
184
+ />
185
+ </ div >
186
+ </ div >
187
+ </ div >
188
+ </ div >
189
+
190
+ { /* Social Links */ }
104
191
< div className = "flex justify-center gap-6 mt-8" >
105
192
< SocialLink
106
193
href = { leetcodeUserProfile . githubUrl }
@@ -120,25 +207,53 @@ export default function Dashboard() {
120
207
</ div >
121
208
) ;
122
209
}
210
+
123
211
function StatItem ( {
124
212
icon,
125
213
value,
126
214
label,
215
+ subtitle,
127
216
} : {
128
217
icon : React . ReactNode ;
129
218
value : number ;
130
219
label : string ;
220
+ subtitle ?: string ;
131
221
} ) {
132
222
return (
133
- < div className = "flex items-center space-x-3 bg-secondary/50 rounded-lg p-3 " >
134
- { icon }
223
+ < div className = "flex items-center space-x-3 bg-secondary/50 rounded-lg p-4 hover:bg-secondary/70 transition-colors " >
224
+ < div className = "p-2 bg-background rounded-full" > { icon } </ div >
135
225
< div >
136
- < div className = "text-2xl font-bold" > { value } </ div >
137
- < div className = "text-sm text-muted-foreground" > { label } </ div >
226
+ < div className = "text-2xl font-bold" > { value . toLocaleString ( ) } </ div >
227
+ < div className = "text-sm font-medium" > { label } </ div >
228
+ { subtitle && (
229
+ < div className = "text-xs text-muted-foreground" > { subtitle } </ div >
230
+ ) }
231
+ </ div >
232
+ </ div >
233
+ ) ;
234
+ }
235
+
236
+ function TimelineStat ( {
237
+ label,
238
+ value,
239
+ total,
240
+ } : {
241
+ label : string ;
242
+ value : number ;
243
+ total : number ;
244
+ } ) {
245
+ const percentage = ( ( value / total ) * 100 ) . toFixed ( 1 ) ;
246
+ return (
247
+ < div className = "text-center" >
248
+ < div className = "text-sm font-medium text-muted-foreground" > { label } </ div >
249
+ < div className = "text-xl font-bold" > { value . toLocaleString ( ) } </ div >
250
+ < div className = "text-xs text-muted-foreground" >
251
+ { percentage } % of total
138
252
</ div >
139
253
</ div >
140
254
) ;
141
255
}
256
+
142
257
function SocialLink ( { href, icon } : { href : string ; icon : React . ReactNode } ) {
143
258
if ( ! href ) return null ;
144
259
return (
@@ -152,6 +267,7 @@ function SocialLink({ href, icon }: { href: string; icon: React.ReactNode }) {
152
267
</ a >
153
268
) ;
154
269
}
270
+
155
271
function DashboardSkeleton ( ) {
156
272
return (
157
273
< div className = "flex flex-col min-h-screen bg-gradient-to-b from-gray-100 to-gray-200 dark:from-gray-900 dark:to-gray-800 p-4 sm:p-6 md:p-8" >
0 commit comments