Files
Integration-kit/template/client/src/routes/public/Clans.jsx
wtclaude 43308c3f7f
All checks were successful
PR Checks / prose (pull_request) Successful in 10s
PR Checks / template (pull_request) Successful in 37s
fix(template): EmptyState takes children, not message
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
2026-09-23 00:32:52 -05:00

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>
)
}