Verify Mobile with OTP and Reset Password in Flutter

Verify Mobile with OTP and Reset Password in Flutter

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.

forget password process 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

 Features structure

 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.

forget password mobile number fill the screen

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.

OTP_Screen_2022
OTP verification 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.

Forget password full video demo

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

new password enter the 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.

final success screen

I hope it was a useful article. See you soon 🤗 

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *