@@ -2,14 +2,59 @@ import _map from "lodash/map";
22import { Component } from "react" ;
33import { FormattedMessage } from "react-intl" ;
44import QuickWidget from "../../../components/QuickWidget/QuickWidget" ;
5+ import BusySpinner from "../../../components/BusySpinner/BusySpinner" ;
56import messages from "../Messages" ;
67
78export default class LeaderboardStats extends Component {
89 render ( ) {
9- if ( ! this . props . leaderboardMetrics ) {
10+ // Check if user has opted out of leaderboard
11+ const userOptedOut =
12+ this . props . targetUser ?. settings ?. leaderboardOptOut &&
13+ this . props . targetUser ?. id !== this . props . currentUser ?. userId ;
14+
15+ // If user opted out, don't show the leaderboard widget at all
16+ if ( userOptedOut ) {
1017 return null ;
1118 }
1219
20+ // Show loading spinner only if we're explicitly in a loading state
21+ if ( this . props . loading === true ) {
22+ return (
23+ < QuickWidget
24+ { ...this . props }
25+ className = "mr-card-widget mr-card-widget--padded mr-mb-4"
26+ widgetTitle = { < FormattedMessage { ...messages . leaderboardTitle } /> }
27+ noMain
28+ permanent
29+ >
30+ < div className = "mr-flex mr-justify-center mr-py-8" >
31+ < BusySpinner />
32+ </ div >
33+ </ QuickWidget >
34+ ) ;
35+ }
36+
37+ // If leaderboardMetrics is null or undefined, show "no data" state
38+ if ( ! this . props . leaderboardMetrics ) {
39+ return (
40+ < QuickWidget
41+ { ...this . props }
42+ className = "mr-card-widget mr-card-widget--padded mr-mb-4"
43+ widgetTitle = { < FormattedMessage { ...messages . leaderboardTitle } /> }
44+ noMain
45+ permanent
46+ >
47+ < div className = "mr-text-center mr-py-8 mr-text-grey-light" >
48+ < FormattedMessage { ...messages . noChallengesCompleted } />
49+ </ div >
50+ </ QuickWidget >
51+ ) ;
52+ }
53+
54+ // At this point we have leaderboard data, so render it
55+ const leaderboardMetrics = this . props . leaderboardMetrics ;
56+ const topChallenges = leaderboardMetrics . topChallenges || [ ] ;
57+
1358 return (
1459 < QuickWidget
1560 { ...this . props }
@@ -21,13 +66,13 @@ export default class LeaderboardStats extends Component {
2166 < ul className = "mr-list-reset mr-mt-3 mr-mb-6" >
2267 < li className = "mr-flex mr-items-center" >
2368 < strong className = "mr-font-light mr-text-4xl mr-min-w-28 mr-text-yellow" >
24- { this . props . leaderboardMetrics . rank }
69+ { leaderboardMetrics . rank || "N/A" }
2570 </ strong >
2671 < FormattedMessage { ...messages . globalRank } />
2772 </ li >
2873 < li className = "mr-flex mr-items-center" >
2974 < strong className = "mr-font-light mr-text-4xl mr-min-w-28 mr-text-yellow" >
30- { this . props . leaderboardMetrics . score }
75+ { leaderboardMetrics . score || "N/A" }
3176 </ strong >
3277 < FormattedMessage { ...messages . totalPoints } />
3378 </ li >
@@ -36,13 +81,19 @@ export default class LeaderboardStats extends Component {
3681 < FormattedMessage { ...messages . topChallenges } />
3782 </ h3 >
3883 < ol className = "mr-list-reset mr-links-green-lighter" >
39- { _map ( this . props . leaderboardMetrics . topChallenges . slice ( 0 , 4 ) , ( challenge , index ) => {
40- return (
41- < li key = { index } className = "mr-mt-3" >
42- < a href = { "/browse/challenges/" + challenge . id } > { challenge . name } </ a >
43- </ li >
44- ) ;
45- } ) }
84+ { topChallenges . length > 0 ? (
85+ _map ( topChallenges . slice ( 0 , 4 ) , ( challenge , index ) => {
86+ return (
87+ < li key = { index } className = "mr-mt-3" >
88+ < a href = { "/browse/challenges/" + challenge . id } > { challenge . name } </ a >
89+ </ li >
90+ ) ;
91+ } )
92+ ) : (
93+ < li className = "mr-mt-3 mr-text-grey-light" >
94+ < FormattedMessage { ...messages . noChallengesCompleted } />
95+ </ li >
96+ ) }
4697 </ ol >
4798 </ QuickWidget >
4899 ) ;
0 commit comments