Skip to content

Commit 7636b19

Browse files
committed
Added profile picture to leaderboard
1 parent cdec894 commit 7636b19

File tree

7 files changed

+364
-45
lines changed

7 files changed

+364
-45
lines changed

components/tabs/Ranking/Cadenas.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ function Cadenas({ highline }: Props) {
6262
name: entry.instagram,
6363
position: pageIdx * PAGE_SIZE + idx + 1,
6464
value: entry.total_cadenas.toString(),
65+
profilePicture: entry.profile_picture,
6566
};
6667
}) || []
6768
);

components/tabs/Ranking/Distance.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ function Distance({ highline }: Props) {
6262
name: entry.instagram,
6363
position: pageIdx * PAGE_SIZE + idx + 1,
6464
value: `${entry.total_distance_walked}m`,
65+
profilePicture: entry.profile_picture,
6566
};
6667
}) || []
6768
);

components/tabs/Ranking/FullLine.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ function FullLine({ highline }: Props) {
6262
name: entry.instagram,
6363
position: pageIdx * PAGE_SIZE + idx + 1,
6464
value: entry.total_full_lines.toString(),
65+
profilePicture: entry.profile_picture,
6566
};
6667
}) || []
6768
);

components/tabs/Ranking/Speedline.tsx

+7-8
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,12 @@ function Speedline({ highline }: Props) {
2121
const format = useFormatter();
2222

2323
async function fetchEntries({ pageParam = 1 }) {
24-
const { data } = await supabase
25-
.from("entry")
26-
.select()
27-
.match({ highline_id: highline.id })
28-
.order("crossing_time", { ascending: true })
29-
.range((pageParam - 1) * PAGE_SIZE, pageParam * PAGE_SIZE - 1);
30-
24+
const { data, error } = await supabase.rpc("get_crossing_time", {
25+
highline_id: highline.id,
26+
page_number: pageParam,
27+
page_size: PAGE_SIZE,
28+
});
29+
console.log({ data });
3130
return data;
3231
}
3332

@@ -63,11 +62,11 @@ function Speedline({ highline }: Props) {
6362
entries?.pages.flatMap((page, pageIdx) => {
6463
return (
6564
page?.map((entry, idx) => {
66-
if (!entry.crossing_time || !entry.created_at) return null;
6765
return {
6866
name: entry.instagram,
6967
position: pageIdx * PAGE_SIZE + idx + 1,
7068
value: transformSecondsToTimeString(entry.crossing_time),
69+
profilePicture: entry.profile_picture || "",
7170
};
7271
}) || []
7372
);

components/tabs/Ranking/leaderboard.tsx

+52-33
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { cva } from "class-variance-authority";
22
import { CrownIcon } from "lucide-react";
3+
import Image from "next/image";
34
import React from "react";
45

56
import { cn } from "@/lib/utils";
@@ -11,6 +12,7 @@ interface PodiumProps {
1112
username: string;
1213
value: string;
1314
position: number;
15+
profilePicture?: string;
1416
}
1517

1618
const podiumVariants = cva("", {
@@ -32,7 +34,39 @@ const podiumVariants = cva("", {
3234
},
3335
});
3436

35-
const Podium = ({ username, value, position }: PodiumProps) => {
37+
const RankingPosition = ({ position }: { position: number }) => (
38+
<div className="flex items-center justify-center gap-1">
39+
<span className="xs:text-sm text-xs text-neutral-400 dark:text-neutral-600 md:text-lg">
40+
#
41+
</span>
42+
<span className="xs:text-base text-sm font-semibold text-neutral-800 dark:text-neutral-50 md:text-2xl">
43+
{position}
44+
</span>
45+
</div>
46+
);
47+
48+
const ProfilePicture = ({
49+
username,
50+
src,
51+
}: {
52+
username?: string;
53+
src?: string;
54+
}) => {
55+
return (
56+
<div className="relative flex h-12 w-12 items-center justify-center rounded-full bg-neutral-200/40 dark:bg-neutral-800/60 md:h-16 md:w-16">
57+
{username ? (
58+
<Image
59+
src={src || "/default-profile-picture.png"}
60+
fill={true}
61+
alt="Profile picture"
62+
className="rounded-full"
63+
/>
64+
) : null}
65+
</div>
66+
);
67+
};
68+
69+
const Podium = ({ username, value, position, profilePicture }: PodiumProps) => {
3670
const variant =
3771
position === 1 ? "gold" : position === 2 ? "silver" : "bronze";
3872

@@ -60,12 +94,7 @@ const Podium = ({ username, value, position }: PodiumProps) => {
6094
)}
6195
/>
6296
</div>
63-
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-neutral-200/40 dark:bg-neutral-800/60 md:h-16 md:w-16">
64-
<i
65-
className="fa-regular fa-user text-lg text-neutral-600 dark:text-neutral-50 md:text-2xl"
66-
aria-hidden="true"
67-
/>
68-
</div>
97+
<ProfilePicture username={username} src={profilePicture} />
6998
</div>
7099
<div className="flex w-full flex-col items-center gap-0.5 md:gap-0">
71100
<span className="xs:text-sm max-w-[calc(100%-1rem)] overflow-hidden text-ellipsis whitespace-nowrap text-xs font-normal text-neutral-800 dark:text-neutral-50 md:text-lg">
@@ -78,14 +107,7 @@ const Podium = ({ username, value, position }: PodiumProps) => {
78107
podiumVariants({ text: variant })
79108
)}
80109
>
81-
<span className="whitespace-nowrap">
82-
<i
83-
className="fas fa-dice-d8"
84-
aria-hidden="true"
85-
style={{ scale: "0.6" }}
86-
/>{" "}
87-
{value}
88-
</span>
110+
<span className="whitespace-nowrap">{value}</span>
89111
</span>
90112
</div>
91113
</div>
@@ -99,32 +121,24 @@ const Podium = ({ username, value, position }: PodiumProps) => {
99121
})
100122
)}
101123
>
102-
<div className="flex items-center justify-center gap-1">
103-
<span className="xs:text-sm text-xs text-neutral-400 dark:text-neutral-600 md:text-lg">
104-
#
105-
</span>
106-
<span className="xs:text-base text-sm font-semibold text-neutral-800 dark:text-neutral-50 md:text-2xl">
107-
{position}
108-
</span>
109-
</div>
124+
<RankingPosition position={position} />
110125
</div>
111126
</div>
112127
</Link>
113128
);
114129
};
115130

