import 'dart:math';
import 'package:flutter/[Link]';
import 'package:flutter/[Link]';
import 'package:flutter/[Link]';
import 'package:flutter/[Link]';
import 'package:hexcolor/[Link]';
import 'package:my_tasklist/views/reset_password.dart';
import
'package:page_animation_transition/animations/right_to_left_faded_transition.dart';
import 'package:page_animation_transition/page_animation_transition.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/my_button_styles.dart';
import '../models/my_text_styles.dart';
class OtpPage extends StatefulWidget {
const OtpPage({[Link]});
@override
State<OtpPage> createState() => _OtpPageState();
}
class _OtpPageState extends State<OtpPage> {
//
// Controllers
final TextEditingController _firstController = TextEditingController();
final TextEditingController _secondController = TextEditingController();
final TextEditingController _thirdController = TextEditingController();
final TextEditingController _fourthController = TextEditingController();
final TextEditingController _fifthController = TextEditingController();
// Errors
String? _firstFieldError,
_secondFieldError,
_thirdFieldError,
_fourthFieldError,
_fifthFieldError;
// FocusNode
final FocusNode _firstField = FocusNode();
final FocusNode _secondField = FocusNode();
final FocusNode _thirdField = FocusNode();
final FocusNode _fourthField = FocusNode();
final FocusNode _fifthField = FocusNode();
// Strings
String firstDigit = "",
secondDigit = "",
thirdDigit = "",
fourthDigit = "",
fifthDigit = "";
// int
int codeGenerated = 0;
// Form's key
final _formKey = GlobalKey<FormState>();
//String
String email = "";
// Get email
Future getEmail() async {
final prefs = await [Link]();
email = [Link]("email") ?? "example...@[Link]";
}
// Send code
void sendCode() {
// Generate a code
setState(() {
Random random = Random();
codeGenerated = 10000 + [Link](99999);
// Send this code generated by email
// debug
if (kDebugMode) {
return print("===> This the code generated : $codeGenerated <===");
}
});
}
// Verify code
void verifyCode() {
int codeTapped = 0;
setState(() {
// Check if the fields aren't empty
if ([Link] &&
[Link] &&
[Link] &&
[Link] &&
[Link]) {
// Enable errors
_firstFieldError = "";
_secondFieldError = "";
_thirdFieldError = "";
_fourthFieldError = "";
_fifthFieldError = "";
} else {
// Check each field to how which one is empty
if ([Link]) {
if ([Link]) {
if ([Link]) {
if ([Link]) {
if ([Link]) {
// Unable errors
_firstFieldError = null;
_secondFieldError = null;
_thirdFieldError = null;
_fourthFieldError = null;
_fifthFieldError = null;
// Get code tapped
codeTapped = [Link](firstDigit +
secondDigit +
thirdDigit +
fourthDigit +
fifthDigit);
// Compare the number tapped and code generated
if (codeTapped == codeGenerated) {
// Go to the reset password page
[Link](context).pushReplacement(
PageAnimationTransition(
page: const ResetPassword(),
pageAnimationType: RightToLeftFadedTransition()));
} else {
// Enable errors
_firstFieldError = "";
_secondFieldError = "";
_thirdFieldError = "";
_fourthFieldError = "";
_fifthFieldError = "";
// Show a error message through a snackbar
[Link](context).showSnackBar(SnackBar(
content: Text(
"Sorry ! the number tapped is incorrect.",
style: [Link](
color: [Link],
fontSize: 14,
fontWeight: [Link]),
),
duration: const Duration(seconds: 2),
backgroundColor: [Link][900],
dismissDirection: [Link],
));
}
} else {
// Enable error 5
_fifthFieldError = "";
}
} else {
// Enable error 4
_fourthFieldError = "";
}
} else {
// Enable error 3
_thirdFieldError = "";
}
} else {
// Enable error 2
_secondFieldError = "";
}
} else {
// Enable error 1
_firstFieldError = "";
}
}
});
}
@override
void initState() {
[Link]();
// Get email's user
getEmail();
}
@override
void dispose() {
[Link]();
// Dispose controllers
// that means empty the fields memory
_firstController.dispose();
_secondController.dispose();
_thirdController.dispose();
_fourthController.dispose();
_fifthController.dispose();
// Dispose Focus
_firstField.dispose();
_secondField.dispose();
_thirdField.dispose();
_fourthField.dispose();
_fifthField.dispose();
}
//
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: [Link],
extendBody: true,
body: GestureDetector(
// Disable the focus of all the fields
onTap: () => [Link](context).unfocus(),
//
child: SafeArea(
minimum:
const [Link](left: 30, top: 50, right: 30, bottom: 20),
child: SingleChildScrollView(
child: Column(
children: [
//
// Back IconButton
Row(
children: [
CircleAvatar(
backgroundColor: [Link][300],
foregroundColor: [Link],
radius: 23,
child: IconButton(
onPressed: () => [Link](context).pop(),
icon: const Icon(
Icons.arrow_back_ios_new_rounded,
color: [Link],
size: 20,
),
),
),
],
),
//
// Space
const SizedBox(
height: 30,
),
// Forgot Password Page
Align(
alignment: [Link],
child: Text(
"Check your email",
style: [Link](
color: [Link],
fontSize: 25,
),
),
),
//
// Subtitle
Padding(
padding: const [Link](top: 10),
child: Align(
alignment: [Link],
child: [Link](
TextSpan(
text: "We send a reset link to ",
style: [Link](
fontSize: 13, fontWeight: [Link]),
children: [
TextSpan(
text: email,
style: [Link](
color: [Link],
fontSize: 13,
fontWeight: [Link])),
TextSpan(
text:
" enter 5 digit code that mentioned in the email.
",
style: [Link](
fontSize: 13, fontWeight: [Link]),
),
TextSpan(
text: "This the code : $codeGenerated",
style: [Link](
fontWeight: [Link],
fontSize: 13,
color: HexColor("#2EE78A")))
],
),
),
),
),
//
// Space
const SizedBox(
height: 50,
),
//
// Form
Form(
key: _formKey,
// Row of field
child: SingleChildScrollView(
scrollDirection: [Link],
child: Row(
mainAxisAlignment: [Link],
children: [
//
// field 1
Padding(
padding: const [Link](5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _firstController,
focusNode: _firstField,
style: [Link](
color: HexColor("#253036"),
fontWeight: [Link],
fontSize: 20),
textAlign: [Link],
decoration: InputDecoration(
hintText: "1",
hintStyle: [Link](
fontSize: 20,
fontWeight: [Link],
),
errorText: _firstFieldError,
errorStyle: [Link],
errorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: [Link](15),
// borderSide: const BorderSide(
// color: [Link],
// width: 3,
// ),
// ),
),
keyboardType: [Link],
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
[Link],
],
onChanged: (value) => setState(() {
// check if value isn't empty
if ([Link] == 1) {
//
firstDigit = value;
// if value isn't empty, focus the next field
[Link](context).nextFocus();
} else {
// if value is empty, focus the previous field
[Link](context).previousFocus();
}
}),
),
),
),
//
// Field 2
Padding(
padding: const [Link](5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _secondController,
focusNode: _secondField,
style: [Link](
color: HexColor("#253036"),
fontWeight: [Link],
fontSize: 20),
textAlign: [Link],
decoration: InputDecoration(
hintText: "2",
hintStyle: [Link](
fontSize: 20,
fontWeight: [Link],
),
errorText: _secondFieldError,
errorStyle: [Link],
errorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: [Link](15),
// borderSide: const BorderSide(
// color: [Link],
// width: 3,
// ),
// ),
),
keyboardType: [Link],
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
[Link],
],
onChanged: (value) => setState(() {
// check if value isn't empty
if ([Link]() != "" ||
[Link]().isNotEmpty) {
//
secondDigit = value;
// if value isn't empty, focus the next field
[Link](context).nextFocus();
} else {
// if value is empty, focus the previous field
[Link](context).previousFocus();
}
}),
),
),
),
//
// Field 3
Padding(
padding: const [Link](5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _thirdController,
focusNode: _thirdField,
style: [Link](
color: HexColor("#253036"),
fontWeight: [Link],
fontSize: 20),
textAlign: [Link],
decoration: InputDecoration(
hintText: "3",
hintStyle: [Link](
fontSize: 20,
fontWeight: [Link],
),
errorText: _thirdFieldError,
errorStyle: [Link],
errorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: [Link](15),
// borderSide: const BorderSide(
// color: [Link],
// width: 3,
// ),
// ),
),
keyboardType: [Link],
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
[Link],
],
onChanged: (value) => setState(() {
// check if value isn't empty
if ([Link]() != "" ||
[Link]().isNotEmpty) {
//
thirdDigit = value;
// if value isn't empty, focus the next field
[Link](context).nextFocus();
} else {
// if value is empty, focus the previous field
[Link](context).previousFocus();
}
}),
),
),
),
//
// Field 4
Padding(
padding: const [Link](5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _fourthController,
focusNode: _fourthField,
style: [Link](
color: HexColor("#253036"),
fontWeight: [Link],
fontSize: 20),
textAlign: [Link],
decoration: InputDecoration(
hintText: "4",
hintStyle: [Link](
fontSize: 20,
fontWeight: [Link],
),
errorText: _fourthFieldError,
errorStyle: [Link],
errorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: [Link](15),
// borderSide: const BorderSide(
// color: [Link],
// width: 3,
// ),
// ),
),
keyboardType: [Link],
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
[Link],
],
onChanged: (value) => setState(() {
// check if value isn't empty
if ([Link]() != "" ||
[Link]().isNotEmpty) {
//
fourthDigit = value;
// if value isn't empty, focus the next field
[Link](context).nextFocus();
} else {
// if value is empty, focus the previous field
[Link](context).previousFocus();
}
}),
),
),
),
//
// Field 5
Padding(
padding: const [Link](5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _fifthController,
focusNode: _fifthField,
style: [Link](
color: HexColor("#253036"),
fontWeight: [Link],
fontSize: 20),
textAlign: [Link],
decoration: InputDecoration(
hintText: "5",
hintStyle: [Link](
fontSize: 20,
fontWeight: [Link],
),
errorText: _fifthFieldError,
errorStyle: [Link],
errorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: const BorderSide(
color: [Link],
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: [Link](0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: [Link](15),
// borderSide: const BorderSide(
// color: [Link],
// width: 3,
// ),
// ),
),
keyboardType: [Link],
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
[Link],
],
onChanged: (value) => setState(() {
// check if value isn't empty
if ([Link]() != "" ||
[Link]().isNotEmpty) {
//
fifthDigit = value;
// if value isn't empty, unfocus
[Link](context).unfocus();
} else {
// if value is empty, focus this field
[Link](context).requestFocus();
}
}),
),
),
),
//
//
],
),
),
),
//
// Reset Password Button
Padding(
padding: const [Link](top: 50),
child: ElevatedButton(
onPressed: () => verifyCode(),
style: [Link](
minimumSize: const WidgetStatePropertyAll(
Size([Link], 50)),
),
child: Text(
"Verify Code",
style: [Link](
color: [Link], fontWeight: [Link]),
),
),
),
//
// Heven't got the email yet ? Resend email
Padding(
padding: const [Link](10.0),
child: [Link](
TextSpan(
text: "Haven't got the email yet ? ",
style: [Link]
.copyWith(fontSize: 13, color: [Link]),
children: [
TextSpan(
text: "Resend email",
recognizer: TapGestureRecognizer()
..onTap = () => sendCode(),
style: [Link](
fontSize: 13,
color: HexColor("#2EE78A"),
fontWeight: [Link]),
),
],
),
),
),
],
),
),
),
),
);
}
}