OTP screen rewrite: 6 rounded boxes, auto-advance focus, auto-submit on the 6th digit, hardware-backspace on empty boxes (intercepted via Focus.onKeyEvent since TextField.onChanged doesn't fire on already-empty input), resend cooldown sourced from /api/shared/config/otp, and an inline error message under the boxes instead of a SnackBar. Several bugs fixed inline that surfaced during testing: - ref.listen inside build() accumulates listeners on every rebuild — the resend countdown's per-second setState was piling up duplicate listeners so one error triggered N callback fires. Moved to ref.listenManual in initState; subscription disposed in dispose(). - RouterNotifier was calling notifyListeners() on every auth state change including AsyncError, which rebuilt the Navigator/Scaffold mid-snackbar and visually duplicated the error toast. Now skips AsyncError and same-data-variant transitions. - ScaffoldMessenger.showSnackBar from a Riverpod listener callback could still render twice even with hideCurrentSnackBar — replaced with an inline error widget to sidestep the snackbar machinery entirely. - register_screen now uses context.go instead of context.push for the OTP route, so re-submitting the phone form doesn't stack multiple OtpScreen instances with active subscriptions. Lockout UX: AuthErrorInfo wraps the error message + code + retry_after_seconds parsed from the backend's structured error response. On rate-limit codes (OTP_COOLDOWN, OTP_RATE_LIMIT_PHONE, OTP_RATE_LIMIT_IP), the OTP screen extends "Kirim ulang kode" cooldown to match the server's wait, and the register screen disables "Kirim OTP" with a "Coba lagi dalam …" countdown. formatCountdown() in core/constants.dart renders Xd under 90 seconds and Xm Yd above (clearer than raw seconds for long lockouts). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
client_app
A new Flutter project.
Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
For help getting started with Flutter development, view the online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.