Phase 2: the public UI for the four new boards, following the ChampSpawns live pattern (snapshot via useAsync + merge SSE deltas with useShardFeed). - Players Online widget (components/PlayersOnline.jsx): total + region breakdown rolled up into display buckets (data/regionBuckets.js — the one place to retune the grouping); live via presence.online. Placed on the Shard page, replacing the static players-online stat tile. - Guilds (/site/guilds): searchable board of rosters/alliances/leaders with a "recently joined" strip from guild.join. - Governors (/site/governors): one card per city with a placeholder crest (data/cityCrests.js — swap for real art without touching components), election phase badge + autoPickAt countdown, and an on-demand "past governors" term history (the look-back reads the ledger captured in Phase 1). Clean empty state when City Loyalty isn't enabled. - Houses (/site/houses): searchable registry with decay badges; price labelled "placement value", not a for-sale flag. - API client methods + nav links (Guilds / Governors / Houses). Client build clean (240 modules). Refs .plans/protocol2-integration.md (Phase 2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
32 lines
1.5 KiB
JavaScript
32 lines
1.5 KiB
JavaScript
// Placeholder heraldry for the eight City-Loyalty cities. Each entry is a simple
|
|
// emoji sigil + a ring colour — enough to make the Governors board and the
|
|
// governor badge read as distinct "crests" today, swappable for real artwork
|
|
// later WITHOUT touching any component: drop an `img` (an imported asset URL or a
|
|
// public path) onto an entry and update CityCrest to prefer it.
|
|
//
|
|
// Keyed by the exact `city` string the sidecar sends (see INTEGRATION.md §4:
|
|
// Moonglow, Britain, Jhelom, Yew, Minoc, Trinsic, SkaraBrae, NewMagincia).
|
|
|
|
export const CITY_CRESTS = {
|
|
Britain: { sigil: '⚜', color: '#c9a24b', label: 'Britain' },
|
|
Moonglow: { sigil: '🔮', color: '#7f8fd0', label: 'Moonglow' },
|
|
Minoc: { sigil: '⚒', color: '#b0763f', label: 'Minoc' },
|
|
Trinsic: { sigil: '⚓', color: '#5f9bd0', label: 'Trinsic' },
|
|
Yew: { sigil: '🌳', color: '#5fb98a', label: 'Yew' },
|
|
Jhelom: { sigil: '⚔', color: '#c76f6f', label: 'Jhelom' },
|
|
SkaraBrae: { sigil: '🐎', color: '#9a8bbf', label: 'Skara Brae' },
|
|
NewMagincia: { sigil: '🕊', color: '#cfc3a0', label: 'New Magincia' },
|
|
}
|
|
|
|
const FALLBACK = { sigil: '🏰', color: '#8c96a5', label: '' }
|
|
|
|
// Look up a crest by the raw city key, tolerating spacing variants
|
|
// ("Skara Brae" / "New Magincia"). `label` falls back to the given name.
|
|
export function crestFor(city) {
|
|
if (!city) return FALLBACK
|
|
const key = String(city).replace(/\s+/g, '')
|
|
const crest = CITY_CRESTS[city] || CITY_CRESTS[key]
|
|
if (crest) return crest
|
|
return { ...FALLBACK, label: String(city) }
|
|
}
|