master @ 176 LINES
[ HISTORY ] [ UP ]
┌─ ASTRO ────────────────────────────────────────────────────────────────────┐
│ --- │
│ // Three-card profile header: Identity / Character ranks / Account ranks. │
│ // Cards 2 and 3 share the same `RanksCard` component so the per-character │
│ // and per-account stats stay visually aligned and styled from one place. │
│ import { getClassTextClass } from "../../../lib/wow-constants"; │
│ import AccountAlts from "../../AccountAlts/AccountAlts.astro"; │
│ import RanksCard from "../RanksCard/RanksCard.astro"; │
│ import type { AccountCharSummary, AccountSeasonData } from "../../../lib/types"; │
│ import "./PlayerHeader.scss"; │
│ │
│ interface SeasonData { │
│ main_spec_id?: number; │
│ dungeons_completed: number; │
│ total_runs: number; │
│ combined_best_time?: number; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ last_updated?: number; │
│ } │
│ │
│ interface Player { │
│ id: number; │
│ name: string; │
│ region: string; │
│ realm_name: string; │
│ realm_slug: string; │
│ class_name?: string; │
│ active_spec_name?: string; │
│ race_name?: string; │
│ avatar_url?: string; │
│ guild_name?: string; │
│ average_item_level?: number; │
│ equipped_item_level?: number; │
│ all_time_total_runs?: number; │
│ account_lifetime_total_runs?: number; │
│ alts?: AccountCharSummary[]; │
│ } │
│ │
│ interface Props { │
│ player: Player; │
│ seasonData: SeasonData; │
│ seasonId?: string | null; │
│ accountSeasonData?: AccountSeasonData; │
│ } │
│ │
│ const { player, seasonData, seasonId, accountSeasonData } = Astro.props; │
│ const seasonLabel = │
│ seasonId === "all-time" ? "All Time" : seasonId ? `Season ${seasonId}` : ""; │
│ │
│ const regionLabel = (player.region || "").toUpperCase(); │
│ │
│ function getRaceId(raceName: string): number { │
│ const raceIds: Record<string, number> = { │
│ Human: 1, │
│ Orc: 2, │
│ Dwarf: 3, │
│ "Night Elf": 4, │
│ Undead: 5, │
│ Tauren: 6, │
│ Gnome: 7, │
│ Troll: 8, │
│ Goblin: 9, │
│ "Blood Elf": 10, │
│ Draenei: 11, │
│ Worgen: 22, │
│ }; │
│ return raceIds[raceName] || 1; │
│ } │
│ │
│ const raceId = getRaceId(player.race_name || "Human"); │
│ const genderId = 0; │
│ const fallbackUrl = `/wow/static/images/2d/avatar/${raceId}-${genderId}.jpg`; │
│ const avatarUrl = player.avatar_url │
│ ? `${player.avatar_url}?alt=${fallbackUrl}` │
│ : fallbackUrl; │
│ │
│ const characterSubtitle = [ │
│ player.race_name, │
│ player.active_spec_name, │
│ player.class_name, │
│ ] │
│ .filter(Boolean) │
│ .join(" "); │
│ │
│ const accountSubtitle = accountSeasonData │
│ ? `${accountSeasonData.character_count} character${accountSeasonData.character_c │
│ ount === 1 ? "" : "s"}` │
│ : undefined; │
│ --- │
│ │
│ <div class="player-header-cards"> │
│ <section class="player-card player-card--identity"> │
│ <div class="player-identity"> │
│ <img │
│ src={avatarUrl} │
│ alt={`${player.name} avatar`} │
│ class="player-identity__avatar" │
│ /> │
│ <div class="player-identity__body"> │
│ <div class="player-identity__name-row"> │
│ <h1 │
│ class:list={[ │
│ "player-identity__name", │
│ getClassTextClass(player.class_name || "common"), │
│ ]} │
│ > │
│ {player.name} │
│ </h1> │
│ { │
│ player.alts && player.alts.length > 0 && ( │
│ <AccountAlts alts={player.alts} align="left" /> │
│ ) │
│ } │
│ </div> │
│ { │
│ player.guild_name && ( │
│ <div class="player-identity__guild"> │
│ <{player.guild_name}> │
│ </div> │
│ ) │
│ } │
│ <div class="player-identity__details">{characterSubtitle}</div> │
│ <div class="player-identity__ilvl"> │
│ ilvl {player.equipped_item_level || "-"} equipped / { │
│ player.average_item_level || "-" │
│ } avg │
│ </div> │
│ </div> │
│ </div> │
│ </section> │
│ │
│ <RanksCard │
│ title="Character" │
│ subtitle={seasonLabel} │
│ combinedTime={seasonData.combined_best_time} │
│ combinedTimeBracket={seasonData.global_ranking_bracket} │
│ globalRanking={seasonData.global_ranking} │
│ globalBracket={seasonData.global_ranking_bracket} │
│ regionalRanking={seasonData.regional_ranking} │
│ regionalBracket={seasonData.regional_ranking_bracket} │
│ regionLabel={regionLabel} │
│ realmRanking={seasonData.realm_ranking} │
│ realmBracket={seasonData.realm_ranking_bracket} │
│ totalRuns={seasonData.total_runs} │
│ /> │
│ │
│ { │
│ accountSeasonData ? ( │
│ <RanksCard │
│ title="Account" │
│ subtitle={[seasonLabel, accountSubtitle].filter(Boolean).join(" ? ")} │
│ combinedTime={accountSeasonData.combined_best_time} │
│ combinedTimeBracket={accountSeasonData.global_ranking_bracket} │
│ globalRanking={accountSeasonData.global_ranking} │
│ globalBracket={accountSeasonData.global_ranking_bracket} │
│ regionalRanking={accountSeasonData.regional_ranking} │
│ regionalBracket={accountSeasonData.regional_ranking_bracket} │
│ regionLabel={regionLabel} │
│ realmRanking={accountSeasonData.realm_ranking} │
│ realmBracket={accountSeasonData.realm_ranking_bracket} │
│ totalRuns={accountSeasonData.total_runs} │
│ /> │
│ ) : ( │
│ <section class="player-card player-card--account-empty"> │
│ <div class="player-card__placeholder"> │
│ <h2 class="player-card__placeholder-title">Account</h2> │
│ <p>This character isn't grouped to an account yet.</p> │
│ </div> │
│ </section> │
│ ) │
│ } │
│ </div> │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ ASTRO ──────────────────────────────┐
│ --- │
│ // Three-card profile header: Identity / Cha │
│ racter ranks / Account ranks. │
│ // Cards 2 and 3 share the same `RanksCard` │
│ component so the per-character │
│ // and per-account stats stay visually align │
│ ed and styled from one place. │
│ import { getClassTextClass } from "../../../ │
│ lib/wow-constants"; │
│ import AccountAlts from "../../AccountAlts/A │
│ ccountAlts.astro"; │
│ import RanksCard from "../RanksCard/RanksCar │
│ d.astro"; │
│ import type { AccountCharSummary, AccountSea │
│ sonData } from "../../../lib/types"; │
│ import "./PlayerHeader.scss"; │
│ │
│ interface SeasonData { │
│ main_spec_id?: number; │
│ dungeons_completed: number; │
│ total_runs: number; │
│ combined_best_time?: number; │
│ global_ranking?: number; │
│ regional_ranking?: number; │
│ realm_ranking?: number; │
│ global_ranking_bracket?: string; │
│ regional_ranking_bracket?: string; │
│ realm_ranking_bracket?: string; │
│ last_updated?: number; │
│ } │
│ │
│ interface Player { │
│ id: number; │
│ name: string; │
│ region: string; │
│ realm_name: string; │
│ realm_slug: string; │
│ class_name?: string; │
│ active_spec_name?: string; │
│ race_name?: string; │
│ avatar_url?: string; │
│ guild_name?: string; │
│ average_item_level?: number; │
│ equipped_item_level?: number; │
│ all_time_total_runs?: number; │
│ account_lifetime_total_runs?: number; │
│ alts?: AccountCharSummary[]; │
│ } │
│ │
│ interface Props { │
│ player: Player; │
│ seasonData: SeasonData; │
│ seasonId?: string | null; │
│ accountSeasonData?: AccountSeasonData; │
│ } │
│ │
│ const { player, seasonData, seasonId, accoun │
│ tSeasonData } = Astro.props; │
│ const seasonLabel = │
│ seasonId === "all-time" ? "All Time" : sea │
│ sonId ? `Season ${seasonId}` : ""; │
│ │
│ const regionLabel = (player.region || "").to │
│ UpperCase(); │
│ │
│ function getRaceId(raceName: string): number │
│ { │
│ const raceIds: Record<string, number> = { │
│ Human: 1, │
│ Orc: 2, │
│ Dwarf: 3, │
│ "Night Elf": 4, │
│ Undead: 5, │
│ Tauren: 6, │
│ Gnome: 7, │
│ Troll: 8, │
│ Goblin: 9, │
│ "Blood Elf": 10, │
│ Draenei: 11, │
│ Worgen: 22, │
│ }; │
│ return raceIds[raceName] || 1; │
│ } │
│ │
│ const raceId = getRaceId(player.race_name || │
│ "Human"); │
│ const genderId = 0; │
│ const fallbackUrl = `/wow/static/images/2d/a │
│ vatar/${raceId}-${genderId}.jpg`; │
│ const avatarUrl = player.avatar_url │
│ ? `${player.avatar_url}?alt=${fallbackUrl} │
│ ` │
│ : fallbackUrl; │
│ │
│ const characterSubtitle = [ │
│ player.race_name, │
│ player.active_spec_name, │
│ player.class_name, │
│ ] │
│ .filter(Boolean) │
│ .join(" "); │
│ │
│ const accountSubtitle = accountSeasonData │
│ ? `${accountSeasonData.character_count} ch │
│ aracter${accountSeasonData.character_count = │
│ == 1 ? "" : "s"}` │
│ : undefined; │
│ --- │
│ │
│ <div class="player-header-cards"> │
│ <section class="player-card player-card--i │
│ dentity"> │
│ <div class="player-identity"> │
│ <img │
│ src={avatarUrl} │
│ alt={`${player.name} avatar`} │
│ class="player-identity__avatar" │
│ /> │
│ <div class="player-identity__body"> │
│ <div class="player-identity__name-ro │
│ w"> │
│ <h1 │
│ class:list={[ │
│ "player-identity__name", │
│ getClassTextClass(player.class │
│ _name || "common"), │
│ ]} │
│ > │
│ {player.name} │
│ </h1> │
│ { │
│ player.alts && player.alts.lengt │
│ h > 0 && ( │
│ <AccountAlts alts={player.alts │
│ } align="left" /> │
│ ) │
│ } │
│ </div> │
│ { │
│ player.guild_name && ( │
│ <div class="player-identity__gui │
│ ld"> │
│ <{player.guild_name}> │
│ </div> │
│ ) │
│ } │
│ <div class="player-identity__details │
│ ">{characterSubtitle}</div> │
│ <div class="player-identity__ilvl"> │
│ ilvl {player.equipped_item_level | │
│ | "-"} equipped / { │
│ player.average_item_level || "-" │
│ } avg │
│ </div> │
│ </div> │
│ </div> │
│ </section> │
│ │
│ <RanksCard │
│ title="Character" │
│ subtitle={seasonLabel} │
│ combinedTime={seasonData.combined_best_t │
│ ime} │
│ combinedTimeBracket={seasonData.global_r │
│ anking_bracket} │
│ globalRanking={seasonData.global_ranking │
│ } │
│ globalBracket={seasonData.global_ranking │
│ _bracket} │
│ regionalRanking={seasonData.regional_ran │
│ king} │
│ regionalBracket={seasonData.regional_ran │
│ king_bracket} │
│ regionLabel={regionLabel} │
│ realmRanking={seasonData.realm_ranking} │
│ realmBracket={seasonData.realm_ranking_b │
│ racket} │
│ totalRuns={seasonData.total_runs} │
│ /> │
│ │
│ { │
│ accountSeasonData ? ( │
│ <RanksCard │
│ title="Account" │
│ subtitle={[seasonLabel, accountSubti │
│ tle].filter(Boolean).join(" ? ")} │
│ combinedTime={accountSeasonData.comb │
│ ined_best_time} │
│ combinedTimeBracket={accountSeasonDa │
│ ta.global_ranking_bracket} │
│ globalRanking={accountSeasonData.glo │
│ bal_ranking} │
│ globalBracket={accountSeasonData.glo │
│ bal_ranking_bracket} │
│ regionalRanking={accountSeasonData.r │
│ egional_ranking} │
│ regionalBracket={accountSeasonData.r │
│ egional_ranking_bracket} │
│ regionLabel={regionLabel} │
│ realmRanking={accountSeasonData.real │
│ m_ranking} │
│ realmBracket={accountSeasonData.real │
│ m_ranking_bracket} │
│ totalRuns={accountSeasonData.total_r │
│ uns} │
│ /> │
│ ) : ( │
│ <section class="player-card player-car │
│ d--account-empty"> │
│ <div class="player-card__placeholder │
│ "> │
│ <h2 class="player-card__placeholde │
│ r-title">Account</h2> │
│ <p>This character isn't grouped to │
│ an account yet.</p> │
│ </div> │
│ </section> │
│ ) │
│ } │
│ </div> │
└──────────────────────────────────────────────┘
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET