201 lines
5.8 KiB
Svelte

<script lang="ts">
import { onMount } from 'svelte';
import PlayerCard from '$lib/components/PlayerCard.svelte';
type Identity = {
id?: string;
name?: string;
};
type Player = {
id?: string;
name?: string;
avatar?: string | null;
country?: string | null;
role?: string | null;
rank?: number | null;
countryRank?: number | null;
techPp?: number | null;
accPp?: number | null;
passPp?: number | null;
pp?: number | null;
mapperId?: number | null;
level?: number | null;
banned?: boolean;
profileSettings?: { showAllRatings: boolean } | null;
patreon?: unknown;
};
let identity: Identity | null = null;
let player: Player | null = null;
let rawPlayer: unknown = null;
let error: string | null = null;
let loading = true;
onMount(async () => {
try {
const res = await fetch('/api/beatleader/me');
if (!res.ok) {
const body = await res.text();
throw new Error(body || `Request failed: ${res.status}`);
}
const data = (await res.json()) as { identity?: Identity; player?: Player | null; rawPlayer?: unknown };
identity = data.identity ?? null;
player = data.player ?? null;
rawPlayer = data.rawPlayer ?? null;
console.log('BeatLeader /me raw player:', rawPlayer ?? player ?? data);
} catch (err) {
error = err instanceof Error ? err.message : 'Unknown error';
} finally {
loading = false;
}
});
</script>
<section class="py-8">
<h1 class="font-display text-3xl sm:text-4xl">Player Info</h1>
<p class="mt-2 text-muted text-sm">Debug view for the current BeatLeader OAuth session.</p>
{#if loading}
<div class="mt-6 text-sm text-muted">Loading player info…</div>
{:else if error}
<div class="mt-6 rounded border border-rose-500/40 bg-rose-500/10 px-4 py-3 text-rose-200 text-sm">
{error}
</div>
{:else}
{#if player}
<div class="mt-6">
<div class="player-tile">
<PlayerCard
name={player.name ?? identity?.name ?? 'Unknown'}
country={player.country ?? null}
rank={player.rank ?? null}
showRank={typeof player.rank === 'number'}
avatar={player.avatar ?? null}
width="100%"
avatarSize={64}
techPp={player.techPp}
accPp={player.accPp}
passPp={player.passPp}
playerId={player.id ?? null}
gradientId="player-header"
/>
</div>
<div class="mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<div class="stat-tile">
<dt>Country Rank</dt>
<dd>{typeof player.countryRank === 'number' ? `#${player.countryRank.toLocaleString()}` : '—'}</dd>
</div>
<div class="stat-tile">
<dt>Global Rank</dt>
<dd>{typeof player.rank === 'number' ? `#${player.rank.toLocaleString()}` : '—'}</dd>
</div>
<div class="stat-tile">
<dt>PP (Global)</dt>
<dd>{typeof player.pp === 'number' ? player.pp.toFixed(2) : '—'}</dd>
</div>
<div class="stat-tile">
<dt>Tech PP</dt>
<dd>{typeof player.techPp === 'number' ? player.techPp.toFixed(2) : '—'}</dd>
</div>
<div class="stat-tile">
<dt>Acc PP</dt>
<dd>{typeof player.accPp === 'number' ? player.accPp.toFixed(2) : '—'}</dd>
</div>
<div class="stat-tile">
<dt>Pass PP</dt>
<dd>{typeof player.passPp === 'number' ? player.passPp.toFixed(2) : '—'}</dd>
</div>
<div class="stat-tile">
<dt>Level</dt>
<dd>{player.level ?? '—'}</dd>
</div>
<div class="stat-tile">
<dt>Role</dt>
<dd>{player.role ?? '—'}</dd>
</div>
<div class="stat-tile">
<dt>Mapper</dt>
<dd>
{#if player.mapperId}
<a class="link" href={`https://beatsaver.com/profile/${player.mapperId}`} target="_blank" rel="noreferrer">
{player.mapperId}
</a>
{:else}
{/if}
</dd>
</div>
<div class="stat-tile">
<dt>Banned</dt>
<dd>{player.banned ? 'Yes' : 'No'}</dd>
</div>
<div class="stat-tile">
<dt>Show All Ratings</dt>
<dd>{player.profileSettings?.showAllRatings ? 'Enabled' : 'Disabled'}</dd>
</div>
</div>
</div>
{:else}
<div class="mt-6 player-tile">
<p class="empty">No player profile found for this identity.</p>
</div>
{/if}
{/if}
</section>
<style>
.player-tile {
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 0.75rem;
padding: 1.5rem;
background: linear-gradient(160deg, rgba(15, 23, 42, 0.9), rgba(5, 9, 20, 0.92));
box-shadow: 0 20px 40px rgba(8, 14, 35, 0.35);
}
.stat-tile {
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 0.5rem;
padding: 1rem;
background: linear-gradient(160deg, rgba(15, 23, 42, 0.8), rgba(5, 9, 20, 0.85));
transition: border-color 0.2s ease;
}
.stat-tile:hover {
border-color: rgba(34, 211, 238, 0.25);
}
dt {
color: rgba(148, 163, 184, 0.75);
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.08em;
margin-bottom: 0.35rem;
font-weight: 600;
}
dd {
color: rgba(226, 232, 240, 0.95);
margin: 0;
font-size: 1.1rem;
font-weight: 500;
}
.link {
color: rgba(34, 211, 238, 0.85);
text-decoration: underline;
}
.link:hover {
color: rgba(34, 211, 238, 1);
}
.empty {
font-size: 0.85rem;
color: rgba(148, 163, 184, 0.7);
}
</style>