| <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} | |