import { css, html, LitElement } from "lit"; import { customElement, query, state } from "lit/decorators.js"; import { ClanLeaderboardResponse, ClanLeaderboardResponseSchema, } from "../core/ApiSchemas"; import { getApiBase } from "./Api"; import { translateText } from "./Utils"; @customElement("stats-modal") export class StatsModal extends LitElement { @query("o-modal") private modalEl!: HTMLElement & { open: () => void; close: () => void; }; @state() private isLoading: boolean = false; @state() private error: string | null = null; @state() private data: ClanLeaderboardResponse | null = null; private hasLoaded = false; createRenderRoot() { return this; } public open() { this.modalEl?.open(); if (!this.hasLoaded && !this.isLoading) { void this.loadLeaderboard(); } } public close() { this.modalEl?.close(); } private async loadLeaderboard() { this.isLoading = true; this.error = null; try { const res = await fetch(`${getApiBase()}/public/clans/leaderboard`, { headers: { Accept: "application/json", }, }); if (!res.ok) { throw new Error(`Unexpected status ${res.status}`); } const json = await res.json(); const parsed = ClanLeaderboardResponseSchema.safeParse(json); if (!parsed.success) { console.warn( "ClanLeaderboardModal: invalid response schema", parsed.error, ); throw new Error("Invalid response format"); } this.data = parsed.data; this.hasLoaded = true; } catch (err) { console.warn("ClanLeaderboardModal: failed to load leaderboard", err); this.error = translateText("stats_modal.error"); } finally { this.isLoading = false; this.requestUpdate(); } } private renderBody() { if (this.isLoading) { return html`
${translateText("stats_modal.loading")}
${this.error}
${translateText("stats_modal.no_stats")}
${startDate.toLocaleDateString()} · ${endDate.toLocaleDateString()}
| ${translateText("stats_modal.rank")} | ${translateText("stats_modal.clan")} | ${translateText("stats_modal.games")} | ${translateText("stats_modal.win_score")} | ${translateText("stats_modal.loss_score")} | ${translateText("stats_modal.win_loss_ratio")} |
|---|---|---|---|---|---|
| ${(index + 1).toLocaleString()} | ${clan.clanTag} | ${clan.games.toLocaleString()} | ${clan.weightedWins} | ${clan.weightedLosses} | ${clan.weightedWLRatio} |