Skip to content

Commit 836cd40

Browse files
Update: API endpoint for the leaderboard
1 parent 5032661 commit 836cd40

File tree

1 file changed

+104
-40
lines changed

1 file changed

+104
-40
lines changed

src/pages/LeaderBoard.tsx

Lines changed: 104 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import React, { useEffect, useState } from 'react';
2-
import { Helmet } from 'react-helmet-async';
3-
import { Link } from 'react-router-dom'; // Import Link
1+
import React, { useEffect, useState } from "react";
2+
import { Helmet } from "react-helmet-async";
3+
import { Link } from "react-router-dom"; // Import Link
44
import { Button } from "@/components/ui/button"; // Keep Button import for potential future use or consistency
55

66
interface PointsDetails {
@@ -16,30 +16,52 @@ interface LeaderboardEntry {
1616
total_points: number;
1717
}
1818

19-
const Modal: React.FC<{ isOpen: boolean; onClose: () => void; data: PointsDetails[]; name: string }> = ({ isOpen, onClose, data, name }) => {
19+
const Modal: React.FC<{
20+
isOpen: boolean;
21+
onClose: () => void;
22+
data: PointsDetails[];
23+
name: string;
24+
}> = ({ isOpen, onClose, data, name }) => {
2025
if (!isOpen) return null;
2126

2227
return (
23-
<div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50" onClick={onClose}>
24-
<div className="bg-zinc-900 p-6 rounded-lg max-w-2xl w-full max-h-[80vh] overflow-y-auto text-white border border-zinc-700" onClick={(e) => e.stopPropagation()}>
28+
<div
29+
className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50"
30+
onClick={onClose}
31+
>
32+
<div
33+
className="bg-zinc-900 p-6 rounded-lg max-w-2xl w-full max-h-[80vh] overflow-y-auto text-white border border-zinc-700"
34+
onClick={(e) => e.stopPropagation()}
35+
>
2536
<h2 className="text-2xl font-bold mb-4">Points Breakdown for {name}</h2>
2637
<div className="overflow-x-auto">
2738
<table className="w-full">
2839
<thead>
2940
<tr className="bg-zinc-800">
3041
<th className="p-2 text-left border border-zinc-700">Event</th>
3142
<th className="p-2 text-left border border-zinc-700">Points</th>
32-
<th className="p-2 text-left border border-zinc-700">Awarded By</th>
43+
<th className="p-2 text-left border border-zinc-700">
44+
Awarded By
45+
</th>
3346
<th className="p-2 text-left border border-zinc-700">Date</th>
3447
</tr>
3548
</thead>
3649
<tbody>
3750
{data.map((detail, index) => (
38-
<tr key={index} className="hover:bg-soda-blue/5 transition-colors">
51+
<tr
52+
key={index}
53+
className="hover:bg-soda-blue/5 transition-colors"
54+
>
3955
<td className="p-2 border border-zinc-700">{detail.event}</td>
40-
<td className="p-2 border border-zinc-700">{detail.points}</td>
41-
<td className="p-2 border border-zinc-700">{detail.awarded_by}</td>
42-
<td className="p-2 border border-zinc-700">{new Date(detail.timestamp).toLocaleDateString()}</td>
56+
<td className="p-2 border border-zinc-700">
57+
{detail.points}
58+
</td>
59+
<td className="p-2 border border-zinc-700">
60+
{detail.awarded_by}
61+
</td>
62+
<td className="p-2 border border-zinc-700">
63+
{new Date(detail.timestamp).toLocaleDateString()}
64+
</td>
4365
</tr>
4466
))}
4567
</tbody>
@@ -58,21 +80,27 @@ const Modal: React.FC<{ isOpen: boolean; onClose: () => void; data: PointsDetail
5880
};
5981

6082
const Leaderboard: React.FC = () => {
61-
const [leaderboardData, setLeaderboardData] = useState<LeaderboardEntry[]>([]);
83+
const [leaderboardData, setLeaderboardData] = useState<LeaderboardEntry[]>(
84+
[],
85+
);
6286
const [loading, setLoading] = useState(true);
6387
const [error, setError] = useState<any | null>(null);
6488
const [currentPage, setCurrentPage] = useState(1);
6589
const [itemsPerPage, setItemsPerPage] = useState(10);
66-
const [searchTerm, setSearchTerm] = useState('');
90+
const [searchTerm, setSearchTerm] = useState("");
6791
const [modalOpen, setModalOpen] = useState(false);
68-
const [selectedEntry, setSelectedEntry] = useState<LeaderboardEntry | null>(null);
92+
const [selectedEntry, setSelectedEntry] = useState<LeaderboardEntry | null>(
93+
null,
94+
);
6995

7096
useEffect(() => {
7197
const fetchData = async () => {
7298
try {
73-
const response = await fetch('https://api.thesoda.io/leaderboard');
99+
const response = await fetch(
100+
"https://api.thesoda.io/api/points/soda/leaderboard",
101+
);
74102
if (!response.ok) {
75-
throw new Error('Network response was not ok');
103+
throw new Error("Network response was not ok");
76104
}
77105
const data: LeaderboardEntry[] = await response.json();
78106
setLeaderboardData(data);
@@ -87,63 +115,94 @@ const Leaderboard: React.FC = () => {
87115
}, []);
88116

89117
const filteredData = leaderboardData.filter((entry) =>
90-
entry.name.toLowerCase().includes(searchTerm.toLowerCase())
118+
entry.name.toLowerCase().includes(searchTerm.toLowerCase()),
91119
);
92120

93121
const totalPages = Math.ceil(filteredData.length / itemsPerPage);
94122
const startIndex = (currentPage - 1) * itemsPerPage;
95-
const currentItems = filteredData.slice(startIndex, startIndex + itemsPerPage);
123+
const currentItems = filteredData.slice(
124+
startIndex,
125+
startIndex + itemsPerPage,
126+
);
96127

97128
const handlePrevious = () => setCurrentPage((prev) => Math.max(prev - 1, 1));
98-
const handleNext = () => setCurrentPage((prev) => Math.min(prev + 1, totalPages));
129+
const handleNext = () =>
130+
setCurrentPage((prev) => Math.min(prev + 1, totalPages));
99131

100132
return (
101133
<div className="flex flex-col items-center w-full max-w-5xl mx-auto p-4 sm:p-6 my-8 sm:my-16 md:my-24 lg:my-36 shadow-md rounded-lg bg-zinc-900/80 text-white border border-zinc-800">
102134
<Helmet>
103135
<title>Leaderboard</title>
104-
<meta name="description" content="Check out the top performers in SoDA's leaderboard and see who's leading the rankings!" />
105-
<meta name="keywords" content="leaderboard, asu soda, asu, software developers association, arizona state university, benifits, computer science" />
136+
<meta
137+
name="description"
138+
content="Check out the top performers in SoDA's leaderboard and see who's leading the rankings!"
139+
/>
140+
<meta
141+
name="keywords"
142+
content="leaderboard, asu soda, asu, software developers association, arizona state university, benifits, computer science"
143+
/>
106144
</Helmet>
107145

108-
<h1 className="text-2xl sm:text-3xl font-bold mb-4 sm:mb-6">Leaderboard</h1>
146+
<h1 className="text-2xl sm:text-3xl font-bold mb-4 sm:mb-6">
147+
Leaderboard
148+
</h1>
109149

110150
<div className="flex flex-col sm:flex-row justify-between items-center mb-2 w-full px-2 rounded-lg">
111151
<input
112-
type="text"
113-
placeholder="Search by name..."
114-
value={searchTerm}
115-
onChange={(e) => setSearchTerm(e.target.value)}
116-
className="border border-zinc-700 bg-zinc-800 py-1.5 px-2 rounded w-full sm:w-64 text-white placeholder-zinc-400 focus:outline-none focus:border-soda-blue/50"
152+
type="text"
153+
placeholder="Search by name..."
154+
value={searchTerm}
155+
onChange={(e) => setSearchTerm(e.target.value)}
156+
className="border border-zinc-700 bg-zinc-800 py-1.5 px-2 rounded w-full sm:w-64 text-white placeholder-zinc-400 focus:outline-none focus:border-soda-blue/50"
117157
/>
118-
<p className="text-zinc-500 mt-2 sm:mt-0">Click any row for point details</p>
158+
<p className="text-zinc-500 mt-2 sm:mt-0">
159+
Click any row for point details
160+
</p>
119161
</div>
120162

121163
{/* Description of the leaderboard */}
122-
<p className="text-zinc-300 text-center px-2 mb-4"> {/* Removed my-4, added mb-4 for spacing below */}
123-
This leaderboard tracks points earned through the{' '}
124-
<Link to="/distinguishedMembers" className="text-soda-blue hover:underline">
164+
<p className="text-zinc-300 text-center px-2 mb-4">
165+
{" "}
166+
{/* Removed my-4, added mb-4 for spacing below */}
167+
This leaderboard tracks points earned through the{" "}
168+
<Link
169+
to="/distinguishedMembers"
170+
className="text-soda-blue hover:underline"
171+
>
125172
Distinguished Members Program
126173
</Link>
127-
, recognizing active participation in SoDA meetings, workshops, and community engagement.
174+
, recognizing active participation in SoDA meetings, workshops, and
175+
community engagement.
128176
</p>
129177

130178
<div className="w-full overflow-x-auto">
131179
<table className="table-auto border-collapse border border-zinc-700 w-full text-center">
132180
<thead>
133181
<tr className="bg-zinc-800">
134-
<th className="w-1/2 border border-zinc-700 py-2 px-4 text-base sm:text-lg font-semibold text-center">Name</th>
135-
<th className="w-1/2 border border-zinc-700 py-2 px-4 text-base sm:text-lg font-semibold text-center">Points Earned</th>
182+
<th className="w-1/2 border border-zinc-700 py-2 px-4 text-base sm:text-lg font-semibold text-center">
183+
Name
184+
</th>
185+
<th className="w-1/2 border border-zinc-700 py-2 px-4 text-base sm:text-lg font-semibold text-center">
186+
Points Earned
187+
</th>
136188
</tr>
137189
</thead>
138190
<tbody>
139191
{currentItems.map((entry, index) => (
140192
<tr
141193
key={index}
142-
onClick={() => { setSelectedEntry(entry); setModalOpen(true); }}
194+
onClick={() => {
195+
setSelectedEntry(entry);
196+
setModalOpen(true);
197+
}}
143198
className="hover:bg-soda-blue/5 transition-colors cursor-pointer"
144199
>
145-
<td className="border border-zinc-700 py-2 px-4 text-center">{entry.name}</td>
146-
<td className="border border-zinc-700 py-2 px-4 text-center">{entry.total_points}</td>
200+
<td className="border border-zinc-700 py-2 px-4 text-center">
201+
{entry.name}
202+
</td>
203+
<td className="border border-zinc-700 py-2 px-4 text-center">
204+
{entry.total_points}
205+
</td>
147206
</tr>
148207
))}
149208
</tbody>
@@ -159,7 +218,9 @@ const Leaderboard: React.FC = () => {
159218
>
160219
Previous
161220
</button>
162-
<span className="text-base sm:text-lg">Page {currentPage} of {totalPages}</span>
221+
<span className="text-base sm:text-lg">
222+
Page {currentPage} of {totalPages}
223+
</span>
163224
{/* Updated Next Button Hover Styling */}
164225
<button
165226
onClick={handleNext}
@@ -172,9 +233,12 @@ const Leaderboard: React.FC = () => {
172233

173234
<Modal
174235
isOpen={modalOpen}
175-
onClose={() => { setModalOpen(false); setSelectedEntry(null); }}
236+
onClose={() => {
237+
setModalOpen(false);
238+
setSelectedEntry(null);
239+
}}
176240
data={selectedEntry?.points_details || []}
177-
name={selectedEntry?.name || ''}
241+
name={selectedEntry?.name || ""}
178242
/>
179243
</div>
180244
);

0 commit comments

Comments
 (0)