Skip to content

Commit 1300768

Browse files
feat: add public profile pages, cleanup user profile structure, improve profile responsiveness
1 parent 8c4b7ac commit 1300768

File tree

6 files changed

+315
-229
lines changed

6 files changed

+315
-229
lines changed

src/api/profile/profile.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { buildUrl } from '../utils'
22

3-
export const getPlayerStats = async () => {
4-
const res = await fetch(buildUrl('auth/get_player_stats'))
3+
export const getPlayerStats = async (name?: string) => {
4+
const res = await fetch(
5+
buildUrl(`auth/get_player_stats${name ? `/${name}` : ''}`),
6+
)
57
const data = await res.json()
68
return {
79
regularRating: data.play_elo as number,

src/components/Leaderboard/LeaderboardColumn.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Link from 'next/link'
2+
13
interface Props {
24
icon: JSX.Element
35
name: string
@@ -26,10 +28,16 @@ export const LeaderboardColumn: React.FC<Props> = ({
2628
>
2729
<div className="flex items-center gap-2">
2830
<p className="w-5">{index + 1}</p>
29-
<p>
30-
{player.display_name} {index == 0 && '👑'}
31-
</p>
31+
<Link
32+
href={`/profile/${player.display_name}`}
33+
className="flex items-center gap-2 hover:underline"
34+
>
35+
<p>
36+
{player.display_name} {index == 0 && '👑'}
37+
</p>
38+
</Link>
3239
</div>
40+
3341
<p>{player.elo}</p>
3442
</div>
3543
))}
Lines changed: 72 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -1,223 +1,85 @@
1-
/* eslint-disable prettier/prettier */
2-
/* eslint-disable import/named */
3-
/* eslint-disable jsx-a11y/click-events-have-key-events */
4-
/* eslint-disable jsx-a11y/no-static-element-interactions */
5-
import { useRouter } from 'next/router'
6-
import React, { useState, useEffect, useContext } from 'react'
1+
import React from 'react'
72

83
import {
9-
UserIcon,
104
HandIcon,
115
BrainIcon,
126
TrainIcon,
137
TuringIcon,
148
RegularPlayIcon,
159
} from '../Icons/icons'
16-
import { getPlayerStats } from 'src/api'
17-
import { GameList, ProfileColumn } from 'src/components'
18-
import { AuthContext, WindowSizeContext } from 'src/contexts'
10+
import { ProfileColumn } from 'src/components'
1911

20-
export const UserProfile: React.FC = () => {
21-
const router = useRouter()
22-
const { user } = useContext(AuthContext)
23-
const { isMobile } = useContext(WindowSizeContext)
24-
25-
if (!user?.lichessId) router.push('/')
26-
27-
const [stats, setStats] = useState({
28-
regularRating: 0,
29-
regularWins: 0,
30-
regularDraws: 0,
31-
regularGames: 0,
32-
regularMax: 0,
33-
regularMin: 0,
34-
regularHours: 0,
35-
36-
handRating: 0,
37-
handWins: 0,
38-
handDraws: 0,
39-
handGames: 0,
40-
handMax: 0,
41-
handMin: 0,
42-
handHours: 0,
43-
44-
brainRating: 0,
45-
brainWins: 0,
46-
brainDraws: 0,
47-
brainGames: 0,
48-
brainMax: 0,
49-
brainMin: 0,
50-
brainHours: 0,
51-
52-
trainRating: 0,
53-
trainCorrect: 0,
54-
trainGames: 0,
55-
trainMax: 0,
56-
trainMin: 0,
57-
trainHours: 0,
58-
59-
botNotRating: 0,
60-
botNotCorrect: 0,
61-
botNotWrong: 0,
62-
botNotMax: 0,
63-
botNotMin: 0,
64-
botNotHours: 0,
65-
})
66-
67-
useEffect(() => {
68-
const fetchStats = async () => {
69-
const playerStats = await getPlayerStats()
70-
setStats(playerStats)
71-
}
72-
73-
fetchStats()
74-
}, [])
75-
76-
const desktopLayout = () => (
77-
<div className="flex h-full w-full flex-col items-start justify-center gap-6 px-[4%] md:py-[2%]">
78-
<div className="flex flex-row items-center gap-4">
79-
<div className="*:w-16 *:fill-primary">{UserIcon}</div>
80-
<h1 className="text-3xl font-semibold">{user?.displayName}</h1>
81-
</div>
82-
<div className="flex flex-col items-start gap-6 md:flex-row">
83-
<GameList />
84-
<div className="grid h-full w-full grid-cols-2 gap-6">
85-
<ProfileColumn
86-
icon={<RegularPlayIcon />}
87-
name="Regular"
88-
data={{
89-
rating: stats.regularRating,
90-
highest: stats.regularMax,
91-
hours: stats.regularHours,
92-
games: stats.regularGames,
93-
wins: stats.regularWins,
94-
draws: stats.regularDraws,
95-
}}
96-
/>
97-
<ProfileColumn
98-
icon={<HandIcon />}
99-
name="Hand"
100-
data={{
101-
rating: stats.handRating,
102-
highest: stats.handMax,
103-
hours: stats.handHours,
104-
games: stats.handGames,
105-
wins: stats.handWins,
106-
draws: stats.handDraws,
107-
}}
108-
/>
109-
<ProfileColumn
110-
icon={<BrainIcon />}
111-
name="Brain"
112-
data={{
113-
rating: stats.brainRating,
114-
highest: stats.brainMax,
115-
hours: stats.brainHours,
116-
games: stats.brainGames,
117-
wins: stats.brainWins,
118-
draws: stats.brainDraws,
119-
}}
120-
/>
121-
<ProfileColumn
122-
icon={<TrainIcon />}
123-
name="Train"
124-
data={{
125-
rating: stats.trainRating,
126-
highest: stats.trainMax,
127-
hours: stats.trainHours,
128-
games: stats.trainGames,
129-
wins: stats.trainCorrect,
130-
}}
131-
/>
132-
<ProfileColumn
133-
icon={<TuringIcon />}
134-
name="Bot / Not"
135-
data={{
136-
rating: stats.botNotRating,
137-
highest: stats.botNotMax,
138-
hours: stats.botNotHours,
139-
games: stats.botNotCorrect + stats.botNotWrong,
140-
wins: stats.botNotCorrect,
141-
losses: stats.botNotWrong,
142-
}}
143-
/>
144-
</div>
145-
</div>
146-
</div>
147-
)
12+
interface Props {
13+
wide?: boolean
14+
stats: {
15+
[key: string]: number
16+
}
17+
}
14818

149-
const mobileLayout = () => (
150-
<div className="mt-6 flex flex-col gap-3 px-[4%]">
151-
<div className="flex flex-row items-center gap-3">
152-
<div className="*:w-12 *:fill-primary">{UserIcon}</div>
153-
<h1 className="text-3xl font-semibold">{user?.displayName}</h1>
154-
</div>
155-
<div className="flex w-full flex-col gap-6">
156-
<GameList />
157-
<div className="flex h-full w-full flex-col flex-wrap justify-start gap-6">
158-
<ProfileColumn
159-
icon={<RegularPlayIcon />}
160-
name="REGULAR"
161-
data={{
162-
rating: stats.regularRating,
163-
highest: stats.regularMax,
164-
hours: stats.regularHours,
165-
games: stats.regularGames,
166-
wins: stats.regularWins,
167-
draws: stats.regularDraws,
168-
}}
169-
/>
170-
<ProfileColumn
171-
icon={<HandIcon />}
172-
name="HAND"
173-
data={{
174-
rating: stats.handRating,
175-
highest: stats.handMax,
176-
hours: stats.handHours,
177-
games: stats.handGames,
178-
wins: stats.handWins,
179-
draws: stats.handDraws,
180-
}}
181-
/>
182-
<ProfileColumn
183-
icon={<BrainIcon />}
184-
name="BRAIN"
185-
data={{
186-
rating: stats.brainRating,
187-
highest: stats.brainMax,
188-
hours: stats.brainHours,
189-
games: stats.brainGames,
190-
wins: stats.brainWins,
191-
draws: stats.brainDraws,
192-
}}
193-
/>
194-
<ProfileColumn
195-
icon={<TrainIcon />}
196-
name="TRAIN"
197-
data={{
198-
rating: stats.trainRating,
199-
highest: stats.trainMax,
200-
hours: stats.trainHours,
201-
games: stats.trainGames,
202-
wins: stats.trainCorrect,
203-
}}
204-
/>
205-
<ProfileColumn
206-
icon={<TuringIcon />}
207-
name="BOT/NOT"
208-
data={{
209-
rating: stats.botNotRating,
210-
highest: stats.botNotMax,
211-
hours: stats.botNotHours,
212-
games: stats.botNotCorrect + stats.botNotWrong,
213-
wins: stats.botNotCorrect,
214-
losses: stats.botNotWrong,
215-
}}
216-
/>
217-
</div>
218-
</div>
19+
export const UserProfile = ({ wide, stats }: Props) => {
20+
return (
21+
<div
22+
className={`grid h-full w-full grid-cols-1 gap-6 ${wide ? 'md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4' : 'lg:grid-cols-2'}`}
23+
>
24+
<ProfileColumn
25+
icon={<RegularPlayIcon />}
26+
name="Regular"
27+
data={{
28+
rating: stats.regularRating,
29+
highest: stats.regularMax,
30+
hours: stats.regularHours,
31+
games: stats.regularGames,
32+
wins: stats.regularWins,
33+
draws: stats.regularDraws,
34+
}}
35+
/>
36+
<ProfileColumn
37+
icon={<HandIcon />}
38+
name="Hand"
39+
data={{
40+
rating: stats.handRating,
41+
highest: stats.handMax,
42+
hours: stats.handHours,
43+
games: stats.handGames,
44+
wins: stats.handWins,
45+
draws: stats.handDraws,
46+
}}
47+
/>
48+
<ProfileColumn
49+
icon={<BrainIcon />}
50+
name="Brain"
51+
data={{
52+
rating: stats.brainRating,
53+
highest: stats.brainMax,
54+
hours: stats.brainHours,
55+
games: stats.brainGames,
56+
wins: stats.brainWins,
57+
draws: stats.brainDraws,
58+
}}
59+
/>
60+
<ProfileColumn
61+
icon={<TrainIcon />}
62+
name="Train"
63+
data={{
64+
rating: stats.trainRating,
65+
highest: stats.trainMax,
66+
hours: stats.trainHours,
67+
games: stats.trainGames,
68+
wins: stats.trainCorrect,
69+
}}
70+
/>
71+
<ProfileColumn
72+
icon={<TuringIcon />}
73+
name="Bot / Not"
74+
data={{
75+
rating: stats.botNotRating,
76+
highest: stats.botNotMax,
77+
hours: stats.botNotHours,
78+
games: stats.botNotCorrect + stats.botNotWrong,
79+
wins: stats.botNotCorrect,
80+
losses: stats.botNotWrong,
81+
}}
82+
/>
21983
</div>
22084
)
221-
222-
return <>{isMobile ? mobileLayout() : desktopLayout()}</>
22385
}

src/pages/profile.tsx

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)