import 'dart:async'; import 'dart:convert'; import 'package:cathaypay_mobile/Numpad.dart'; import 'package:cathaypay_mobile/utils/utils.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:pin_code_fields/pin_code_fields.dart'; import '../api/api.dart'; import '../utils/color_custom.dart'; TextEditingController _textEditingController = TextEditingController(); class OtpPage extends StatefulWidget { const OtpPage({Key? key, required this.email, required this.phone}) : super(key: key); final String email; final String phone; @override State createState() => _OtpPageState(); } class _OtpPageState extends State { int _remainingSeconds = 900; // 15 minutes in seconds String _displayTime = '15:00'; Timer? timer; void _startTimer() { const oneSec = const Duration(seconds: 1); timer = Timer.periodic( oneSec, (timer) => setState(() { if (_remainingSeconds < 1) { timer.cancel(); } else { _remainingSeconds = _remainingSeconds - 1; _displayTime = _formatTime(_remainingSeconds); } }), ); } refreshTimer() { _textEditingController.text = ""; timer?.cancel(); _remainingSeconds = 900; // 15 minutes in seconds _displayTime = '15:00'; _startTimer(); } String _formatTime(int seconds) { int minutes = (seconds / 60).floor(); int remainingSeconds = seconds - (minutes * 60); String formattedMinutes = minutes < 10 ? '0$minutes' : '$minutes'; String formattedSeconds = remainingSeconds < 10 ? '0$remainingSeconds' : '$remainingSeconds'; return '$formattedMinutes:$formattedSeconds'; } TextEditingController pin = TextEditingController(); setValue(String val) { setState(() { _textEditingController.text += val; }); } backspace() { if (_textEditingController.text.length > 0) { setState(() { _textEditingController.text = _textEditingController.text.substring(0, _textEditingController.text.length - 1); }); } } @override void initState() { getOtp(); _startTimer(); super.initState(); } // String otp = ""; String refno = ""; String token = ""; String otpConfirm = ""; getOtp() async { var param = jsonEncode({"key": Api.API_KEY, "secret": Api.API_SECRET, "msisdn": widget.phone}); Api.getRaw(context, Api.otpEmail + widget.email).then((value) => { print(value), setState(() { otpConfirm = value.toString(); }) }); } verify(String otp) { if (otp == otpConfirm) { Navigator.pushNamed(context, '/PolicyPage'); } else { Utils.showAlertDialog(context, "รหัส OTP ไม่ถูกต้อง"); } // var param = jsonEncode({"key": Api.API_KEY, "secret": Api.API_SECRET, "token": token, "pin": otp}); // Api.postStatus(context, Api.verify, param).then((value) => { // print(value), // if (value != null) {Navigator.pushNamed(context, '/PolicyPage')} else {Utils.showAlertDialog(context, "รหัส OTP ไม่ถูกต้อง")} // }); } Widget build(BuildContext context) { return Scaffold( // extendBodyBehindAppBar: true, appBar: AppBar( backgroundColor: Colors.transparent, actions: [ CupertinoButton( onPressed: () { Navigator.pop(context); }, child: IconButton( onPressed: () { Navigator.of(context).pop(); }, icon: const Icon( Icons.clear, color: Colors.grey, ), ), ), ], elevation: 0, // title: Text( // "ยืนยันตัวตน", // textAlign: TextAlign.center, // style: GoogleFonts.kanit( // color: Colors.black, // fontSize: 20, // ), // ), ), body: SafeArea( child: Container( padding: EdgeInsets.all(10), child: Column(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "${"Please enter the OTP code.".tr()}\n${"The code will be sent to".tr()}${widget.email}\nRef:$refno", textAlign: TextAlign.center, style: GoogleFonts.kanit( color: Color(0xff65676b), fontSize: 18, fontWeight: FontWeight.w300, ), ), Expanded(child: PinCodeVerificationScreen()), InkWell( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "ขอรหัส OTP ใหม่อีกครั้ง", textAlign: TextAlign.center, style: GoogleFonts.kanit( color: Colors.blue, fontSize: 14, fontWeight: FontWeight.w300, ), ), SizedBox( width: 10, ), Icon( Icons.refresh, size: 20, color: Colors.blue, ) ], ), onTap: () { getOtp(); refreshTimer(); }, ), SizedBox( height: 10, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "within the specified time".tr(), textAlign: TextAlign.center, style: GoogleFonts.kanit( color: Color(0xff65676b), fontSize: 18, fontWeight: FontWeight.w300, ), ), SizedBox( width: 10, ), Text( _displayTime, textAlign: TextAlign.center, style: GoogleFonts.kanit( color: Color(0xffad022c), fontSize: 24, ), ) ], ), Container( // padding: EdgeInsets.symmetric(horizontal: 50.0), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ NumpadButton( text: '1', onPressed: () => setValue('1'), ), NumpadButton( text: '2', onPressed: () => setValue('2'), ), NumpadButton( text: '3', onPressed: () => setValue('3'), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ NumpadButton( text: '4', onPressed: () => setValue('4'), ), NumpadButton( text: '5', onPressed: () => setValue('5'), ), NumpadButton( text: '6', onPressed: () => setValue('6'), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ NumpadButton( text: '7', onPressed: () => setValue('7'), ), NumpadButton( text: '8', onPressed: () => setValue('8'), ), NumpadButton( text: '9', onPressed: () => setValue('9'), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ SizedBox( height: 90, width: 90, ), NumpadButton( text: '0', onPressed: () => setValue('0'), ), NumpadButton( haveBorder: false, icon: Icons.backspace, onPressed: () => backspace(), ), ], ) ], ), ), InkWell( onTap: () { verify(_textEditingController.text); }, child: SizedBox( width: 374, child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(40), ), child: Container( padding: EdgeInsets.all(10), child: Text( "Confirm".tr(), textAlign: TextAlign.center, style: GoogleFonts.kanit( color: ColorCustom.greyBorder, fontSize: 20, fontWeight: FontWeight.w500, ), ), ), ), ), ) ]), ), )); } } class PinCodeVerificationScreen extends StatefulWidget { final String? phoneNumber; const PinCodeVerificationScreen({ Key? key, this.phoneNumber, }) : super(key: key); @override _PinCodeVerificationScreenState createState() => _PinCodeVerificationScreenState(); } class _PinCodeVerificationScreenState extends State { // ..text = "123456"; // ignore: close_sinks // StreamController? errorController; bool hasError = false; String currentText = ""; final formKey = GlobalKey(); @override void initState() { // errorController = StreamController(); super.initState(); } @override void dispose() { // errorController!.close(); super.dispose(); } // snackBar Widget snackBar(String? message) { return ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message!), duration: const Duration(seconds: 2), ), ); } @override Widget build(BuildContext context) { return Scaffold( body: GestureDetector( onTap: () {}, child: SizedBox( height: 100, width: MediaQuery.of(context).size.width, child: Form( key: formKey, child: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30), child: PinCodeTextField( appContext: context, pastedTextStyle: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), length: 6, // obscureText: true, // obscuringCharacter: '-', // obscuringWidget: const FlutterLogo( // size: 24, // ), blinkWhenObscuring: true, animationType: AnimationType.fade, // validator: (v) { // if (v!.length < 3) { // return "I'm from validator"; // } else { // return null; // } // }, pinTheme: PinTheme( shape: PinCodeFieldShape.box, borderRadius: BorderRadius.circular(5), fieldHeight: 50, fieldWidth: 40, activeFillColor: Colors.black, inactiveColor: Colors.black, selectedColor: Colors.black, activeColor: Colors.black, selectedFillColor: Colors.black, inactiveFillColor: Colors.black, ), cursorColor: Colors.white, textStyle: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), animationDuration: const Duration(milliseconds: 300), enableActiveFill: true, autoDisposeControllers: false, // errorAnimationController: errorController, controller: _textEditingController, keyboardType: TextInputType.number, boxShadows: const [ BoxShadow( offset: Offset(0, 1), color: Colors.black12, blurRadius: 10, ) ], onCompleted: (v) { debugPrint("Completed"); }, // onTap: () { // print("Pressed"); // }, onChanged: (value) { debugPrint(value); setState(() { currentText = value; }); }, beforeTextPaste: (text) { debugPrint("Allowing to paste $text"); //if you return true then it will show the paste confirmation dialog. Otherwise if false, then nothing will happen. //but you can show anything you want here, like your pop up saying wrong paste format or etc return true; }, )), ), ), ), ); } }