|
<script lang="ts"> |
|
import { onMount } from "svelte"; |
|
import { ProgressBarRound } from "carbon-icons-svelte"; |
|
|
|
interface Entry { |
|
name: string; |
|
rank: number; |
|
score: number; |
|
votes: number; |
|
} |
|
|
|
export let onEntryClick: (entry: Entry) => void; |
|
|
|
const baseUrl = "https://huggingface.co/datasets/dylanebert/3d-arena/resolve/main/outputs"; |
|
let leaderboard: Entry[] = []; |
|
|
|
const fetchLeaderboardData = async () => { |
|
const url = "https://dylanebert-3d-arena-backend.hf.space/leaderboard"; |
|
const response = await fetch(url, { |
|
method: "GET", |
|
headers: { |
|
Authorization: "Bearer " + import.meta.env.VITE_HF_TOKEN, |
|
"Cache-Control": "no-cache", |
|
}, |
|
}); |
|
const data = (await response.json()) as Entry[]; |
|
data.sort((a, b) => a.rank - b.rank); |
|
|
|
leaderboard = data; |
|
}; |
|
|
|
onMount(async () => { |
|
await fetchLeaderboardData(); |
|
}); |
|
</script> |
|
|
|
{#if leaderboard.length > 0} |
|
<div class="grid"> |
|
{#each leaderboard as entry} |
|
<button class="grid-item" on:click={() => onEntryClick(entry)}> |
|
<img src={`${baseUrl}/${entry.name}/thumbnail.png`} alt={entry.name} class="thumbnail" /> |
|
<div class="ranking">{entry.rank}</div> |
|
<div class="title">{entry.name}</div> |
|
<div class="score-container"> |
|
<div class="score"> |
|
<span class="label">Score:</span> |
|
{entry.score} |
|
</div> |
|
<div class="votes"> |
|
<span class="label">Votes:</span> |
|
{entry.votes} |
|
</div> |
|
</div> |
|
</button> |
|
{/each} |
|
</div> |
|
{:else} |
|
<div class="loading-container"> |
|
<ProgressBarRound class="loading-icon" /> |
|
<div class="loading-text">Loading...</div> |
|
</div> |
|
{/if} |
|
|