Verify Mobile with OTP and Reset Password in Flutter | Verify Email/Mobile and Reset Password in Flutter
hello, I’m Mukesh, an IOS/Android/Flutter Developer This project is practicing to make an IOS/Android flutter Verify, Mobile with OTP, and Reset Password-Screen Application. This article is based on the live project I have covered in this article login page linking with forget password navigation login screen to mobile number verification screen, mobile verification screen sends the OTP verification screen with 6 digits valid code sen on the API with user mobile number and after valid OTP entered by the user then show the next screen as a reset password screen.
Flutter intro
Flutter transforms the app development process. Build, test, and deploy beautiful mobile, web, desktop, and embedded apps from a single codebase. Flutter is an open-source framework by Google for building beautiful, natively compiled, multi-platform applications from a single codebase.
I have used this app in live API and the result is properly working with iOS and Android devices. I have used the worldwide mobile number country code active and validation.
Environment
- 1.71.0 (Universal)
- Dart Programming
- Flutter 3.0.5+ Version
- Build iOS
- Build Android
- Run iPhone 11 Pro
- Android SDK
- XCODE
- CMD (on Windows) or Terminal Terminal (on Mac/Linux)
- IDE (Android Studio/IntelliJ/Visual Studio Code)
Features structure
- MVC structure
- Refactor data model and user default
- A lot of enum used
- Delegate pass value
- ListView UI Design
- Widgets – Button / Textfield / link / Text
Pods(http://pub.dev)
- path_provider: ^2.0.8
- http: ^0.13.0
- shared_preferences: ^2.0.7
- fluttertoast: ^8.0.8
- flutter_spinkit: ^5.1.0
- intl_utils: ^2.7.0
- package_info: ^2.0.0
- permission_handler: ^6.0.1+1
- google_fonts: ^2.1.0
- progress_dialog_null_safe: ^1.0.6
- intl_phone_field: ^3.1.0
- pin_code_fields: ^7.4.0
Fonts
fonts:
– family: Poppins
fonts:
– asset: assets/fonts/Poppins-Regular.ttf
weight: 500
– asset: assets/fonts/Poppins-SemiBold.ttf
weight: 600
– asset: assets/fonts/Poppins-Bold.ttf
weight: 700
Use Layout (Screens) | Verify Email / Mobile and Reset Password in Flutter.
Login:- The login screen most important used scenario of any mobile app and website page or an entry page to a web/mobile application that requires user identification and authentication, regularly performed by entering a username and password combination as per the required combination.
Login screen with click navigation link – Forget Password click.
Mobile Number Enter screen:- Show the mobile number enter the screen and fill the number with your own country. Have the user choose the country as per the selection of country code and mobile number verification process with the help of REST API and send the OTP on their full mobile number to the user.
OTP Screen password:
This screen fills the 6-digit PIN verification on the enter previous screen its shows on the mobile number pin box. PIN validation is set by the user by giving the error message on the invalid and blank value and pressing the button.
The user is not getting any message on the fill previous mobile number then clicks resend button and it defines the 15 sent on the reload of the screen and gets the OTP by using the mobile number. If 6 digits enter correctly and REST API check validation the show the next screen new password screen.
New Password Screen:
This screen fills the new password and confirm password 2 box and confirms the password is set the validation on this screen
1-Validation apply value is not blank.
2-Validation confirms the password is the same value accepted.
3-Page is getting back option/screen is closed then its cancel action.
Success Screen / Message / Login Screen:
This screen shows the Success massage and shows the logo of the company (app) and the bottom button is to add the login button click this then go to the main login screen and the user fills in their ID and Password then login again to the application and used for any app.
Let’s get started on the main steps!
Main Class
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:my_app/l10n/l10n.dart';
import '<a href="package:my_app">package:my_app</a>/language_setup/local_language.dart';
import 'package:my_app/mainapp/main_login.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:get/get.dart';
import 'package:my_app/mainapp/password/password_success_screen.dart';
import 'package:my_app/mainapp/policy_registration.dart';
import 'package:my_app/mainapp/password/secu_eset_password.dart';
import 'package:my_app/mainapp/singup_form.dart';
import 'package:my_app/other_desgin/screens/home/main_screen.dart';
import 'package:my_app/other_desgin/screens/login_and_reg/login.dart';
// import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:my_app/utlity/colors.dart';
import 'package:lottie/lottie.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: '',
debugShowCheckedModeBanner: false,
theme: ThemeData(
// primarySwatch: Colors.blue,
// platform: TargetPlatform.iOS,
),
translations: LocaleString(),
locale: const Locale('en', 'US'),
// locale: provider.locale,
supportedLocales: L10n.all,
// ignore: prefer_const_literals_to_create_immutables
localizationsDelegates: [
// RefreshLocalizations.delegate,
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
home: loginMain(),
routes: {
"/mainlogin": (context) => MainLogin(),
"/singUp": (context) => SignupForm(),
"/selectLocation": (context) => GoogleMapForm(),
"/dashboard": (context) => DashboardForm(),
"/policyReg": (context) => PolicyRegistration(),
"/loginMain": (context) => MainLogin(),
"/ResetPassword": (context) => ResetPassword(),
"/successScreen": (context) => SuccessScreen(),
});
}
}
Mobile Verify Screen
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:securisk_app/mainapp/password/forget_otp.dart';
import 'package:securisk_app/other_desgin/screens/google_map.dart';
import 'package:securisk_app/other_desgin/screens/login_and_reg/google_map2.dart';
import 'package:securisk_app/other_desgin/screens/login_and_reg/map.dart';
import 'package:securisk_app/other_desgin/screens/login_and_reg/otp_verification_screen.dart';
import 'package:securisk_app/other_desgin/screens/reg_form.dart';
import 'package:securisk_app/remote/api_client.dart';
import 'package:securisk_app/utlity/colors.dart';
import 'package:securisk_app/widgets/bg_image.dart';
import 'package:intl_phone_field/intl_phone_field.dart';
import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
import 'package:fluttertoast/fluttertoast.dart';
class ForgetPasswordScreen extends StatefulWidget {
const ForgetPasswordScreen({Key? key}) : super(key: key);
@override
State<ForgetPasswordScreen> createState() => _ForgetPasswordScreenState();
}
class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
final phoneController = TextEditingController();
bool isShowPass = false;
bool onError = false;
String? codeMobile;
final formKey = GlobalKey<FormState>();
late ProgressDialog prg;
@override
Widget build(BuildContext context) {
prg = ProgressDialog(context, type: ProgressDialogType.normal);
prg.style(
message: 'Please wait.......',
borderRadius: 4.0,
backgroundColor: Colors.grey,
progressWidget: CircularProgressIndicator(),
maxProgress: 1.0,
);
return Container(
child: Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: AppColors.headerColor,
title:
Text('Forget Password', style: TextStyle(color: Colors.white)),
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.of(context).pop(),
),
elevation: 0,
),
//backgroundColor: Colors.transparent,
body: Container(
color: AppColors.mainBg,
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ForgetPasswordImage(),
SizedBox(
height: 300,
),
Padding(
padding: const EdgeInsets.only(left: 30.0, right: 13),
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 8.0, top: 10),
child: Text(
'Phone Number',
style: TextStyle(
fontFamily: 'Poppins',
fontStyle: FontStyle.normal,
fontSize: 16,
color: AppColors.textPolicyBlackColor),
),
),
),
),
Container(
padding:
EdgeInsets.only(left: 30, right: 30, top: 10),
child: Column(children: <Widget>[
Container(
child: IntlPhoneField(
controller: phoneController,
// textAlign: TextAlign.right,
// dropdownIconPosition: IconPosition.trailing,
// dropdownTextStyle: ,
style: TextStyle(
fontFamily: 'Poppins',
fontStyle: FontStyle.normal,
fontSize: 16,
color: AppColors.textWaterColor,
),
decoration: InputDecoration(
floatingLabelBehavior:
FloatingLabelBehavior.never,
contentPadding:
EdgeInsets.fromLTRB(8, 5, 10, 5),
fillColor: Colors.white,
filled: true,
border: OutlineInputBorder(
borderSide: BorderSide(),
),
),
initialCountryCode:
'IN', //default contry code, NP for Nepal
onChanged: (phone) {
setState(() {
codeMobile = phone.countryCode;
});
//when phone number country code is changed
print(
phone.completeNumber); //get complete number
print(
phone.countryCode); // get country code only
print(phone.number); // only phone number
},
)),
])),
onError
? Positioned(
bottom: 0,
child: Padding(
padding: const EdgeInsets.only(left: 30),
child: Text('',
style: TextStyle(color: Colors.red)),
))
: Container(),
SizedBox(
height: 5,
),
SizedBox(
height: 5,
),
Padding(
padding: EdgeInsets.only(left: 35, right: 35),
child: Container(
padding: EdgeInsets.all(8.0),
// height: 100,
child: Row(
children: [
Expanded(
// ignore: avoid_unnecessary_containers
child: Container(
//height: 100,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: AppColors.buttonColor,
onPrimary: Colors.white,
side: BorderSide(
color: AppColors.buttonColor,
width: 5,
),
),
onPressed: () async {
if (formKey.currentState!.validate()) {
FocusScope.of(context).unfocus();
prg.show();
await ApiClient.oTPApi(
phoneController.text,
).then((myOTP) async {
if (myOTP.status == 'fail') {
prg.hide();
Fluttertoast.showToast(
msg: myOTP.message.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
} else {
prg.hide();
Fluttertoast.showToast(
msg: myOTP.message.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ForgetOtpVerificationScreen(
mobileNumber:
phoneController
.text,
countryCode: codeMobile,
)));
}
});
}
},
child: Text("Next"),
),
)),
],
),
),
),
],
),
),
),
),
)),
);
}
}
OTP Verification Screen
// ignore_for_file: avoid_unnecessary_containers, unused_local_variable, prefer_const_constructors
import 'dart:async';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:securisk_app/mainapp/password/secu_eset_password.dart';
import 'package:securisk_app/model/laguage.dart';
import 'package:securisk_app/model/location.dart';
import 'package:securisk_app/remote/api_client.dart';
import 'package:securisk_app/utlity/colors.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:intl/intl.dart';
import 'package:flutter/gestures.dart';
import 'package:securisk_app/mainapp/google_location.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:sms_autofill/sms_autofill.dart';
import 'package:pin_input_text_field/pin_input_text_field.dart';
class ForgetOtpVerificationScreen extends StatefulWidget {
final String? mobileNumber;
final String? countryCode;
ForgetOtpVerificationScreen({
this.mobileNumber,
this.countryCode,
});
@override
_ForgetOtpVerificationScreenState createState() =>
_ForgetOtpVerificationScreenState();
}
class _ForgetOtpVerificationScreenState
extends State<ForgetOtpVerificationScreen> with CodeAutoFill {
final formKey = GlobalKey<FormState>();
String _code = "";
String codeValue = "";
String signature = "{{ app signature }}";
TextEditingController textEditingController = TextEditingController();
StreamController<ErrorAnimationType>? errorController;
var mySelectedLang = '';
List<LocationInfo> userLocation = [];
final List<String> locationInfo = [];
String? currentLocation;
int? currentStateId;
int? currentCityID;
String? getOTPValue;
final List locale = [
{'name': 'English', 'locale': Locale('en', 'US')},
{'name': 'हिन्दी', 'locale': Locale('hi', 'IN')},
{'name': 'ਪੰਜਾਬੀ', 'locale': Locale('pa', 'IN')},
];
String getOrderDateCurrentDate() {
var date = DateTime.now().toString();
var dateParse = DateTime.parse(date);
var formattedDate = DateFormat('yyyy-MM-dd hh:mm:ss').format(dateParse);
return formattedDate.toString();
}
List<String>? Lan = ['English', 'हिन्दी', 'ਪੰਜਾਬੀ'];
bool hasError = false;
String currentText = "";
String errorMsg = '';
late bool _loading;
late ProgressDialog prg;
var getMobile = "";
_getOTPToSharedPref() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences prefs = await SharedPreferences.getInstance();
var saveOTP = prefs.getString('OTP');
getOTPValue = saveOTP;
print(getOTPValue);
}
@override
void initState() {
errorController = StreamController<ErrorAnimationType>();
_getOTPToSharedPref();
autosmsget();
// print(widget.languageList);
getMobile = widget.mobileNumber.toString();
listenOtp();
setState(() {
startTimer();
});
//getdata();
super.initState();
}
void listenOtp() async {
await SmsAutoFill().unregisterListener();
listenForCode();
await SmsAutoFill().listenForCode;
print("OTP listen Called");
}
Future<void> autosmsget() async {
await SmsAutoFill().listenForCode;
}
@override
void dispose() {
super.dispose();
SmsAutoFill().unregisterListener();
errorController!.close();
_timer.cancel();
}
late Timer _timer;
int _start = 15;
void startTimer() {
const oneSec = Duration(seconds: 1);
// ignore: unnecessary_new
_timer = new Timer.periodic(
oneSec,
(Timer timer) => setState(
() {
if (_start < 1) {
timer.cancel();
} else {
_start = _start - 1;
}
},
),
);
}
Future<void> resendM() async {
_start = 15; //_start - 1;
setState(() {
startTimer();
});
textWidget();
listenOtp();
prg.show();
var signatureID = await SmsAutoFill().getAppSignature;
print(signatureID);
await ApiClient.oTPApi(
widget.mobileNumber.toString(),
).then((myOTP) async {
if (myOTP.status == 'fail') {
prg.hide();
Fluttertoast.showToast(
msg: myOTP.message.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
} else {
prg.hide();
Fluttertoast.showToast(
msg: myOTP.message.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0);
}
});
}
buildLoading(BuildContext context) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
),
);
});
}
Widget textWidget() {
if (_start > 0) {
print(_start);
return AutoSizeText(
"Wait $_start",
style: GoogleFonts.montserrat(
fontSize: 12,
// color: WidgetColors.TextColor,
),
);
} else {
return InkWell(
child: AutoSizeText(
"Resend Code", //
style: GoogleFonts.montserrat(
fontSize: 12,
// color: WidgetColors.MainTitleColor,
),
),
onTap: () {
startTimer();
resendM();
},
);
}
}
@override
void codeUpdated() {
print("Update code $code");
setState(() {
print("codeUpdated");
});
}
final bool _btnEnabled = false;
// snackBar Widget
snackBar(String? message) {
return ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message!),
duration: const Duration(seconds: 2),
),
);
}
Widget oTPService() {
return Container(
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(horizontal: 50.0, vertical: 8),
child: Center(
child: Text.rich(TextSpan(
text: "we,ve sent a 6 digit confirmation code to ",
style: TextStyle(
fontFamily: 'Poppins',
fontStyle: FontStyle.normal,
fontSize: 14,
color: AppColors.darkColor),
children: <TextSpan>[
TextSpan(
text: widget.countryCode.toString() +
' ' +
widget.mobileNumber.toString(),
style: TextStyle(
fontFamily: 'Poppins',
fontStyle: FontStyle.normal,
fontSize: 16,
color: AppColors.textRegColor,
// decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () {
// code to open / launch terms of service link here
}),
TextSpan(
text: '.',
style: TextStyle(
fontFamily: 'Poppins',
fontStyle: FontStyle.normal,
fontSize: 14,
color: AppColors.darkColor),
children: <TextSpan>[
TextSpan(
text: 'Make sure you enter correct code.',
style: TextStyle(
fontSize: 14,
fontFamily: 'Poppins',
fontStyle: FontStyle.normal,
color: AppColors.darkColor,
//decoration: TextDecoration.underline
),
recognizer: TapGestureRecognizer()
..onTap = () {
// code to open / launch privacy policy link here
})
])
]))),
);
}
@override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
prg = ProgressDialog(context, type: ProgressDialogType.normal);
prg.style(
message: 'Please wait.......',
borderRadius: 4.0,
backgroundColor: Colors.grey,
progressWidget: CircularProgressIndicator(),
maxProgress: 1.0,
);
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 0,
backgroundColor: AppColors.headerColor,
title: Text('Check your Mobile'),
),
backgroundColor: AppColors.mainBg,
body: Container(
child: GestureDetector(
onTap: () {},
child: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ListView(children: <Widget>[
// TopContainerOTP(),
Padding(
padding:
const EdgeInsets.only(top: 1.0, left: 15.0, right: 15.0),
),
const SizedBox(height: 50),
oTPService(),
const SizedBox(
height: 5,
),
Form(
key: formKey,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 8.0, horizontal: 80),
child: PinFieldAutoFill(
currentCode: codeValue,
controller: textEditingController,
codeLength: 6,
onCodeChanged: (code) {
print("onCodeChanged $code");
setState(() {
codeValue = code.toString();
});
},
onCodeSubmitted: (val) {
print("onCodeSubmitted $val");
},
),
),
),
const SizedBox(
height: 50,
),
Padding(
padding: EdgeInsets.only(left: 35, right: 35),
child: Container(
padding: EdgeInsets.all(8.0),
// height: 100,
child: Row(
children: [
Expanded(
child: Container(
//height: 100,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: AppColors.buttonColor,
onPrimary: Colors.white,
side: BorderSide(
color: AppColors.buttonColor, width: 5),
),
onPressed: () async {
var now = DateTime.now();
var formatter = DateFormat('yyyy-MM-dd hh:mm:ss');
String formattedDate = formatter.format(now);
print(formattedDate);
var deviceDateTimeInfo = formattedDate;
// prg.show();
if (formKey.currentState!.validate()) {
if (getOTPValue == codeValue) {
//prg.hide();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => SecuResetPassword(
phoneNumber:
widget.mobileNumber.toString(),
countryCode:
widget.countryCode.toString())),
ModalRoute.withName("/SecuResetPassword"));
} else {
//prg.hide();
Fluttertoast.showToast(
msg: 'Invalid OTP',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
}
},
child: Text("Verify"),
),
)),
],
),
),
),
Spacer(),
const SizedBox(
height: 10,
),
]),
),
),
),
bottomNavigationBar: Container(
height: 50,
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
decoration: const BoxDecoration(
color: AppColors.mainBg,
),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: const Text(
"Didn't receive the code? ",
style: TextStyle(color: Colors.black54, fontSize: 15),
),
),
TextButton(
onPressed: () => snackBar("OTP resend!!"),
child: Padding(
padding: const EdgeInsets.only(right: 29.0),
child: textWidget(),
))
],
),
),
),
);
}
}
This screen is under full fill the app requirement validation and resends the OTP – Didn’t receive the code? is given the timer set by the user to define time and send again on the same screen OTP.
Password Reset Screen
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:securisk_app/mainapp/password/password_success_screen.dart';
import 'package:securisk_app/other_desgin/screens/google_map.dart';
import 'package:securisk_app/other_desgin/screens/login_and_reg/google_map2.dart';
import 'package:securisk_app/other_desgin/screens/login_and_reg/map.dart';
import 'package:securisk_app/other_desgin/screens/login_and_reg/order_accept_screen.dart';
import 'package:securisk_app/other_desgin/screens/login_and_reg/otp_verification_screen.dart';
import 'package:securisk_app/other_desgin/screens/reg_form.dart';
import 'package:securisk_app/remote/api_client.dart';
import 'package:securisk_app/utlity/colors.dart';
import 'package:securisk_app/widgets/bg_image.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
import 'package:intl/intl.dart';
class SecuResetPassword extends StatefulWidget {
final String? phoneNumber;
final String? countryCode;
const SecuResetPassword({Key? key, this.phoneNumber, this.countryCode})
: super(key: key);
@override
State<SecuResetPassword> createState() => _SecuResetPasswordState();
}
class _SecuResetPasswordState extends State<SecuResetPassword> {
final newPasswordController = TextEditingController();
final confirmPassController = TextEditingController();
bool isShowPass = true;
bool isShowConfirmPass = true;
bool onError = false;
late ProgressDialog prg;
final formKey = GlobalKey<FormState>();
String password = '';
String confirmPassword = '';
@override
Widget build(BuildContext context) {
prg = ProgressDialog(context, type: ProgressDialogType.normal);
prg.style(
message: 'Please wait.......',
borderRadius: 4.0,
backgroundColor: Colors.grey,
progressWidget: CircularProgressIndicator(),
maxProgress: 1.0,
);
return Container(
// decoration: BoxDecoration(
// image: DecorationImage(
// image: AssetImage("assets/images/regBg.png"),
// fit: BoxFit.cover,
// ),
// ),
child: Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
title:
Text('Change Password', style: TextStyle(color: Colors.white)),
backgroundColor: AppColors.headerColor,
// leading: IconButton(
// icon: Icon(Icons.arrow_back, color: Colors.white),
// onPressed: () => Navigator.of(context).pop(),
// ),
elevation: 0,
),
//backgroundColor: Colors.transparent,
body: Center(
child: Form(
key: formKey,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// ResetPasswordImage(),
// Container(
// height: 2,
// width: double.infinity,
// color: Colors.amber,
// ),
SizedBox(
height: 150,
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 32.0),
child: Text(
'New Password',
style: TextStyle(
fontFamily: 'Poppins',
fontStyle: FontStyle.normal,
fontSize: 16,
color: AppColors.textRegColor),
),
),
),
Container(
padding: EdgeInsets.only(left: 30, right: 35, top: 10),
child: TextFormField(
style: TextStyle(
color: AppColors.textRegColor, fontSize: 14),
controller: newPasswordController,
obscureText: isShowPass,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
labelText: "Your Password",
alignLabelWithHint: true,
prefixIcon: InkWell(
child: Padding(
padding: EdgeInsets.all(5.0),
child: SizedBox(
height: 20,
child: SvgPicture.asset(
"assets/images/lock.svg",
fit: BoxFit.scaleDown),
),
),
onTap: () {}),
floatingLabelBehavior: FloatingLabelBehavior.never,
contentPadding: EdgeInsets.fromLTRB(8, 5, 10, 5),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(2.0),
),
labelStyle: TextStyle(
color: AppColors.textWaterColor, fontSize: 16),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
isShowPass = !isShowPass;
});
},
child: Icon(
isShowPass
? Icons.visibility
: Icons.visibility_off,
size: 16,
)),
),
// inputFormatters: [new LengthLimitingTextInputFormatter(10)],
onChanged: (value) {
password = value;
},
validator: (value) {
if (value != null && value.isEmpty) {
return 'Password is required please enter';
}
// you can check password length and specifications
return null;
})),
onError
? Positioned(
bottom: 0,
child: Padding(
padding: const EdgeInsets.only(left: 30),
child:
Text('', style: TextStyle(color: Colors.red)),
))
: Container(),
SizedBox(
height: 5,
),
// Padding(
// padding: EdgeInsets.only(left: 1, right: 230),
// child: Text("@ Confirm Password"),
// //"Don't worry! it happens.Please enter the \n address associated with your account."),
// ),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 32.0),
child: Text(
'Conform Password',
style: TextStyle(
fontFamily: 'Poppins',
fontStyle: FontStyle.normal,
fontSize: 16,
color: AppColors.textRegColor),
),
),
),
Container(
padding: EdgeInsets.only(left: 30, right: 35, top: 10),
child: TextFormField(
style: TextStyle(
color: AppColors.textRegColor, fontSize: 14),
controller: confirmPassController,
obscureText: isShowConfirmPass,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
labelText: "Your Password",
alignLabelWithHint: true,
prefixIcon: InkWell(
child: Padding(
padding: EdgeInsets.all(5.0),
child: SizedBox(
height: 20,
child: SvgPicture.asset(
"assets/images/lock.svg",
fit: BoxFit.scaleDown),
),
),
onTap: () {}),
floatingLabelBehavior: FloatingLabelBehavior.never,
contentPadding: EdgeInsets.fromLTRB(8, 5, 10, 5),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(2.0),
),
labelStyle: TextStyle(
color: AppColors.textWaterColor, fontSize: 16),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
isShowConfirmPass = !isShowConfirmPass;
});
},
child: Icon(
isShowConfirmPass
? Icons.visibility
: Icons.visibility_off,
size: 16,
)),
),
// inputFormatters: [new LengthLimitingTextInputFormatter(10)],
onChanged: (value) {
confirmPassword = value;
},
validator: (value) {
if (value != null && value.isEmpty) {
return 'Conform password is required please enter';
}
if (value != password) {
return 'Confirm password not matching';
}
return null;
})),
onError
? Positioned(
bottom: 0,
child: Padding(
padding: const EdgeInsets.only(left: 30),
child:
Text('', style: TextStyle(color: Colors.red)),
))
: Container(),
SizedBox(
height: 5,
),
SizedBox(
height: 5,
),
Padding(
padding: EdgeInsets.only(left: 35, right: 35),
child: Container(
padding: EdgeInsets.all(8.0),
// height: 100,
child: Row(
children: [
Expanded(
child: Container(
//height: 100,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: AppColors.buttonColor,
// textStyle: CustomTextStyle.textFormFieldMedium
// .copyWith(fontSize: 15, fontWeight: FontWeight.normal)
),
onPressed: () async {
if (formKey.currentState!.validate()) {
FocusScope.of(context).unfocus();
var now = DateTime.now();
var formatter =
DateFormat('yyyy-MM-dd hh:mm:ss');
String formattedDate = formatter.format(now);
print(formattedDate);
var deviceDateTimeInfo = formattedDate;
print(confirmPassController.text);
print(widget.phoneNumber.toString());
prg.show();
await ApiClient.resetPasswordAPI(
widget.phoneNumber.toString(),
confirmPassController.text,
'1.2',
deviceDateTimeInfo)
.then((forgetpass) async {
if (forgetpass.status == 'fail') {
prg.hide();
Fluttertoast.showToast(
msg:
"Something went wrong please try again",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
} else {
prg.hide();
Fluttertoast.showToast(
msg: forgetpass.message.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) =>
// ignore: prefer_const_constructors
SuccessScreen()),
ModalRoute.withName(
"/successScreen"));
}
});
}
},
child: Text("Submitting"),
),
)),
],
),
),
),
],
),
),
))),
);
}
}
Change Password Screen
Success message / Screen
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:securisk_app/mainapp/main_login.dart';
import 'package:securisk_app/other_desgin/screens/login_and_reg/login.dart';
import 'package:securisk_app/utlity/colors.dart';
import 'package:lottie/lottie.dart';
class SuccessScreen extends StatelessWidget {
final String? orderNumber;
const SuccessScreen({
Key? key,
this.orderNumber,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.maxFinite,
padding: const EdgeInsets.symmetric(horizontal: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Spacer(
flex: 2,
),
Padding(
padding: const EdgeInsets.only(top: 2.0, left: 10.0, right: 10.0),
child: Container(
height: 120.0,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
"assets/images/logo.png",
))),
),
),
const Spacer(
flex: 2,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Lottie.network(
"https://assets8.lottiefiles.com/packages/lf20_jz2wa00k.json",
height: 300, //SizeConfig.screenHeight!/2.28, /// 300
width: 300, //SizeConfig.screenWidth!/1.37, /// 300
repeat: true),
),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Icon (
// Icons.call,
// size: 35,
// color: Colors.redAccent
// ),
Text(
'Password changed successfully',
// 'shipper_SucessSuport'.tr,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 17),
), //"Thank you for your cooperation \n our support team will be contact \n you shortly within 24 hrs.")
],
)),
],
),
const Spacer(
flex: 8,
),
const Spacer(
flex: 2,
),
SizedBox(height: 20 * 0.08),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//
],
),
],
),
),
bottomNavigationBar: Container(
height: 65,
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
decoration: const BoxDecoration(
color: Colors.white,
),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: AppColors.buttonColor,
),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => MainLogin()),
ModalRoute.withName("/mainlogin"));
},
child: Text('Login'),
),
),
);
}
}
After password change then given the success screen on the my project and go to the login screen.
I hope it was a useful article. See you soon 🤗