refactor: AreaHeader extraction + one typed contacts object (#1176) - #1212
Conversation
📝 WalkthroughWalkthroughThe PR adds ChangesArea rendering and contact data
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant AreaPage
participant AreaHeader
participant Socials
participant Tip
AreaPage->>AreaHeader: Pass SSR area data
AreaHeader->>Socials: Pass consolidated contacts
AreaHeader->>Tip: Pass lightning tip destination
AreaPage->>AreaPage: Update section and area state
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
PR Summary by QodoRefactor area pages: extract AreaHeader and unify contacts into typed object
AI Description
Diagram
High-Level Assessment
Files changed (7)
|
There was a problem hiding this comment.
Pull request overview
Refactors the community/country area pages by centralizing contact:* tag extraction into a shared helper and extracting the header portion of AreaPage into a dedicated AreaHeader component, reducing prop fan-out and improving correctness across client-side area navigations.
Changes:
- Introduce
$lib/area/contacts.tsand update consumers to pass a single typedcontactsobject. - Update
Socialsto accept{ contacts }instead of 22 named props. - Extract the profile/header markup into
AreaHeader.svelteand simplifyAreaPagesection wiring/state resets.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/routes/communities/map/+page.svelte | Uses extractContacts() when instantiating Socials in map popups. |
| src/routes/communities/[section]/components/CommunityCard.svelte | Collapses many contact:* locals into a single contacts object passed to Socials. |
| src/lib/areaSectionLoad.ts | Uses shared extractContacts() to populate AreaPageProps.contacts. |
| src/lib/area/contacts.ts | New shared helper to lift contact:* tags into typed AreaContacts. |
| src/components/Socials.svelte | Refactors component API to accept contacts object and destructure internally. |
| src/components/area/AreaPage.svelte | Extracts header into AreaHeader, simplifies sections, and adjusts sweep gating. |
| src/components/area/AreaHeader.svelte | New extracted header component deriving all display state from SSR data. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Code Review by Qodo
1.
|
extractContacts moves to $lib/area/contacts, shared by the SSR bundle and both client consumers. Socials' interface collapses from 22 named props to one AreaContacts object (its internals and sanitization keep their per-key names); the communities-map popup and CommunityCard drop their own 22-line contact:* fan-outs for the same helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AreaPage sheds its header half into AreaHeader — a prop-in/markup-out
component whose state fully DERIVES from the SSR bundle: no imperative
init, no reset lifecycle, an area navigation swaps data and every value
follows. That deletes initializeData wholesale, the 22 contact locals,
and most of the manual reset block (only the async machinery — taggers
fetch and containment sweep — still needs explicit resets). The three
parallel section Records collapse into one SECTIONS array whose id is
the route slug is the i18n key suffix. Also fixes a latent staleness
bug: alias/name were consts frozen at first mount while the component
instance is reused across area navigations.
Deliberately NOT done, per the issue's re-review: no {#key} boundary
(AreaMap's instance-reuse path — setData + animated fitBounds across
area navs — must survive; a keyed teardown would refetch style and
tiles), and reportsSync stays page-level because the merchants section
consumes the report-fed AreaMap stars (#1186).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot follow-up catching a #1210-pruning interaction: the link's legacy in-place section switch rendered maintain with an empty issues table (issues arrive only with the maintain route's own load) and left the URL on the old section. The anchor now navigates natively — the maintain load fetches the issues, the hash scrolls to the form, and AreaHeader's onVerifyClick prop disappears along with the page-side handler and its manual activeSection override. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rop change #1176 Two qodo follow-ups. Socials drops the reactive destructure entirely — the sanitized derivations and template read contacts.* directly, so there's no Svelte-4 auto-declaration magic for tooling (or the future runes migration) to trip over. IssuesTable resets its render guard when the issues prop identity changes: the TanStack table snapshots issues at build time, and a client-side area navigation reusing the component previously left the OLD area's rows under the NEW area's count — a pre-existing bug this stack's loading={false} merely unmasked. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8eca3f9 to
0d62516
Compare
✅ Deploy Preview for btcmap ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@src/components/area/AreaPage.svelte`:
- Around line 163-165: The reactive block gating runContainmentSweep uses
`$places.length` (and similarly `$reports.length` in the areaReports logic) as a
proxy for "sync complete," but this is indistinguishable from a valid empty
result, causing filteredPlaces/sweepDone and AreaStats to remain stuck in a
loading state when the collection is legitimately empty. Replace the
length-based checks with an explicit sync/loading completion flag (e.g., a
status field from the data/store indicating fetch completion) to gate the
`sweptAreaId !== data.id` condition. Ensure that when the underlying data sync
completes with an empty result, the code still calls runContainmentSweep (or the
equivalent reporting logic) to publish `[]` and set `sweepDone = true`, rather
than skipping it due to zero length. Apply the same fix to the analogous
areaReports block referenced at the other line ranges.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: dc84b7cb-8a16-467b-9771-6994a88d462b
📒 Files selected for processing (8)
src/components/IssuesTable.sveltesrc/components/Socials.sveltesrc/components/area/AreaHeader.sveltesrc/components/area/AreaPage.sveltesrc/lib/area/contacts.tssrc/lib/areaSectionLoad.tssrc/routes/communities/[section]/components/CommunityCard.sveltesrc/routes/communities/map/+page.svelte

Summary
The #1176 split, scoped per the re-review on the issue. Stacked on #1211 (
refactor/places-in-area) — GitHub retargets tomainwhen it merges; only the last two commits are new here. Refs #1176 (the remaining slice — per-route section components — is a judgment call once this lands; see below).Commit 1 —
Socialstakes one typedcontactsobjectextractContactsmoves to$lib/area/contacts.ts, shared by the SSR bundle (areaSectionLoad), the communities-map popups, andCommunityCard— which each carried their own 22-linecontact:*fan-out. All three now passcontacts: AreaContacts.Socials' interface collapses from 22 named props to one object; its internals (per-key sanitization, template) are unchanged — only the seam moved.Commit 2 —
AreaHeaderextraction; derive, don't initializeAreaHeader.svelte: prop-in/markup-out, with every value derived from the SSR bundle — no imperative init, no reset lifecycle. An area navigation swapsdataand everything follows.initializeDatawholesale, the 22 contact locals,dataInitialized(each child now gets an honest signal: merchant highlights gate on sweep completion, the issues table'sloadingisfalsebecause issues arrive with the maintain route's own load), and most of the manual reset block — only the async machinery (taggers fetch, containment sweep) still needs explicit resets.Records collapse into oneSECTIONSarray: the section id is the route slug is the i18n key suffix.alias/namewereconsts frozen at first mount, while the component instance is reused across client-side area navigations — stale header identity after any /community/X → /community/Y transition.Deliberately NOT done (the re-review's constraints):
{#key}boundary. AreaMap's instance-reuse path (setData + animated fitBounds across area navs) must survive; a keyed teardown would refetch style + tiles per navigation — a visible regression. The (now much smaller) reset block is the accepted cost.reportsSyncstays page-level — the merchants section consumes the report-fed AreaMap stars (fix(area): grade the area map stars from the real report data #1163 #1186), so pushing it into stats-only would leave them pulsing forever.Test plan
pnpm run format:fix/check/lintclean, 557/557 unit tests#profileheader, name, and verified chip; country stats 200🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes