feat(client): page-level edit toggle on Profile (per design package) #266
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!266
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "profile-page-level-edit"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Scope
Refactor Carol's Profile screen to match the design package's pattern: a single page-level Edit / Cancel / Done control in the header that flips every card on the page (Picture, Basics, Contact details) between view and edit mode together.
Mirrors
/var/home/wynnj/projects/carol-design/design_files/ProfileScreen.jsx:PageHeadrenders title + lede on the left with an Edit (secondary, pencil-leading) button on the right that becomes Cancel (ghost) + Done (primary) when editing; cards are stateless w.r.t. that flag and render view/edit UI from props.Per-surface narrative
PageHeader(new). Replaces the standalone header<View>. Renders title + lede + the edit control. Edit shows the LucidePencilicon next to the label; Done shows "Saving…" while the batched basics PUT is in flight. Cancel is disabled while committing so a half-committed state can't get cancelled.PictureCard. View mode: avatar + name + "Used on your profile and when you chat with me." hint. Edit mode: avatar + Upload + Remove buttons + the upload hint. The card-level inline remove-confirm is gone — picture ops are atomic, the page-level toggle is the gate. The error banner stays.BasicsCard. No card-level Edit button.forwardRefexposescommit()/revert()so the page's Done flushes a single PUT for name + title statement + brief and Cancel re-seeds inputs from server state.commit()is a no-op when nothing changed.ContactsCard. Each row in view mode is just badge + value + label, no action buttons. In edit mode each row picks up LucidePencil+Trash2icon buttons; pencil expands the existing inline edit form (per-row Save / Cancel + Enter chain preserved), trash deletes immediately. The Add inline form moves to the bottom of the list and renders only when the page is in edit mode.profile.edit.{edit,cancel,done,saving,editAria,cancelAria,doneAria}keys pluscontacts.{editRowAria,removeRowAria}for the per-row icon buttons.Decisions worth flagging
EditableHandleimperative API. Picture upload/remove and Contact CRUD remain immediate mutations behind the page-level toggle — batching them would have meant inverting their existing per-op state machines for no user-visible win.<IconButton>are<Pressable>wrappers around the Lucide icon component (32×32 tap target, 16px icon at 1.75 stroke).hitSlop={6}cushions touch on Android.Trash2) plus theaccessibilityLabelare now the only affordance.Plain-object styles
Every
<View>,<Text>,<Pressable>,<Image>, and<TextInput>on the touched code paths hands off a{ ...style, ...overrides }plain object — no nestedstyle={[a, b]}arrays — per #239 and the runtime crash documented in #232's PR body.Test plan
pnpm install --frozen-lockfilepnpm -F @carol/api typecheck/lint/test— unchanged surfacepnpm -F @carol/api-client typecheck/lint/test/checkpnpm -F @carol/client typecheck/lint/testpnpm -F @carol/client export:web/profile, click Edit, edit a name, click Done; observe single PUT lands and screen returns to view mode.🤖 Generated with Claude Code
📊 Test coverage
Patch coverage: no testable lines changed.
Overall (
app/,lib/,db/, excluding UI per ADR-0019):Soft thresholds per ADR-0019. Coverage is informational and does not block merge.