high priority medium complexity frontend pending frontend specialist Tier 3

Acceptance Criteria

Each AppTextField in EditContactScreen has an onChanged and onEditingComplete (blur) callback that runs the corresponding contact-form-validator function
Validation errors are displayed as plain-language text directly below the offending field within one frame of the triggering event
Error messages are resolved through the org-label system — no hardcoded strings in the widget
Save button is disabled whenever one or more fields have an active validation error
Save button re-enables as soon as all validation errors are cleared
Validation runs on change (live) AND on blur — first error shown on blur to avoid premature error display while typing
Clearing a field that was valid does not show an error until the user blurs the field
All error messages meet WCAG 2.2 AA contrast requirements and are announced by screen readers (Semantics with error role or equivalent)
Widget test: entering invalid email shows error message below email field; correcting it removes the error and re-enables save

Technical Requirements

frameworks
Flutter
Riverpod
BLoC
data models
ContactEditFormState
ValidationResult
performance requirements
Validation on each keystroke must complete synchronously — no debouncing needed for pure validators
UI must not jank during rapid typing — validators are O(1) regex checks
security requirements
Error messages must never expose raw exception messages or stack traces to the UI
Org-label keys must be resolved server-side or from a local bundle — not constructed by concatenating user input
ui components
AppTextField (errorText prop)
FieldErrorText
AppButton (disabled state)

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Implement a two-phase validation strategy: (1) 'touched' flag per field set on first blur, (2) error displayed only if field is touched OR a save attempt has been made. This prevents all fields showing errors immediately on screen load. Store validation state in ContactEditFormNotifier alongside field values — call notifier.setFieldValue(field, value) on change and notifier.touchField(field) on blur. The notifier computes isFormValid as a derived getter: true only when all touched fields (or all fields after save attempt) are valid.

Pass the computed error string (resolved from org-labels) directly to AppTextField's errorText parameter. For WCAG compliance, verify that AppTextField wraps errorText in a Semantics widget with error semantics — if not, wrap it manually.

Testing Requirements

Widget tests: (1) enter invalid email → assert error text visible below email field; (2) fix email → assert error text gone and save button enabled; (3) clear required name field → blur → assert 'required' error shown; (4) assert save button disabled when any error active; (5) assert error text uses org-label resolved string (inject mock org-label provider). Unit tests: ContactEditFormNotifier.validateField dispatches correct ValidationResult for each field type. All tests use mock contact-detail-service and mock org-label provider via Riverpod overrides.

Component
Edit Contact Screen
ui medium
Epic Risks (3)
medium impact medium prob scope

The encrypted-field-display confirmation dialog adds interaction steps that may frustrate coordinators who access sensitive fields frequently, leading to requests to bypass the flow or skip read-receipt logging, which would violate Blindeforbundet's compliance requirements.

Mitigation & Contingency

Mitigation: Design the confirmation dialog to be as minimal as possible (one clear sentence, single confirm action) and ensure it does not reappear for the same field within a single screen session. Validate the UX with Blindeforbundet coordinators during the TestFlight pilot before finalising.

Contingency: If coordinators raise strong objections, escalate to Blindeforbundet's data protection officer to determine whether a lighter confirmation pattern (e.g., biometric confirmation instead of dialog) satisfies their compliance obligation.

medium impact medium prob technical

The activity-history-list infinite scroll requires paginated Supabase queries. Contacts with hundreds of activities (e.g., an HLF peer mentor with 380 annual registrations) could cause slow page loads or memory pressure on older devices if pagination boundaries are set too large.

Mitigation & Contingency

Mitigation: Use a page size of 20 records with cursor-based pagination. Implement list item recycling using Flutter's ListView.builder. Benchmark memory usage with 400+ item simulation on a low-end test device before TestFlight release.

Contingency: If performance degrades on older devices, reduce page size to 10 and add a time-window filter (last 30 days, last 6 months, all) so the default view loads a manageable record count for most coordinators.

low impact high prob scope

The cognitive load rule engine (from the Cognitive Accessibility feature) mandates no more than 7 fields per screen section. If a contact model has more than 7 editable fields, the edit-contact-screen layout must be split into sections, adding complexity not accounted for in the initial scope.

Mitigation & Contingency

Mitigation: Audit the full contact field list from all four organisations before implementation. Group fields into logical sections (personal info, contact details, affiliation) so no single section exceeds 7 fields. Use the cognitive-load-rule-engine component if it is already delivered by the Cognitive Accessibility feature.

Contingency: If the rule-engine component is not yet available, implement a simple manual section layout with accordion-style expansion for less-frequently edited fields to stay within the 7-field guideline without blocking delivery.