import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../core/theme/app_theme.dart'; const Color primaryBrown = Color(0xFF4A3C3C); /// Reusable 5-digit verification code input widget class VerificationCodeInput extends StatefulWidget { final List controllers; final bool isError; final VoidCallback? onErrorReset; final bool enabled; const VerificationCodeInput({ super.key, required this.controllers, this.isError = false, this.onErrorReset, this.enabled = true, }); @override State createState() => _VerificationCodeInputState(); /// Get the combined code from all controllers String get code => controllers.map((c) => c.text).join(); /// Check if all 5 digits are entered bool get isComplete => code.length == 5; } class _VerificationCodeInputState extends State { late List _focusNodes; @override void initState() { super.initState(); _focusNodes = List.generate(5, (index) => FocusNode()); } @override void dispose() { for (var node in _focusNodes) { node.dispose(); } super.dispose(); } @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate( 5, (index) => SizedBox( width: 50, height: 50, child: RawKeyboardListener( focusNode: FocusNode(), // Separate dummy node for listener onKey: (event) { // Handle backspace on empty field to move focus back if (event is RawKeyDownEvent && event.logicalKey == LogicalKeyboardKey.backspace) { if (widget.controllers[index].text.isEmpty && index > 0) { _focusNodes[index - 1].requestFocus(); } } }, child: TextField( controller: widget.controllers[index], focusNode: _focusNodes[index], textAlign: TextAlign.center, keyboardType: TextInputType.number, maxLength: 1, enabled: widget.enabled, style: const TextStyle( fontFamily: 'Poppins', fontSize: 18, fontWeight: FontWeight.bold, color: primaryBrown, ), decoration: InputDecoration( counterText: "", contentPadding: EdgeInsets.zero, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: widget.isError ? AppTheme.error : primaryBrown.withOpacity(0.3), ), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: widget.isError ? AppTheme.error : primaryBrown.withOpacity(0.3), ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: widget.isError ? AppTheme.error : primaryBrown, width: 2, ), ), disabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: primaryBrown.withOpacity(0.2)), ), ), onChanged: (val) { // Reset error state when user types if (widget.isError && widget.onErrorReset != null) { widget.onErrorReset!(); } if (val.isNotEmpty) { // Move to next field if current is filled if (index < 4) { _focusNodes[index + 1].requestFocus(); } else if (index == 4) { // Hide keyboard on last field if filled FocusScope.of(context).unfocus(); } } else { // Move to previous field if current is cleared if (index > 0) { _focusNodes[index - 1].requestFocus(); } } }, ), ), ), ), ); } /// Clear all controllers void clear() { for (var c in widget.controllers) { c.clear(); } // Return focus to first field after clearing if (_focusNodes.isNotEmpty) { _focusNodes[0].requestFocus(); } } }