Skip to content

Commit 28d963a

Browse files
feat: add global stats component
1 parent dd7b32f commit 28d963a

4 files changed

Lines changed: 83 additions & 3 deletions

File tree

src/api/auth/auth.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,10 @@ export const getLeaderboard = async () => {
3131

3232
return data
3333
}
34+
35+
export const getGlobalStats = async () => {
36+
const res = await fetch(buildUrl('auth/global_stats'))
37+
const data = await res.json()
38+
39+
return data
40+
}

src/components/Home/HomeHero.tsx

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Link from 'next/link'
2-
import { useCallback, useContext } from 'react'
32
import { motion } from 'framer-motion'
3+
import { useCallback, useContext, useEffect, useState } from 'react'
44

55
import {
66
SunIcon,
@@ -13,7 +13,9 @@ import {
1313
StarIcon,
1414
} from 'src/components/Icons/icons'
1515
import { PlayType } from 'src/types'
16+
import { getGlobalStats } from 'src/api'
1617
import { AuthContext, ModalContext } from 'src/contexts'
18+
import { AnimatedNumber } from 'src/components/Misc/AnimatedNumber'
1719

1820
interface Props {
1921
scrollHandler: () => void
@@ -117,6 +119,11 @@ const FeatureCard: React.FC<FeatureCardProps> = ({
117119
}
118120

119121
export const HomeHero: React.FC<Props> = ({ scrollHandler }: Props) => {
122+
const [globalStats, setGlobalStats] = useState<{
123+
play_moves_total: number
124+
puzzle_games_total: number
125+
turing_games_total: number
126+
}>()
120127
const { setPlaySetupModalProps } = useContext(ModalContext)
121128
const { user, connectLichess } = useContext(AuthContext)
122129

@@ -127,8 +134,15 @@ export const HomeHero: React.FC<Props> = ({ scrollHandler }: Props) => {
127134
[setPlaySetupModalProps],
128135
)
129136

137+
useEffect(() => {
138+
;(async () => {
139+
const data = await getGlobalStats()
140+
setGlobalStats(data)
141+
})()
142+
}, [])
143+
130144
return (
131-
<div className="relative flex flex-col items-center justify-center overflow-hidden pb-12 pt-16 md:pb-28 md:pt-36">
145+
<div className="relative flex flex-col items-center justify-center gap-14 overflow-hidden pb-12 pt-16 md:pb-16 md:pt-36">
132146
<div className="z-10 flex w-full max-w-[1200px] flex-col items-center justify-center gap-10 p-4 text-left md:flex-row md:gap-20">
133147
<div className="flex w-full flex-col items-start justify-center gap-6 md:w-[40%] md:gap-8">
134148
<div className="flex flex-col gap-3 md:gap-4">
@@ -189,7 +203,6 @@ export const HomeHero: React.FC<Props> = ({ scrollHandler }: Props) => {
189203
)}
190204
</motion.div>
191205
</div>
192-
193206
<div className="grid w-full flex-1 grid-cols-1 gap-4 md:grid-cols-3">
194207
<FeatureCard
195208
icon={<RegularPlayIcon />}
@@ -237,6 +250,34 @@ export const HomeHero: React.FC<Props> = ({ scrollHandler }: Props) => {
237250
/>
238251
</div>
239252
</div>
253+
<motion.div
254+
className="flex gap-6"
255+
initial={{ opacity: 0, y: 10 }}
256+
animate={{ opacity: 1, y: 0 }}
257+
transition={{ duration: 0.4, delay: 0.3 }}
258+
>
259+
<p className="text-base text-primary/80">
260+
<AnimatedNumber
261+
value={globalStats?.play_moves_total || 0}
262+
className="font-bold"
263+
/>{' '}
264+
moves played
265+
</p>
266+
<p className="text-base text-primary/80">
267+
<AnimatedNumber
268+
value={globalStats?.puzzle_games_total || 0}
269+
className="font-bold"
270+
/>{' '}
271+
puzzle games solved
272+
</p>
273+
<p className="text-base text-primary/80">
274+
<AnimatedNumber
275+
value={globalStats?.turing_games_total || 0}
276+
className="font-bold"
277+
/>{' '}
278+
turing games played
279+
</p>
280+
</motion.div>
240281
</div>
241282
)
242283
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useEffect, useState } from 'react'
2+
import { motion, useSpring, useTransform } from 'framer-motion'
3+
4+
interface AnimatedNumberProps {
5+
value: number
6+
duration?: number
7+
formatValue?: (value: number) => string
8+
className?: string
9+
}
10+
11+
export const AnimatedNumber: React.FC<AnimatedNumberProps> = ({
12+
value,
13+
duration = 1.5,
14+
formatValue = (val) => Math.round(val).toLocaleString(),
15+
className = '',
16+
}) => {
17+
const springValue = useSpring(value, {
18+
stiffness: 150,
19+
damping: 30,
20+
duration,
21+
restDelta: 0.001,
22+
})
23+
24+
const displayValue = useTransform(springValue, (val) => formatValue(val))
25+
26+
useEffect(() => {
27+
springValue.set(value)
28+
}, [springValue, value])
29+
30+
return <motion.span className={className}>{displayValue}</motion.span>
31+
}

src/components/Misc/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export * from './PlaySetupModal'
55
export * from './ModalContainer'
66
export * from './InstructionsModal'
77
export * from './ContinueAgainstMaia'
8+
export * from './AnimatedNumber'

0 commit comments

Comments
 (0)