Skip to content

Commit 16cf76b

Browse files
committed
feat(leaderboard): more work with hero & table sections on mobile
1 parent 23aa290 commit 16cf76b

File tree

5 files changed

+40
-27
lines changed

5 files changed

+40
-27
lines changed

src/app/(app)/(default_layout)/leaderboard/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default async function TodaysLeaderboardPage() {
2525
{/** @ts-ignore - this is the valid type */}
2626
<LeaderboardHero topThreeUsers={topThreeUsers} />
2727
<div className="lg:container flex flex-col xl:flex-row gap-10 mt-5">
28-
<LeaderboardMostQuestionsAnswered userUid={user?.uid} />
28+
<LeaderboardMostQuestionsAnswered user={user} />
2929
</div>
3030
</>
3131
);

src/components/app/leaderboard/leaderboard-hero.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,20 @@ export default function LeaderboardHero(opts: {
6262
<ProfilePicture
6363
src={user.userProfilePicture}
6464
alt={`${user.username} profile picture`}
65-
className="size-6 md:size-8 rounded-full shadow-lg"
65+
className="size-8 md:size-12 rounded-full shadow-lg"
6666
/>
6767
{/** if first, add a crown top right of the profile picture */}
6868
{position === 1 && (
69-
<div className="absolute -top-3 left-2 size-4">
69+
<div className="absolute -top-3 left-4 size-4">
7070
<Crown className="size-4 text-yellow-500 fill-yellow-400" />
7171
</div>
7272
)}
73+
{/** if the user is a premium users */}
74+
{user.userLevel === 'PREMIUM' && (
75+
<div className="relative -top-3 left-1.5 w-fit bg-accent text-xs flex items-center justify-center px-2 py-0.5 rounded-full">
76+
<span className="text-[10px]">PRO</span>
77+
</div>
78+
)}
7379
</div>
7480
<span className="mt-2 text-sm md:text-base font-semibold line-clamp-1">
7581
{getUserDisplayName(user as unknown as UserRecord)}
@@ -82,7 +88,7 @@ export default function LeaderboardHero(opts: {
8288
<div
8389
className={`absolute inset-0 transform-3d rotate-x-55 rotate-y-45 ${
8490
position === 1
85-
? 'bg-[#202020]'
91+
? 'bg-[#252525]'
8692
: position === 2
8793
? 'bg-black-100'
8894
: 'bg-black-100'

src/components/app/leaderboard/leaderboard-most-questions-answered.tsx

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Trophy } from 'lucide-react';
1+
import { FileQuestion, Trophy } from 'lucide-react';
22
import { getMostQuestionsAnswered } from '@/utils/data/leaderboard/get-most-questions-answered';
33
import ProfilePicture from '@/components/ui/profile-picture';
44
import { UserRecord } from '@/types/User';
@@ -23,17 +23,17 @@ import { Badge } from '@/components/ui/badge';
2323
import ShowTimeTakenToggle from './show-time-taken';
2424

2525
export default async function LeaderboardMostQuestionsAnswered({
26-
userUid,
26+
user,
2727
}: {
28-
userUid?: string;
28+
user?: UserRecord | null;
2929
}) {
3030
const topUsersByQuestionCount = await getMostQuestionsAnswered();
3131

3232
return (
3333
<Card className="border-none">
3434
<CardHeader className="p-0 md:p-6 w-full flex gap-2 justify-between">
35-
<div className="flex flex-wrap items-center justify-between gap-2">
36-
<div className="flex items-center gap-x-2">
35+
<div className="flex flex-wrap items-center justify-between gap-4">
36+
<div className="order-last md:order-first flex items-center gap-x-2">
3737
<Trophy className="size-5 text-accent" />
3838
<div>
3939
<CardTitle className="text-white">
@@ -44,7 +44,7 @@ export default async function LeaderboardMostQuestionsAnswered({
4444
</CardDescription>
4545
</div>
4646
</div>
47-
<ShowTimeTakenToggle />
47+
<ShowTimeTakenToggle user={user} />
4848
</div>
4949
</CardHeader>
5050
<CardContent className="p-0 pt-6 md:p-6 md:pt-0">
@@ -57,15 +57,18 @@ export default async function LeaderboardMostQuestionsAnswered({
5757
<TableHead className="!border-t-0 text-white bg-transparent">
5858
User
5959
</TableHead>
60-
<TableHead className="!border-t-0 text-right text-white bg-transparent">
61-
Questions Solved
60+
<TableHead className="!border-t-0 flex justify-center items-center xs:justify-end gap-2 md:text-right text-white bg-transparent">
61+
<span className="hidden sm:block">Questions Solved</span>
62+
<span className="block sm:hidden">
63+
<FileQuestion className="size-4 text-white" />
64+
</span>
6265
</TableHead>
6366
</TableRow>
6467
</TableHeader>
6568
<TableBody>
66-
{topUsersByQuestionCount.map((user, index) => (
69+
{topUsersByQuestionCount.map((userData, index) => (
6770
<TableRow
68-
key={user.uid}
71+
key={userData.uid}
6972
className="border-white/10 hover:bg-white/5 transition-colors"
7073
>
7174
<TableCell className="font-medium text-white">
@@ -87,18 +90,18 @@ export default async function LeaderboardMostQuestionsAnswered({
8790
<TableCell>
8891
<div className="flex items-center gap-4">
8992
<ProfilePicture
90-
src={user.userProfilePicture}
91-
alt={`${user.username} profile picture`}
93+
src={userData.userProfilePicture}
94+
alt={`${userData.username} profile picture`}
9295
className="text-white"
9396
/>
9497
<div className="flex gap-2">
95-
<span className="text-white font-medium">
96-
{shortenText(
97-
getUserDisplayName(user as unknown as UserRecord),
98-
25
99-
)}
98+
<span className="text-white font-medium hidden md:block">
99+
{shortenText(getUserDisplayName(userData as any), 25)}
100100
</span>
101-
{userUid === user.uid && (
101+
<span className="text-white font-medium block md:hidden">
102+
{shortenText(getUserDisplayName(userData as any), 10)}
103+
</span>
104+
{user?.uid === userData.uid && (
102105
<span className="text-xs text-white">(You)</span>
103106
)}
104107
</div>
@@ -109,7 +112,7 @@ export default async function LeaderboardMostQuestionsAnswered({
109112
variant="outline"
110113
className="border-white/10 text-white"
111114
>
112-
{user._count.answers}
115+
{userData._count.answers}
113116
</Badge>
114117
</TableCell>
115118
</TableRow>

src/components/app/leaderboard/show-time-taken.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import { Label } from '@/components/ui/label';
55
import { updateUser } from '@/actions/user/authed/update-user';
66
import { useState } from 'react';
77
import { toast } from 'sonner';
8+
import { UserRecord } from '@/types/User';
89

9-
export default function ShowTimeTakenToggle() {
10-
const [checked, setChecked] = useState(true);
10+
export default function ShowTimeTakenToggle(opts: {
11+
user?: UserRecord | null;
12+
}) {
13+
const [checked, setChecked] = useState(opts.user?.showTimeTaken ?? true);
1114

1215
const handleSubmit = async (formData: FormData) => {
1316
const showTimeTaken = formData.get('showTimeTaken') === 'on';
@@ -17,7 +20,6 @@ export default function ShowTimeTakenToggle() {
1720
showTimeTaken,
1821
},
1922
});
20-
2123
toast.success('User updated');
2224
} catch (error) {
2325
toast.error('Failed to update user');
@@ -40,6 +42,7 @@ export default function ShowTimeTakenToggle() {
4042
handleSubmit(formData);
4143
}}
4244
className="bg-black-50"
45+
disabled={!opts.user}
4346
/>
4447
<Label htmlFor="showTimeTaken" className="text-white">
4548
{checked ? 'Hide' : 'Show'} on leaderboard?

src/utils/data/leaderboard/get-most-questions-answered.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ export const getMostQuestionsAnswered = async (take: number = 20) => {
2222
answers: true,
2323
userProfilePicture: true,
2424
_count: {
25-
select: { answers: true }, // Count on actual references
25+
select: { answers: true },
2626
},
27+
userLevel: true,
2728
},
2829
});
2930
};

0 commit comments

Comments
 (0)