paginate stats page
This commit is contained in:
@@ -3,21 +3,30 @@
|
||||
import type { ActivitySummary, BASIndex, Sport } from '../lib/types';
|
||||
import { formatDistance, formatDuration, sportIcon, sportColor, sportLabel } from '../lib/format';
|
||||
|
||||
const PAGE_YEARS = 4;
|
||||
|
||||
let all: ActivitySummary[] = [];
|
||||
let sport: Sport | 'all' = 'all';
|
||||
let page = 0;
|
||||
let loading = true;
|
||||
let theme = 'dark';
|
||||
let mounted = false;
|
||||
|
||||
$: totalPages = Math.ceil(allYears.length / PAGE_YEARS);
|
||||
$: years = allYears.slice(page * PAGE_YEARS, (page + 1) * PAGE_YEARS);
|
||||
|
||||
$: if (mounted) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (sport === 'all') params.delete('sport'); else params.set('sport', sport);
|
||||
if (page === 0) params.delete('page'); else params.set('page', String(page));
|
||||
const qs = params.toString();
|
||||
history.replaceState(null, '', qs ? `?${qs}` : window.location.pathname);
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
sport = (new URLSearchParams(window.location.search).get('sport') as Sport | 'all') ?? 'all';
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
sport = (params.get('sport') as Sport | 'all') ?? 'all';
|
||||
page = parseInt(params.get('page') ?? '0', 10) || 0;
|
||||
mounted = true;
|
||||
const res = await fetch(`${import.meta.env.BASE_URL}data/index.json`);
|
||||
const index: BASIndex = await res.json();
|
||||
@@ -209,8 +218,6 @@
|
||||
: ([] as Sport[]);
|
||||
|
||||
// ── Calendar helpers ──────────────────────────────────────────────────────
|
||||
const now = new Date();
|
||||
const years = [now.getFullYear(), now.getFullYear()-1, now.getFullYear()-2, now.getFullYear()-3];
|
||||
|
||||
function localISO(d: Date): string {
|
||||
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
||||
@@ -277,9 +284,26 @@
|
||||
<div class="h-64 rounded-xl bg-zinc-800 animate-pulse mb-6"></div>
|
||||
{:else}
|
||||
|
||||
<!-- Pagination controls -->
|
||||
{#if totalPages > 1}
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<button
|
||||
class="px-3 py-1.5 rounded-lg border border-zinc-700 text-sm text-zinc-400 hover:border-zinc-500 hover:text-white transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
disabled={page === 0}
|
||||
on:click={() => page -= 1}
|
||||
>← Newer</button>
|
||||
<span class="text-sm text-zinc-500">{years[years.length - 1]} – {years[0]}</span>
|
||||
<button
|
||||
class="px-3 py-1.5 rounded-lg border border-zinc-700 text-sm text-zinc-400 hover:border-zinc-500 hover:text-white transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
disabled={page >= totalPages - 1}
|
||||
on:click={() => page += 1}
|
||||
>Older →</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Year totals -->
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-8">
|
||||
{#each allYears.slice(0, 4) as year}
|
||||
{#each years as year}
|
||||
{@const t = totalsByYear.get(year)}
|
||||
<div class="bg-zinc-900 rounded-xl border border-zinc-800 p-4">
|
||||
<p class="text-xs text-zinc-500 mb-1">{year}</p>
|
||||
|
||||
Reference in New Issue
Block a user