import { lazy, Suspense, useEffect, useRef, useState, type CSSProperties } from "react"; import { BOSS_CARD_RARITIES, BOSS_CARD_RARITY_INFO } from "../game/bossCards"; import type { DungeonBossCard as BossCard } from "../game/dungeonBossCards"; import "./dungeonBossCards.css"; const BossCardPortrait = lazy(() => import("./BossCardPortrait")); function DungeonBossModel({ card }: { readonly card: BossCard }) { const container = useRef(null); const [visible, setVisible] = useState(false); useEffect(() => { const element = container.current; if (!element || !card.model) return; if (typeof IntersectionObserver === "undefined") { setVisible(true); return; } const observer = new IntersectionObserver(([entry]) => setVisible(entry.isIntersecting), { rootMargin: "40px", threshold: 0.01, }); observer.observe(element); return () => observer.disconnect(); }, [card.model]); return
{!card.model ? Model unavailable : visible ? Loading model…}> : Loading model…}
; } export function DungeonBossCards({ cards, compact = false }: { readonly cards: readonly BossCard[]; readonly compact?: boolean; }) { if (!cards.length) return

No boss cards are listed for this dungeon.

; return
{cards.map((card, index) => { const highestRarity = card.ownedRarities.at(-1); const accent = highestRarity ? BOSS_CARD_RARITY_INFO[highestRarity].color : "#9a947f"; return
Boss {String(index + 1).padStart(2, "0")}{card.copies ? "Collected" : "Uncollected"}

{card.name}

{card.copies ? `${card.copies} ${card.copies === 1 ? "copy" : "copies"} owned` : "Card not collected"}

; })}
; }