FL03: Validated Asynchronous Form
Field-level validation, preserved input, controlled async submission, failure retry, and duplicate flight locking
Naive Flutter form implementations frequently suffer from four critical production bugs: 1. **Lost User Input on Failure**: When an API returns a 500 or 504 Gateway Timeout, poorly architected controllers clear the form state or rebuild from scratch, wiping complex user inputs and causing immediate user churn. 2. **Duplicate Concurrent Submissions**: Without a single-flight locking guard, impatient users double-tapping or spamming the submit button trigger multiple simultaneous POST requests, resulting in duplicate account creation, double billing, or race conditions. 3. **Poor Accessibility & Focus Abandonment**: When client validation fails, failing to programmatically focus the first invalid field forces users to scroll and guess which input blocked submission. 4. **Post-Dispose Memory Leaks**: If a user hits submit and immediately navigates away, uncancelled async repository calls trigger `setState() called after dispose()` and leak network sockets.
The FL03 architecture solves these problems through a clean layered pattern: 1. **Pure Validation Rules (`FormValidationRules`)**: Independent, functional validation functions that return field-keyed error maps without side effects. 2. **Single-Flight Lock**: While submission is in-flight, rapid repeated taps are intercepted and recorded in `blockedDuplicateCount` without dispatching redundant network requests. 3. **Resilient Input Preservation**: If the network or server rejects the submission, all entered fields, passwords, and toggles remain intact in state. A high-contrast failure banner renders with an explicit "Retry Submission" action. 4. **First-Invalid-Field Focus Routing**: When validation fails, the controller inspects `FormFieldId.values` in visual reading order and immediately calls `requestFocus()` on the first offending field. 5. **Cooperative Cancellation (`CancellationToken`)**: Controller cancellation on `dispose()` aborts pending simulated network timers and prevents memory leaks or dangling state notifications.
- Single-Flight Lock: Tap "Create Workspace" multiple times rapidly. Notice the Blocked counter increment in the telemetry bar while only 1 submission attempt fires.
- Failure Recovery & Input Preservation: Toggle "504 Sim" in the telemetry bar and submit. The red error banner will appear with a "Retry Submission" action, and all your inputs remain completely preserved.
- First-Field Focus Routing: Submit an empty form; notice that client validation automatically requests focus on the first invalid field ("Full Name").
- Compact 320px Viewport: Click the "Compact 320px" preset above to confirm that inputs, error labels, and buttons wrap smoothly without overflow.