import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/auth/auth_notifier.dart'; class OtpScreen extends ConsumerStatefulWidget { final String phone; const OtpScreen({super.key, required this.phone}); @override ConsumerState createState() => _OtpScreenState(); } class _OtpScreenState extends ConsumerState { final List _controllers = List.generate(6, (_) => TextEditingController()); final List _focusNodes = List.generate(6, (_) => FocusNode()); String? _verificationId; @override void initState() { super.initState(); final data = ref.read(mitraAuthProvider).valueOrNull; if (data is MitraAuthOtpSentData) { _verificationId = data.verificationId; } } @override void dispose() { for (final c in _controllers) { c.dispose(); } for (final f in _focusNodes) { f.dispose(); } super.dispose(); } String get _otp => _controllers.map((c) => c.text).join(); void _onChanged(int index, String value) { if (value.length == 1 && index < 5) { _focusNodes[index + 1].requestFocus(); } if (_otp.length == 6) { _submit(); } } void _onKeyDown(int index, KeyEvent event) { if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.backspace && _controllers[index].text.isEmpty && index > 0) { _controllers[index - 1].clear(); _focusNodes[index - 1].requestFocus(); } } void _submit() { final otp = _otp; if (otp.length != 6 || _verificationId == null) return; ref.read(mitraAuthProvider.notifier).verifyOtp(_verificationId!, otp); } @override Widget build(BuildContext context) { final authState = ref.watch(mitraAuthProvider); final isLoading = authState is AsyncLoading; // Update verification ID if state changes final data = authState.valueOrNull; if (data is MitraAuthOtpSentData) { _verificationId = data.verificationId; } ref.listen(mitraAuthProvider, (prev, next) { if (next is AsyncError) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(next.error.toString()))); for (final c in _controllers) { c.clear(); } _focusNodes[0].requestFocus(); } }); return Scaffold( appBar: AppBar(title: const Text('Masukkan OTP')), body: Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( 'Kode OTP telah dikirim ke ${widget.phone}', textAlign: TextAlign.center, ), const SizedBox(height: 32), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(6, (index) { return SizedBox( width: 48, child: KeyboardListener( focusNode: FocusNode(), onKeyEvent: (event) => _onKeyDown(index, event), child: TextField( controller: _controllers[index], focusNode: _focusNodes[index], textAlign: TextAlign.center, keyboardType: TextInputType.number, maxLength: 1, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), decoration: const InputDecoration( counterText: '', border: OutlineInputBorder(), contentPadding: EdgeInsets.symmetric(vertical: 14), ), inputFormatters: [ FilteringTextInputFormatter.digitsOnly, ], onChanged: (value) => _onChanged(index, value), ), ), ); }), ), const SizedBox(height: 32), ElevatedButton( onPressed: isLoading ? null : _submit, child: isLoading ? const CircularProgressIndicator() : const Text('Verifikasi'), ), ], ), ), ); } }