import { useParams, Link } from 'react-router-dom' import api from '../../api.js' import { ErrorState, Loading, PageHeader, PublicLayout, Slot, useAsync } from '../../core.js' // One guild: its roster, and the place core puts the Team activity feed. // // **This page is the reason the extension-slot direction inverts** // (docs/website/TEAMS.md Part 3). Teams are a core platform primitive and this // module is what populates them — but core does not own the word "guild", so it // publishes no Team page of its own. The page is this module's; the activity feed // on it is core's, because only core can resolve whether the viewer is inside the // Team, and the public/members split on that feed is a security boundary. // // So the module declares `uo.guild.detail` (entry.jsx) and core fills it. On a // core that does not know about Teams the slot is simply never filled and this // page renders its roster alone, which is the same tolerance every other slot has. // // The roster comes from this module's OWN board — the same data it answers core's // Team provider from — rather than from core's Team API. That is deliberate: the // board is the authoritative copy here, and reading core's projection of our own // answer back would be a round trip through a staler copy of our own data. function rankOf(m) { // Absent rank means NOT KNOWN, never rank 0. The bridge omits it entirely for // staff, because ServUO reports GameMaster-and-above as Leader whatever their // real rank — emitting that verbatim would publish every staff member in a // guild as one of its leaders (docs/link/v4.md). if (m.rankName) return m.rankName return null } function MemberRow({ m }) { const rank = rankOf(m) const linked = m.webId != null || m.acct != null return (
← All guilds
{loading &&{data.members ?? roster.length} members {data.online != null && ` · ${data.online} online`} {data.alliance && ` · ${data.alliance}`}
{/* A third place for core, up here rather than below the roster: core puts this guild's notification control in it, and a control that acts on the page belongs beside the page's title and not after its content. Empty for a visitor with no membership, and on a core that fills nothing. */}| Name | Rank | Account |
|---|
No roster has been received for this guild yet.
)} {/* Core's Team activity feed lands here. Nothing renders on a core that does not fill it, or when there is nothing to show. The guild is named in OUR terms — core maps its own Team from these two. */}