Core's EmptyState renders its children and nothing else. The template's clan list passed the sentence as message=, which React drops without a word, so the panel rendered as an empty box - and module-rust, built from this template, shipped six of those across four phases before a browser walk noticed (docs modules/rust/PLAN.md §23.4). Same class of bug as the PageHeader subtitle the Teams work found here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
57 lines
2.3 KiB
JavaScript
57 lines
2.3 KiB
JavaScript
// ── The clan list ─────────────────────────────────────────────────────────
|
|
//
|
|
// An ordinary index page, here mostly so the clan page below it has somewhere to
|
|
// be linked from. The interesting file is `Clan.jsx`.
|
|
//
|
|
// `Link` comes from `react-router-dom`, which resolves through this module's shim
|
|
// to core's router — so a click navigates inside the SPA rather than reloading
|
|
// the site. An `<a href>` here would work and would cost a full page load and the
|
|
// session-shaped flash that comes with it.
|
|
|
|
import { Link } from 'react-router-dom'
|
|
|
|
import { EmptyState, ErrorState, Loading, PageHeader, PublicLayout, useAsync } from '../../core.js'
|
|
import api from '../../api.js'
|
|
|
|
export default function Clans() {
|
|
const { data, loading, error } = useAsync(() => api.clans.list(), [])
|
|
|
|
return (
|
|
<PublicLayout shell="narrow">
|
|
<PageHeader title="Clans" lead="The companies, orders and warbands of the world" />
|
|
|
|
{loading && <Loading />}
|
|
{error && <ErrorState error={error} />}
|
|
|
|
{/* `EmptyState` renders its CHILDREN and takes no other prop. Pass the
|
|
sentence as `message=` and React drops it without a word: the panel
|
|
renders as an empty box. module-rust shipped six of those for four
|
|
phases, learned from this line when it said `message=`. */}
|
|
{data && data.clans.length === 0 && (
|
|
<EmptyState>No clans have been reported yet.</EmptyState>
|
|
)}
|
|
|
|
{data && data.clans.length > 0 && (
|
|
<ul style={{ listStyle: 'none', padding: 0, display: 'grid', gap: '0.5rem' }}>
|
|
{data.clans.map((clan) => (
|
|
<li key={clan.externalId}>
|
|
<Link to={`/examplegame/clans/${clan.externalId}`}>
|
|
{clan.name}{clan.abbr ? ` [${clan.abbr}]` : ''}
|
|
</Link>
|
|
<span style={{ opacity: 0.7 }}>
|
|
{' '}— {clan.memberCount} member{clan.memberCount === 1 ? '' : 's'}
|
|
</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
|
|
{data && data.stale && (
|
|
<p style={{ opacity: 0.7, marginTop: '1rem' }}>
|
|
The game has not reported recently, so this list may be out of date.
|
|
</p>
|
|
)}
|
|
</PublicLayout>
|
|
)
|
|
}
|