import { useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import api from '../../api.js'
import { EmptyState, ErrorState, Loading, PageHeader, PublicLayout, useAsync } from '../../core.js'
import { CreaturePortrait } from './Atlas.jsx'
// One creature: where it spawns, and what spawns alongside it.
//
// `places` is the point of the page — the aggregate that turns 62 raw
// coordinates into "Shrines, Isamu-Jima, Yew". The individual spawners are
// available underneath for the reader who actually wants a coordinate, but they
// are secondary and collapsed by default.
const num = (v) => (Number.isFinite(v) ? v.toLocaleString() : '—')
// Spawn delays are stored in seconds. A raw "1200" tells the reader nothing.
function delay(min, max) {
const fmt = (s) => (s >= 60 ? `${Math.round(s / 60)}m` : `${s}s`)
if (!Number.isFinite(min) || !Number.isFinite(max)) return null
if (min === max) return fmt(min)
return `${fmt(min)}–${fmt(max)}`
}
function Panel({ title, right, children }) {
return (
{title}
{right}
{children}
)
}
function Places({ places }) {
if (places.length === 0) {
return
No placed spawners.
}
return (
{places.map((place) => (
{place.label}
{place.facet} · {num(place.spawners)} spawner{place.spawners === 1 ? '' : 's'} · up to{' '}
{num(place.maxAlive)} at once
)}
)
}
export default function AtlasCreature() {
const { slug } = useParams()
const { loading, error, data } = useAsync(() => api.atlas.creature(slug), [slug])
// A 404 here means "no such creature in this atlas", which is a real answer
// and not a failure — a visitor following a stale link deserves to be told
// that plainly rather than shown a generic error box.
const missing = error?.status === 404 || error?.message === 'Not Found'
const facets = useMemo(
() => Object.entries(data?.facets || {}).sort((a, b) => b[1] - a[1]),
[data],
)
return (
← Spawn atlas
{loading && }
{error && !missing && }
{missing && Nothing by that name spawns on this shard.}
{!loading && !error && data && (
<>
{/* The portrait sits BESIDE the header rather than inside it: `art`
is NULL for most creatures on most installs — no shard link, a
host that cannot render images, or simply a body this client has
no art for — and a header component that had to lay out around an
absent picture would be carrying that case forever. Here the row
collapses to exactly the header, which is what it was before. */}