Implement Contact Form Validator
epic-contact-detail-and-edit-main-screen-task-003 — Create the infrastructure-layer contact form validator that enforces business rules for contact data: required field checks, format validation for Norwegian personnummer, phone numbers, and email addresses. Expose a reusable validation API consumed by both the edit service and the edit screen's inline error display.
Acceptance Criteria
Technical Requirements
Implementation Notes
Implement as a stateless class ContactFormValidator with a single public validate() method. Keep each field rule in a private named method (e.g., _validatePersonnummer, _validatePhone) for readability and independent testability. For personnummer: extract birth digits and control digits, apply the two Modulus 11 weight sequences per the Norwegian Tax Authority specification, and handle the edge case where check digit 10 is invalid (no valid number exists). Do not use third-party validation packages — the logic is simple enough and adding a package creates a maintenance dependency.
Return a Map
Testing Requirements
Pure unit tests with flutter_test (no widget tests needed). Cover: valid personnummer (Modulus 11 passes), invalid personnummer (wrong check digit), personnummer with invalid birth date, valid Norwegian mobile number, number with +47 prefix, 7-digit number (too short), valid email, email missing @, email missing domain, all required fields empty, partial required fields, full valid form returns isValid true. Target 100% branch coverage — this is a pure logic class with no I/O.
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.