From 621771428b8a3894feabe9bb019a7e94a5fef920 Mon Sep 17 00:00:00 2001
From: shoaib-mohmad <shoaib.mohmad@tarento.com>
Date: Thu, 10 Mar 2022 18:16:42 +0530
Subject: [PATCH] Completed login pin flow.

---
 lib/constants/api_endpoints.dart             |   1 +
 lib/constants/app_constants.dart             |   7 +
 lib/database/offline_model.dart              |  62 ++-
 lib/l10n/app_en.arb                          |  18 +-
 lib/landing_page.dart                        |  21 +-
 lib/pages/application_details_page.dart      |  25 +-
 lib/pages/create_pin_page.dart               | 384 +++++++++++++++++++
 lib/pages/home_page.dart                     |  81 ++--
 lib/pages/inspection_summary.dart            |  17 +-
 lib/pages/login_email_page.dart              | 164 ++++++--
 lib/pages/login_otp_page.dart                |  64 +++-
 lib/repositories/application_repository.dart |  67 +++-
 lib/repositories/login_repository.dart       |  61 ++-
 lib/routes.dart                              |   5 +-
 lib/services/login_service.dart              |  28 +-
 lib/util/helper.dart                         |  20 +
 lib/util/notification_helper.dart            |  46 +--
 17 files changed, 905 insertions(+), 166 deletions(-)
 create mode 100644 lib/pages/create_pin_page.dart

diff --git a/lib/constants/api_endpoints.dart b/lib/constants/api_endpoints.dart
index 15d99c0..ab3a522 100644
--- a/lib/constants/api_endpoints.dart
+++ b/lib/constants/api_endpoints.dart
@@ -2,6 +2,7 @@ class ApiUrl {
   static const baseUrl = 'https://smfdev.idc.tarento.com';
   static const getOtp = '$baseUrl/api/user/requestOTP';
   static const validateOtp = '$baseUrl/api/signIn';
+  static const generatePin = '$baseUrl/api/user/generatePin';
   static const updateUserDeviceToken =
       '$baseUrl/api/user/updateUserDeviceToken';
   static const getAllApplications = '$baseUrl/api/forms/getAllApplications';
diff --git a/lib/constants/app_constants.dart b/lib/constants/app_constants.dart
index 1109546..9bf19be 100644
--- a/lib/constants/app_constants.dart
+++ b/lib/constants/app_constants.dart
@@ -35,6 +35,7 @@ class AppDatabase {
   static const String name = 'smf_db';
   static const String applicationsTable = 'applications';
   static const String inspectionTable = 'inspections';
+  static const String loginPinsTable = 'login_pins';
 }
 
 class Storage {
@@ -44,4 +45,10 @@ class Storage {
   static const String firstname = 'smf_user_first_name';
   static const String lastname = 'smf_user_last_name';
   static const String authtoken = 'smf_user_auth_token';
+  static const String applicationId = 'smf_application_id';
+}
+
+class Inspector {
+  static const String leadInspector = 'lead_inspector';
+  static const String assistantInspector = 'assistant_inspector';
 }
diff --git a/lib/database/offline_model.dart b/lib/database/offline_model.dart
index bb6d3ec..ef73324 100644
--- a/lib/database/offline_model.dart
+++ b/lib/database/offline_model.dart
@@ -10,17 +10,23 @@ class OfflineModel {
         onCreate: (db, version) async {
       const String applicationsTable = AppDatabase.applicationsTable;
       const String inspectionTable = AppDatabase.inspectionTable;
+      const String loginPinsTable = AppDatabase.loginPinsTable;
 
       await db.execute('''CREATE TABLE $applicationsTable (
             id INTEGER PRIMARY KEY AUTOINCREMENT,
-            user_id INTEGER NOT NULL,
+            username VARCHAR(64),
             application_data TEXT
             )''');
       await db.execute('''CREATE TABLE $inspectionTable (
             id INTEGER PRIMARY KEY AUTOINCREMENT,
-            user_id INTEGER NOT NULL,
+            inspector_type CHECK( inspector_type IN ('${Inspector.leadInspector}','${Inspector.assistantInspector}') ),
             inspection_data TEXT
             )''');
+      await db.execute('''CREATE TABLE $loginPinsTable (
+            id INTEGER PRIMARY KEY AUTOINCREMENT,
+            username VARCHAR(64),
+            pin VARCHAR(4)
+            )''');
     }, version: 1);
   }
 
@@ -33,19 +39,19 @@ class OfflineModel {
     );
   }
 
-  static Future<Map> getApplications(int userId) async {
+  static Future<Map> getApplications(String username) async {
     final db = await OfflineModel.database();
-    List<dynamic> whereArgs = [userId];
+    List<dynamic> whereArgs = [username];
     List<Map> rows = await db.query(AppDatabase.applicationsTable,
-        where: 'user_id = ?', orderBy: 'id DESC', whereArgs: whereArgs);
+        where: 'username = ?', orderBy: 'id DESC', whereArgs: whereArgs);
     return rows[0];
   }
 
-  static Future<void> deleteApplications(int userId) async {
+  static Future<void> deleteApplications(String username) async {
     Database db = await OfflineModel.database();
-    List<dynamic> whereArgs = [userId];
+    List<dynamic> whereArgs = [username];
     await db.delete(AppDatabase.applicationsTable,
-        where: 'user_id = ?', whereArgs: whereArgs);
+        where: 'username = ?', whereArgs: whereArgs);
   }
 
   static Future<void> saveInspection(Map<String, Object> data) async {
@@ -57,17 +63,41 @@ class OfflineModel {
     );
   }
 
-  static Future<List<Map<String, dynamic>>> getInspections(int userId) async {
+  static Future<List<Map<String, dynamic>>> getInspections() async {
     final db = await OfflineModel.database();
-    List<dynamic> whereArgs = [userId];
-    return db.query(AppDatabase.inspectionTable,
-        where: 'user_id = ?', whereArgs: whereArgs);
+    return db.query(
+      AppDatabase.inspectionTable,
+    );
   }
 
-  static Future<void> deleteInspections(int userId) async {
+  static Future<void> deleteInspections() async {
     Database db = await OfflineModel.database();
-    List<dynamic> whereArgs = [userId];
-    await db.delete(AppDatabase.inspectionTable,
-        where: 'user_id = ?', whereArgs: whereArgs);
+    await db.delete(
+      AppDatabase.inspectionTable,
+    );
+  }
+
+  static Future<void> savePin(Map<String, Object> data) async {
+    final db = await OfflineModel.database();
+    db.insert(
+      AppDatabase.loginPinsTable,
+      data,
+      conflictAlgorithm: ConflictAlgorithm.replace,
+    );
+  }
+
+  static Future<void> deletePin(String username) async {
+    Database db = await OfflineModel.database();
+    List<dynamic> whereArgs = [username];
+    await db.delete(AppDatabase.loginPinsTable,
+        where: 'username = ?', whereArgs: whereArgs);
+  }
+
+  static Future<Map> getPinDetails(String pin) async {
+    final db = await OfflineModel.database();
+    List<dynamic> whereArgs = [pin];
+    List<Map> rows = await db.query(AppDatabase.loginPinsTable,
+        where: 'pin = ?', orderBy: 'id DESC', whereArgs: whereArgs);
+    return rows.isNotEmpty ? rows[0] : {};
   }
 }
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index acbfc98..659768f 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -2,10 +2,22 @@
     "login": "Login",
     "logout": "Logout", 
     "emailId": "Email Id",
+    "enterHere": "Enter here",
+    "orEnterPin": "Or, Enter your 4 Digit Login Pin",
+    "enterPin": "Enter 4 Digit Login Pin",
+    "confirmPin": "Confirm 4 Digit Login Pin",
+    "createPin": "Create PIN",
+    "inValidPin": "Invalid PIN",
     "getOtp": "GET OTP",
     "enterOtp": "Enter OTP",
     "otpFieldDescription": "Enter the 6 digit OTP sent to your email address.",
+    "pleaseEnterEmail": "Please enter email id",
+    "pleaseEnterPin": "Please enter pin to proceed",
+    "pleaseMatchPin": "Please match pin to proceed",
+    "pleaseEnterValidPin": "Please enter valid pin to proceed",
+    "pinGeneratedMessage": "Pin generated successfully, please login",
     "signIn": "SIGN IN",
+    "goBack": "Go back",
     "goBackText": "Go back, re-enter the email",
     "pendingApplications": "Pending applications",
     "today": "Today",
@@ -19,13 +31,13 @@
     "completed": "Completed",
     "sentForInspection": "Sent for inspection",
     "noApplications": "No applications at the moment",
-    "sessionExpiredMessage": "Your session has expired.",
+    "sessionExpiredMessage": "Your session has expired",
     "isGivenInformationCorrect": "Is the given information found correct?",
     "typeHere": "Type here",
     "cancel": "Cancel",
     "submit": "Submit",
     "actualValue": "Actual value(s)",
-    "pleaseConcentDisagree": "Please concent or disagree",
+    "pleaseConsentDisagree": "Please consent or disagree",
     "status": "Status",
     "scheduledOn": "Scheduled on",
     "inspetionCompletedOn": "Inspection completed on",
@@ -33,5 +45,5 @@
     "leadInspector": "Lead inspector",
     "assistingInspectors": "Assisting inspectors",
     "iDisagree": "I disagree",
-    "iConcent": "I concent"
+    "iConsent": "I consent"
 }