116-
export const LeaderboardRow = ({ username, value, position }: PodiumProps) => {
131+
export const LeaderboardRow = ({
132+
username,
133+
value,
134+
position,
135+
profilePicture,
136+
}: PodiumProps) => {
117137
return (
118138
<li className="py-3 sm:py-4">
119-
<div className="flex items-start space-x-4">
120-
<div className="flex items-center justify-center gap-1">
121-
<span className="xs:text-sm text-xs text-neutral-400 dark:text-neutral-600 md:text-lg">
122-
#
123-
</span>
124-
<span className="xs:text-base text-sm font-semibold text-neutral-800 dark:text-neutral-50 md:text-2xl">
125-
{position}
126-
</span>
127-
</div>
139+
<div className="flex space-x-4">
140+
<RankingPosition position={position} />
141+
<ProfilePicture username={username} src={profilePicture} />
128142
<div className="min-w-0 flex-1">
129143
<UsernameLink username={username} />
130144
{/* <div className="text-sm text-muted-foreground ">
@@ -146,6 +160,7 @@ interface LeaderboardProps {
146160
name: string;
147161
value: string;
148162
position: number;
163+
profilePicture: string;
149164
} | null>;
150165
}
151166

@@ -157,16 +172,19 @@ export const Leaderboard = ({ entries }: LeaderboardProps) => {
157172
username={entries[1]?.name || ""}
158173
value={entries[1]?.value || ""}
159174
position={2}
175+
profilePicture={entries[1]?.profilePicture}
160176
/>
161177
<Podium
162178
username={entries[0]?.name || ""}
163179
value={entries[0]?.value || ""}
164180
position={1}
181+
profilePicture={entries[0]?.profilePicture}
165182
/>
166183
<Podium
167184
username={entries[2]?.name || ""}
168185
value={entries[2]?.value || ""}
169186
position={3}
187+
profilePicture={entries[2]?.profilePicture}
170188
/>
171189
</div>
172190
<ul className="divide-y divide-gray-200 dark:divide-gray-700">
@@ -179,6 +197,7 @@ export const Leaderboard = ({ entries }: LeaderboardProps) => {
179197
username={entry?.name}
180198
position={entry?.position}
181199
value={entry?.value}
200+
profilePicture={entry.profilePicture}
182201
/>
183202
) : null
184203
)}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
drop function if exists "public"."get_total_cadenas"(highline_id uuid, page_number integer, page_size integer);
2+
3+
drop function if exists "public"."get_total_full_lines"(highline_id uuid, page_number integer, page_size integer);
4+
5+
drop function if exists "public"."get_total_walked"(highline_id uuid, page_number integer, page_size integer);
6+
7+
set check_function_bodies = off;
8+
9+
CREATE OR REPLACE FUNCTION public.get_crossing_time(highline_id uuid, page_number integer, page_size integer)
10+
RETURNS TABLE(instagram text, crossing_time integer, profile_picture text)
11+
LANGUAGE sql
12+
AS $function$
13+
select e.instagram, e.crossing_time, p.profile_picture
14+
from entry e
15+
JOIN profiles p on e.instagram = p.username
16+
where highline_id = get_crossing_time.highline_id
17+
order by e.crossing_time asc
18+
OFFSET (get_crossing_time.page_number - 1) * get_crossing_time.page_size
19+
LIMIT get_crossing_time.page_size;
20+
$function$
21+
;
22+
23+
CREATE OR REPLACE FUNCTION public.get_total_cadenas(highline_id uuid, page_number integer, page_size integer)
24+
RETURNS TABLE(instagram text, total_cadenas integer, profile_picture text)
25+
LANGUAGE sql
26+
AS $function$ SELECT e.instagram, SUM(e.cadenas) AS total_cadenas, p.profile_picture
27+
FROM entry e
28+
JOIN profiles p on e.instagram = p.username
29+
WHERE highline_id = get_total_cadenas.highline_id
30+
GROUP BY e.instagram, p.profile_picture
31+
HAVING SUM(e.cadenas) > 0
32+
ORDER BY total_cadenas DESC
33+
OFFSET (get_total_cadenas.page_number - 1) * get_total_cadenas.page_size
34+
LIMIT get_total_cadenas.page_size;
35+
$function$
36+
;
37+
38+
CREATE OR REPLACE FUNCTION public.get_total_full_lines(highline_id uuid, page_number integer, page_size integer)
39+
RETURNS TABLE(instagram text, total_full_lines integer, profile_picture text)
40+
LANGUAGE sql
41+
AS $function$
42+
SELECT e.instagram, SUM(e.full_lines) AS total_full_lines, p.profile_picture
43+
FROM entry e
44+
JOIN profiles p ON e.instagram = p.username
45+
WHERE e.highline_id = get_total_full_lines.highline_id
46+
GROUP BY e.instagram, p.profile_picture
47+
HAVING SUM(e.full_lines) > 0
48+
ORDER BY total_full_lines DESC
49+
OFFSET (get_total_full_lines.page_number - 1) * get_total_full_lines.page_size
50+
LIMIT get_total_full_lines.page_size;
51+
$function$
52+
;
53+
54+
CREATE OR REPLACE FUNCTION public.get_total_walked(highline_id uuid, page_number integer, page_size integer)
55+
RETURNS TABLE(instagram text, total_distance_walked integer, profile_picture text)
56+
LANGUAGE sql
57+
AS $function$
58+
SELECT e.instagram, SUM(e.distance_walked) AS total_distance_walked, p.profile_picture
59+
FROM entry e
60+
JOIN profiles p on e.instagram = p.username
61+
WHERE highline_id = get_total_walked.highline_id
62+
AND distance_walked IS NOT NULL
63+
GROUP BY e.instagram, p.profile_picture
64+
ORDER BY total_distance_walked DESC
65+
OFFSET (get_total_walked.page_number - 1) * get_total_walked.page_size
66+
LIMIT page_size;
67+
$function$
68+
;
69+
70+

0 commit comments

Comments
 (0)