Some checks failed
Test and deploy staging / staging (push) Failing after 5m29s
212 lines
7.4 KiB
Svelte
212 lines
7.4 KiB
Svelte
<script lang="ts">
|
||
import { resolve } from '$app/paths';
|
||
import GameLogo from '$lib/game-tracker/GameLogo.svelte';
|
||
import ProgressMeter from '$lib/game-tracker/ProgressMeter.svelte';
|
||
import type { PageProps } from './$types';
|
||
let { data }: PageProps = $props();
|
||
</script>
|
||
|
||
<div class="tracker-library mx-auto flex w-full max-w-[1600px] flex-col px-4 py-5 sm:px-6">
|
||
<div class="mb-5 flex flex-wrap items-end justify-between gap-2">
|
||
<div>
|
||
<p class="text-xs tracking-[.18em] text-muted-foreground uppercase">Your next session</p>
|
||
<h1 class="mt-1 text-3xl font-semibold tracking-tight">Game tracker</h1>
|
||
</div>
|
||
{#if !data.user}<a
|
||
class="text-sm text-muted-foreground underline"
|
||
href={resolve('/login?returnTo=/projects/game-tracker')}>Sign in to save progress</a
|
||
>{:else}<a
|
||
class="text-xs text-muted-foreground underline"
|
||
href={resolve('/projects/game-tracker/credits')}>Artwork credits</a
|
||
>{/if}
|
||
</div>
|
||
<div
|
||
class="mb-4 grid grid-cols-2 gap-3 rounded-xl border bg-card p-3 lg:grid-cols-4"
|
||
aria-label="Your completion dashboard"
|
||
>
|
||
<ProgressMeter
|
||
label="National collection"
|
||
progress={data.pokemon.caught}
|
||
detail={`${data.pokemon.caught.value} unique species caught`}
|
||
hint="Unique species caught across the Pokémon games in your rules, out of the full species catalog."
|
||
/>
|
||
<ProgressMeter
|
||
label="Species seen at least once"
|
||
progress={data.pokemon.seen}
|
||
color="sky"
|
||
detail={`${data.pokemon.seen.value} species discovered`}
|
||
/>
|
||
<ProgressMeter
|
||
label="Pokémon games completed"
|
||
progress={data.pokemon.completed}
|
||
color="amber"
|
||
hint="Games marked story complete, or with all default story milestones checked."
|
||
/>
|
||
<ProgressMeter
|
||
label="Call of Duty overall"
|
||
progress={data.codOverall}
|
||
color="violet"
|
||
detail="Mastery · achievements · challenges"
|
||
/>
|
||
</div>
|
||
<div class="series-grid grid min-h-0 flex-1 gap-4">
|
||
<section
|
||
class="series-column flex min-h-0 min-w-0 flex-col rounded-2xl border bg-card p-3"
|
||
aria-labelledby="pokemon-series"
|
||
>
|
||
<a
|
||
href={resolve('/projects/game-tracker/pokemon')}
|
||
class="series-heading mb-3 flex items-center gap-3 rounded-xl bg-amber-500/10 p-3 transition-colors hover:bg-amber-500/20"
|
||
>
|
||
<GameLogo slug="pokemon" name="Pokémon" class="h-12 w-24" />
|
||
<div class="min-w-0 flex-1">
|
||
<h2 id="pokemon-series" class="font-semibold">Pokémon</h2>
|
||
<p class="text-xs text-muted-foreground">Open your adventure journal →</p>
|
||
<p class="mt-1 text-xs text-muted-foreground">
|
||
{data.pokemon.caught.value} / {data.pokemon.caught.total} species
|
||
</p>
|
||
</div>
|
||
</a>
|
||
<div class="mb-3 space-y-2 rounded-lg bg-muted/20 p-2">
|
||
<ProgressMeter
|
||
label="Across every adventure"
|
||
progress={data.pokemon.overall}
|
||
color="amber"
|
||
compact
|
||
hint="Equal weight per game; collection and story stages each contribute."
|
||
/>
|
||
<ProgressMeter
|
||
label="Every game’s collection"
|
||
progress={data.pokemon.collection}
|
||
compact
|
||
hint="Each confirmed species/game pairing counts once, including trades and events."
|
||
/>
|
||
</div>
|
||
{#if data.pokemon.games.length}
|
||
<div class="collection-grid grid grid-cols-2 gap-2">
|
||
{#each data.pokemon.games as game (game.id)}
|
||
<a
|
||
class="game-row flex min-h-0 min-w-0 items-center gap-2 rounded-lg border px-2 py-1.5 transition-colors hover:border-amber-500/50 hover:bg-amber-500/5"
|
||
href={resolve(`/projects/game-tracker/pokemon?game=${game.slug ?? game.id}`)}
|
||
title={`${game.name} · ${game.releaseYear}`}
|
||
>
|
||
<GameLogo
|
||
slug={`pokemon/${game.slug}`}
|
||
name={game.name}
|
||
class="game-cover h-10 w-10"
|
||
/>
|
||
<div class="min-w-0 flex-1">
|
||
<p class="game-name text-xs leading-tight font-medium">{game.name}</p>
|
||
<p class="game-year mt-0.5 text-[10px] text-muted-foreground">
|
||
{game.releaseYear}{game.completed ? ' · ✓ story' : ''}
|
||
</p>
|
||
<ProgressMeter
|
||
label="Game progress"
|
||
progress={game.overall}
|
||
color="amber"
|
||
compact
|
||
/>
|
||
</div>
|
||
</a>
|
||
{/each}
|
||
</div>
|
||
{:else}<a
|
||
class="rounded-xl border border-dashed p-5 text-sm text-muted-foreground hover:text-foreground"
|
||
href={resolve('/projects/game-tracker/pokemon')}
|
||
>Choose your games in “set rules” to build your collection here.</a
|
||
>{/if}
|
||
</section>
|
||
<section
|
||
class="series-column flex min-h-0 min-w-0 flex-col rounded-2xl border bg-card p-3"
|
||
aria-labelledby="cod-series"
|
||
>
|
||
<div class="series-heading mb-3 flex items-center gap-3 rounded-xl bg-zinc-500/10 p-3">
|
||
<GameLogo slug="call-of-duty" name="Call of Duty" class="h-12 w-24" />
|
||
<div>
|
||
<h2 id="cod-series" class="font-semibold">Call of Duty</h2>
|
||
<p class="text-xs text-muted-foreground">
|
||
{data.callOfDuty.length} campaigns of progress
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="mb-3 px-1">
|
||
<ProgressMeter label="COD completion" progress={data.codOverall} color="violet" compact />
|
||
</div>
|
||
<div class="cod-rows grid min-h-0 gap-1.5">
|
||
{#each data.callOfDuty as game (game.slug)}
|
||
<a
|
||
href={resolve(`/projects/game-tracker/call-of-duty/${game.slug}`)}
|
||
class="game-row flex min-h-0 items-center gap-3 rounded-lg border p-2 transition-colors hover:border-primary/40 hover:bg-muted/50"
|
||
>
|
||
<GameLogo slug={`cod/${game.slug}`} name={game.name} class="h-11 w-24" />
|
||
<div class="min-w-0 flex-1">
|
||
<p class="text-sm leading-tight font-medium">{game.name}</p>
|
||
<p class="mt-1 text-[11px] text-muted-foreground">
|
||
{game.releaseYear}<span class="ml-2"
|
||
>{game.achievements.value}/{game.achievements.total} achievements</span
|
||
>
|
||
</p>
|
||
<ProgressMeter
|
||
label={`${game.name} progress`}
|
||
progress={game.overall}
|
||
color="violet"
|
||
compact
|
||
/>
|
||
</div>
|
||
</a>
|
||
{/each}
|
||
</div>
|
||
</section>
|
||
<section
|
||
class="series-column flex min-w-0 flex-col rounded-2xl border bg-card p-3"
|
||
aria-labelledby="osu-series"
|
||
>
|
||
<div class="series-heading mb-3 flex items-center gap-3 rounded-xl bg-pink-500/10 p-3">
|
||
<GameLogo slug="osu" name="osu!" class="h-12 w-12" />
|
||
<div>
|
||
<h2 id="osu-series" class="font-semibold">osu!</h2>
|
||
<p class="text-xs text-muted-foreground">One more attempt</p>
|
||
</div>
|
||
</div>
|
||
<a
|
||
href={resolve('/projects/game-tracker/osu')}
|
||
class="rounded-xl border p-4 transition-colors hover:border-pink-500/50 hover:bg-pink-500/5"
|
||
><div class="flex items-center gap-3">
|
||
<GameLogo slug="osu" name="osu!" class="h-14 w-14" />
|
||
<div>
|
||
<p class="font-semibold">osu!</p>
|
||
<p class="text-xs text-muted-foreground">2007</p>
|
||
</div>
|
||
</div>
|
||
<p class="mt-4 text-sm">Your training room →</p>
|
||
<p class="mt-1 text-xs leading-relaxed text-muted-foreground">
|
||
Scores, dream FCs, stamina and speed. Build your next personal best.
|
||
</p>
|
||
<div class="mt-4">
|
||
<ProgressMeter label="osu! goals achieved" progress={data.osuGoals} color="pink" />
|
||
</div></a
|
||
>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.series-grid {
|
||
grid-template-columns: minmax(0, 1.5fr) minmax(0, 1.2fr) minmax(0, 0.8fr);
|
||
align-items: start;
|
||
}
|
||
.game-row {
|
||
min-height: 64px;
|
||
}
|
||
@media (max-width: 1100px) {
|
||
.series-grid {
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
}
|
||
}
|
||
@media (max-width: 639px) {
|
||
.series-grid {
|
||
grid-template-columns: minmax(0, 1fr);
|
||
}
|
||
}
|
||
</style>
|