Assemble Contact Detail Screen
epic-contact-detail-and-edit-main-screen-task-013 — Implement the top-level contact-detail-screen that composes all previously built components into a single cohesive profile view. Renders profile header (name, role badge, org metadata), embeds assignment-status-indicator for Blindeforbundet, lays out multi-chapter-affiliation-chip for NHF contacts (up to 5 chapters), places encrypted-field-display widgets for sensitive fields, includes activity-history-list, and conditionally surfaces a Peer Mentor Profile tab/button for contacts with the peer mentor role navigating to peer-mentor-detail-screen-widget. Edit button in header is shown only to coordinators and admins via permission-checker. Handles GoRouter route contact/:id, meets 500ms open target, and passes full VoiceOver/TalkBack traversal with meaningful announcements for every element per WCAG 2.2 AA.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Use a `StreamProvider` (Riverpod) that wraps `contact-detail-service.watchContact(id)` to reactively drive the screen. The screen widget is a `ConsumerWidget` that maps the `AsyncValue
Organisation-specific sections (`AssignmentStatusIndicator`, `MultiChapterAffiliationChip`, encrypted fields) should be conditionally rendered based on `contact.organisationType` and `contact.roles` — centralise this logic in a `ContactDetailSectionResolver` helper to keep the screen widget clean. For accessibility traversal, wrap the profile header, each section, and the activity list in `MergeSemantics` or explicit `Semantics` nodes with `sortKey` to enforce VoiceOver reading order independent of widget tree order.
Testing Requirements
Widget tests (flutter_test): (1) render with NHF coordinator contact — verify header, chapter chips, activity list, no encrypted fields, no assignment indicator; (2) render with Blindeforbundet contact — verify encrypted field widgets present, assignment indicator visible, no chapter chips; (3) render with peer mentor contact — verify peer mentor button/tab is present; (4) render with non-peer-mentor — verify peer mentor button absent; (5) render as read-only role — verify edit button absent; (6) render as coordinator — verify edit button present and tappable; (7) loading state — verify skeleton renders; (8) error state — verify retry button; (9) contact not found — verify 404 state. Integration test: navigate via GoRouter to `contact/:id` with a mock route parameter and verify correct contact is loaded. Accessibility: full `SemanticsHandle` traversal test — verify all interactive elements have labels and traversal order. Performance: measure frame build time for initial render using `WidgetTester.pump()` timing.
Target ≥85% widget test coverage.
The Peer Mentor Profile tab on the contact detail screen depends on the peer-mentor-detail-screen-widget being delivered by the separate Peer Mentor Detail feature. If that feature is delayed, the navigation affordance will be present but lead to a stub screen, which may confuse coordinators in the TestFlight pilot.
Mitigation & Contingency
Mitigation: Implement the peer mentor tab with a feature flag guard. When the Peer Mentor Detail feature is incomplete, the flag disables the tab. Coordinate delivery timelines with the team responsible for Peer Mentor Detail to align TestFlight releases.
Contingency: If the Peer Mentor Detail feature is significantly delayed, ship the contact detail screen without the peer mentor tab in the first TestFlight build and add it as an incremental update once the dependent screen is ready.
The contact detail screen must adapt its layout significantly based on organisation context: NHF shows affiliation chips, Blindeforbundet shows encrypted fields and assignment status, standard contacts show neither. Managing this conditional rendering without introducing bugs in each variant is complex and increases the risk of organisation-specific regressions.
Mitigation & Contingency
Mitigation: Define a ContactDetailViewModel that resolves all org-specific flags (showEncryptedFields, showAssignmentStatus, showMultiChapterChips) from the organisation config before the widget tree renders. Widget tests must cover all three organisation variants as separate test cases to catch regressions.
Contingency: If conditional rendering logic grows unwieldy, refactor into separate composable section widgets (ProfileHeaderSection, AffiliationSection, EncryptedFieldsSection) that are conditionally included by the parent screen, isolating org-specific logic to individual components.