11import React , { useEffect , useState } from 'react' ;
2- import { Center , Group , Paper , RingProgress , Stack , Text } from '@mantine/core' ;
2+ import {
3+ Center ,
4+ Group ,
5+ Paper ,
6+ PaperProps ,
7+ RingProgress ,
8+ RingProgressProps ,
9+ Stack ,
10+ Text
11+ } from '@mantine/core' ;
312import { Notification } from '@jupyterlab/apputils' ;
413import { getStatistics } from '../services/leetcode' ;
514import { LeetCodeStatistics } from '../types/leetcode' ;
615import DifficultyStatistics from './DifficultyStatistics' ;
16+ import { IconCheck } from '@tabler/icons-react' ;
17+ import { StatusColors } from './QuestionItem' ;
718
819export const DifficultyColors : Record < string , string > = {
920 easy : '#1CBBBA' ,
@@ -12,58 +23,72 @@ export const DifficultyColors: Record<string, string> = {
1223} ;
1324
1425const Statistics : React . FC < {
15- username : string ;
16- } > = ( { username } ) => {
26+ username ?: string ;
27+ paperProps : PaperProps ;
28+ } > = ( { username, paperProps } ) => {
1729 const [ statistics , setStatistics ] = useState < LeetCodeStatistics | null > ( null ) ;
18- const [ all , setAll ] = useState < Map < string , number > | null > ( null ) ;
19- const [ accepted , setAccepted ] = useState < Map < string , number > | null > ( null ) ;
20- const [ __beats , setBeats ] = useState < Map < string , number > | null > ( null ) ;
30+ const [ isHovering , setIsHovering ] = useState ( false ) ;
31+ const [ difficultySections , setDifficultySections ] = useState <
32+ RingProgressProps [ 'sections' ] | null
33+ > ( null ) ;
34+ const [ beats , setBeats ] = useState < number | null > ( null ) ;
2135
2236 useEffect ( ( ) => {
37+ if ( ! username ) {
38+ return ;
39+ }
2340 getStatistics ( username )
24- . then ( d => {
25- setStatistics ( d ) ;
26- } )
41+ . then ( d => setStatistics ( d ) )
2742 . catch ( e => Notification . error ( e . message , { autoClose : 3000 } ) ) ;
28- } , [ ] ) ;
43+ } , [ username ] ) ;
2944
30- useEffect ( ( ) => {
45+ const getAllQuestions = ( ) => {
3146 if ( ! statistics ?. userSessionProgress ) {
3247 return ;
3348 }
3449
3550 const { userSessionProgress : sp } = statistics ;
36- setAll (
37- new Map (
38- sp . allQuestionsCount . map ( o => [ o . difficulty . toLowerCase ( ) , o . count ] )
39- )
51+ return new Map (
52+ sp . allQuestionsCount . map ( o => [ o . difficulty . toLowerCase ( ) , o . count ] )
4053 ) ;
41- } , [ statistics ?. userSessionProgress ] ) ;
54+ } ;
4255
43- useEffect ( ( ) => {
56+ const getAcceptedQuestions = ( ) => {
4457 const up =
4558 statistics ?. userProfileUserQuestionProgressV2
4659 . userProfileUserQuestionProgressV2 ;
4760 if ( ! up ) {
4861 return ;
4962 }
5063
51- setAccepted (
52- new Map (
53- up . numAcceptedQuestions . map ( o => [ o . difficulty . toLowerCase ( ) , o . count ] )
54- )
64+ return new Map (
65+ up . numAcceptedQuestions . map ( o => [ o . difficulty . toLowerCase ( ) , o . count ] )
5566 ) ;
67+ } ;
5668
57- const b = new Map (
69+ const getBeats = ( ) => {
70+ const up =
71+ statistics ?. userProfileUserQuestionProgressV2
72+ . userProfileUserQuestionProgressV2 ;
73+ if ( ! up ) {
74+ return ;
75+ }
76+ return new Map (
5877 up . userSessionBeatsPercentage . map ( o => [
5978 o . difficulty . toLowerCase ( ) ,
6079 o . percentage
6180 ] )
6281 ) ;
63- setBeats ( b ) ;
64- } , [ statistics ?. userProfileUserQuestionProgressV2 ] ) ;
82+ } ;
83+
84+ const all = getAllQuestions ( ) ;
85+ const accepted = getAcceptedQuestions ( ) ;
86+ const totalBeats =
87+ statistics ?. userProfileUserQuestionProgressV2
88+ . userProfileUserQuestionProgressV2 . totalQuestionBeatsPercentage ?? 0 ;
89+ const difficultyBeats = getBeats ( ) ;
6590
66- const getSections = ( ) => {
91+ const getProgressSections = ( ) => {
6792 if ( ! all || ! accepted ) {
6893 return [ ] ;
6994 }
@@ -81,31 +106,82 @@ const Statistics: React.FC<{
81106 const getTotalCount = ( ) => all ?. get ( 'all' ) || 0 ;
82107
83108 return (
84- < Paper
85- shadow = "md"
86- radius = "md"
87- withBorder
88- p = "sm"
89- bg = "var(--mantine-color-body)"
90- >
109+ < Paper { ...paperProps } >
91110 < Group >
92111 < RingProgress
93112 size = { 120 }
94113 thickness = { 8 }
95114 roundCaps
96- sections = { getSections ( ) }
115+ sections = {
116+ isHovering && difficultySections
117+ ? difficultySections
118+ : getProgressSections ( )
119+ }
97120 label = {
98121 < Center >
99- < Text fw = { 500 } fz = "md" >
100- { getTotalAc ( ) }
101- </ Text >
102- < Text fz = "sm" > /{ getTotalCount ( ) } </ Text >
122+ < Stack gap = { 0 } align = "center" >
123+ { isHovering ? (
124+ < >
125+ < Text fz = "xs" > Beats</ Text >
126+ < Group gap = { 0 } >
127+ < Text fw = "bolder" fz = "lg" >
128+ { Math . floor ( beats ?? totalBeats ) }
129+ </ Text >
130+ < Text fz = "sm" >
131+ .{ ( beats ?? totalBeats ) . toFixed ( 2 ) . split ( '.' ) [ 1 ] } %
132+ </ Text >
133+ </ Group >
134+ </ >
135+ ) : (
136+ < >
137+ < Group gap = { 0 } >
138+ < Text fw = "bolder" fz = "lg" >
139+ { getTotalAc ( ) }
140+ </ Text >
141+ < Text fz = "sm" > /{ getTotalCount ( ) } </ Text >
142+ </ Group >
143+ < Group gap = { 0 } >
144+ < IconCheck
145+ size = { 12 }
146+ stroke = { 1.5 }
147+ color = { StatusColors [ 'SOLVED' ] }
148+ />
149+ < Text fz = "xs" > Solved</ Text >
150+ </ Group >
151+ </ >
152+ ) }
153+ </ Stack >
103154 </ Center >
104155 }
156+ onMouseOver = { ( ) => setIsHovering ( true ) }
157+ onMouseLeave = { ( ) => setIsHovering ( false ) }
105158 />
106- < Stack >
159+ < Stack gap = "xs" w = "5em" >
107160 { Object . entries ( DifficultyColors ) . map ( ( [ d , c ] ) => (
108- < DifficultyStatistics key = { d } text = { d } color = { c } />
161+ < DifficultyStatistics
162+ key = { d }
163+ text = { d }
164+ color = { c }
165+ solved = { accepted ?. get ( d ) ?? 0 }
166+ total = { all ?. get ( d ) ?? 0 }
167+ onHover = { ( ) => {
168+ setIsHovering ( true ) ;
169+ setBeats ( difficultyBeats ?. get ( d ) ?? 0 ) ;
170+ setDifficultySections ( [
171+ {
172+ value : Math . round (
173+ ( ( accepted ?. get ( d ) ?? 0 ) / ( all ?. get ( d ) ?? 0 ) ) * 100
174+ ) ,
175+ color : c
176+ }
177+ ] ) ;
178+ } }
179+ onLeave = { ( ) => {
180+ setIsHovering ( false ) ;
181+ setBeats ( null ) ;
182+ setDifficultySections ( null ) ;
183+ } }
184+ />
109185 ) ) }
110186 </ Stack >
111187 </ Group >
0 commit comments