import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:lba/res/colors.dart'; import 'package:lba/screens/auth/bloc/auth_bloc.dart'; import 'package:lba/widgets/app_snackbar.dart'; import '../../gen/assets.gen.dart'; import '../../widgets/button.dart'; import 'user_info_page.dart'; class OTPVerificationPage extends StatefulWidget { final String phoneNumber; final String timeDue; const OTPVerificationPage({ super.key, required this.phoneNumber, required this.timeDue, }); @override State createState() => _OTPVerificationPageState(); } class _OTPVerificationPageState extends State { final List _focusNodes = List.generate(6, (_) => FocusNode()); final List _controllers = List.generate(6, (_) => TextEditingController()); @override void dispose() { for (final node in _focusNodes) { node.dispose(); } for (final controller in _controllers) { controller.dispose(); } super.dispose(); } Widget _buildOTPFields() { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: List.generate(6, (index) { return SizedBox( width: 50, child: TextField( controller: _controllers[index], focusNode: _focusNodes[index], keyboardType: TextInputType.number, textAlign: TextAlign.center, maxLength: 1, decoration: InputDecoration( counterText: '', hintText: "0", enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: AppColors.greyBorder), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: AppColors.borderPrimary), ), ), onChanged: (value) { if (value.length == 1 && index < 5) { FocusScope.of(context).requestFocus(_focusNodes[index + 1]); } if (value.isEmpty && index > 0) { FocusScope.of(context).requestFocus(_focusNodes[index - 1]); } }, ), ); }), ); } @override Widget build(BuildContext context) { final height = MediaQuery.of(context).size.height; return Scaffold( body: SafeArea( child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ IconButton( icon: SvgPicture.asset(Assets.icons.back.path), onPressed: () => Navigator.pop(context), ), ], ), Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Padding( padding: const EdgeInsets.only(top: 0), child: SvgPicture.asset(Assets.images.logo.path, height: height / 5.2), ), ), SizedBox(height: height / 20), const Text("OTP Verification", style: TextStyle(fontSize: 33, fontWeight: FontWeight.bold)), const SizedBox(height: 8), Text( "Enter the 6-digit verification code sent to your device.", style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w500), ), const SizedBox(height: 25), _buildOTPFields(), SizedBox(height: height / 7), BlocConsumer( listener: (context, state) { if (state is OTPVerified) { Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => const UserInfoPage()), (route) => false, ); } if (state is AuthError) { AppSnackBar.showError( context: context, message: state.message, duration: const Duration(seconds: 3), ); } }, builder: (context, state) { if (state is AuthLoading) { return const Center(child: CircularProgressIndicator()); } return SizedBox( width: double.infinity, height: 48, child: Button( text: "Verify", onPressed: () { final otpCode = _controllers.map((c) => c.text).join(); if (otpCode.length == 6) { context.read().add(VerifyOTPEvent( otpCode: otpCode, phoneNumber: widget.phoneNumber, )); } else { AppSnackBar.showWarning( context: context, message: 'Please enter the complete 6-digit OTP code', ); } }, color: AppColors.buttonPrimary, ), ); }, ), SizedBox(height: height / 25), Center( child: InkWell( onTap: () { context.read().add(SendOTPEvent(phoneNumber: widget.phoneNumber)); AppSnackBar.showInfo(context: context, message: "A new code has been sent."); }, child: Text( "Resend Code", style: TextStyle( fontSize: 16, color: AppColors.primary, fontWeight: FontWeight.bold, ), ), ), ), ], ), ), ], ), ), ), ); } }