Skip to content

Commit 7f7f65e

Browse files
Leaderboard
1 parent 32ab229 commit 7f7f65e

File tree

7 files changed

+199
-138
lines changed

7 files changed

+199
-138
lines changed

sanity.config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export default defineConfig({
4646
codeInput(),
4747
documentInternationalization({
4848
supportedLanguages,
49-
schemaTypes: ["page", "homepage", "post", "settings"],
49+
schemaTypes: ["page", "homepage", "post", "settings", "project"],
5050
}),
5151
structureTool({
5252
structure: (S, context) => {
@@ -76,7 +76,7 @@ export default defineConfig({
7676
.documentId("homepage"),
7777
),
7878

79-
createLocalizedList(S, "post", "News"),
79+
createLocalizedList(S, "project", "Projects"),
8080
createLocalizedList(S, "page", "Pages"),
8181
]
8282
: [createLocalizedList(S, "post", "News")],
@@ -93,7 +93,7 @@ export default defineConfig({
9393
(role) => role.name === "administrator",
9494
);
9595
return templates.filter(({ id }) =>
96-
isAdmin ? id === "page" || id === "post" : id === "post",
96+
isAdmin ? id === "page" || id === "project" : id === "post",
9797
);
9898
},
9999
},

src/components/Sanity/Leaderboard.tsx

Lines changed: 130 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,44 @@
1-
import { useState } from "react";
1+
import { useEffect, useState } from "react";
22
import ScrollText from "./ScrollText";
3+
import { getProjects } from "../../utils/sanity";
34

45
interface DataProps {
56
data: {
6-
tabs: TabProps[];
7+
projects: ProjectProps[];
78
headline: string;
89
};
910
}
1011

11-
interface TabProps {
12-
title: string;
13-
projects: ProjectProps[];
14-
}
15-
1612
interface ProjectProps {
1713
name: string;
1814
github?: string;
1915
link?: string;
2016
score: number;
17+
tab?: string;
2118
}
2219

20+
const TABS = ["Top 100", "America", "Europe", "Asia", "Africa"];
21+
2322
export const Leaderboard = ({ data }: DataProps) => {
24-
const [activeTab, setTab] = useState(0);
23+
const [projects, setProjects] = useState<ProjectProps[]>([]);
24+
const [activeTab, setActiveTab] = useState<number>(0);
25+
const [searchTerm, setSearchTerm] = useState<string>("");
2526

26-
function handleClick(i: number) {
27-
setTab(i);
28-
}
27+
useEffect(() => {
28+
getProjects(activeTab.toString())
29+
.then((data) => {
30+
//console.log("Loaded projects:", data); // ✅ Actual data
31+
setProjects(data || []);
32+
})
33+
.catch((error) => {
34+
console.error("Error loading projects:", error);
35+
setProjects([]);
36+
});
37+
}, [activeTab]);
38+
39+
const filteredProjects = projects.filter((project) =>
40+
project.name.toLowerCase().includes(searchTerm.toLowerCase()),
41+
);
2942

3043
return (
3144
<div>
@@ -35,19 +48,47 @@ export const Leaderboard = ({ data }: DataProps) => {
3548
</div>
3649
{data && (
3750
<div className="px-8">
38-
<div className="flex gap-2">
39-
{data.tabs.map((tab, i: number) => (
40-
<button
41-
onClick={() => handleClick(i)}
42-
className={`bg-pink cursor-pointer rounded-full px-3 py-2 ${activeTab === i ? "" : "opacity-50"}`}
51+
<div className="mb-8 flex flex-col gap-4 md:flex-row">
52+
<div className="flex flex-wrap justify-center gap-2 md:justify-start">
53+
{TABS.map((tab, index: number) => (
54+
<button
55+
key={tab}
56+
onClick={() => setActiveTab(index)}
57+
className={`bg-pink cursor-pointer rounded-full px-4 py-2 text-white transition ${
58+
activeTab === index ? "" : "opacity-60 hover:opacity-80"
59+
}`}
60+
>
61+
{tab}
62+
</button>
63+
))}
64+
</div>
65+
<div className="mx-auto flex items-center justify-between gap-4 rounded-full border border-white pr-4 md:mr-0">
66+
<input
67+
name="search"
68+
id="search"
69+
placeholder="Search project"
70+
value={searchTerm}
71+
onChange={(e) => setSearchTerm(e.target.value)}
72+
className="px-4 py-2 text-white focus:outline-none"
73+
/>
74+
<svg
75+
width="16"
76+
height="17"
77+
viewBox="0 0 16 17"
78+
fill="none"
79+
xmlns="http://www.w3.org/2000/svg"
80+
className="w-4"
4381
>
44-
{tab.title}
45-
</button>
46-
))}
82+
<path
83+
d="M15.8233 15.3129L12.0528 11.5432C15.3217 7.61869 13.1164 1.6272 8.08322 0.758511C3.05005 -0.11017 -1.03606 4.79546 0.728222 9.58865C2.31195 13.8913 7.67828 15.3292 11.2012 12.3949L14.9708 16.1653C15.2989 16.4934 15.8592 16.3433 15.9793 15.8951C16.035 15.6871 15.9755 15.4651 15.8233 15.3129ZM1.54131 7.30515C1.54131 3.13144 6.05948 0.522861 9.67403 2.60972C13.2886 4.69658 13.2886 9.91372 9.67403 12.0006C8.84988 12.4764 7.91477 12.7269 6.96312 12.727C3.97012 12.7236 1.54463 10.2982 1.54131 7.30515Z"
84+
fill="#F1F1F5"
85+
/>
86+
</svg>
87+
</div>
4788
</div>
4889
<div className="grid">
4990
<div
50-
className={`text-pink grid items-center gap-4 border-b border-gray-200/30 px-4 py-4 md:grid-cols-6`}
91+
className={`md:text-pink grid hidden items-center gap-4 border-b border-gray-200/30 px-4 py-4 md:grid-cols-6`}
5192
>
5293
<div className="flex gap-4 md:col-span-3">
5394
<span className="block min-w-16"></span>
@@ -57,79 +98,78 @@ export const Leaderboard = ({ data }: DataProps) => {
5798
<div className="">App</div>
5899
<div className="">Score</div>
59100
</div>
60-
{[...data.tabs[activeTab].projects]
61-
.sort((a, b) => b.score - a.score)
62-
.map((p, index: number) => (
63-
<div
64-
className={`grid items-center gap-4 border-b border-gray-200/30 px-4 py-4 md:grid-cols-6 ${index % 2 === 0 ? "bg-white/10" : ""}`}
65-
>
66-
<div className="font-pp flex gap-4 text-3xl md:col-span-3">
67-
<span className="text-blue block min-w-16">
68-
{index + 1}.
69-
</span>
70-
{p.name}
71-
</div>
72-
<div className="">
73-
{p.github && (
74-
<a
75-
href={p.github}
76-
target="_blank"
77-
className="flex items-center gap-2"
101+
{filteredProjects.map((p, i) => (
102+
<div
103+
className={`grid items-center gap-4 border-b border-gray-200/30 px-4 py-4 md:grid-cols-6 ${i % 2 === 0 ? "bg-white/10" : ""}`}
104+
>
105+
<div className="font-pp flex gap-4 text-3xl md:col-span-3">
106+
<span className="text-blue block min-w-16">{i + 1}.</span>
107+
{p.name}
108+
</div>
109+
<div className="">
110+
{p.github && (
111+
<a
112+
href={p.github}
113+
target="_blank"
114+
className="flex items-center gap-2"
115+
>
116+
<svg
117+
width="24"
118+
height="23"
119+
viewBox="0 0 24 23"
120+
fill="none"
121+
xmlns="http://www.w3.org/2000/svg"
122+
className="w-5"
78123
>
79-
<svg
80-
width="24"
81-
height="23"
82-
viewBox="0 0 24 23"
83-
fill="none"
84-
xmlns="http://www.w3.org/2000/svg"
85-
className="w-5"
86-
>
87-
<path
88-
d="M11.7599 0C8.96748 0.0001 6.26618 0.9939 4.13948 2.8034C2.01268 4.6129 0.599183 7.1202 0.151883 9.8766C-0.295417 12.6329 0.252683 15.4585 1.69808 17.8478C3.14338 20.2369 5.39178 22.0339 8.04088 22.9171C8.62888 23.02 8.84938 22.6672 8.84938 22.3585C8.84938 22.0792 8.83468 21.1531 8.83468 20.1682C5.87998 20.7121 5.11558 19.448 4.88038 18.7865C4.61938 18.1432 4.20568 17.5731 3.67498 17.1254C3.26338 16.9049 2.67538 16.361 3.66028 16.3463C4.03638 16.3871 4.39698 16.518 4.71178 16.7278C5.02648 16.9376 5.28608 17.2203 5.46838 17.5517C5.62918 17.8406 5.84548 18.095 6.10478 18.3002C6.36408 18.5054 6.66138 18.6575 6.97958 18.7475C7.29778 18.8376 7.63058 18.8641 7.95898 18.8254C8.28738 18.7867 8.60498 18.6836 8.89338 18.5219C8.94428 17.924 9.21078 17.365 9.64318 16.949C7.02658 16.655 4.29238 15.6407 4.29238 11.1425C4.27588 9.9738 4.70708 8.843 5.49778 7.9821C5.13828 6.9663 5.18028 5.8515 5.61538 4.8657C5.61538 4.8657 6.60018 4.557 8.84938 6.0711C10.7736 5.5419 12.805 5.5419 14.7293 6.0711C16.9784 4.5423 17.9633 4.8657 17.9633 4.8657C18.3984 5.8515 18.4405 6.9663 18.0809 7.9821C18.8738 8.8415 19.3056 9.9734 19.2863 11.1425C19.2863 15.6554 16.5374 16.655 13.9208 16.949C14.2014 17.2334 14.4175 17.575 14.5545 17.9503C14.6915 18.3258 14.7461 18.7263 14.7146 19.1246C14.7146 20.6976 14.6999 21.9616 14.6999 22.3585C14.6999 22.6672 14.9204 23.0347 15.5084 22.9171C18.1528 22.0268 20.3947 20.2256 21.8339 17.8352C23.2732 15.4447 23.816 12.6205 23.3656 9.8668C22.9152 7.1132 21.5009 4.6092 19.375 2.8019C17.2492 0.9945 14.5502 0.0015 11.7599 0Z"
89-
fill="#F1F1F5"
90-
/>
91-
</svg>{" "}
92-
Github
93-
</a>
94-
)}
95-
</div>
96-
<div className="">
97-
{p.link && (
98-
<a
99-
href={p.link}
100-
target="_blank"
101-
className="flex items-center gap-2"
124+
<path
125+
d="M11.7599 0C8.96748 0.0001 6.26618 0.9939 4.13948 2.8034C2.01268 4.6129 0.599183 7.1202 0.151883 9.8766C-0.295417 12.6329 0.252683 15.4585 1.69808 17.8478C3.14338 20.2369 5.39178 22.0339 8.04088 22.9171C8.62888 23.02 8.84938 22.6672 8.84938 22.3585C8.84938 22.0792 8.83468 21.1531 8.83468 20.1682C5.87998 20.7121 5.11558 19.448 4.88038 18.7865C4.61938 18.1432 4.20568 17.5731 3.67498 17.1254C3.26338 16.9049 2.67538 16.361 3.66028 16.3463C4.03638 16.3871 4.39698 16.518 4.71178 16.7278C5.02648 16.9376 5.28608 17.2203 5.46838 17.5517C5.62918 17.8406 5.84548 18.095 6.10478 18.3002C6.36408 18.5054 6.66138 18.6575 6.97958 18.7475C7.29778 18.8376 7.63058 18.8641 7.95898 18.8254C8.28738 18.7867 8.60498 18.6836 8.89338 18.5219C8.94428 17.924 9.21078 17.365 9.64318 16.949C7.02658 16.655 4.29238 15.6407 4.29238 11.1425C4.27588 9.9738 4.70708 8.843 5.49778 7.9821C5.13828 6.9663 5.18028 5.8515 5.61538 4.8657C5.61538 4.8657 6.60018 4.557 8.84938 6.0711C10.7736 5.5419 12.805 5.5419 14.7293 6.0711C16.9784 4.5423 17.9633 4.8657 17.9633 4.8657C18.3984 5.8515 18.4405 6.9663 18.0809 7.9821C18.8738 8.8415 19.3056 9.9734 19.2863 11.1425C19.2863 15.6554 16.5374 16.655 13.9208 16.949C14.2014 17.2334 14.4175 17.575 14.5545 17.9503C14.6915 18.3258 14.7461 18.7263 14.7146 19.1246C14.7146 20.6976 14.6999 21.9616 14.6999 22.3585C14.6999 22.6672 14.9204 23.0347 15.5084 22.9171C18.1528 22.0268 20.3947 20.2256 21.8339 17.8352C23.2732 15.4447 23.816 12.6205 23.3656 9.8668C22.9152 7.1132 21.5009 4.6092 19.375 2.8019C17.2492 0.9945 14.5502 0.0015 11.7599 0Z"
126+
fill="#F1F1F5"
127+
/>
128+
</svg>{" "}
129+
Github
130+
</a>
131+
)}
132+
</div>
133+
<div className="">
134+
{p.link && (
135+
<a
136+
href={p.link}
137+
target="_blank"
138+
className="flex items-center gap-2"
139+
>
140+
<svg
141+
width="25"
142+
height="24"
143+
viewBox="0 0 25 24"
144+
fill="none"
145+
xmlns="http://www.w3.org/2000/svg"
146+
className="w-5"
102147
>
103-
<svg
104-
width="25"
105-
height="24"
106-
viewBox="0 0 25 24"
107-
fill="none"
108-
xmlns="http://www.w3.org/2000/svg"
109-
className="w-5"
110-
>
111-
<path
112-
d="M10.5195 13C10.949 13.5742 11.4969 14.0492 12.1261 14.393C12.7553 14.7367 13.451 14.9411 14.1662 14.9924C14.8813 15.0436 15.5991 14.9404 16.2709 14.6898C16.9426 14.4392 17.5526 14.0471 18.0595 13.54L21.0595 10.54C21.9703 9.59702 22.4743 8.334 22.4629 7.02302C22.4515 5.71204 21.9257 4.45797 20.9986 3.53093C20.0716 2.60389 18.8175 2.07805 17.5065 2.06666C16.1956 2.05526 14.9325 2.55924 13.9895 3.47003L12.2695 5.18003"
113-
stroke="#F1F1F5"
114-
strokeWidth="2"
115-
strokeLinecap="round"
116-
strokeLinejoin="round"
117-
/>
118-
<path
119-
d="M14.5197 11C14.0903 10.4259 13.5424 9.9508 12.9132 9.60704C12.284 9.26328 11.5882 9.05886 10.8731 9.00765C10.1579 8.95643 9.44014 9.05961 8.76839 9.3102C8.09663 9.56079 7.48662 9.95291 6.97973 10.46L3.97973 13.46C3.06894 14.403 2.56497 15.666 2.57636 16.977C2.58775 18.288 3.1136 19.542 4.04064 20.4691C4.96768 21.3961 6.22174 21.922 7.53272 21.9334C8.84371 21.9447 10.1067 21.4408 11.0497 20.53L12.7597 18.82"
120-
stroke="#F1F1F5"
121-
strokeWidth="2"
122-
strokeLinecap="round"
123-
strokeLinejoin="round"
124-
/>
125-
</svg>
126-
App
127-
</a>
128-
)}
129-
</div>
130-
<div className="font-pp text-pink text-3xl">{p.score}</div>
148+
<path
149+
d="M10.5195 13C10.949 13.5742 11.4969 14.0492 12.1261 14.393C12.7553 14.7367 13.451 14.9411 14.1662 14.9924C14.8813 15.0436 15.5991 14.9404 16.2709 14.6898C16.9426 14.4392 17.5526 14.0471 18.0595 13.54L21.0595 10.54C21.9703 9.59702 22.4743 8.334 22.4629 7.02302C22.4515 5.71204 21.9257 4.45797 20.9986 3.53093C20.0716 2.60389 18.8175 2.07805 17.5065 2.06666C16.1956 2.05526 14.9325 2.55924 13.9895 3.47003L12.2695 5.18003"
150+
stroke="#F1F1F5"
151+
strokeWidth="2"
152+
strokeLinecap="round"
153+
strokeLinejoin="round"
154+
/>
155+
<path
156+
d="M14.5197 11C14.0903 10.4259 13.5424 9.9508 12.9132 9.60704C12.284 9.26328 11.5882 9.05886 10.8731 9.00765C10.1579 8.95643 9.44014 9.05961 8.76839 9.3102C8.09663 9.56079 7.48662 9.95291 6.97973 10.46L3.97973 13.46C3.06894 14.403 2.56497 15.666 2.57636 16.977C2.58775 18.288 3.1136 19.542 4.04064 20.4691C4.96768 21.3961 6.22174 21.922 7.53272 21.9334C8.84371 21.9447 10.1067 21.4408 11.0497 20.53L12.7597 18.82"
157+
stroke="#F1F1F5"
158+
strokeWidth="2"
159+
strokeLinecap="round"
160+
strokeLinejoin="round"
161+
/>
162+
</svg>
163+
App
164+
</a>
165+
)}
131166
</div>
132-
))}
167+
<div className="text-pink flex flex-col md:items-end">
168+
<div className="md:hidden">Score</div>
169+
<span className="font-pp text-3xl">{p.score}</span>
170+
</div>
171+
</div>
172+
))}
133173
</div>
134174
</div>
135175
)}

src/components/Sanity/Winners.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const Winners = ({ data }: DataProps) => {
5454
>
5555
<button
5656
onClick={() => handleClick(i)}
57-
className={`bg-pink cursor-pointer rounded-full px-3 py-2 ${activeTab === i ? "" : "opacity-50"} ${item.hubs && item.hubs?.length > 0 ? "" : "pointer-events-none"}`}
57+
className={`bg-pink cursor-pointer rounded-full px-3 py-2 transition ${activeTab === i ? "" : "opacity-60 hover:opacity-80"} ${item.hubs && item.hubs?.length > 0 ? "" : "pointer-events-none"}`}
5858
>
5959
{item.title}
6060
</button>
@@ -98,7 +98,11 @@ export const Winners = ({ data }: DataProps) => {
9898
<div className="text-2xl font-bold">{p.name}</div>
9999
<div className="flex gap-4">
100100
{p.github && (
101-
<a href={p.github} target="_blank">
101+
<a
102+
href={p.github}
103+
target="_blank"
104+
className="transition hover:opacity-70"
105+
>
102106
<svg
103107
width="24"
104108
height="23"
@@ -115,7 +119,11 @@ export const Winners = ({ data }: DataProps) => {
115119
</a>
116120
)}
117121
{p.link && (
118-
<a href={p.link} target="_blank">
122+
<a
123+
href={p.link}
124+
target="_blank"
125+
className="transition hover:opacity-70"
126+
>
119127
<svg
120128
width="25"
121129
height="24"

src/sanity/schemaTypes/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { postType } from "./post";
55
import { homepageType } from "./homepage";
66
import { faqType } from "./faq";
77
import { settingsType } from "./settings";
8+
import { projectType } from "./project";
89

910
export const schemaTypes = [
1011
pageType,
@@ -14,4 +15,5 @@ export const schemaTypes = [
1415
postType,
1516
homepageType,
1617
settingsType,
18+
projectType,
1719
];

src/sanity/schemaTypes/page.ts

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -45,48 +45,6 @@ export const pageType = defineType({
4545
name: "headline",
4646
type: "string",
4747
},
48-
{
49-
name: "tabs",
50-
type: "array",
51-
of: [
52-
{
53-
type: "object",
54-
fields: [
55-
{
56-
name: "title",
57-
type: "string",
58-
},
59-
{
60-
name: "projects",
61-
type: "array",
62-
of: [
63-
{
64-
type: "object",
65-
fields: [
66-
{
67-
name: "name",
68-
type: "string",
69-
},
70-
{
71-
name: "github",
72-
type: "url",
73-
},
74-
{
75-
name: "link",
76-
type: "url",
77-
},
78-
{
79-
name: "score",
80-
type: "number",
81-
},
82-
],
83-
},
84-
],
85-
},
86-
],
87-
},
88-
],
89-
},
9048
],
9149
hidden: ({ parent }) => parent?.template !== "leaderboard",
9250
}),

0 commit comments

Comments
 (0)