import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:lba/gen/assets.gen.dart'; import 'package:lba/screens/auth/cubit/auth_cubit.dart'; import 'package:lba/screens/auth/userInfo.dart'; import 'package:lba/widgets/button.dart'; import 'package:lba/widgets/remainingTime.dart'; class OTPVerification extends StatefulWidget { final String phoneNumber; const OTPVerification({super.key, required this.phoneNumber}); @override State createState() => _OTPVerificationState(); } class _OTPVerificationState extends State { final List _focusNodes = List.generate(5, (_) => FocusNode()); final List _controllers = List.generate(5, (_) => TextEditingController()); late RemainingTime _otpTimer; @override void initState() { super.initState(); _otpTimer = RemainingTime(); _initializeTimer(); } void _initializeTimer() { final authCubit = context.read(); _otpTimer.initializeFromExpiry(expiryTime: authCubit.timeDue); } void _resendOTP() { if (_otpTimer.canResend.value) { context.read().sendOTP(widget.phoneNumber); _otpTimer.remainingSeconds.value = 60; _otpTimer.startTimer(); } } @override void dispose() { for (final node in _focusNodes) { node.dispose(); } for (final controller in _controllers) { controller.dispose(); } _otpTimer.dispose(); super.dispose(); } Widget _buildOTPFields() { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(5, (index) { return SizedBox( width: 60, child: TextField( controller: _controllers[index], focusNode: _focusNodes[index], keyboardType: TextInputType.number, textAlign: TextAlign.center, maxLength: 1, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), decoration: InputDecoration( counterText: '', hintText: "0", enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: Colors.grey), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide( color: Color.fromARGB(255, 14, 63, 102)), ), ), onChanged: (value) { if (value.length == 1 && index < 4) { FocusScope.of(context).requestFocus(_focusNodes[index + 1]); } }, ), ); }), ); } @override Widget build(BuildContext context) { // ignore: unused_local_variable final width = MediaQuery.of(context).size.width; 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), const Text( "Enter the verification code we just sent to your device.", style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500), ), const SizedBox(height: 25), _buildOTPFields(), SizedBox(height: height / 7), SizedBox( width: double.infinity, height: 48, child: Button( text: "Verify", onPressed: () { final otpCode = _controllers.map((c) => c.text).join(); if (otpCode.length == 5) { context.read().verifyOTP(otpCode); Navigator.push( context, MaterialPageRoute( builder: (context) => const UserInfo())); } }, color: const Color.fromARGB(255, 30, 137, 221), ), ), SizedBox(height: height / 25), Center( child: Column( children: [ Row( children: [ const Expanded( child: Divider(thickness: 1, color: Colors.grey), ), ValueListenableBuilder( valueListenable: _otpTimer.remainingSeconds, builder: (context, seconds, _) { return Padding( padding: const EdgeInsets.symmetric( horizontal: 8.0), child: Text( "Resend OTP in ${_otpTimer.formatTime()}", style: const TextStyle( fontWeight: FontWeight.w500, fontSize: 18), ), ); }, ), const Expanded( child: Divider(thickness: 1, color: Colors.grey), ), ], ), const SizedBox(height: 8), ValueListenableBuilder( valueListenable: _otpTimer.canResend, builder: (context, canResend, _) { return GestureDetector( onTap: canResend ? _resendOTP : null, child: Text( "Resend OTP", style: TextStyle( fontSize: 16, color: canResend ? const Color.fromARGB(255, 0, 0, 0) : Colors.grey, ), ), ); }, ), ], ), ), ], ), ), ], ), ), ), ); } }