Skip to content

feat(store): tribe stats page in the Tribes tab - #4823

Open
evanpelle wants to merge 1 commit into
mainfrom
feat/tribe-stats-page
Open

feat(store): tribe stats page in the Tribes tab#4823
evanpelle wants to merge 1 commit into
mainfrom
feat/tribe-stats-page

Conversation

@evanpelle

Copy link
Copy Markdown
Collaborator

What

Adds a Stats button to each active tribe name row in the store's Tribes tab. Clicking it swaps the tab content to the tribe page — same modal, with a modalHeader back button returning to the list (the profile-modal ← leaderboard pattern) — showing live figures from the new public API endpoint:

  • Owner (<player-name>: account username with verified badge, publicId fallback)
  • Boost badge when boosted — "N× boosted", multiplier = 1 + activeBoosts, same convention as the leaderboard's Boosts column
  • Last 30 days (Jul 2 – Aug 1) — games appeared + player reach for the same rolling window the tribes leaderboard ranks by
  • Lifetime — same two figures

How

  • TribeStatsResponseSchema (src/core/ApiSchemas.ts): coerced activeBoosts, plain-string window bounds (same display-only tolerance as the leaderboard's), impressions warning on playerReach
  • fetchTribeStats() (src/client/Api.ts): GET /public/tribe/:name, public/no-auth, name URL-encoded; 404 folds into the generic failure since callers can't act on the difference
  • <tribe-stats-view> (new): fetches on open, canonical display name takes over the heading once loaded, window heading falls back to a dateless form if the date format wobbles
  • Rejected/revoked rows get no Stats button — the endpoint 404s for them on purpose

Copy rules honored

  • Player reach is impressions: tooltip says "Appeared in games with {count} players", never "seen by N people"
  • Responses are live (unlike the board's ~1h cache), so small discrepancies vs. the leaderboard are expected

Deploy ordering

⚠️ The endpoint ships with infra#489, not deployed yet. Until it's live the page shows its error state ("Couldn't load stats"). Nothing breaks, but hold announcing/deploying this until the API side is out.

Tests

  • 9 new TribeStatsResponseSchema tests (null owner username, zeroed new-name response, coerced boost count, non-YYYY-MM-DD window bounds, missing-field rejections)
  • tsc --noEmit, ESLint, en.json sort check all clean

🤖 Generated with Claude Code

…/:name

Each active tribe name row gets a Stats button that swaps the tab to an
in-modal tribe page (profile-modal style back button) showing the owner,
active boost multiplier, and games/player-reach figures for both the
rolling 30-day leaderboard window and lifetime.

Rejected/revoked rows get no button: the public endpoint 404s for them
on purpose. Reach copy follows the API rule ("appeared in games with N
players" — impressions, not distinct players).

The endpoint ships with infra#489; until that deploys the page shows
its error state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds a public tribe statistics API and schema, a Lit statistics view, and TribesPanel navigation. The view displays validated metrics, owner data, reporting windows, and active boosts with localized English strings.

Changes

Tribe statistics

Layer / File(s) Summary
Statistics contract and API
src/core/ApiSchemas.ts, src/client/Api.ts, tests/ApiSchemas.test.ts
Defines and tests the tribe statistics response. Adds fetchTribeStats with URL encoding, response validation, and failure handling.
Statistics display
src/client/components/TribeStatsView.ts, resources/lang/en.json
Adds loading, error, metric, owner, date-window, lifetime, and boost rendering with English translations.
TribesPanel navigation
src/client/components/TribesPanel.ts
Adds a stats button for active tribes and supports opening and closing the statistics view.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant TribeUser
  participant TribesPanel
  participant TribeStatsView
  participant Api
  participant PublicTribeEndpoint
  TribeUser->>TribesPanel: Select active tribe statistics
  TribesPanel->>TribeStatsView: Set tribeName
  TribeStatsView->>Api: fetchTribeStats(name)
  Api->>PublicTribeEndpoint: GET encoded tribe name
  PublicTribeEndpoint-->>Api: Statistics response
  Api-->>TribeStatsView: Validated response or false
  TribeStatsView-->>TribeUser: Render statistics or error
Loading

Suggested labels: UI/UX

Suggested reviewers: celant

Poem

Tribe stats wake with numbers bright,
Games and reach come into sight.
Boosts glow and windows flow,
Back returns the list below.
Clean schemas guard the show.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a tribe stats page in the store's Tribes tab.
Description check ✅ Passed The description accurately explains the stats button, page behavior, API integration, schema validation, tests, and deployment dependency.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
tests/ApiSchemas.test.ts (1)

1061-1068: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add ownerUsername and activeBoosts to the required-field rejection test.

The sibling test for TribeLeaderboardResponseSchema checks ownerPublicId, ownerUsername, and activeBoosts for required-field rejection. The new TribeStatsResponseSchema test only checks name, ownerPublicId, lifetime, and window. Both ownerUsername and activeBoosts are required fields on TribeStatsResponseSchema too. Add them to keep test coverage consistent with the leaderboard schema's test.

✅ Proposed test coverage addition
-  it.each(["name", "ownerPublicId", "lifetime", "window"])(
+  it.each(["name", "ownerPublicId", "ownerUsername", "activeBoosts", "lifetime", "window"])(
     "rejects a response missing %s",
     (field) => {
       const body: Record<string, unknown> = { ...base };
       delete body[field];
       expect(TribeStatsResponseSchema.safeParse(body).success).toBe(false);
     },
   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/ApiSchemas.test.ts` around lines 1061 - 1068, Extend the parameter list
for the TribeStatsResponseSchema required-field test to include ownerUsername
and activeBoosts alongside the existing fields, ensuring each required field is
individually deleted and rejected by safeParse.
src/client/components/TribeStatsView.ts (1)

37-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a test for the stale-response guard.

load() uses loadSeq to discard stale responses when tribeName changes quickly. This asynchronous race logic has no test coverage in the provided files. Add a test that triggers two rapid tribeName changes and asserts the view renders the second name's data, not the first. Based on learnings, focused client-component tests can instantiate the custom element directly without the setup() helper, since this component does not exercise game/simulation infrastructure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/components/TribeStatsView.ts` around lines 37 - 43, Add focused
client-component coverage for TribeStatsView.load by instantiating the custom
element directly, triggering two rapid tribeName changes with controlled fetch
responses, and resolving the second request before the first. Assert the
rendered state uses the second tribe’s data, confirming the loadSeq
stale-response guard discards the first result.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/client/components/TribeStatsView.ts`:
- Around line 37-43: Add focused client-component coverage for
TribeStatsView.load by instantiating the custom element directly, triggering two
rapid tribeName changes with controlled fetch responses, and resolving the
second request before the first. Assert the rendered state uses the second
tribe’s data, confirming the loadSeq stale-response guard discards the first
result.

In `@tests/ApiSchemas.test.ts`:
- Around line 1061-1068: Extend the parameter list for the
TribeStatsResponseSchema required-field test to include ownerUsername and
activeBoosts alongside the existing fields, ensuring each required field is
individually deleted and rejected by safeParse.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dc996d65-0902-40dd-80fa-eb7e2cf89b98

📥 Commits

Reviewing files that changed from the base of the PR and between 753c66e and c545333.

📒 Files selected for processing (6)
  • resources/lang/en.json
  • src/client/Api.ts
  • src/client/components/TribeStatsView.ts
  • src/client/components/TribesPanel.ts
  • src/core/ApiSchemas.ts
  • tests/ApiSchemas.test.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

1 participant