feat(supporter): render chip on /discover/profiles listing#148
Open
ntatschner wants to merge 1 commit into
Open
feat(supporter): render chip on /discover/profiles listing#148ntatschner wants to merge 1 commit into
ntatschner wants to merge 1 commit into
Conversation
Final piece of the chip rollout: #143 (self profile) → #144 (topbar) → #145 (public/friend profile) → **#146 (this PR — discover bulk)**. Every public-profile surface now carries supporter recognition. Server changes: - `SupporterStore` gains `get_many_public_by_handle(handles)` — single SQL round-trip with `WHERE LOWER(claimed_handle) = ANY($1)` returning a `HashMap<lowercased_handle, SupporterStatus>`. The critical bit is that this is ONE query for N profiles instead of N individual lookups; with `DEFAULT_LIMIT=50` profiles per page that's the difference between 1 round-trip and 50. Filters to `active`/`lapsed` states server-side so non-supporters simply don't have a map entry. - `DiscoverProfile` gains `supporter: Option<PublicSupporterInfo>`, reusing the projection type added in PR #145 (sharing_routes). `PublicSupporterInfo` gets `Clone` derived (was Debug+Serde only) so `DiscoverProfile`'s derive(Clone) propagates. - `list_discover_profiles` handler takes `Extension(Arc<dyn SupporterStore>)` (the layer was wired in #145; no main.rs change needed), bulk-fetches supporter info AFTER the listing SQL completes, then merges results into each row. Fail-soft: a supporter-store error logs a `warn` and leaves chips absent on the listing — the discover page still renders. Web changes: - `apps/web/src/app/discover/page.tsx` (server component, first page) renders `<SupporterChip status={p.supporter} size="sm">` between the display-name line and the "Active X ago" timestamp. Full tier-specific palette via the shared component. - `apps/web/src/app/discover/_components/DiscoverLoadMore.tsx` (client component, subsequent pages) builds an imperative-DOM chip with the standard accent palette. Tier-specific colours only apply on the first page; the load-more path uses the accent palette uniformly. This is a deliberate trade-off — the alternative is replicating the full tier-palette mapping twice (TS + imperative DOM string-building), which would drift. Tests: - 3 new SupporterStore tests: empty-input shortcut, skips unknown/unbound handles in the bulk path, filters none-state rows. All 11 supporter tests + 8 discover_routes tests + 35 sharing_routes tests pass. - cargo fmt + clippy clean on starstats-server. - pnpm vitest + typecheck + lint clean on web. Smoke after platform promote: - Visit /discover signed-out; supporter chips appear on profile cards for any user with active/lapsed state. - Click "Load more" past 50 profiles; subsequent cards also show a chip (simpler palette as documented).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Final piece of the supporter chip rollout: #143 (self profile) → #144 (topbar) → #145 (public/friend profile) → #146 (this PR — discover bulk). Every public-profile surface now carries supporter recognition.
Server changes
SupporterStoregainsget_many_public_by_handle(handles)— single SQL round-trip withWHERE LOWER(claimed_handle) = ANY($1)returning aHashMap<lowercased_handle, SupporterStatus>. The critical bit is one query for N profiles instead of N individual lookups; withDEFAULT_LIMIT=50profiles per page that's a 50× round-trip reduction. Filters toactive/lapsedserver-side so non-supporters simply don't appear in the map.DiscoverProfilegainssupporter: Option<PublicSupporterInfo>, reusing the projection type added in feat(supporter): expose chip on public + friend profile views #145.PublicSupporterInfogetsClonederived (one-char change).list_discover_profileshandler takesExtension(Arc<dyn SupporterStore>)— the Extension layer was wired in feat(supporter): expose chip on public + friend profile views #145, nomain.rschange needed. Bulk-fetches AFTER the listing SQL completes and merges into each row. Fail-soft on store error (warn log; chips absent on the listing but discover page still renders).Web changes
discover/page.tsx(server, first page) — renders<SupporterChip status={p.supporter} size="sm">between display-name and "Active X ago". Full tier-specific palette via the shared component.DiscoverLoadMore.tsx(client, subsequent pages) — builds an imperative-DOM chip with the standard accent palette. Tier-specific colours only on the first page; load-more uses accent uniformly. Deliberate trade-off — the alternative is replicating the full tier-palette mapping in two places (TS + imperative DOM strings) which would drift.Tests
Test plan
cargo test -p starstats-server --bin starstats-server supporters— 11 tests pass (3 new)cargo test -p starstats-server --bin starstats-server discover— 8 tests pass (existing)cargo clippy -p starstats-server --bin starstats-server -- -D warningscleanpnpm --filter web run typecheckcleanpnpm --filter web run test:run— 40 tests pass/discoversigned-out, supporter chips appear on profile cards for any user with active/lapsed state. Click "Load more" past 50 profiles; subsequent cards also show a (simpler-palette) chip.This completes the four-PR chip rollout. No further follow-ups planned.