import 'dart:async'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../../../common/theme/theme.dart'; import '../../../router/app_router.gr.dart'; @RoutePage() class OtpPage extends StatefulWidget { final String registrationToken; const OtpPage({super.key, required this.registrationToken}); @override State createState() => _OtpPageState(); } class _OtpPageState extends State { final List _controllers = List.generate( 6, (index) => TextEditingController(), ); final List _focusNodes = List.generate(6, (index) => FocusNode()); Timer? _timer; int _secondsRemaining = 18; bool _canResend = false; @override void initState() { super.initState(); _startTimer(); } void _startTimer() { _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (_secondsRemaining > 0) { setState(() { _secondsRemaining--; }); } else { setState(() { _canResend = true; }); _timer?.cancel(); } }); } void _resendCode() { setState(() { _secondsRemaining = 18; _canResend = false; }); _startTimer(); // Add your resend logic here } String _formatTime(int seconds) { int minutes = seconds ~/ 60; int remainingSeconds = seconds % 60; return '${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}'; } void _onCodeChanged(String value, int index) { if (value.isNotEmpty) { // Move to next field if (index < 5) { _focusNodes[index + 1].requestFocus(); } else { // Last field, unfocus _focusNodes[index].unfocus(); _verifyCode(); } } else { // Handle backspace - move to previous field if (index > 0) { _focusNodes[index - 1].requestFocus(); } } } void _verifyCode() { String code = _controllers.map((controller) => controller.text).join(); if (code.length == 6) { context.router.push(CreatePasswordRoute()); } } @override void dispose() { _timer?.cancel(); for (var controller in _controllers) { controller.dispose(); } for (var focusNode in _focusNodes) { focusNode.dispose(); } super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Verifikasi')), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 20), // Title Text( 'Masukan Kode Verifikasi', style: AppStyle.xl.copyWith( fontWeight: FontWeight.w600, color: AppColor.textPrimary, ), ), const SizedBox(height: 12), // Description RichText( text: TextSpan( children: [ TextSpan( text: 'Kami telah mengirimkan kode verifikasi melalui ', style: AppStyle.sm.copyWith( color: AppColor.textSecondary, height: 1.4, ), ), TextSpan( text: 'Whatsapp', style: AppStyle.sm.copyWith( color: AppColor.success, fontWeight: FontWeight.w500, height: 1.4, ), ), TextSpan( text: ' ke ', style: AppStyle.sm.copyWith( color: AppColor.textSecondary, height: 1.4, ), ), TextSpan( text: '+6288976680234', style: AppStyle.sm.copyWith( color: AppColor.textPrimary, fontWeight: FontWeight.w500, height: 1.4, ), ), ], ), ), const SizedBox(height: 6), // Hidden text fields for input Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(6, (index) { return Expanded( child: Padding( padding: EdgeInsets.only(right: index == 5 ? 0 : 8.0), child: TextFormField( controller: _controllers[index], focusNode: _focusNodes[index], keyboardType: TextInputType.number, maxLength: 1, inputFormatters: [FilteringTextInputFormatter.digitsOnly], decoration: InputDecoration(counterText: ''), textAlign: TextAlign.center, style: AppStyle.lg.copyWith( color: AppColor.primary, fontWeight: FontWeight.w600, ), cursorColor: AppColor.primary, onChanged: (value) { setState(() {}); _onCodeChanged(value, index); }, ), ), ); }), ), const SizedBox(height: 40), // Timer and Resend Section Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( 'Mohon tunggu untuk kirim ulang kode ', style: AppStyle.xs.copyWith(color: AppColor.textSecondary), ), Text( _formatTime(_secondsRemaining), style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, ), ), ], ), if (_canResend) ...[ const SizedBox(height: 12), Center( child: TextButton( onPressed: _resendCode, child: Text( 'Kirim Ulang Kode', style: AppStyle.sm.copyWith( color: AppColor.success, fontWeight: FontWeight.w500, ), ), ), ), ], const SizedBox(height: 24), ], ), ), ); } }