refactor(frontend): Split collective-detail into data-driven sections (#187) - #189
Conversation
Coverage Report
and 2 more...
|
There was a problem hiding this comment.
Pull request overview
Refactors the large collective-detail.svelte component into smaller, data-driven Svelte components to preserve existing collective subresource/member behavior while making the implementation easier to maintain and test.
Changes:
- Introduces
SubresourceDescriptordefinitions to drive per-type CRUD behavior (phones/emails/addresses/urls/circles) without central if/switch chains. - Adds a generic
SubresourceSectioncomponent and a dedicatedMemberSectioncomponent, with new component tests for each. - Slims
collective-detail.sveltedown to a container that orchestrates the new sections.
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 |
|---|---|
| apps/frontend/src/lib/components/collectives/collective-detail.svelte | Replaces in-component CRUD/member logic with orchestrated section components. |
| apps/frontend/src/lib/components/collectives/subresource-descriptors.ts | Defines the data-driven descriptor table for collective subresource CRUD. |
| apps/frontend/src/lib/components/collectives/subresource-section.svelte | Implements the generic, descriptor-driven subresource section (load/create/update/delete + modals + shortcut). |
| apps/frontend/src/lib/components/collectives/member-section.svelte | Extracts member lifecycle UI/shortcuts and visible-member tracking into its own component. |
| apps/frontend/src/lib/components/collectives/subresource-descriptors.test.ts | Adds unit coverage for descriptor mapping and per-type behaviors. |
| apps/frontend/src/lib/components/collectives/subresource-section.test.ts | Adds component tests for generic subresource section rendering, create/delete, and shortcut behavior. |
| apps/frontend/src/lib/components/collectives/member-section.test.ts | Adds component tests for member add/deactivate/reactivate/remove flows via the store. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Pushed 0e3c9c6 addressing both review comments and the coverage report:
24 tests pass; biome + frontend type-check clean. |
|
Pushed 7f2d457 addressing this round:
43 collective tests pass; biome + frontend type-check clean (0 errors). |
0321b6e to
5c9e0d9
Compare
…#187) collective-detail.svelte (893 LOC) was the lone grab-bag component flagged in the PR #186 review: it mixed the header/notes template, collective-delete state, per-subresource CRUD for five types, member lifecycle, and keyboard wiring — via a central editingType discriminator with a parallel if/else save chain and a switch delete chain. Decompose it behavior-preservingly: - subresource-descriptors.ts: one descriptor per type (phone/email/address/ url/circle) capturing icon, i18n keys, API calls, Row/Form components, and per-type quirks (address geocoding refetch, circle add-only). - subresource-section.svelte: a single generic, branch-free section driven by a descriptor — owns its CRUD/modal/delete state and add-shortcut listener, mirroring the friend section lifecycle. Drops stale in-flight loads and resets its items/modals when the collective changes (the instance is reused across collectives without unmounting). - member-section.svelte: member list, add-member modal, deactivate modal, the member add-shortcut, and the visibleMemberContactIds effect. Marks the deactivate dialog as a modal (isModalOpen) to suppress global shortcuts, and resets its modal state when the collective changes. - collective-detail.svelte: thin container (893 -> 193 LOC) — header, notes, collective-delete confirmation (suppressing shortcuts while open and resetting the deleting state in a finally), and the section/member orchestration. DetailEditModal gains an asForm prop so a section whose children supply their own <form> (add-member) avoids invalid nested forms; its footer Save still calls onSave whether or not it owns the form. Drops the dead availableCircles fetch (CircleEditForm uses the current circles). Reuses the existing friends/subresources shared components, the $lib/api/collectives CRUD fns, and the same markup/strings/shortcuts, so behavior is unchanged. Adds first component coverage for the collective pieces via $lib/test: descriptor mapping and delegation, the generic section (render/add/create/ update/delete/shortcut/non-editable/stale-load/reset-on-change), member management (lifecycle, modal flag, reset-on-change), the collective-detail delete lifecycle, and DetailEditModal's form/non-form Save. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5c9e0d9 to
6e7f82d
Compare
|
🎉 This PR is included in version 2.89.2 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Closes #187.
What
collective-detail.svelte(893 LOC) was the lone grab-bag component flagged in the PR #186 review — it mixed the header/notes template, collective-delete state, per-subresource CRUD for five types, member lifecycle, and keyboard wiring via a centraleditingTypediscriminator with a parallelif/elsesave chain and aswitchdelete chain.This decomposes it behavior-preservingly, using a data-driven descriptor (per the issue's first bullet) plus an extracted member section:
subresource-descriptors.tssubresource-section.sveltemember-section.sveltevisibleMemberContactIdseffectcollective-detail.svelteThe central
if/elsesave chain andswitchdelete chain collapse into the descriptor table. Reuses the existingfriends/subresourcesshared components, the$lib/api/collectivesCRUD fns, and the same markup/strings/shortcuts, so behavior is unchanged. Sections are always-mounted so the add-shortcut works even when a section is empty. Drops the deadavailableCirclesfetch (CircleEditFormuses the current circles).Tests
Adds the collective component's first coverage via the
$lib/testinfra from PR #186:subresource-descriptors.test.ts— delete-name extraction, row-prop mapping, editable/error mappingsubresource-section.test.ts— render, add, create, delete, shortcut-opens-when-empty, non-editable affordance (injects a fake descriptor withvi.fn()CRUD — no API mocking needed)member-section.test.ts— member render, add modal, deactivate/reactivate/remove through the storeVerification
aube type-check/ svelte-check: 0 errorscollectives/[id]routeaube dev) still pending — see the Refactor: split collective-detail.svelte (893 LOC) into focused pieces #187 checklistAcceptance criteria
$lib/test)aube type-check,aube run check, and the full test suite passaube dev) — pending🤖 Generated with Claude Code