import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_otp_text_field/flutter_otp_text_field.dart'; import 'package:injector/injector.dart'; import 'package:intl_phone_field/intl_phone_field.dart'; import 'package:prosappco/blocs/auth_bloc/auth_bloc.dart'; import 'package:prosappco/blocs/authentication_bloc/authentication_bloc.dart'; import 'package:prosappco/components/general_primary_button.dart'; class PhoneVerifyRequiredScreen extends StatefulWidget { final String? phone; const PhoneVerifyRequiredScreen({super.key, this.phone}); @override State createState() => _PhoneVerifyRequiredScreenState(); } class _PhoneVerifyRequiredScreenState extends State { late final AuthBloc authBloc; String? _phone; String _otpCode = ''; bool _codeSent = false; int _resendSeconds = 0; Timer? _timer; @override void initState() { super.initState(); authBloc = Injector.appInstance.get(); _phone = widget.phone; } @override void dispose() { _timer?.cancel(); super.dispose(); } void _startResendTimer() { setState(() => _resendSeconds = 60); _timer = Timer.periodic(const Duration(seconds: 1), (t) { if (_resendSeconds == 0) { t.cancel(); } else { setState(() => _resendSeconds--); } }); } void _sendCode() { final phone = _phone; if (phone == null || phone.isEmpty) return; authBloc.add(AuthEventLoginOAuth(phone: phone)); setState(() => _codeSent = true); _startResendTimer(); } @override Widget build(BuildContext context) { return BlocProvider( create: (_) => authBloc, child: BlocConsumer( listener: (context, state) { if (state is AuthStateSuccess) { context.read().add( AuthenticationUserChanged(null), ); } else if (state is AuthStateVerifyOAuth && state.isWrongCode) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Código incorrecto, intenta de nuevo')), ); } }, builder: (context, state) { return Scaffold( body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0xFF42A4EF), Color(0xFF1565C0)], ), ), child: SafeArea( child: Column( children: [ const SizedBox(height: 40), Image.asset('images/logo_prosapp.png', width: 160), const SizedBox(height: 12), const Text( 'Verificación requerida', style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold), ), const SizedBox(height: 4), const Text( 'Verifica tu número para continuar', style: TextStyle(color: Colors.white70, fontSize: 14), ), const SizedBox(height: 30), Expanded( child: Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(32)), ), padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 32), child: SingleChildScrollView( child: _codeSent ? _buildOtpSection(state) : _buildPhoneSection(), ), ), ), ], ), ), ), ); }, ), ); } Widget _buildPhoneSection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Número de celular', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16)), const SizedBox(height: 4), const Text('Ingresa tu número para recibir el código de verificación', style: TextStyle(color: Colors.grey, fontSize: 13)), const SizedBox(height: 20), IntlPhoneField( initialCountryCode: 'CO', initialValue: _phone?.replaceAll('+57', '').replaceAll('+', ''), keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], onChanged: (phone) => _phone = phone.completeNumber, decoration: InputDecoration( hintText: 'Número de celular', border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), ), ), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _sendCode, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF42A4EF), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), child: const Text('Enviar código', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)), ), ), const SizedBox(height: 16), Center( child: TextButton( onPressed: () => context.read().add(AuthenticationLogoutRequested()), child: const Text('Cerrar sesión', style: TextStyle(color: Colors.grey)), ), ), ], ); } Widget _buildOtpSection(AuthState state) { return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const Text('Ingresa el código', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 18)), const SizedBox(height: 8), Text( 'Enviamos un código de 6 dígitos a\n${_phone ?? ''}', textAlign: TextAlign.center, style: const TextStyle(color: Colors.grey, fontSize: 13), ), const SizedBox(height: 28), OtpTextField( numberOfFields: 6, borderColor: const Color(0xFF42A4EF), focusedBorderColor: const Color(0xFF1565C0), showFieldAsBox: true, fieldWidth: 44, borderRadius: BorderRadius.circular(10), onCodeChanged: (code) => _otpCode = code, onSubmit: (code) => authBloc.add(AuthEventVerifyOAuth(code: code)), ), const SizedBox(height: 28), if (state is AuthStateProcess) const CircularProgressIndicator() else SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { if (_otpCode.length == 6) { authBloc.add(AuthEventVerifyOAuth(code: _otpCode)); } }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF42A4EF), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), child: const Text('Verificar', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)), ), ), const SizedBox(height: 20), _resendSeconds > 0 ? Text('Reenviar código en $_resendSeconds s', style: const TextStyle(color: Colors.grey)) : TextButton( onPressed: _sendCode, child: const Text('Reenviar código', style: TextStyle(color: Color(0xFF42A4EF))), ), const SizedBox(height: 8), TextButton( onPressed: () => setState(() { _codeSent = false; _otpCode = ''; }), child: const Text('Cambiar número', style: TextStyle(color: Colors.grey)), ), ], ); } }