Connect LoginForm to LoginFormBLoC event dispatch
epic-email-password-login-ui-task-005 — Bind LoginForm widget to LoginFormBLoC: dispatch EmailChanged and PasswordChanged events on text change, dispatch LoginSubmitted event on form submit. Listen to BLoC state stream to toggle submit button enabled/disabled state, show field errors from validation state, and propagate loading state to disable inputs during auth request.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Refactor LoginForm from the previous tasks to remove local validation state — all validation state now comes from LoginFormBLoC. Keep local FocusNodes and TextEditingControllers (owned by LoginForm's State). In initState, attach listeners to text controllers that dispatch BLoC events via context.read
Avoid a single top-level BlocBuilder that rebuilds the whole form. For the loading state, disable both text fields and replace the button label with a SizedBox containing a small CircularProgressIndicator. Ensure TextEditingController.dispose() is called in State.dispose() alongside FocusNode.dispose().
Testing Requirements
Write bloc_test and widget tests. Bloc tests: verify EmailChanged event updates email validation state, PasswordChanged updates password state, LoginSubmitted triggers auth call. Widget tests: mock LoginFormBLoC using mocktail or bloc_test's MockBloc; assert (1) text input triggers correct event dispatch, (2) state with isLoading=true disables fields and button, (3) state with emailError non-null shows error under email field, (4) state with isValid=false disables submit button, (5) state with isValid=true enables submit button. Use whenListen to emit state sequences in widget tests.
Automated accessibility checks (e.g., flutter_accessibility_service) may pass while manual VoiceOver/TalkBack testing reveals focus-order issues, missing semantic roles, or live region announcements that fire too early or not at all. Discovering these late risks delaying the MVP release.
Mitigation & Contingency
Mitigation: Conduct manual VoiceOver and TalkBack testing on physical devices at the end of every sprint, not only at release. Define accessibility acceptance criteria per component and include them in the DoD. Use Semantics widgets explicitly rather than relying on implicit semantics from Flutter's default widgets for all interactive elements.
Contingency: Maintain a prioritized accessibility bug backlog separate from the main backlog. If critical VoiceOver issues are found close to release, create an explicit accessibility hotfix sprint before TestFlight distribution to Blindeforbundet testers.
Keyboard height varies significantly between iOS and Android, between device sizes (iPhone SE vs iPad), and with third-party keyboards. The KeyboardAwareLayout may not correctly adjust scroll offset in all combinations, causing input fields to remain hidden behind the keyboard on certain device/keyboard configurations.
Mitigation & Contingency
Mitigation: Test on a matrix of devices including iPhone SE (small viewport), a mid-size Android phone, and a tablet. Implement the layout using MediaQuery.viewInsets.bottom rather than a fixed padding value to correctly respond to any keyboard height. Include edge cases for floating keyboards on iPads.
Contingency: If device-specific issues are found after release, implement a bottom-padding fallback using BottomPadding inset and allow users to manually scroll. Log affected device/OS combinations for targeted fixes.
If the design token system's colour palette is updated without re-running contrast validation, form field labels, error messages, or placeholder text could fall below the WCAG 2.2 AA 4.5:1 ratio, causing a compliance regression.
Mitigation & Contingency
Mitigation: Integrate a contrast ratio validator (e.g., a CI lint step using the contrast-ratio-validator component) that checks all colour pairs used in the login form on every pull request. Document which token pairs are used for labels, errors, and backgrounds in the login form.
Contingency: If a contrast regression is detected post-merge, hot-patch the affected design token value. Do not ship a TestFlight build with known WCAG AA failures to Blindeforbundet testers.