\ No newline at end of file
diff --git a/lib/landing_page.dart b/lib/landing_page.dart
index 888d48f..2fbec39 100644
--- a/lib/landing_page.dart
+++ b/lib/landing_page.dart
@@ -9,12 +9,16 @@ import 'package:smf_mobile/repositories/form_repository.dart';
 import 'package:smf_mobile/repositories/login_repository.dart';
 import 'package:smf_mobile/repositories/user_repository.dart';
 import 'package:smf_mobile/util/helper.dart';
+import 'package:smf_mobile/util/notification_helper.dart';
+// import 'package:smf_mobile/util/notification_helper.dart';
 import 'constants/app_constants.dart';
 import 'constants/app_urls.dart';
 import 'constants/color_constants.dart';
 import 'routes.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:firebase_core/firebase_core.dart';
+import 'package:firebase_messaging/firebase_messaging.dart';
+// import 'package:flutter_secure_storage/flutter_secure_storage.dart';
 
 class LandingPage extends StatefulWidget {
   static const route = AppUrl.landingPage;
@@ -27,10 +31,23 @@ class LandingPage extends StatefulWidget {
       context.findAncestorStateOfType<_LandingPageState>();
 }
 
+Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
+  print("Handling a background message...");
+  // BuildContext context;
+  // if (message.notification != null) {
+  //   String applicationId = message.data['applicationId'] ?? '';
+  //   String body = message.notification!.body.toString();
+  // for (int i = 0; i < 10; i++) {
+  // NotificationHelper.scheduleNotification(DateTime.now(), 0,
+  //     message.notification!.title.toString(), body, applicationId);
+  // }
+}
+
 class _LandingPageState extends State<LandingPage> {
   final client = HttpClient();
   Locale _locale = const Locale('en', 'US');
   bool _isTokenExpired = false;
+  // final _storage = const FlutterSecureStorage();
 
   @override
   void initState() {
@@ -43,7 +60,7 @@ class _LandingPageState extends State<LandingPage> {
     });
   }
 
