code
code
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hexcolor/hexcolor.dart';
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';
@override
State<OtpPage> createState() => _OtpPageState();
}
// 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 SharedPreferences.getInstance();
email = prefs.getString("email") ?? "[email protected]";
}
// Send code
void sendCode() {
// Generate a code
setState(() {
Random random = Random();
codeGenerated = 10000 + random.nextInt(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 (firstDigit.isEmpty &&
secondDigit.isEmpty &&
thirdDigit.isEmpty &&
fourthDigit.isEmpty &&
fifthDigit.isEmpty) {
// Enable errors
_firstFieldError = "";
_secondFieldError = "";
_thirdFieldError = "";
_fourthFieldError = "";
_fifthFieldError = "";
} else {
// Check each field to how which one is empty
if (firstDigit.isNotEmpty) {
if (secondDigit.isNotEmpty) {
if (thirdDigit.isNotEmpty) {
if (fourthDigit.isNotEmpty) {
if (fifthDigit.isNotEmpty) {
// Unable errors
_firstFieldError = null;
_secondFieldError = null;
_thirdFieldError = null;
_fourthFieldError = null;
_fifthFieldError = null;
// Get code tapped
codeTapped = int.parse(firstDigit +
secondDigit +
thirdDigit +
fourthDigit +
fifthDigit);
// Compare the number tapped and code generated
if (codeTapped == codeGenerated) {
// Go to the reset password page
Navigator.of(context).pushReplacement(
PageAnimationTransition(
page: const ResetPassword(),
pageAnimationType: RightToLeftFadedTransition()));
} else {
// Enable errors
_firstFieldError = "";
_secondFieldError = "";
_thirdFieldError = "";
_fourthFieldError = "";
_fifthFieldError = "";
@override
void initState() {
super.initState();
// Get email's user
getEmail();
}
@override
void dispose() {
super.dispose();
// 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: Colors.white,
extendBody: true,
body: GestureDetector(
// Disable the focus of all the fields
onTap: () => FocusScope.of(context).unfocus(),
//
child: SafeArea(
minimum:
const EdgeInsets.only(left: 30, top: 50, right: 30, bottom: 20),
child: SingleChildScrollView(
child: Column(
children: [
//
// Back IconButton
Row(
children: [
CircleAvatar(
backgroundColor: Colors.grey[300],
foregroundColor: Colors.grey,
radius: 23,
child: IconButton(
onPressed: () => Navigator.of(context).pop(),
icon: const Icon(
Icons.arrow_back_ios_new_rounded,
color: Colors.black,
size: 20,
),
),
),
],
),
//
// Space
const SizedBox(
height: 30,
),
// Forgot Password Page
Align(
alignment: Alignment.centerLeft,
child: Text(
"Check your email",
style: MyTextStyles.heading.copyWith(
color: Colors.black,
fontSize: 25,
),
),
),
//
// Subtitle
Padding(
padding: const EdgeInsets.only(top: 10),
child: Align(
alignment: Alignment.centerLeft,
child: Text.rich(
TextSpan(
text: "We send a reset link to ",
style: MyTextStyles.hintStyle.copyWith(
fontSize: 13, fontWeight: FontWeight.bold),
children: [
TextSpan(
text: email,
style: MyTextStyles.bodyText.copyWith(
color: Colors.black,
fontSize: 13,
fontWeight: FontWeight.bold)),
TextSpan(
text:
" enter 5 digit code that mentioned in the email.
",
style: MyTextStyles.hintStyle.copyWith(
fontSize: 13, fontWeight: FontWeight.bold),
),
TextSpan(
text: "This the code : $codeGenerated",
style: MyTextStyles.hintStyle.copyWith(
fontWeight: FontWeight.bold,
fontSize: 13,
color: HexColor("#2EE78A")))
],
),
),
),
),
//
// Space
const SizedBox(
height: 50,
),
//
// Form
Form(
key: _formKey,
// Row of field
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//
// field 1
Padding(
padding: const EdgeInsets.all(5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _firstController,
focusNode: _firstField,
style: MyTextStyles.bodyText.copyWith(
color: HexColor("#253036"),
fontWeight: FontWeight.bold,
fontSize: 20),
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: "1",
hintStyle: MyTextStyles.hintStyle.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
errorText: _firstFieldError,
errorStyle: MyTextStyles.errorStyle,
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(15),
// borderSide: const BorderSide(
// color: Colors.grey,
// width: 3,
// ),
// ),
),
keyboardType: TextInputType.number,
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
FilteringTextInputFormatter.digitsOnly,
],
onChanged: (value) => setState(() {
// check if value isn't empty
if (value.length == 1) {
//
firstDigit = value;
// if value isn't empty, focus the next field
FocusScope.of(context).nextFocus();
} else {
// if value is empty, focus the previous field
FocusScope.of(context).previousFocus();
}
}),
),
),
),
//
// Field 2
Padding(
padding: const EdgeInsets.all(5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _secondController,
focusNode: _secondField,
style: MyTextStyles.bodyText.copyWith(
color: HexColor("#253036"),
fontWeight: FontWeight.bold,
fontSize: 20),
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: "2",
hintStyle: MyTextStyles.hintStyle.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
errorText: _secondFieldError,
errorStyle: MyTextStyles.errorStyle,
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(15),
// borderSide: const BorderSide(
// color: Colors.grey,
// width: 3,
// ),
// ),
),
keyboardType: TextInputType.number,
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
FilteringTextInputFormatter.digitsOnly,
],
onChanged: (value) => setState(() {
// check if value isn't empty
if (value.trim() != "" ||
value.trim().isNotEmpty) {
//
secondDigit = value;
// if value isn't empty, focus the next field
FocusScope.of(context).nextFocus();
} else {
// if value is empty, focus the previous field
FocusScope.of(context).previousFocus();
}
}),
),
),
),
//
// Field 3
Padding(
padding: const EdgeInsets.all(5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _thirdController,
focusNode: _thirdField,
style: MyTextStyles.bodyText.copyWith(
color: HexColor("#253036"),
fontWeight: FontWeight.bold,
fontSize: 20),
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: "3",
hintStyle: MyTextStyles.hintStyle.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
errorText: _thirdFieldError,
errorStyle: MyTextStyles.errorStyle,
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(15),
// borderSide: const BorderSide(
// color: Colors.grey,
// width: 3,
// ),
// ),
),
keyboardType: TextInputType.number,
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
FilteringTextInputFormatter.digitsOnly,
],
onChanged: (value) => setState(() {
// check if value isn't empty
if (value.trim() != "" ||
value.trim().isNotEmpty) {
//
thirdDigit = value;
// if value isn't empty, focus the next field
FocusScope.of(context).nextFocus();
} else {
// if value is empty, focus the previous field
FocusScope.of(context).previousFocus();
}
}),
),
),
),
//
// Field 4
Padding(
padding: const EdgeInsets.all(5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _fourthController,
focusNode: _fourthField,
style: MyTextStyles.bodyText.copyWith(
color: HexColor("#253036"),
fontWeight: FontWeight.bold,
fontSize: 20),
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: "4",
hintStyle: MyTextStyles.hintStyle.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
errorText: _fourthFieldError,
errorStyle: MyTextStyles.errorStyle,
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(15),
// borderSide: const BorderSide(
// color: Colors.grey,
// width: 3,
// ),
// ),
),
keyboardType: TextInputType.number,
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
FilteringTextInputFormatter.digitsOnly,
],
onChanged: (value) => setState(() {
// check if value isn't empty
if (value.trim() != "" ||
value.trim().isNotEmpty) {
//
fourthDigit = value;
// if value isn't empty, focus the next field
FocusScope.of(context).nextFocus();
} else {
// if value is empty, focus the previous field
FocusScope.of(context).previousFocus();
}
}),
),
),
),
//
// Field 5
Padding(
padding: const EdgeInsets.all(5.0),
child: SizedBox(
height: 58,
width: 50,
child: TextFormField(
controller: _fifthController,
focusNode: _fifthField,
style: MyTextStyles.bodyText.copyWith(
color: HexColor("#253036"),
fontWeight: FontWeight.bold,
fontSize: 20),
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: "5",
hintStyle: MyTextStyles.hintStyle.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
errorText: _fifthFieldError,
errorStyle: MyTextStyles.errorStyle,
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: const BorderSide(
color: Colors.red,
width: 3,
),
),
focusedBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(0),
borderSide: BorderSide(
color: HexColor("#253036"),
width: 3,
),
),
// disabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(15),
// borderSide: const BorderSide(
// color: Colors.grey,
// width: 3,
// ),
// ),
),
keyboardType: TextInputType.number,
inputFormatters: [
// To limit the caracter to 1
LengthLimitingTextInputFormatter(1),
// To force caracter to be only a digit
FilteringTextInputFormatter.digitsOnly,
],
onChanged: (value) => setState(() {
// check if value isn't empty
if (value.trim() != "" ||
value.trim().isNotEmpty) {
//
fifthDigit = value;
// if value isn't empty, unfocus
FocusScope.of(context).unfocus();
} else {
// if value is empty, focus this field
FocusScope.of(context).requestFocus();
}
}),
),
),
),
//
//
],
),
),
),
//
// Reset Password Button
Padding(
padding: const EdgeInsets.only(top: 50),
child: ElevatedButton(
onPressed: () => verifyCode(),
style: MyButtonStyles.primaryButton.copyWith(
minimumSize: const WidgetStatePropertyAll(
Size(double.infinity, 50)),
),
child: Text(
"Verify Code",
style: MyTextStyles.bodyText.copyWith(
color: Colors.white, fontWeight: FontWeight.bold),
),
),
),
//
// Heven't got the email yet ? Resend email
Padding(
padding: const EdgeInsets.all(10.0),
child: Text.rich(
TextSpan(
text: "Haven't got the email yet ? ",
style: MyTextStyles.bodyText
.copyWith(fontSize: 13, color: Colors.grey),
children: [
TextSpan(
text: "Resend email",
recognizer: TapGestureRecognizer()
..onTap = () => sendCode(),
style: MyTextStyles.bodyText.copyWith(
fontSize: 13,
color: HexColor("#2EE78A"),
fontWeight: FontWeight.bold),
),
],
),
),
),
],
),
),
),
),
);
}
}