5.4 KiB
5.4 KiB
Tasks: enterprise-react-contacts
Change ID: enterprise-react-contacts
Package: @suaveplan/react-contacts
Target path: react/platform/react-contacts
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/contacts, @suaveplan/react-translate, @suaveplan/react-virtual, @suaveplan/react-error-boundary
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory tree. Write
package.jsonat0.1.0,tsconfig.json,vitest.config.ts, scripts. - Dependencies:
@suaveplan/error workspace:^,@suaveplan/contacts workspace:^,@suaveplan/react-translate workspace:^,@suaveplan/react-virtual workspace:^,@suaveplan/react-error-boundary workspace:^,@opentelemetry/api catalog:observability,zod catalog:forms,tslib catalog:build.
2. Error codes and types
- Define
ContactsUiError; codes:CONTACTS_LOAD_FAILED,CONTACTS_SAVE_FAILED,AUDIENCE_RESOLVE_FAILED. - Define all prop types:
ContactDetailProps,ContactListProps,ContactTagInputProps,GroupMembershipPanelProps,GroupTreeEditorProps,UseContactsConfig,UseContactsResult,UseGroupsConfig,UseGroupsResult,UseGroupTreeResult,UseAudienceResolverConfig,UseAudienceResolverResult.
3. Hooks
useContacts
- CRUD + server search via
ContactManager. OTel spans:contacts.create,contacts.update,contacts.delete,contacts.search. Zod-validates create/update payloads via@suaveplan/contactsschemas. - Write
use-contacts.test.ts(≤500 lines): CRUD, search, error states, Zod rejection.{ timeout: 10000 }. - Write
use-contacts.md.
useGroups
- Group CRUD via
ContactManager. OTelgroups.renamecounter. - Write
use-groups.test.ts(≤500 lines).{ timeout: 10000 }. - Write
use-groups.md.
useGroupTree
- Converts flat group list to tree; maintains visible-node flattening for virtual rendering.
- Write test + md.
useAudienceResolver
- Resolves group → contact list with preview count. OTel
audience.resolvespan. ThrowsContactsUiError(AUDIENCE_RESOLVE_FAILED)on engine error. - Write
use-audience-resolver.test.ts(≤500 lines): resolves contacts, count preview, error state.{ timeout: 10000 }. - Write
use-audience-resolver.md.
4. Components
ContactsErrorBoundary
- Wrapper via
@suaveplan/react-error-boundary; localised error message + retry button. - Write test + md.
ContactTagInput
- Token-style tag input with autocomplete suggestions from
useContacts. All labels viauseTranslation. - Write test, stories (default, with-suggestions, max-tags, playground), md.
GroupMembershipPanel
- Add/remove contacts in a group with membership count. All labels via
useTranslation. - Write
group-membership-panel.test.tsx(≤500 lines): renders members, add fires useGroups, remove fires useGroups.{ timeout: 5000 }. - Write stories (default, empty, readonly, playground), md.
GroupTreeEditor
- Hierarchical tree with
role="tree"/role="treeitem". Keyboard navigation: Up/Down/Left/Right/Home/End.indentPxprop +--contacts-tree-indentCSS variable. All labels viauseTranslation. - Write test, stories (default, deep-tree, collapsed, keyboard, playground), md.
ContactDetail
- Full contact view with tag-apply flow, group membership list, channel info. All labels via
useTranslation. - Write
contact-detail.test.tsx(≤500 lines): renders contact fields, tag apply calls useContacts, group list renders.{ timeout: 5000 }. - Write stories (default, with-tags, with-groups, playground), md.
ContactList
- Virtualised via
@suaveplan/react-virtualfor >500 rows. Searchable (fuzzy on displayName/firstName/lastName), paginated. Select/edit/delete handlers. All labels viauseTranslation. - Write
contact-list.test.tsx(≤500 lines): renders contacts, search filters list, virtualisation renders visible rows, pagination.{ timeout: 10000 }. - Write stories (default, filtered, large-dataset, empty, playground), md.
5. E2E
e2e/contacts.spec.ts— Playwright:- Filter contact list by name; verify results narrow.
- Expand and rename a group in
GroupTreeEditorusing keyboard. - Add a contact to a group via
GroupMembershipPanel; verify count updates. - Resolve audience in
AudienceSelector; verify preview count. - Navigate the full list and detail using keyboard only.
- Verify mobile viewport single-column layout.
6. Verify and publish
bunx turbo lint typecheck test --filter=@suaveplan/react-contacts— green.bunx turbo test:coverage --filter=@suaveplan/react-contacts— 100%.bun scripts/publish.ts --package @suaveplan/react-contacts.- Archive change folder.