-  Future<dynamic> _initilizeApp() async {
+  Future<dynamic> _initilizeApp(context) async {
     _isTokenExpired = await Helper.isTokenExpired();
     await Firebase.initializeApp();
     // await Future.delayed(const Duration(microseconds: 100));
@@ -56,7 +73,7 @@ class _LandingPageState extends State<LandingPage> {
         color: AppColors.scaffoldBackground,
         child: FutureBuilder(
             // Initialize FlutterFire
-            future: _initilizeApp(),
+            future: _initilizeApp(context),
             builder: (context, AsyncSnapshot<dynamic> snapshot) {
               // Check for errors
               if (snapshot.hasData) {
diff --git a/lib/pages/application_details_page.dart b/lib/pages/application_details_page.dart
index d115763..f8553c1 100644
--- a/lib/pages/application_details_page.dart
+++ b/lib/pages/application_details_page.dart
@@ -17,6 +17,9 @@ import 'package:smf_mobile/widgets/lead_inspector_application_field.dart';
 import 'package:smf_mobile/widgets/people_card.dart';
 import 'package:smf_mobile/widgets/silverappbar_delegate.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'dart:async';
+import 'package:connectivity_plus/connectivity_plus.dart';
+import 'package:smf_mobile/util/connectivity_helper.dart';
 
 class ApplicationDetailsPage extends StatefulWidget {
   final Application application;
@@ -31,6 +34,8 @@ class ApplicationDetailsPage extends StatefulWidget {
 
 class _ApplicationDetailsPageState extends State<ApplicationDetailsPage>
     with SingleTickerProviderStateMixin {
+  Map _source = {ConnectivityResult.none: false};
+  final MyConnectivity _connectivity = MyConnectivity.instance;
   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
   TabController? _tabController;
   late FormData _formData;
@@ -51,10 +56,15 @@ class _ApplicationDetailsPageState extends State<ApplicationDetailsPage>
   String _inspectionSummary = '';
   String _errorMessage = '';
   String _inspectionStatus = '';
+  late int _userId;
 
   @override
   void initState() {
     super.initState();
+    _connectivity.initialise();
+    _connectivity.myStream.listen((source) {
+      setState(() => _source = source);
+    });
     widget.application.dataObject.forEach((key, value) => _tabs.add(key));
     _tabController = TabController(vsync: this, length: _tabs.length);
     _tabController!.addListener(_setActiveTabIndex);
@@ -64,10 +74,10 @@ class _ApplicationDetailsPageState extends State<ApplicationDetailsPage>
 
   Future<void> _checkInspectorRole() async {
     String id = await Helper.getUser(Storage.userId);
-    int userId = int.parse(id);
+    _userId = int.parse(id);
     if (widget.application.leadInspector.isNotEmpty) {
       _leadInspectorId = widget.application.leadInspector[0];
-      if (widget.application.leadInspector[0] == userId) {
+      if (widget.application.leadInspector[0] == _userId) {
         setState(() {
           _isleadInspector = true;
         });
@@ -88,7 +98,7 @@ class _ApplicationDetailsPageState extends State<ApplicationDetailsPage>
         'name':
             '${widget.application.inspectors[i]['firstName']} ${widget.application.inspectors[i]['lastName']}',
       });
-      if (widget.application.inspectors[i]['id'] == userId &&
+      if (widget.application.inspectors[i]['id'] == _userId &&
           !_isleadInspector) {
         _note = widget.application.inspectors[i]['comments'] ?? '';
         _inspectionStatus = widget.application.inspectors[i]['status'] ?? false;
@@ -191,6 +201,7 @@ class _ApplicationDetailsPageState extends State<ApplicationDetailsPage>
     if (_isleadInspector) {
       Map data = {
         'applicationId': widget.application.applicationId,
+        'userId': _userId,
         'dataObject': _data
       };
 
@@ -205,19 +216,20 @@ class _ApplicationDetailsPageState extends State<ApplicationDetailsPage>
     } else {
       if (!_iConcent && !_iDisagree) {
         Helper.toastMessage(
-            AppLocalizations.of(context)!.pleaseConcentDisagree);
+            AppLocalizations.of(context)!.pleaseConsentDisagree);
         return;
       }
       try {
         Map data = {
           'applicationId': widget.application.applicationId,
+          'userId': _userId,
           'agree': _iConcent,
           'comments': _note
         };
 
         final responseCode =
             await Provider.of<ApplicationRespository>(context, listen: false)
-                .submitConcent(data);
+                .submitConcent(Helper.isInternetConnected(_source), data);
         if (responseCode != 0) {
           Navigator.of(context).pushReplacement(MaterialPageRoute(
               builder: (context) => const InspectionCompletedPage()));
@@ -256,6 +268,7 @@ class _ApplicationDetailsPageState extends State<ApplicationDetailsPage>
   @override
   void dispose() {
     _tabController?.dispose();
+    // _connectivity.disposeStream();
     super.dispose();
   }
 
@@ -802,7 +815,7 @@ class _ApplicationDetailsPageState extends State<ApplicationDetailsPage>
                                         children: [
                                           Text(
                                             AppLocalizations.of(context)!
-                                                .iConcent,
+                                                .iConsent,
                                             style: GoogleFonts.lato(
                                                 color: _iConcent
                                                     ? Colors.white
diff --git a/lib/pages/create_pin_page.dart b/lib/pages/create_pin_page.dart
new file mode 100644
index 0000000..ed1f45a
--- /dev/null
+++ b/lib/pages/create_pin_page.dart
@@ -0,0 +1,384 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:otp_text_field/style.dart';
+import 'package:provider/provider.dart';
+import 'package:smf_mobile/constants/app_urls.dart';
+import 'package:smf_mobile/constants/color_constants.dart';
+import 'package:google_fonts/google_fonts.dart';
+import 'package:smf_mobile/pages/home_page.dart';
+import 'package:smf_mobile/pages/login_email_page.dart';
+import 'package:smf_mobile/pages/login_otp_page.dart';
+import 'package:smf_mobile/repositories/login_repository.dart';
+import 'package:smf_mobile/util/helper.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:otp_text_field/otp_field.dart';
+import 'package:unique_identifier/unique_identifier.dart';
+
+class CreatePinPage extends StatefulWidget {
+  static const route = AppUrl.loginEmailPage;
+
+  const CreatePinPage({Key? key}) : super(key: key);
+  @override
+  _CreatePinPageState createState() => _CreatePinPageState();
+}
+
+class _CreatePinPageState extends State<CreatePinPage> {
+  final TextEditingController _emailController = TextEditingController();
+  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
+  String _errorMessage = '';
+  late Locale locale;
+  String _pin1 = '';
+  String _pin2 = '';
+
+  @override
+  void initState() {
+    super.initState();
+  }
+
+  Future<void> _generateOtp() async {
+    final email = _emailController.text.trim();
+    if (email == '') {
+      Helper.toastMessage(AppLocalizations.of(context)!.pleaseEnterEmail);
+      return;
+    }
+    if (_pin1 == '' || _pin2 == '') {
+      Helper.toastMessage(AppLocalizations.of(context)!.pleaseEnterPin);
+      return;
+    }
+    if (_pin1.length < 4 || _pin2.length < 4) {
+      Helper.toastMessage(AppLocalizations.of(context)!.pleaseEnterValidPin);
+      return;
+    }
+    if (_pin1 != _pin2) {
+      Helper.toastMessage(AppLocalizations.of(context)!.pleaseMatchPin);
+      return;
+    }
+    SystemChannels.textInput.invokeMethod('TextInput.hide');
+    try {
+      final responseCode =
+          await Provider.of<LoginRespository>(context, listen: false)
+              .getOtp(email.trim());
+      if (responseCode == 200) {
+        Navigator.of(context).pushReplacement(MaterialPageRoute(
+          builder: (context) => LoginOtpPage(
+            username: email,
+            pin: _pin1,
+            loginRequest: false,
+          ),
+        ));
+      } else {
+        _errorMessage =
+            Provider.of<LoginRespository>(context, listen: false).errorMessage;
+        Helper.toastMessage(_errorMessage);
+      }
+    } catch (err) {
+      throw Exception(err);
+    }
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        key: _scaffoldKey,
+        body: SingleChildScrollView(
+          reverse: true,
+          child: SizedBox(
+              width: MediaQuery.of(context).size.width,
+              height: MediaQuery.of(context).size.height,
+              child: Column(
+                children: [
+                  Container(
+                    padding: const EdgeInsets.only(top: 60, bottom: 60),
+                    child: Center(
+                      child: Image.asset(
+                        'assets/images/logo.png',
+                        // width: 50.0,
+                        // height: 50.0,
+                      ),
+                    ),
+                  ),
+                  Container(
+                    padding:
+                        const EdgeInsets.only(left: 40, right: 40, bottom: 40),
+                    margin: const EdgeInsets.only(left: 20, right: 20),
+                    decoration: BoxDecoration(
+                      borderRadius: BorderRadius.circular(4),
+                      color: Colors.white,
+                      boxShadow: const [
+                        BoxShadow(
+                            color: AppColors.black16,
+                            offset: Offset(0, 2),
+                            blurRadius: 2)
+                      ],
+                    ),
+                    child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          Padding(
+                              padding: const EdgeInsets.only(top: 40),
+                              child: Align(
+                                  alignment: Alignment.center,
+                                  child: Text(
+                                    AppLocalizations.of(context)!.createPin,
+                                    textAlign: TextAlign.center,
+                                    style: GoogleFonts.lato(
+                                        color: AppColors.black87,
+                                        fontSize: 20,
+                                        letterSpacing:
+                                            0.25 /*percentages not used in flutter. defaulting to zero*/,
+                                        fontWeight: FontWeight.w600,
+                                        height: 1.4),
+                                  ))),
+                          Padding(
+                              padding: const EdgeInsets.only(
+                                top: 50,
+                              ),
+                              child: Text(
+                                AppLocalizations.of(context)!.emailId,
+                                textAlign: TextAlign.left,
+                                style: GoogleFonts.lato(
+                                    color: AppColors.black87,
+                                    fontSize: 16,
+                                    letterSpacing:
+                                        0.25 /*percentages not used in flutter. defaulting to zero*/,
+                                    fontWeight: FontWeight.w400,
+                                    height: 1.4),
+                              )),
+                          Container(
+                            width: double.infinity,
+                            margin: const EdgeInsets.only(
+                              top: 0,
+                            ),
+                            child: Padding(
+                              padding: const EdgeInsets.fromLTRB(0, 5, 0, 10),
+                              child: Column(
+                                crossAxisAlignment: CrossAxisAlignment.start,
+                                children: [
+                                  const SizedBox(height: 10.0),
+                                  Container(
+                                    alignment: Alignment.centerLeft,
+                                    height: 50.0,
+                                    decoration: BoxDecoration(
+                                      borderRadius: BorderRadius.circular(4),
+                                      border:
+                                          Border.all(color: AppColors.black16),
+                                      color: Colors.white,
+                                    ),
+                                    child: Focus(
+                                      child: TextFormField(
+                                        textCapitalization:
+                                            TextCapitalization.none,
+                                        textInputAction: TextInputAction.done,
+                                        controller: _emailController,
+                                        style: GoogleFonts.lato(
+                                            color: AppColors.black40,
+                                            fontSize: 16,
+                                            letterSpacing:
+                                                0 /*percentages not used in flutter. defaulting to zero*/,
+                                            fontWeight: FontWeight.normal,
+                                            height:
+                                                1.5 /*PERCENT not supported*/
+                                            ),
+                                        keyboardType:
+                                            TextInputType.emailAddress,
+                                        decoration: const InputDecoration(
+                                          contentPadding: EdgeInsets.fromLTRB(
+                                              20.0, 0.0, 20.0, 0.0),
+                                          border: InputBorder.none,
+                                          hintText: 'Enter here',
+                                          hintStyle: TextStyle(
+                                              color: AppColors.black40,
+                                              fontSize: 14,
+                                              letterSpacing:
+                                                  0 /*percentages not used in flutter. defaulting to zero*/,
+                                              fontWeight: FontWeight.normal,
+                                              height:
+                                                  1.5 /*PERCENT not supported*/
+                                              ),
+                                          focusedBorder: OutlineInputBorder(
+                                            borderSide: BorderSide(
+                                                color: Colors.transparent,
+                                                width: 2.0),
+                                          ),
+                                        ),
+                                      ),
+                                    ),
+                                  )
+                                ],
+                              ),
+                            ),
+                          ),
+                          Padding(
+                              padding: const EdgeInsets.only(
+                                top: 20,
+                              ),
+                              child: Text(
+                                AppLocalizations.of(context)!.enterPin,
+                                textAlign: TextAlign.left,
+                                style: GoogleFonts.lato(
+                                    color: AppColors.black87,
+                                    fontSize: 16,
+                                    letterSpacing:
+                                        0.25 /*percentages not used in flutter. defaulting to zero*/,
+                                    fontWeight: FontWeight.w400,
+                                    height: 1.4),
+                              )),
+                          Container(
+                            alignment: Alignment.centerLeft,
+                            height: 30.0,
+                            margin: const EdgeInsets.only(top: 5),
+                            decoration: BoxDecoration(
+                              borderRadius: BorderRadius.circular(4),
+                              // border:
+                              //     Border.all(color: AppColors.black16),
+                              color: Colors.white,
+                            ),
+                            child: OTPTextField(
+                                length: 4,
+                                width: MediaQuery.of(context).size.width / 2,
+                                fieldWidth: 38,
+                                style: const TextStyle(fontSize: 14),
+                                textFieldAlignment:
+                                    MainAxisAlignment.spaceAround,
+                                fieldStyle: FieldStyle.underline,
+                                onCompleted: (pin) {
+                                  setState(() {
+                                    _pin1 = pin;
+                                  });
+                                },
+                                onChanged: (String? pin) {
+                                  if (pin?.length == 4) {
+                                    setState(() {
+                                      _pin1 = pin.toString();
+                                    });
+                                  }
+                                }),
+                          ),
+                          Padding(
+                              padding: const EdgeInsets.only(
+                                top: 20,
+                              ),
+                              child: Text(
+                                AppLocalizations.of(context)!.confirmPin,
+                                textAlign: TextAlign.left,
+                                style: GoogleFonts.lato(
+                                    color: AppColors.black87,
+                                    fontSize: 16,
+                                    letterSpacing:
+                                        0.25 /*percentages not used in flutter. defaulting to zero*/,
+                                    fontWeight: FontWeight.w400,
+                                    height: 1.4),
+                              )),
+                          Container(
+                            alignment: Alignment.centerLeft,
+                            height: 30.0,
+                            margin: const EdgeInsets.only(top: 5),
+                            decoration: BoxDecoration(
+                              borderRadius: BorderRadius.circular(4),
+                              // border:
+                              //     Border.all(color: AppColors.black16),
+                              color: Colors.white,
+                            ),
+                            child: OTPTextField(
+                                length: 4,
+                                width: MediaQuery.of(context).size.width / 2,
+                                fieldWidth: 38,
+                                style: const TextStyle(fontSize: 14),
+                                textFieldAlignment:
+                                    MainAxisAlignment.spaceAround,
+                                fieldStyle: FieldStyle.underline,
+                                onCompleted: (pin) {
+                                  setState(() {
+                                    _pin2 = pin;
+                                  });
+                                },
+                                onChanged: (String? pin) {
+                                  if (pin?.length == 4) {
+                                    setState(() {
+                                      _pin2 = pin.toString();
+                                    });
+                                  }
+                                }),
+                          ),
+                          Padding(
+                            padding: const EdgeInsets.only(top: 40),
+                            child: InkWell(
+                                // ignore: avoid_print
+                                onTap: () => _generateOtp(),
+                                child: SizedBox(
+                                    width:
+                                        MediaQuery.of(context).size.width - 80,
+                                    height: 50,
+                                    child: Stack(children: <Widget>[
+                                      Align(
+                                          alignment: Alignment.bottomCenter,
+                                          child: Container(
+                                              width: MediaQuery.of(context)
+                                                      .size
+                                                      .width -
+                                                  80,
+                                              height: 50,
+                                              decoration: BoxDecoration(
+                                                color: AppColors.primaryBlue,
+                                                borderRadius:
+                                                    BorderRadius.circular(4),
+                                              ))),
+                                      Align(
+                                          alignment: Alignment.center,
+                                          child: Text(
+                                            AppLocalizations.of(context)!
+                                                .submit,
+                                            textAlign: TextAlign.center,
+                                            style: GoogleFonts.lato(
+                                                color: Colors.white,
+                                                fontSize: 17,
+                                                letterSpacing:
+                                                    0 /*percentages not used in flutter. defaulting to zero*/,
+                                                fontWeight: FontWeight.normal,
+                                                height:
+                                                    1.5 /*PERCENT not supported*/
+                                                ),
+                                          )),
+                                    ]))),
+                          ),
+                          const Padding(
+                              padding: EdgeInsets.only(
+                                top: 20,
+                              ),
+                              child: Divider(
+                                color: AppColors.black16,
+                              )),
+                          InkWell(
+                            onTap: () => Navigator.of(context)
+                                .pushReplacement(MaterialPageRoute(
+                              builder: (context) => const LoginEmailPage(),
+                            )),
+                            child: Container(
+                                width: double.infinity,
+                                padding: const EdgeInsets.only(
+                                  top: 10,
+                                ),
+                                child: Text(
+                                  AppLocalizations.of(context)!.goBack,
+                                  textAlign: TextAlign.center,
+                                  style: GoogleFonts.lato(
+                                      color: AppColors.primaryBlue,
+                                      fontSize: 14,
+                                      letterSpacing:
+                                          0.5 /*percentages not used in flutter. defaulting to zero*/,
+                                      fontWeight: FontWeight.w700,
+                                      height: 1.4),
+                                )),
+                          )
+                        ]),
+                  )
+                ],
+              )),
+        ));
+  }
+}
diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart
index 4636a74..370e9a8 100644
--- a/lib/pages/home_page.dart
+++ b/lib/pages/home_page.dart
@@ -1,9 +1,12 @@
+import 'package:firebase_messaging/firebase_messaging.dart';
 import 'package:flutter/material.dart';
 import 'package:google_fonts/google_fonts.dart';
 import 'package:provider/provider.dart';
+import 'package:smf_mobile/constants/app_constants.dart';
 import 'package:smf_mobile/constants/app_urls.dart';
 import 'package:smf_mobile/constants/color_constants.dart';
 import 'package:smf_mobile/models/application_model.dart';
+import 'package:smf_mobile/pages/application_details_page.dart';
 import 'package:smf_mobile/pages/login_email_page.dart';
 import 'package:smf_mobile/pages/past_applications.dart';
 import 'package:smf_mobile/repositories/application_repository.dart';
@@ -19,26 +22,76 @@ import 'package:smf_mobile/util/connectivity_helper.dart';
 
 class HomePage extends StatefulWidget {
   static const route = AppUrl.homePage;
-
+  // final String applicationId;
   const HomePage({Key? key}) : super(key: key);
   @override
   _HomePageState createState() => _HomePageState();
 }
 
-class _HomePageState extends State<HomePage> {
+class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
   Map _source = {ConnectivityResult.none: false};
   final MyConnectivity _connectivity = MyConnectivity.instance;
   List<Application> _allApplications = [];
   final List<Application> _pendingApplications = [];
   final List<Application> _upcomingApplications = [];
   final List<Application> _pastApplications = [];
+  bool _isInForeground = true;
+
   @override
   void initState() {
     super.initState();
     _connectivity.initialise();
     _connectivity.myStream.listen((source) {
-      setState(() => _source = source);
+      setState(() {
+        _source = source;
+      });
     });
+    // print('applicationId:' + widget.applicationId);
+    WidgetsBinding.instance!.addObserver(this);
+  }
+
+  void _checkNewApplication(String applicationId) {
+    print('applicationId $applicationId');
+    if (applicationId != '') {
+      for (Application application in _allApplications) {
+        if (application.applicationId == applicationId) {
+          Navigator.push(
+            context,
+            MaterialPageRoute(
+                builder: (context) => ApplicationDetailsPage(
+                      application: application,
+                    )),
+          );
+          return;
+        }
+      }
+    }
+  }
+
+  @override
+  void didChangeAppLifecycleState(AppLifecycleState state) {
+    super.didChangeAppLifecycleState(state);
+    _isInForeground = state == AppLifecycleState.resumed;
+    if (_isInForeground) {
+      FirebaseMessaging.instance.getInitialMessage().then((message) {
+        if (message != null) {
+          // print('getInitialMessage: ${message.data}');
+          _checkNewApplication(message.data['applicationId']);
+        }
+      });
+      // setState(() {});
+      // print('_isInForeground...');
+      // Future.delayed(const Duration(milliseconds: 500), () {
+      //   _checkNewApplication();
+      // });
+    }
+  }
+
+  @override
+  void dispose() {
+    // WidgetsBinding.instance!.removeObserver(this);
+    // _connectivity.disposeStream();
+    super.dispose();
   }
 
   void _validateUser() async {
@@ -51,31 +104,11 @@ class _HomePageState extends State<HomePage> {
     }
   }
 
-  bool _isInternetConnected() {
-    bool connected;
-    switch (_source.keys.toList()[0]) {
-      case ConnectivityResult.mobile:
-        print('connected to mobile...');
-        connected = true;
-        break;
-      case ConnectivityResult.wifi:
-        print('connected to wifi...');
-        connected = true;
-        break;
-      case ConnectivityResult.none:
-      default:
-        print('offline...');
-        connected = false;
-    }
-    return connected;
-  }
-
   Future<dynamic> _getApplications() async {
-    print('_getApplications...');
     _validateUser();
     _allApplications =
         await Provider.of<ApplicationRespository>(context, listen: false)
-            .getApplications(_isInternetConnected());
+            .getApplications(Helper.isInternetConnected(_source));
     String _errorMessage =
         Provider.of<ApplicationRespository>(context, listen: false)
             .errorMessage;
diff --git a/lib/pages/inspection_summary.dart b/lib/pages/inspection_summary.dart
index 8856f68..2fb38fb 100644
--- a/lib/pages/inspection_summary.dart
+++ b/lib/pages/inspection_summary.dart
@@ -12,6 +12,9 @@ import 'package:smf_mobile/util/helper.dart';
 import 'package:smf_mobile/widgets/people_card.dart';
 import 'inspection_completed.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'dart:async';
+import 'package:connectivity_plus/connectivity_plus.dart';
+import 'package:smf_mobile/util/connectivity_helper.dart';
 
 class InspectionSummaryPage extends StatefulWidget {
   static const route = AppUrl.inspectionSummary;
@@ -32,6 +35,8 @@ class InspectionSummaryPage extends StatefulWidget {
 }
 
 class _InspectionSummaryPageState extends State<InspectionSummaryPage> {
+  Map _source = {ConnectivityResult.none: false};
+  final MyConnectivity _connectivity = MyConnectivity.instance;
   final TextEditingController _summaryController = TextEditingController();
   final List<Map> _inspectors = [];
   int _leadInspectorId = 0;
@@ -44,9 +49,19 @@ class _InspectionSummaryPageState extends State<InspectionSummaryPage> {
   @override
   void initState() {
     super.initState();
+    _connectivity.initialise();
+    _connectivity.myStream.listen((source) {
+      setState(() => _source = source);
+    });
     _populateApplicationInspectors();
   }
 
+  // @override
+  // void dispose() {
+  //   // _connectivity.disposeStream();
+  //   super.dispose();
+  // }
+
   Future<void> _populateApplicationInspectors() async {
     if (widget.leadInspector.isNotEmpty) {
       _leadInspectorId = widget.leadInspector[0];
@@ -109,7 +124,7 @@ class _InspectionSummaryPageState extends State<InspectionSummaryPage> {
       };
       final responseCode =
           await Provider.of<ApplicationRespository>(context, listen: false)
-              .submitInspection(data);
+              .submitInspection(Helper.isInternetConnected(_source), data);
       if (responseCode != 0) {
         Navigator.of(context).pushReplacement(MaterialPageRoute(
             builder: (context) => const InspectionCompletedPage()));
diff --git a/lib/pages/login_email_page.dart b/lib/pages/login_email_page.dart
index e623aa3..f4c1ba7 100644
--- a/lib/pages/login_email_page.dart
+++ b/lib/pages/login_email_page.dart
@@ -1,16 +1,19 @@
-// import 'dart:math';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
+import 'package:otp_text_field/style.dart';
 import 'package:provider/provider.dart';
 import 'package:smf_mobile/constants/app_urls.dart';
 import 'package:smf_mobile/constants/color_constants.dart';
 import 'package:google_fonts/google_fonts.dart';
+import 'package:smf_mobile/database/offline_model.dart';
+import 'package:smf_mobile/pages/create_pin_page.dart';
+import 'package:smf_mobile/pages/home_page.dart';
 import 'package:smf_mobile/pages/login_otp_page.dart';
 import 'package:smf_mobile/repositories/login_repository.dart';
 import 'package:smf_mobile/util/helper.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
-import 'package:firebase_messaging/firebase_messaging.dart';
-import 'package:smf_mobile/util/notification_helper.dart';
+import 'package:otp_text_field/otp_field.dart';
+import 'package:unique_identifier/unique_identifier.dart';
 
 class LoginEmailPage extends StatefulWidget {
   static const route = AppUrl.loginEmailPage;
@@ -23,45 +26,36 @@ class LoginEmailPage extends StatefulWidget {
 class _LoginEmailPageState extends State<LoginEmailPage> {
   final TextEditingController _emailController = TextEditingController();
   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
-  FirebaseMessaging messaging = FirebaseMessaging.instance;
   String _errorMessage = '';
   late Locale locale;
+  String _pin = '';
+  late String _identifier;
 
   @override
   void initState() {
     super.initState();
-    // _configureMessaging();
+    initUniqueIdentifierState();
   }
 
-  // _configureMessaging() async {
-  //   NotificationSettings settings = await messaging.requestPermission(
-  //     alert: true,
-  //     announcement: false,
-  //     badge: true,
-  //     carPlay: false,
-  //     criticalAlert: false,
-  //     provisional: false,
-  //     sound: true,
-  //   );
-  //   print('User granted permission: ${settings.authorizationStatus}');
+  Future<void> initUniqueIdentifierState() async {
+    String? identifier;
+    try {
+      identifier = await UniqueIdentifier.serial;
+    } on PlatformException {
+      identifier = 'Failed to get Unique Identifier';
+    }
 
-  //   FirebaseMessaging.onMessage.listen((RemoteMessage message) {
-  //     if (message.notification != null) {
-  //       var random = Random();
-  //       int notificationId = random.nextInt(999999);
-  //       String body =
-  //           message.notification!.body.toString() + message.data.toString();
-  //       NotificationHelper.scheduleNotification(context, DateTime.now(),
-  //           notificationId, message.notification!.title.toString(), body);
-  //     }
-  //     print('Message data: $message');
-  //   });
-  // }
+    if (!mounted) return;
+
+    setState(() {
+      _identifier = identifier!;
+    });
+  }
 
   Future<void> _generateOtp() async {
-    final email = _emailController.text;
+    final email = _emailController.text.trim();
     if (email == '') {
-      Helper.toastMessage('Please enter email.');
+      Helper.toastMessage(AppLocalizations.of(context)!.pleaseEnterEmail);
       return;
     }
     SystemChannels.textInput.invokeMethod('TextInput.hide');
@@ -71,7 +65,7 @@ class _LoginEmailPageState extends State<LoginEmailPage> {
               .getOtp(email.trim());
       if (responseCode == 200) {
         Navigator.of(context).pushReplacement(MaterialPageRoute(
-          builder: (context) => const LoginOtpPage(),
+          builder: (context) => LoginOtpPage(username: email),
         ));
       } else {
         _errorMessage =
@@ -83,6 +77,34 @@ class _LoginEmailPageState extends State<LoginEmailPage> {
     }
   }
 
+  Future<void> _validatePin() async {
+    print('_validatePin...');
+    String pin = _pin;
+    try {
+      Map pinDetails = await OfflineModel.getPinDetails(pin);
+      print(pinDetails);
+      if (pinDetails['username'] != null) {
+        final responseCode = await Provider.of<LoginRespository>(context,
+                listen: false)
+            .validateOtp(
+                context, pinDetails['username'], '', _identifier, pin, false);
+        if (responseCode == 200) {
+          Navigator.of(context).pushReplacement(MaterialPageRoute(
+            builder: (context) => const HomePage(),
+          ));
+        } else {
+          _errorMessage = Provider.of<LoginRespository>(context, listen: false)
+              .errorMessage;
+          Helper.toastMessage(_errorMessage);
+        }
+      } else {
+        Helper.toastMessage(AppLocalizations.of(context)!.inValidPin);
+      }
+    } catch (err) {
+      throw Exception(err);
+    }
+  }
+
   @override
   void dispose() {
     super.dispose();
@@ -100,7 +122,7 @@ class _LoginEmailPageState extends State<LoginEmailPage> {
               child: Column(
                 children: [
                   Container(
-                    padding: const EdgeInsets.only(top: 100, bottom: 100),
+                    padding: const EdgeInsets.only(top: 60, bottom: 60),
                     child: Center(
                       child: Image.asset(
                         'assets/images/logo.png',
@@ -221,7 +243,7 @@ class _LoginEmailPageState extends State<LoginEmailPage> {
                             ),
                           ),
                           Padding(
-                            padding: const EdgeInsets.only(bottom: 80),
+                            padding: const EdgeInsets.only(bottom: 10),
                             child: InkWell(
                                 // ignore: avoid_print
                                 onTap: () => _generateOtp(),
@@ -261,6 +283,82 @@ class _LoginEmailPageState extends State<LoginEmailPage> {
                                           )),
                                     ]))),
                           ),
+                          Padding(
+                              padding: const EdgeInsets.only(
+                                top: 20,
+                              ),
+                              child: Text(
+                                AppLocalizations.of(context)!.orEnterPin,
+                                textAlign: TextAlign.left,
+                                style: GoogleFonts.lato(
+                                    color: AppColors.black87,
+                                    fontSize: 16,
+                                    letterSpacing:
+                                        0.25 /*percentages not used in flutter. defaulting to zero*/,
+                                    fontWeight: FontWeight.w400,
+                                    height: 1.4),
+                              )),
+                          Container(
+                            alignment: Alignment.centerLeft,
+                            height: 30.0,
+                            margin: const EdgeInsets.only(top: 5),
+                            decoration: BoxDecoration(
+                              borderRadius: BorderRadius.circular(4),
+                              // border:
+                              //     Border.all(color: AppColors.black16),
+                              color: Colors.white,
+                            ),
+                            child: OTPTextField(
+                                length: 4,
+                                width: MediaQuery.of(context).size.width / 2,
+                                fieldWidth: 38,
+                                style: const TextStyle(fontSize: 14),
+                                textFieldAlignment:
+                                    MainAxisAlignment.spaceAround,
+                                fieldStyle: FieldStyle.underline,
+                                onCompleted: (pin) {
+                                  setState(() {
+                                    _pin = pin;
+                                  });
+                                },
+                                onChanged: (String? pin) {
+                                  if (pin?.length == 4) {
+                                    setState(() {
+                                      _pin = pin.toString();
+                                    });
+                                    _validatePin();
+                                  }
+                                }),
+                          ),
+                          const Padding(
+                              padding: EdgeInsets.only(
+                                top: 20,
+                              ),
+                              child: Divider(
+                                color: AppColors.black16,
+                              )),
+                          InkWell(
+                            onTap: () => Navigator.of(context)
+                                .pushReplacement(MaterialPageRoute(
+                              builder: (context) => const CreatePinPage(),
+                            )),
+                            child: Container(
+                                width: double.infinity,
+                                padding: const EdgeInsets.only(
+                                  top: 10,
+                                ),
+                                child: Text(
+                                  AppLocalizations.of(context)!.createPin,
+                                  textAlign: TextAlign.center,
+                                  style: GoogleFonts.lato(
+                                      color: AppColors.primaryBlue,
+                                      fontSize: 14,
+                                      letterSpacing:
+                                          0.5 /*percentages not used in flutter. defaulting to zero*/,
+                                      fontWeight: FontWeight.w700,
+                                      height: 1.4),
+                                )),
+                          )
                         ]),
                   )
                 ],
diff --git a/lib/pages/login_otp_page.dart b/lib/pages/login_otp_page.dart
index 4423329..ec000e7 100644
--- a/lib/pages/login_otp_page.dart
+++ b/lib/pages/login_otp_page.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 import 'package:smf_mobile/constants/app_urls.dart';
 import 'package:smf_mobile/constants/color_constants.dart';
+import 'package:smf_mobile/database/offline_model.dart';
 import 'package:smf_mobile/pages/home_page.dart';
 import 'package:google_fonts/google_fonts.dart';
 import 'package:smf_mobile/pages/login_email_page.dart';
@@ -16,7 +17,16 @@ import 'package:flutter/services.dart';
 class LoginOtpPage extends StatefulWidget {
   static const route = AppUrl.loginOtpPage;
 
-  const LoginOtpPage({Key? key}) : super(key: key);
+  final String username;
+  final String pin;
+  final bool loginRequest;
+
+  const LoginOtpPage({
+    Key? key,
+    required this.username,
+    this.pin = '',
+    this.loginRequest = true,
+  }) : super(key: key);
   @override
   _LoginOtpPageState createState() => _LoginOtpPageState();
 }
@@ -51,17 +61,40 @@ class _LoginOtpPageState extends State<LoginOtpPage> {
   Future<void> _validateOtp() async {
     String otp = _otp;
     try {
-      final responseCode =
-          await Provider.of<LoginRespository>(context, listen: false)
-              .validateOtp(context, otp, _identifier);
-      if (responseCode == 200) {
-        Navigator.of(context).pushReplacement(MaterialPageRoute(
-          builder: (context) => const HomePage(),
-        ));
+      if (widget.loginRequest) {
+        final responseCode = await Provider.of<LoginRespository>(context,
+                listen: false)
+            .validateOtp(context, widget.username, otp, _identifier, '', true);
+        if (responseCode == 200) {
+          Navigator.of(context).pushReplacement(MaterialPageRoute(
+            builder: (context) => const HomePage(),
+          ));
+        } else {
+          _errorMessage = Provider.of<LoginRespository>(context, listen: false)
+              .errorMessage;
+          Helper.toastMessage(_errorMessage);
+        }
       } else {
-        _errorMessage =
-            Provider.of<LoginRespository>(context, listen: false).errorMessage;
-        Helper.toastMessage(_errorMessage);
+        final responseData =
+            await Provider.of<LoginRespository>(context, listen: false)
+                .generatePin(widget.username, widget.pin, otp);
+        if (responseData) {
+          Helper.toastMessage(
+              AppLocalizations.of(context)!.pinGeneratedMessage);
+          await OfflineModel.deletePin(widget.username);
+          Map<String, Object> data = {
+            'username': widget.username,
+            'pin': widget.pin
+          };
+          await OfflineModel.savePin(data);
+          Navigator.of(context).pushReplacement(MaterialPageRoute(
+            builder: (context) => const LoginEmailPage(),
+          ));
+        } else {
+          _errorMessage = Provider.of<LoginRespository>(context, listen: false)
+              .errorMessage;
+          Helper.toastMessage(_errorMessage);
+        }
       }
     } catch (err) {
       throw Exception(err);
@@ -85,7 +118,7 @@ class _LoginOtpPageState extends State<LoginOtpPage> {
               child: Column(
                 children: [
                   Container(
-                    padding: const EdgeInsets.only(top: 100, bottom: 100),
+                    padding: const EdgeInsets.only(top: 60, bottom: 60),
                     child: Center(
                       child: Image.asset(
                         'assets/images/logo.png',
@@ -227,8 +260,11 @@ class _LoginOtpPageState extends State<LoginOtpPage> {
                                       Align(
                                           alignment: Alignment.center,
                                           child: Text(
-                                            AppLocalizations.of(context)!
-                                                .signIn,
+                                            widget.loginRequest
+                                                ? AppLocalizations.of(context)!
+                                                    .signIn
+                                                : AppLocalizations.of(context)!
+                                                    .submit,
                                             textAlign: TextAlign.center,
                                             style: GoogleFonts.lato(
                                                 color: Colors.white,
diff --git a/lib/repositories/application_repository.dart b/lib/repositories/application_repository.dart
index 90b4687..d1d1fc7 100644
--- a/lib/repositories/application_repository.dart
+++ b/lib/repositories/application_repository.dart
@@ -6,7 +6,7 @@ import 'package:smf_mobile/database/offline_model.dart';
 import 'package:smf_mobile/models/application_model.dart';
 import 'package:smf_mobile/services/application_service.dart';
 import 'package:smf_mobile/util/helper.dart';
-import 'dart:developer' as developer;
+// import 'dart:developer' as developer;
 
 class ApplicationRespository with ChangeNotifier {
   late Map _data;
@@ -14,20 +14,19 @@ class ApplicationRespository with ChangeNotifier {
   String _errorMessage = '';
 
   Future<dynamic> getApplications(bool internetConnected) async {
-    String rawUserId = await Helper.getUser(Storage.userId);
-    int userId = int.parse(rawUserId);
+    String username = await Helper.getUser(Storage.username);
     try {
       if (internetConnected) {
         final request = await ApplicationService.getApplications();
         _data = json.decode(request.body);
         Map<String, Object> data = {
-          'user_id': userId,
+          'username': username,
           'application_data': request.body
         };
-        await OfflineModel.deleteApplications(userId);
+        await OfflineModel.deleteApplications(username);
         await OfflineModel.saveApplications(data);
       } else {
-        var applications = await OfflineModel.getApplications(userId);
+        var applications = await OfflineModel.getApplications(username);
         _data = json.decode(applications['application_data']);
       }
     } catch (_) {
@@ -44,32 +43,60 @@ class ApplicationRespository with ChangeNotifier {
     return _applications;
   }
 
-  Future<dynamic> submitInspection(Map data) async {
+  Future<dynamic> submitInspection(bool internetConnected, Map data) async {
     try {
-      final request = await ApplicationService.submitInspection(data);
-      _data = json.decode(request.body);
+      if (!internetConnected) {
+        Map<String, Object> applicationData = {
+          'inspector_type': Inspector.leadInspector,
+          'inspection_data': data
+        };
+        await OfflineModel.saveInspection(applicationData);
+      } else {
+        final request = await ApplicationService.submitInspection(data);
+        _data = json.decode(request.body);
+      }
     } catch (_) {
       return _;
     }
-
-    if (_data['statusInfo']['statusCode'] != 200) {
-      _errorMessage = _data['statusInfo']['errorMessage'];
+    int statusCode;
+    if (internetConnected) {
+      if (_data['statusInfo']['statusCode'] != 200) {
+        _errorMessage = _data['statusInfo']['errorMessage'];
+      }
+      statusCode = _data['statusInfo']['statusCode'];
+    } else {
+      statusCode = 200;
     }
-    return _data['statusInfo']['statusCode'];
+    // var tData = await OfflineModel.getInspections();
+    // developer.log(tData.toString());
+    return statusCode;
   }
 
-  Future<dynamic> submitConcent(Map data) async {
+  Future<dynamic> submitConcent(bool internetConnected, Map data) async {
     try {
-      final request = await ApplicationService.submitConcent(data);
-      _data = json.decode(request.body);
+      if (!internetConnected) {
+        Map<String, Object> applicationData = {
+          'inspector_type': Inspector.assistantInspector,
+          'inspection_data': data
+        };
+        await OfflineModel.saveInspection(applicationData);
+      } else {
+        final request = await ApplicationService.submitConcent(data);
+        _data = json.decode(request.body);
+      }
     } catch (_) {
       return _;
     }
-
-    if (_data['statusInfo']['statusCode'] != 200) {
-      _errorMessage = _data['statusInfo']['errorMessage'];
+    int statusCode;
+    if (internetConnected) {
+      if (_data['statusInfo']['statusCode'] != 200) {
+        _errorMessage = _data['statusInfo']['errorMessage'];
+      }
+      statusCode = _data['statusInfo']['statusCode'];
+    } else {
+      statusCode = 200;
     }
-    return _data['statusInfo']['statusCode'];
+    return statusCode;
   }
 
   String get errorMessage => _errorMessage;
diff --git a/lib/repositories/login_repository.dart b/lib/repositories/login_repository.dart
index a6fa747..dd1adc3 100644
--- a/lib/repositories/login_repository.dart
+++ b/lib/repositories/login_repository.dart
@@ -2,11 +2,13 @@ import 'dart:convert';
 import 'package:firebase_messaging/firebase_messaging.dart';
 import 'package:flutter/widgets.dart';
 import 'package:smf_mobile/constants/app_constants.dart';
+import 'package:smf_mobile/landing_page.dart';
+// import 'package:smf_mobile/constants/app_urls.dart';
+// import 'package:smf_mobile/landing_page.dart';
 import 'package:smf_mobile/models/login_model.dart';
 import 'package:flutter_secure_storage/flutter_secure_storage.dart';
 import 'package:smf_mobile/services/login_service.dart';
-import 'package:smf_mobile/util/helper.dart';
-import 'package:smf_mobile/util/notification_helper.dart';
+// import 'package:smf_mobile/util/notification_helper.dart';
 
 class LoginRespository with ChangeNotifier {
   late Map _data;
@@ -26,16 +28,38 @@ class LoginRespository with ChangeNotifier {
 
     if (_data['statusInfo']['statusCode'] != 200) {
       _errorMessage = _data['statusInfo']['errorMessage'];
-    } else {
-      _storage.write(key: 'username', value: username);
     }
     return _data['statusInfo']['statusCode'];
   }
 
-  Future<dynamic> validateOtp(context, String otp, String identifier) async {
+  Future<dynamic> generatePin(String username, String pin, String otp) async {
     try {
-      final username = await _storage.read(key: 'username');
-      final request = await LoginService.validateOtp(username!, otp);
+      final request = await LoginService.generatePin(username, pin, otp);
+      _data = json.decode(request.body);
+    } catch (_) {
+      return _;
+    }
+
+    if (_data['statusInfo']['statusCode'] != 200) {
+      _errorMessage = _data['statusInfo']['errorMessage'];
+    }
+    return _data['responseData'];
+  }
+
+  Future<dynamic> validateOtp(context, String username, String otp,
+      String identifier, String pin, bool isOtp) async {
+    print('res validateOtp');
+    try {
+      Map requestData = {};
+      if (isOtp) {
+        requestData = {'username': username, 'otp': otp};
+      } else {
+        requestData = {
+          'username': username,
+          'pin': pin,
+        };
+      }
+      final request = await LoginService.validateOtp(requestData);
       _data = json.decode(request.body);
     } catch (_) {
       return _;
@@ -59,7 +83,7 @@ class LoginRespository with ChangeNotifier {
         _data = json.decode(request.body);
         // print(_data);
         if (_data['statusInfo']['statusCode'] == 200) {
-          // print('_configureMessaging...');
+          print('_configureMessaging...');
           _configureMessaging(context);
         }
       });
@@ -67,7 +91,7 @@ class LoginRespository with ChangeNotifier {
     return _data['statusInfo']['statusCode'];
   }
 
-  _configureMessaging(context) async {
+  void _configureMessaging(context) async {
     NotificationSettings settings = await _firebaseMessaging.requestPermission(
       alert: true,
       announcement: false,
@@ -77,19 +101,16 @@ class LoginRespository with ChangeNotifier {
       provisional: false,
       sound: true,
     );
-    // print('User granted permission: ${settings.authorizationStatus}');
+    print('User granted permission: ${settings.authorizationStatus}');
 
-    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
-      // print('message.notification...');
-      if (message.notification != null) {
-        // int uniqueNotificationId = Helper.getUniqueId();
-        String body = message.notification!.body.toString();
-        NotificationHelper.scheduleNotification(context, DateTime.now(), 0,
-            message.notification!.title.toString(), body);
-      }
-      print('Message data: $message');
+    FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
+
+    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
+      // print('onMessageOpenedApp ${message.data}');
+      // await _storage.write(
+      //     key: Storage.applicationId,
+      //     value: '${message.data['application_id']}');
     });
-    return;
   }
 
   Future<void> clearData() async {
diff --git a/lib/routes.dart b/lib/routes.dart
index 3e49c95..d2a5a57 100644
--- a/lib/routes.dart
+++ b/lib/routes.dart
@@ -20,7 +20,10 @@ class Routes {
 
         case AppUrl.loginOtpPage:
           return MaterialPageRoute(
-              settings: routeSettings, builder: (_) => const LoginOtpPage());
+              settings: routeSettings,
+              builder: (_) => const LoginOtpPage(
+                    username: '',
+                  ));
 
         case AppUrl.homePage:
           return MaterialPageRoute(
diff --git a/lib/services/login_service.dart b/lib/services/login_service.dart
index 6df9e5a..83d6400 100644
--- a/lib/services/login_service.dart
+++ b/lib/services/login_service.dart
@@ -9,7 +9,10 @@ class LoginService extends BaseService {
   LoginService(HttpClient client) : super(client);
 
   static Future<dynamic> getOtp(String username) async {
-    Map requestData = {'username': username, 'isMobile': true};
+    Map requestData = {
+      'username': username,
+      'isMobile': true,
+    };
     var body = json.encode(requestData);
     Map<String, String> headers = await BaseService.getHeaders();
     final response =
@@ -17,12 +20,31 @@ class LoginService extends BaseService {
     return response;
   }
 
-  static Future<dynamic> validateOtp(String username, String otp) async {
-    Map requestData = {'username': username, 'otp': otp};
+  static Future<dynamic> validateOtp(Map requestData) async {
     var body = json.encode(requestData);
     Map<String, String> headers = await BaseService.getHeaders();
     final response = await http.post(Uri.parse(ApiUrl.validateOtp),
         headers: headers, body: body);
+    // developer.log(ApiUrl.validateOtp);
+    // developer.log(jsonEncode(requestData));
+    // developer.log(response.body);
+    return response;
+  }
+
+  static Future<dynamic> generatePin(
+      String username, String pin, String otp) async {
+    Map requestData = {
+      'username': username,
+      'pin': pin,
+      'otp': otp,
+    };
+    var body = json.encode(requestData);
+    Map<String, String> headers = await BaseService.getHeaders();
+    final response = await http.post(Uri.parse(ApiUrl.generatePin),
+        headers: headers, body: body);
+    // developer.log(ApiUrl.generatePin);
+    // developer.log(jsonEncode(requestData));
+    // developer.log(response.body);
     return response;
   }
 
diff --git a/lib/util/helper.dart b/lib/util/helper.dart
index ecebd84..65afc96 100644
--- a/lib/util/helper.dart
+++ b/lib/util/helper.dart
@@ -1,4 +1,5 @@
 import 'dart:math';
+import 'package:connectivity_plus/connectivity_plus.dart';
 import 'package:flutter/material.dart';
 import 'package:fluttertoast/fluttertoast.dart';
 import 'package:intl/intl.dart';
@@ -93,4 +94,23 @@ class Helper {
     // print(_inspectionStatus);
     return _inspectionStatus;
   }
+
+  static bool isInternetConnected(source) {
+    bool connected;
+    switch (source.keys.toList()[0]) {
+      case ConnectivityResult.mobile:
+        // print('connected to mobile...');
+        connected = true;
+        break;
+      case ConnectivityResult.wifi:
+        // print('connected to wifi...');
+        connected = true;
+        break;
+      case ConnectivityResult.none:
+      default:
+        // print('offline...');
+        connected = false;
+    }
+    return connected;
+  }
 }
diff --git a/lib/util/notification_helper.dart b/lib/util/notification_helper.dart
index c03623f..fbee26f 100644
--- a/lib/util/notification_helper.dart
+++ b/lib/util/notification_helper.dart
@@ -4,36 +4,36 @@ import 'dart:convert';
 
 import 'package:flutter/material.dart';
 import 'package:flutter_local_notifications/flutter_local_notifications.dart';
-import 'package:smf_mobile/pages/home_page.dart';
+// import 'package:smf_mobile/pages/home_page.dart';
 
 class NotificationHelper {
-  // static BuildContext get context => null;
-  static void onSelectNotification(
-    BuildContext context,
-    String payload,
-  ) {
-    Navigator.of(context).pushReplacement(MaterialPageRoute(
-      builder: (context) => const HomePage(),
-    ));
-  }
+  // static void onSelectNotification(
+  //   BuildContext context,
+  //   String payload,
+  // ) {
+  //   Map data = jsonDecode(payload);
+  //   print('Application ID 2: ' + data['applicationId']);
+  // }
 
   static Future<void> scheduleNotification(
-      BuildContext context,
+      // BuildContext context,
       DateTime scheduledNotificationDateTime,
       int notificationId,
       String title,
-      String notes) async {
+      String notes,
+      String applicationId) async {
     FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
         FlutterLocalNotificationsPlugin();
-    var initializationSettingsAndroid =
-        const AndroidInitializationSettings('flutter_devs');
-    var initializationSettingsIOs = const IOSInitializationSettings();
-    var initSetttings = InitializationSettings(
-        android: initializationSettingsAndroid, iOS: initializationSettingsIOs);
-    flutterLocalNotificationsPlugin.initialize(initSetttings,
-        onSelectNotification: (payload) async {
-      onSelectNotification(context, payload!);
-    });
+    // var initializationSettingsAndroid =
+    //     const AndroidInitializationSettings('flutter_devs');
+    // var initializationSettingsIOs = const IOSInitializationSettings();
+    // var initSetttings = InitializationSettings(
+    //     android: initializationSettingsAndroid, iOS: initializationSettingsIOs);
+    // flutterLocalNotificationsPlugin.initialize(initSetttings,
+    //     onSelectNotification: (payload) async {
+    //   // print('payload: $payload');
+    //   // onSelectNotification(context, payload!);
+    // });
 
     var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
       'channel id',
@@ -43,7 +43,7 @@ class NotificationHelper {
       enableLights: true,
       playSound: true,
       // sound: RawResourceAndroidNotificationSound('mixkit_happy_bell'),
-      largeIcon: DrawableResourceAndroidBitmap('flutter_devs'),
+      // largeIcon: DrawableResourceAndroidBitmap('flutter_devs'),
       styleInformation: BigTextStyleInformation(''),
     );
 
@@ -52,7 +52,7 @@ class NotificationHelper {
         android: androidPlatformChannelSpecifics,
         iOS: iOSPlatformChannelSpecifics);
 
-    Map payload = {};
+    Map payload = {'applicationId': applicationId};
     // ignore: deprecated_member_use
     await flutterLocalNotificationsPlugin.schedule(notificationId, title, notes,
         scheduledNotificationDateTime, platformChannelSpecifics,
-- 
GitLab