@@ -7,10 +7,8 @@ import { useLeetcodeStore } from "@/store/LeetcodeStore/useLeetcodeStore";
7
7
import { Card , CardContent , CardHeader } from "@/components/ui/card" ;
8
8
import { Skeleton } from "@/components/ui/skeleton" ;
9
9
import { Doughnut } from "react-chartjs-2" ;
10
-
11
- import CalendarHeatmap from "react-calendar-heatmap" ;
12
- import "../styles/style.css" ;
13
- import 'react-calendar-heatmap/dist/styles.css' ;
10
+ import { Tooltip as MuiTooltip } from '@mui/material'
11
+ import { ActivityCalendar } from 'react-activity-calendar'
14
12
15
13
import {
16
14
Chart as ChartJS ,
@@ -89,13 +87,23 @@ export default function Dashboard() {
89
87
90
88
const processLeetCodeData = ( submissionCalendar : string ) => {
91
89
const parsedData = JSON . parse ( submissionCalendar ) ;
92
-
93
- return Object . entries ( parsedData ) . map ( ( [ timestamp , count ] ) => ( {
94
- date : new Date ( Number ( timestamp ) * 1000 ) . toISOString ( ) . split ( "T" ) [ 0 ] ,
95
- count : count as number
96
- } ) ) ;
90
+
91
+ return Object . entries ( parsedData ) . map ( ( [ timestamp , count ] ) => {
92
+ const contributionCount = count as number ;
93
+ let level = 0 ;
94
+ if ( contributionCount > 0 ) {
95
+ level = Math . min ( Math . ceil ( contributionCount / 5 ) , 4 ) ;
96
+ }
97
+
98
+ return {
99
+ date : new Date ( Number ( timestamp ) * 1000 ) . toISOString ( ) . split ( "T" ) [ 0 ] ,
100
+ count : contributionCount ,
101
+ level : level
102
+ } ;
103
+ } ) ;
97
104
} ;
98
105
106
+ console . log ( processLeetCodeData ( userDetails . submissionCalendar ) ) ;
99
107
return (
100
108
< div className = "w-full max-w-7xl mx-auto px-3 sm:px-4 md:px-6 lg:px-8 py-4 sm:py-6 md:py-8 space-y-4 sm:space-y-6 md:space-y-8" >
101
109
{ /* Profile Header Card */ }
@@ -124,19 +132,19 @@ export default function Dashboard() {
124
132
</ div >
125
133
</ div >
126
134
< div className = "grid grid-cols-3 gap-2 sm:gap-4 w-full sm:w-auto mt-4 sm:mt-0" >
127
- < QuickStat
135
+ < QuickStat
128
136
icon = { < Target /> }
129
137
label = "Rating"
130
138
value = { userContestRanking ?. rating || 0 }
131
139
color = "blue"
132
140
/>
133
- < QuickStat
141
+ < QuickStat
134
142
icon = { < Trophy /> }
135
143
label = "Top"
136
144
value = { `${ userContestRanking ?. topPercentage } %` }
137
145
color = "yellow"
138
146
/>
139
- < QuickStat
147
+ < QuickStat
140
148
icon = { < Award /> }
141
149
label = "Rank"
142
150
value = { userContestRanking ?. globalRanking || 0 }
@@ -162,17 +170,20 @@ export default function Dashboard() {
162
170
</ div >
163
171
</ CardHeader >
164
172
< CardContent className = "p-2 sm:p-4 md:p-6 overflow-x-auto" >
165
- < div className = "min-w-[600px]" >
166
- < CalendarHeatmap
167
- values = { processLeetCodeData ( userDetails . submissionCalendar ) }
168
- startDate = { new Date ( new Date ( ) . setFullYear ( new Date ( ) . getFullYear ( ) - 1 ) ) }
169
- endDate = { new Date ( ) }
170
- classForValue = { ( value ) => {
171
- if ( ! value ) {
172
- return 'color-empty' ;
173
- }
174
- return `color-scale-${ ( value . count ) } ` ;
175
- } }
173
+ < div className = "h-[160px] transform scale-30 origin-center" >
174
+ < ActivityCalendar
175
+ theme = { { dark : [ '#020202' , '#058c42' , '#16DB65' , '#0D2818' , '#04471C' ] } }
176
+ data = { processLeetCodeData ( userDetails . submissionCalendar ) }
177
+ renderBlock = { ( block , activity ) => (
178
+ < MuiTooltip title = { `${ activity . count } activities on ${ activity . date } ` } >
179
+ { block }
180
+ </ MuiTooltip >
181
+ ) }
182
+ renderColorLegend = { ( block , level ) => (
183
+ < MuiTooltip title = { `Level: ${ level } ` } > { block } </ MuiTooltip >
184
+ ) }
185
+ weekStart = { 1 }
186
+ ref = { ( ref ) => console . log ( ref ) }
176
187
/>
177
188
</ div >
178
189
</ CardContent >
@@ -211,9 +222,9 @@ export default function Dashboard() {
211
222
< CardContent className = "p-0 overflow-y-auto h-[calc(350px-3rem)] sm:h-[calc(400px-4rem)]" >
212
223
< div className = "divide-y" >
213
224
{ recentSubmissions . map ( ( submission , idx ) => (
214
- < Link
225
+ < Link
215
226
href = { `https://leetcode.com/problems/${ submission . titleSlug } ` }
216
- key = { idx }
227
+ key = { idx }
217
228
target = "_blank"
218
229
className = "flex items-center p-3 sm:p-4 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors group"
219
230
>
@@ -235,53 +246,53 @@ export default function Dashboard() {
235
246
{ /* Statistics Cards */ }
236
247
< div className = "md:col-span-2 max-h-[400px] sm:max-h-[450px] lg:max-h-[500px] overflow-hidden" >
237
248
< div className = "grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6" >
238
- < DetailCard
249
+ < DetailCard
239
250
title = "Problem Solving Stats"
240
251
icon = { < Star className = "w-4 h-4 sm:w-5 sm:h-5 text-yellow-600" /> }
241
252
stats = { [
242
- {
253
+ {
243
254
label : 'Total Solved' ,
244
255
value : userDetails . submitStats . acSubmissionNum [ 0 ] . count ,
245
256
icon : < CheckCircle className = "w-3 h-3 sm:w-4 sm:h-4 text-green-500" />
246
257
} ,
247
- {
258
+ {
248
259
label : 'Easy Problems' ,
249
260
value : userDetails . submitStats . acSubmissionNum [ 1 ] . count ,
250
261
icon : < Zap className = "w-3 h-3 sm:w-4 sm:h-4 text-green-500" />
251
262
} ,
252
- {
263
+ {
253
264
label : 'Medium Problems' ,
254
265
value : userDetails . submitStats . acSubmissionNum [ 2 ] . count ,
255
266
icon : < Zap className = "w-3 h-3 sm:w-4 sm:h-4 text-yellow-500" />
256
267
} ,
257
- {
268
+ {
258
269
label : 'Hard Problems' ,
259
270
value : userDetails . submitStats . acSubmissionNum [ 3 ] . count ,
260
271
icon : < Zap className = "w-3 h-3 sm:w-4 sm:h-4 text-red-500" />
261
272
} ,
262
273
] }
263
274
/>
264
- < DetailCard
275
+ < DetailCard
265
276
title = "Performance Metrics"
266
277
icon = { < Timer className = "w-4 h-4 sm:w-5 sm:h-5 text-purple-600" /> }
267
278
stats = { [
268
- {
279
+ {
269
280
label : 'Acceptance Rate' ,
270
- value : `${ ( userDetails . submitStats . acSubmissionNum [ 0 ] . count /
281
+ value : `${ ( userDetails . submitStats . acSubmissionNum [ 0 ] . count /
271
282
userDetails . submitStats . totalSubmissionNum [ 0 ] . count * 100 ) . toFixed ( 1 ) } %`,
272
283
icon : < TrendingUp className = "w-3 h-3 sm:w-4 sm:h-4 text-blue-500" />
273
284
} ,
274
- {
285
+ {
275
286
label : 'Total Submissions' ,
276
287
value : userDetails . submitStats . totalSubmissionNum [ 0 ] . count ,
277
288
icon : < Code className = "w-3 h-3 sm:w-4 sm:h-4 text-green-500" />
278
289
} ,
279
- {
290
+ {
280
291
label : 'Contribution Points' ,
281
292
value : userDetails . contributions . points ,
282
293
icon : < Star className = "w-3 h-3 sm:w-4 sm:h-4 text-yellow-500" />
283
294
} ,
284
- {
295
+ {
285
296
label : 'Contest Count' ,
286
297
value : userContestRanking ?. attendedContestsCount || 0 ,
287
298
icon : < Trophy className = "w-3 h-3 sm:w-4 sm:h-4 text-orange-500" />
@@ -304,8 +315,8 @@ export default function Dashboard() {
304
315
< CardContent className = "p-2 sm:p-4 flex justify-center items-center flex-1 overflow-hidden" >
305
316
< div className = "h-full w-full flex items-center justify-center" >
306
317
< div className = "h-48 w-48 sm:h-56 sm:w-56 md:h-64 md:w-64" >
307
- < Doughnut
308
- data = { difficultyData }
318
+ < Doughnut
319
+ data = { difficultyData }
309
320
options = { {
310
321
cutout : '65%' ,
311
322
responsive : true ,
@@ -341,7 +352,7 @@ export default function Dashboard() {
341
352
}
342
353
}
343
354
}
344
- } }
355
+ } }
345
356
/>
346
357
</ div >
347
358
</ div >
@@ -392,7 +403,7 @@ function DetailCard({ title, icon, stats }: { title: string; icon: React.ReactNo
392
403
< CardContent className = "p-2 sm:p-4" >
393
404
< div className = "grid grid-cols-2 gap-2 sm:gap-4" >
394
405
{ stats . map ( ( stat , idx ) => (
395
- < div key = { idx }
406
+ < div key = { idx }
396
407
className = "bg-gray-100/80 dark:bg-gray-700/50 p-2 sm:p-4 rounded-lg hover:bg-gray-200/80 dark:hover:bg-gray-700/80 transition-colors flex flex-col justify-between h-full"
397
408
>
398
409
< div className = "flex items-center gap-1 sm:gap-2 mb-1 sm:mb-2" >
0 commit comments