Update src/App.js
Browse files- src/App.js +18 -19
src/App.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
import React, { useState, useEffect, useMemo } from 'react';
|
2 |
-
import { Search, Trophy, Medal, Award, BarChart3, Filter, RefreshCw, ExternalLink, Clock, Zap, Target, ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react';
|
3 |
|
4 |
-
const
|
5 |
const [searchTerm, setSearchTerm] = useState('');
|
6 |
const [filterLicense, setFilterLicense] = useState('all');
|
7 |
const [sortBy, setSortBy] = useState('accuracy');
|
@@ -174,9 +173,9 @@ const LeaderboardUrology = () => {
|
|
174 |
|
175 |
const getRankIcon = (index) => {
|
176 |
switch(index) {
|
177 |
-
case 0: return <
|
178 |
-
case 1: return <
|
179 |
-
case 2: return <
|
180 |
default: return <span className="text-xl font-bold text-gray-500">#{index + 1}</span>;
|
181 |
}
|
182 |
};
|
@@ -193,7 +192,7 @@ const LeaderboardUrology = () => {
|
|
193 |
};
|
194 |
|
195 |
const formatDate = (dateString) => {
|
196 |
-
return new Date(dateString).toLocaleDateString('
|
197 |
day: '2-digit',
|
198 |
month: '2-digit',
|
199 |
year: 'numeric',
|
@@ -203,18 +202,18 @@ const LeaderboardUrology = () => {
|
|
203 |
};
|
204 |
|
205 |
const getSortIcon = (column) => {
|
206 |
-
if (sortBy !== column) return <
|
207 |
return sortOrder === 'desc' ?
|
208 |
-
<
|
209 |
-
<
|
210 |
};
|
211 |
|
212 |
if (loading) {
|
213 |
return (
|
214 |
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-blue-900 to-indigo-900 flex items-center justify-center">
|
215 |
<div className="text-center">
|
216 |
-
<div className="animate-spin rounded-full h-16 w-16 border-b-2 border-white mb-4"></div>
|
217 |
-
<p className="text-white text-xl">
|
218 |
</div>
|
219 |
</div>
|
220 |
);
|
@@ -249,7 +248,7 @@ const LeaderboardUrology = () => {
|
|
249 |
<div className="mb-6 flex flex-wrap gap-4 items-center justify-between">
|
250 |
<div className="flex flex-wrap gap-4 items-center">
|
251 |
<div className="relative">
|
252 |
-
<
|
253 |
<input
|
254 |
type="text"
|
255 |
placeholder="Search model..."
|
@@ -260,7 +259,7 @@ const LeaderboardUrology = () => {
|
|
260 |
</div>
|
261 |
|
262 |
<div className="relative">
|
263 |
-
<
|
264 |
<select
|
265 |
value={filterLicense}
|
266 |
onChange={(e) => setFilterLicense(e.target.value)}
|
@@ -279,7 +278,7 @@ const LeaderboardUrology = () => {
|
|
279 |
disabled={refreshing}
|
280 |
className="flex items-center space-x-2 px-4 py-2 bg-green-600 hover:bg-green-700 disabled:bg-green-600/50 text-white rounded-lg transition-colors"
|
281 |
>
|
282 |
-
<
|
283 |
<span>{refreshing ? 'Updating...' : 'Update'}</span>
|
284 |
</button>
|
285 |
</div>
|
@@ -304,7 +303,7 @@ const LeaderboardUrology = () => {
|
|
304 |
}}
|
305 |
>
|
306 |
<div className="flex items-center space-x-1">
|
307 |
-
<
|
308 |
<span>Accuracy</span>
|
309 |
{getSortIcon('accuracy')}
|
310 |
</div>
|
@@ -324,7 +323,7 @@ const LeaderboardUrology = () => {
|
|
324 |
}}
|
325 |
>
|
326 |
<div className="flex items-center space-x-1">
|
327 |
-
<
|
328 |
<span>Date</span>
|
329 |
{getSortIcon('submittedTime')}
|
330 |
</div>
|
@@ -346,7 +345,7 @@ const LeaderboardUrology = () => {
|
|
346 |
<div className="flex flex-col">
|
347 |
<div className="flex items-center space-x-2">
|
348 |
<span className="text-white font-medium">{item.model.split('/').pop()}</span>
|
349 |
-
<
|
350 |
</div>
|
351 |
<span className="text-sm text-gray-400">{item.model.split('/')[0]}</span>
|
352 |
</div>
|
@@ -374,7 +373,7 @@ const LeaderboardUrology = () => {
|
|
374 |
</td>
|
375 |
<td className="px-6 py-4">
|
376 |
<div className="flex items-center space-x-2">
|
377 |
-
<
|
378 |
<span className="text-white">{formatParams(item.params)}</span>
|
379 |
</div>
|
380 |
</td>
|
@@ -438,4 +437,4 @@ const LeaderboardUrology = () => {
|
|
438 |
);
|
439 |
};
|
440 |
|
441 |
-
export default
|
|
|
1 |
import React, { useState, useEffect, useMemo } from 'react';
|
|
|
2 |
|
3 |
+
const UrologyLeaderboard = () => {
|
4 |
const [searchTerm, setSearchTerm] = useState('');
|
5 |
const [filterLicense, setFilterLicense] = useState('all');
|
6 |
const [sortBy, setSortBy] = useState('accuracy');
|
|
|
173 |
|
174 |
const getRankIcon = (index) => {
|
175 |
switch(index) {
|
176 |
+
case 0: return <span className="text-2xl">π</span>;
|
177 |
+
case 1: return <span className="text-2xl">π₯</span>;
|
178 |
+
case 2: return <span className="text-2xl">π₯</span>;
|
179 |
default: return <span className="text-xl font-bold text-gray-500">#{index + 1}</span>;
|
180 |
}
|
181 |
};
|
|
|
192 |
};
|
193 |
|
194 |
const formatDate = (dateString) => {
|
195 |
+
return new Date(dateString).toLocaleDateString('en-US', {
|
196 |
day: '2-digit',
|
197 |
month: '2-digit',
|
198 |
year: 'numeric',
|
|
|
202 |
};
|
203 |
|
204 |
const getSortIcon = (column) => {
|
205 |
+
if (sortBy !== column) return <span className="text-gray-400">βοΈ</span>;
|
206 |
return sortOrder === 'desc' ?
|
207 |
+
<span className="text-blue-500">β¬οΈ</span> :
|
208 |
+
<span className="text-blue-500">β¬οΈ</span>;
|
209 |
};
|
210 |
|
211 |
if (loading) {
|
212 |
return (
|
213 |
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-blue-900 to-indigo-900 flex items-center justify-center">
|
214 |
<div className="text-center">
|
215 |
+
<div className="animate-spin rounded-full h-16 w-16 border-b-2 border-white mb-4 mx-auto"></div>
|
216 |
+
<p className="text-white text-xl">Loading leaderboard...</p>
|
217 |
</div>
|
218 |
</div>
|
219 |
);
|
|
|
248 |
<div className="mb-6 flex flex-wrap gap-4 items-center justify-between">
|
249 |
<div className="flex flex-wrap gap-4 items-center">
|
250 |
<div className="relative">
|
251 |
+
<span className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400">π</span>
|
252 |
<input
|
253 |
type="text"
|
254 |
placeholder="Search model..."
|
|
|
259 |
</div>
|
260 |
|
261 |
<div className="relative">
|
262 |
+
<span className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400">π</span>
|
263 |
<select
|
264 |
value={filterLicense}
|
265 |
onChange={(e) => setFilterLicense(e.target.value)}
|
|
|
278 |
disabled={refreshing}
|
279 |
className="flex items-center space-x-2 px-4 py-2 bg-green-600 hover:bg-green-700 disabled:bg-green-600/50 text-white rounded-lg transition-colors"
|
280 |
>
|
281 |
+
<span className={refreshing ? 'animate-spin' : ''}>π</span>
|
282 |
<span>{refreshing ? 'Updating...' : 'Update'}</span>
|
283 |
</button>
|
284 |
</div>
|
|
|
303 |
}}
|
304 |
>
|
305 |
<div className="flex items-center space-x-1">
|
306 |
+
<span>π―</span>
|
307 |
<span>Accuracy</span>
|
308 |
{getSortIcon('accuracy')}
|
309 |
</div>
|
|
|
323 |
}}
|
324 |
>
|
325 |
<div className="flex items-center space-x-1">
|
326 |
+
<span>π</span>
|
327 |
<span>Date</span>
|
328 |
{getSortIcon('submittedTime')}
|
329 |
</div>
|
|
|
345 |
<div className="flex flex-col">
|
346 |
<div className="flex items-center space-x-2">
|
347 |
<span className="text-white font-medium">{item.model.split('/').pop()}</span>
|
348 |
+
<span className="text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer">π</span>
|
349 |
</div>
|
350 |
<span className="text-sm text-gray-400">{item.model.split('/')[0]}</span>
|
351 |
</div>
|
|
|
373 |
</td>
|
374 |
<td className="px-6 py-4">
|
375 |
<div className="flex items-center space-x-2">
|
376 |
+
<span>β‘</span>
|
377 |
<span className="text-white">{formatParams(item.params)}</span>
|
378 |
</div>
|
379 |
</td>
|
|
|
437 |
);
|
438 |
};
|
439 |
|
440 |
+
export default UrologyLeaderboard;
|