Added Login UI and methods

merge-requests/3/head
Zohaib Iqbal Kambrani 3 years ago
parent 21a38df23d
commit 925a993843

Binary file not shown.

@ -0,0 +1,93 @@
Copyright (c) 2014-2015 Wei Huang (wweeiihhuuaanngg@gmail.com)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="38.595" height="38.024" viewBox="0 0 38.595 38.024">
<g id="fingerprint1-scan" transform="translate(0.342 0.655)">
<path id="Path_4539" data-name="Path 4539" d="M38.892,0H33.378A1.379,1.379,0,0,0,32,1.378v8.27a1.378,1.378,0,0,0,2.757,0V2.757h4.135a1.378,1.378,0,1,0,0-2.757Z" transform="translate(-32.342 -0.655)" fill="#28323a"/>
<path id="Path_4540" data-name="Path 4540" d="M38.892,200.27H34.757v-6.892a1.378,1.378,0,1,0-2.757,0v8.27a1.379,1.379,0,0,0,1.378,1.378h5.514a1.378,1.378,0,1,0,0-2.757Z" transform="translate(-32.342 -165.658)" fill="#28323a"/>
<path id="Path_4541" data-name="Path 4541" d="M390.892,0h-5.514a1.378,1.378,0,0,0,0,2.757h4.135V9.649a1.378,1.378,0,0,0,2.757,0V1.378A1.379,1.379,0,0,0,390.892,0Z" transform="translate(-354.018 -0.655)" fill="#28323a"/>
<path id="Path_4542" data-name="Path 4542" d="M390.892,192a1.379,1.379,0,0,0-1.378,1.378v6.892h-4.135a1.378,1.378,0,0,0,0,2.757h5.514a1.379,1.379,0,0,0,1.378-1.378v-8.27A1.379,1.379,0,0,0,390.892,192Z" transform="translate(-354.018 -165.658)" fill="#28323a"/>
<path id="Path_4648" data-name="Path 4648" d="M13.343,0A13.343,13.343,0,1,0,26.686,13.343,13.343,13.343,0,0,0,13.343,0Zm4.924,8.9a1.911,1.911,0,1,1-1.911,1.911A1.912,1.912,0,0,1,18.267,8.9Zm-9.849,0a1.911,1.911,0,1,1-1.911,1.911A1.912,1.912,0,0,1,8.418,8.9Zm12.124,9.083a8.733,8.733,0,0,1-14.4,0A1.169,1.169,0,1,1,8.07,16.657a6.4,6.4,0,0,0,10.55,0,1.168,1.168,0,1,1,1.923,1.325Z" transform="translate(5.611 4.855)" fill="#28323a"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="38.595" height="38.024" viewBox="0 0 38.595 38.024">
<g id="sms-speech-bubble" transform="translate(-1 1.645)">
<g id="textsms">
<path id="Path_4529" data-name="Path 4529" d="M21.992,0H2.444A2.451,2.451,0,0,0,0,2.444V24.436l4.887-4.887h17.1A2.451,2.451,0,0,0,24.436,17.1V2.444A2.451,2.451,0,0,0,21.992,0ZM8.552,11H6.109V8.552H8.552Zm4.887,0H11V8.552H13.44Zm4.887,0H15.883V8.552h2.444Z" transform="translate(8.144 5.013)" fill="#28323a"/>
<path id="Path_4543" data-name="Path 4543" d="M38.892,0H33.378A1.379,1.379,0,0,0,32,1.378v8.27a1.378,1.378,0,0,0,2.757,0V2.757h4.135a1.378,1.378,0,1,0,0-2.757Z" transform="translate(-31 -1.645)" fill="#28323a"/>
<path id="Path_4544" data-name="Path 4544" d="M38.892,200.27H34.757v-6.892a1.378,1.378,0,1,0-2.757,0v8.27a1.379,1.379,0,0,0,1.378,1.378h5.514a1.378,1.378,0,1,0,0-2.757Z" transform="translate(-31 -166.648)" fill="#28323a"/>
<path id="Path_4545" data-name="Path 4545" d="M390.892,0h-5.514a1.378,1.378,0,0,0,0,2.757h4.135V9.649a1.378,1.378,0,0,0,2.757,0V1.378A1.379,1.379,0,0,0,390.892,0Z" transform="translate(-352.676 -1.645)" fill="#28323a"/>
<path id="Path_4546" data-name="Path 4546" d="M390.892,192a1.379,1.379,0,0,0-1.378,1.378v6.892h-4.135a1.378,1.378,0,0,0,0,2.757h5.514a1.379,1.379,0,0,0,1.378-1.378v-8.27A1.379,1.379,0,0,0,390.892,192Z" transform="translate(-352.676 -166.648)" fill="#28323a"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="38.595" height="38.024" viewBox="0 0 38.595 38.024">
<g id="fingerprint-scan" transform="translate(0.342 0.655)">
<path id="Path_4535" data-name="Path 4535" d="M24,0H2.909A2.913,2.913,0,0,0,0,2.909V24a2.913,2.913,0,0,0,2.909,2.909H24A2.913,2.913,0,0,0,26.913,24V2.909A2.913,2.913,0,0,0,24,0ZM5,5.182c5.592-4.061,11.49-4.018,17,.072a.789.789,0,0,1-.47,1.422c-.894,0-6.986-6.478-15.607-.218A.788.788,0,0,1,5,5.182Zm7.349,20.277a.788.788,0,0,1-1.1-.2c-1.111-1.606-3.634-3.4-3.634-6.757a6.063,6.063,0,0,1,5.835-6.255A6.063,6.063,0,0,1,19.291,18.5v.841a.788.788,0,0,1-1.577,0V18.5a4.488,4.488,0,0,0-4.258-4.678A4.488,4.488,0,0,0,9.2,18.5C9.2,22.3,14.037,24.294,12.353,25.459Zm9.8-4.08a4.132,4.132,0,0,1-7.8-2.035c0-3.4-2.327-2.255-1.811-.191a.788.788,0,0,1-1.53.383c-1.074-4.295,4.917-6.037,4.917-.191A2.544,2.544,0,0,0,17.9,21.971c3.65.861,4.733-5.161,1.093-9.037-5.033-5.363-13.16-1.227-13.16,5.148A6.378,6.378,0,0,0,6.95,22.25a.788.788,0,0,1-1.284.916,8.033,8.033,0,0,1-1.408-5.084,9.351,9.351,0,0,1,9.2-9.2c6.8,0,11.128,7.628,8.7,12.5Zm.527-9.761a.788.788,0,0,1-1.075-.293C20.033,8.578,16.234,7.1,13.457,7.1a11.282,11.282,0,0,0-8.175,4.275A.788.788,0,0,1,3.97,10.5a12.781,12.781,0,0,1,9.487-4.977c5.841,0,11.056,5.05,9.222,6.1Z" transform="translate(5.793 4.943)" fill="#28323a"/>
<path id="Path_4539" data-name="Path 4539" d="M38.892,0H33.378A1.379,1.379,0,0,0,32,1.378v8.27a1.378,1.378,0,0,0,2.757,0V2.757h4.135a1.378,1.378,0,1,0,0-2.757Z" transform="translate(-32.342 -0.655)" fill="#28323a"/>
<path id="Path_4540" data-name="Path 4540" d="M38.892,200.27H34.757v-6.892a1.378,1.378,0,1,0-2.757,0v8.27a1.379,1.379,0,0,0,1.378,1.378h5.514a1.378,1.378,0,1,0,0-2.757Z" transform="translate(-32.342 -165.658)" fill="#28323a"/>
<path id="Path_4541" data-name="Path 4541" d="M390.892,0h-5.514a1.378,1.378,0,0,0,0,2.757h4.135V9.649a1.378,1.378,0,0,0,2.757,0V1.378A1.379,1.379,0,0,0,390.892,0Z" transform="translate(-354.018 -0.655)" fill="#28323a"/>
<path id="Path_4542" data-name="Path 4542" d="M390.892,192a1.379,1.379,0,0,0-1.378,1.378v6.892h-4.135a1.378,1.378,0,0,0,0,2.757h5.514a1.379,1.379,0,0,0,1.378-1.378v-8.27A1.379,1.379,0,0,0,390.892,192Z" transform="translate(-354.018 -165.658)" fill="#28323a"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="38.595" height="38.024" viewBox="0 0 38.595 38.024">
<g id="whatsapp_1_" data-name="whatsapp (1)" transform="translate(0.233 -4.309)">
<g id="Group_7424" data-name="Group 7424" transform="translate(4.808 8.729)">
<path id="Path_4537" data-name="Path 4537" d="M0,28.186l2.424-7.271a13.848,13.848,0,1,1,5.468,5.195Z" fill="#2cb742"/>
<path id="Path_4538" data-name="Path 4538" d="M29.341,23.6c-.64-1.209-3-2.591-3-2.591-.534-.3-1.177-.338-1.482.2a12.215,12.215,0,0,1-.961,1.051,1.791,1.791,0,0,1-2.547-.253l-1.935-1.935-1.935-1.935A1.791,1.791,0,0,1,17.23,15.6a12.216,12.216,0,0,1,1.051-.961c.542-.3.508-.948.2-1.482,0,0-1.382-2.358-2.591-3a1.325,1.325,0,0,0-1.557.234l-.854.854c-2.71,2.71-1.376,5.77,1.334,8.48L17.3,22.2l2.477,2.477c2.71,2.71,5.77,4.045,8.48,1.334l.854-.854A1.326,1.326,0,0,0,29.341,23.6Z" transform="translate(-6.169 -5.141)" fill="#fff"/>
</g>
<path id="Path_4547" data-name="Path 4547" d="M38.892,0H33.378A1.379,1.379,0,0,0,32,1.378v8.27a1.378,1.378,0,0,0,2.757,0V2.757h4.135a1.378,1.378,0,1,0,0-2.757Z" transform="translate(-32.233 4.309)" fill="#28323a"/>
<path id="Path_4548" data-name="Path 4548" d="M38.892,200.27H34.757v-6.892a1.378,1.378,0,1,0-2.757,0v8.27a1.379,1.379,0,0,0,1.378,1.378h5.514a1.378,1.378,0,1,0,0-2.757Z" transform="translate(-32.233 -160.693)" fill="#28323a"/>
<path id="Path_4549" data-name="Path 4549" d="M390.892,0h-5.514a1.378,1.378,0,0,0,0,2.757h4.135V9.649a1.378,1.378,0,0,0,2.757,0V1.378A1.379,1.379,0,0,0,390.892,0Z" transform="translate(-353.909 4.309)" fill="#28323a"/>
<path id="Path_4550" data-name="Path 4550" d="M390.892,192a1.379,1.379,0,0,0-1.378,1.378v6.892h-4.135a1.378,1.378,0,0,0,0,2.757h5.514a1.379,1.379,0,0,0,1.378-1.378v-8.27A1.379,1.379,0,0,0,390.892,192Z" transform="translate(-353.909 -160.693)" fill="#28323a"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

@ -2,6 +2,30 @@
"mohemm": "Mohemm",
"english": "English",
"arabic": "عربي",
"login": "تسجيل الدخول"
"login": "تسجيل الدخول",
"drSulaiman": "سليمان الحبيب",
"welcomeTo": "مرحبا بك في",
"userID" : "معرف المستخدم",
"password" : "كلمة المرور",
"branch" : "فرع",
"pleaseEnterLoginDetails": "الرجاء إدخال التفاصيل أدناه لتسجيل الدخول",
"username": "اسم المستخدم",
"welcomeBack": "مرحبا بعودتك",
"wouldYouLikeToLoginWithCurrentUsername": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟",
"lastLoginDetails": "تفاصيل تسجيل الدخول الأخير:",
"verificationType": "نوع التحقق:",
"pleaseVerify": "ارجوك تحقق",
"pleaseVerifyForBio": "الرجاء التحقق من تسجيل الدخول باستخدام أحد هذه الخيارات",
"verifyThroughFace": "تحقق من خلال الوجه",
"verifyThroughFingerprint": "تحقق من خلال بصمة الإصبع",
"verifyThroughSMS": "تحقق من خلال الرسائل القصيرة",
"verifyThroughWhatsapp": "تحقق من خلال Whatsapp",
"useAnotherAccount": "استخدم حسابا آخر",
"pleaseEnterTheVerificationCodeSentTo": "الرجاء إدخال رمز التحقق المرسل إلى ",
"theVerificationCodeWillExpireIn": "ستنتهي صلاحية رمز التحقق في ",
"goodMorning": "صباح الخير",
"markAttendance": "علامة الحضور",
"timeLeftToday": "الوقت المتبقي اليوم",
"checkIn": "تحقق في",
"workList": "قائمة العمل"
}

@ -2,6 +2,30 @@
"mohemm": "Mohemm",
"english": "English",
"arabic": "عربي",
"login": "Login"
"login": "Login",
"drSulaiman" : "Dr Sulaiman Al Habib",
"welcomeTo": "Welcome to",
"userID" : "User ID",
"password" : "Password",
"branch" : "Branch",
"pleaseEnterLoginDetails": "Please enter the detail below to login",
"username": "Username",
"welcomeBack": "Welcome back",
"wouldYouLikeToLoginWithCurrentUsername": "Would you like to login with current Username?",
"lastLoginDetails": "Last Login Details:",
"verificationType": "Verification Type:",
"pleaseVerify": "Please Verify",
"pleaseVerifyForBio": "Please verify login with one of the following options",
"verifyThroughFace": "Verify Through Face",
"verifyThroughFingerprint": "Verify Through Fingerprint",
"verifyThroughSMS": "Verify Through SMS",
"verifyThroughWhatsapp": "Verify Through Whatsapp",
"useAnotherAccount": "Use Another Account",
"pleaseEnterTheVerificationCodeSentTo": "Please enter the verification code sent to ",
"theVerificationCodeWillExpireIn": "The verification code will expire in ",
"goodMorning": "Good Morning",
"markAttendance": "Mark Attendance",
"timeLeftToday": "Time Left Today",
"checkIn": "Check In",
"workList": "Work List"
}

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

@ -1,25 +1,17 @@
import 'package:flutter/material.dart';
import 'package:hmg_nurses/ui/login/splash_page.dart';
import 'package:hmg_nurses/ui/login/login_method_page.dart';
import 'package:hmg_nurses/ui/login/login_page.dart';
class AppRoutes {
//Login
static const String splash = "/splash";
static const String registerSelection = "/registerSelection";
static const String loginVerifyAccount = "/loginVerifyAccount";
static const String loginMethodsPage = "/loginMethodsPage";
static const String login = "/login";
static final Map<String, WidgetBuilder> routes = {
//Login
splash: (BuildContext context) => SplashPage(),
// login: (BuildContext context) => LoginScreen(),
login: (BuildContext context) => const LoginPage(),
loginMethodsPage: (BuildContext context) => const LoginMethodsPage(),
};
}

@ -6,15 +6,75 @@ import 'dart:ui';
import 'package:easy_localization/easy_localization.dart' show AssetLoader;
class CodegenLoader extends AssetLoader {
class CodegenLoader extends AssetLoader{
const CodegenLoader();
@override
Future<Map<String, dynamic>> load(String fullPath, Locale locale) {
Future<Map<String, dynamic>> load(String fullPath, Locale locale ) {
return Future.value(mapLocales[locale.toString()]);
}
static const Map<String, dynamic> ar_SA = {"mohemm": "Mohemm", "english": "English", "arabic": "عربي", "login": "تسجيل الدخول"};
static const Map<String, dynamic> en_US = {"mohemm": "Mohemm", "english": "English", "arabic": "عربي", "login": "Login"};
static const Map<String, Map<String, dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
static const Map<String,dynamic> ar_SA = {
"mohemm": "Mohemm",
"english": "English",
"arabic": "عربي",
"login": "تسجيل الدخول",
"drSulaiman": "سليمان الحبيب",
"welcomeTo": "مرحبا بك في",
"userID": "معرف المستخدم",
"password": "كلمة المرور",
"branch": "فرع",
"pleaseEnterLoginDetails": "الرجاء إدخال التفاصيل أدناه لتسجيل الدخول",
"username": "اسم المستخدم",
"welcomeBack": "مرحبا بعودتك",
"wouldYouLikeToLoginWithCurrentUsername": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟",
"lastLoginDetails": "تفاصيل تسجيل الدخول الأخير:",
"verificationType": "نوع التحقق:",
"pleaseVerify": "ارجوك تحقق",
"pleaseVerifyForBio": "الرجاء التحقق من تسجيل الدخول باستخدام أحد هذه الخيارات",
"verifyThroughFace": "تحقق من خلال الوجه",
"verifyThroughFingerprint": "تحقق من خلال بصمة الإصبع",
"verifyThroughSMS": "تحقق من خلال الرسائل القصيرة",
"verifyThroughWhatsapp": "تحقق من خلال Whatsapp",
"useAnotherAccount": "استخدم حسابا آخر",
"pleaseEnterTheVerificationCodeSentTo": "الرجاء إدخال رمز التحقق المرسل إلى ",
"theVerificationCodeWillExpireIn": "ستنتهي صلاحية رمز التحقق في ",
"goodMorning": "صباح الخير",
"markAttendance": "علامة الحضور",
"timeLeftToday": "الوقت المتبقي اليوم",
"checkIn": "تحقق في",
"workList": "قائمة العمل"
};
static const Map<String,dynamic> en_US = {
"mohemm": "Mohemm",
"english": "English",
"arabic": "عربي",
"login": "Login",
"drSulaiman": "Dr Sulaiman Al Habib",
"welcomeTo": "Welcome to",
"userID": "User ID",
"password": "Password",
"branch": "Branch",
"pleaseEnterLoginDetails": "Please enter the detail below to login",
"username": "Username",
"welcomeBack": "Welcome back",
"wouldYouLikeToLoginWithCurrentUsername": "Would you like to login with current Username?",
"lastLoginDetails": "Last Login Details:",
"verificationType": "Verification Type:",
"pleaseVerify": "Please Verify",
"pleaseVerifyForBio": "Please verify login with one of the following options",
"verifyThroughFace": "Verify Through Face",
"verifyThroughFingerprint": "Verify Through Fingerprint",
"verifyThroughSMS": "Verify Through SMS",
"verifyThroughWhatsapp": "Verify Through Whatsapp",
"useAnotherAccount": "Use Another Account",
"pleaseEnterTheVerificationCodeSentTo": "Please enter the verification code sent to ",
"theVerificationCodeWillExpireIn": "The verification code will expire in ",
"goodMorning": "Good Morning",
"markAttendance": "Mark Attendance",
"timeLeftToday": "Time Left Today",
"checkIn": "Check In",
"workList": "Work List"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -78,7 +78,7 @@ class MyApp extends StatelessWidget {
localizationsDelegates: delegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
initialRoute: AppRoutes.splash,
initialRoute: AppRoutes.login,
routes: AppRoutes.routes,
);
},

@ -0,0 +1,187 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:hmg_nurses/classes/colors.dart';
import 'package:hmg_nurses/classes/utils.dart';
import 'package:hmg_nurses/generated/locale_keys.g.dart';
import 'package:local_auth/local_auth.dart';
import 'package:sizer/sizer.dart';
// WhatsApp 2
// SMS 1
// Face ID 3
// Finger Print 4
class LoginMethodsPage extends StatefulWidget {
const LoginMethodsPage({Key? key}) : super(key: key);
@override
LoginMethodsPageState createState() => LoginMethodsPageState();
}
class LoginMethodsPageState extends State<LoginMethodsPage> {
final LocalAuthentication localAuth = LocalAuthentication();
List<BiometricType> _availableBioMetricType = [];
int selectedFlag = 0;
bool isNeedVerifyWithFaceIDAndBiometrics = false;
@override
void initState() {
_getAvailableBiometrics();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
onPressed: () => Navigator.pop(context),
),
// actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width],
),
body: ListView(
padding: const EdgeInsets.all(21),
physics: const BouncingScrollPhysics(),
children: [
Text(
LocaleKeys.pleaseVerifyForBio.tr(),
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w600),
),
if (isNeedVerifyWithFaceIDAndBiometrics) Text(LocaleKeys.pleaseVerifyForBio.tr()),
GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9),
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.only(top: 9),
shrinkWrap: true,
children: [
if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(3),
if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(4),
getButton(2),
getButton(1),
],
)
],
),
);
}
Future<void> _getAvailableBiometrics() async {
try {
_availableBioMetricType = await localAuth.getAvailableBiometrics();
} on PlatformException catch (e) {
// AppToast.showErrorToast(message: e.message);
if (kDebugMode) {
print(e);
}
}
if (mounted) setState(() {});
}
Future<bool> loginWithFaceIDAndBiometrics() async {
bool authenticated = false;
try {
authenticated = await localAuth.authenticate(
localizedReason: 'Scan your fingerprint to authenticate',
);
} on PlatformException catch (e) {
if (kDebugMode) {
print(e);
}
Utils.hideLoading(context);
Utils.showToast("Please enable your Touch or Face ID");
}
return authenticated;
}
Widget _loginOptionButton(String title, String icon, int flag, int? loginIndex) {
bool isDisable = ((flag == 3 && !checkBiometricIsAvailable(BiometricType.face)) || (flag == 4 && !checkBiometricIsAvailable(BiometricType.fingerprint)));
return InkWell(
onTap: isDisable
? null
: () async {
if (flag == 0) {
setState(() {
// isMoreOption = true;
});
} else {
if (flag == 3 || flag == 4) {
bool authenticateWithFaceAndTouchID = await loginWithFaceIDAndBiometrics();
if (!authenticateWithFaceAndTouchID) {
return;
} else {
isNeedVerifyWithFaceIDAndBiometrics = true;
selectedFlag = flag;
setState(() {
return;
});
}
} else {
if (isNeedVerifyWithFaceIDAndBiometrics) {
// performApiCall(_title, _icon, selectedFlag, _flag);
} else {
// performApiCall(_title, _icon, _flag, _flag);
}
}
}
},
child: Container(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 28),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: isDisable ? Colors.grey.withOpacity(0.3) : Colors.white,
border: Border.all(color: MyColors.lightGreyEFColor, width: 1),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SvgPicture.asset(
icon,
height: 38,
width: 38,
color: isDisable ? MyColors.darkTextColor.withOpacity(0.7) : null,
),
Text(
title,
style: const TextStyle(fontWeight: FontWeight.w600),
)
],
),
),
);
}
Widget getButton(int flag) {
switch (flag) {
case 1:
return _loginOptionButton(LocaleKeys.verifyThroughSMS.tr(), 'assets/images/login/verify_sms.svg', flag, null);
case 2:
return _loginOptionButton(LocaleKeys.verifyThroughWhatsapp.tr(), 'assets/images/login/verify_whatsapp.svg', flag, null);
case 3:
return _loginOptionButton(LocaleKeys.verifyThroughFace.tr(), 'assets/images/login/verify_face.svg', flag, BiometricType.face.index);
case 4:
return _loginOptionButton(LocaleKeys.verifyThroughFingerprint.tr(), 'assets/images/login/verify_thumb.svg', flag, BiometricType.fingerprint.index);
default:
return const SizedBox();
}
}
bool checkBiometricIsAvailable(BiometricType biometricType) {
bool isAvailable = false;
for (int i = 0; i < _availableBioMetricType.length; i++) {
if (biometricType == _availableBioMetricType[i]) {
isAvailable = true;
break;
}
}
return isAvailable;
}
}

@ -0,0 +1,113 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_nurses/classes/colors.dart';
import 'package:hmg_nurses/config/routes.dart';
import 'package:hmg_nurses/generated/locale_keys.g.dart';
import 'package:hmg_nurses/widgets/button/default_button.dart';
import 'package:hmg_nurses/widgets/cupertino_picker.dart';
import 'package:hmg_nurses/widgets/input_widget.dart';
import 'package:sizer/sizer.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final loginFormKey = GlobalKey<FormState>();
var projectIdController = TextEditingController();
var userIdController = TextEditingController();
var passwordController = TextEditingController();
SizedBox buildSpacer20h() => SizedBox(height: 3.h);
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10.h),
Padding(
padding: EdgeInsets.only(left: 8.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
LocaleKeys.welcomeTo.tr(),
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600, fontFamily: 'Poppins'),
),
Text(
LocaleKeys.drSulaiman.tr(),
style: TextStyle(color: MyColors.blackColor, fontWeight: FontWeight.bold, fontSize: 24.sp, fontFamily: 'Poppins'),
),
Text(
"Nurses App",
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600, color: MyColors.redColor),
),
],
),
),
SizedBox(height: 4.h),
Form(
key: loginFormKey,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.w),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
buildSpacer20h(),
CustomTextField(
LocaleKeys.userID.tr(),
userIdController,
isEnableBorder: true,
),
buildSpacer20h(),
CustomTextField(
LocaleKeys.password.tr(),
passwordController,
isTextIsPassword: true,
),
buildSpacer20h(),
CustomTextField(
LocaleKeys.branch.tr(),
projectIdController,
hasSelection: true,
isEnable: false,
onClick: () {
CustomCupertinoPicker.showCupertinoPicker(context, [], (){});
},
),
buildSpacer20h()
]),
),
)
],
),
),
bottomSheet: Container(
height: 12.h,
color: MyColors.backgroundColor,
width: double.infinity,
child: Center(
child: FractionallySizedBox(
widthFactor: 0.9,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 4.w),
child: DefaultButton(LocaleKeys.login.tr(), () {
Navigator.pushNamed(context, AppRoutes.loginMethodsPage);
}, colors: const [MyColors.redColor, MyColors.redColor]),
),
SizedBox(height: 3.h)
],
),
),
),
),
);
}
}

@ -0,0 +1,71 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hmg_nurses/generated/locale_keys.g.dart';
import 'package:sizer/sizer.dart';
class CustomCupertinoPicker {
static TextStyle textStyle(context) => TextStyle(color: Theme.of(context).primaryColor);
static int cupertinoPickerIndex = 0;
static buildPickerItems(context, List items, onSelectFun) {
return CupertinoPicker(
magnification: 1.5,
scrollController: FixedExtentScrollController(initialItem: cupertinoPickerIndex),
itemExtent: 25,
looping: false,
onSelectedItemChanged: (int index) {
cupertinoPickerIndex = index;
},
children: items.map((item) {
return Text(
'${item.facilityName}',
style: TextStyle(fontSize: 12.sp),
);
}).toList(),
);
}
static showCupertinoPicker(context, List items, onSelectFun) {
showModalBottomSheet(
isDismissible: false,
context: context,
builder: (BuildContext builder) {
return Container(
height: 40.h,
color: const Color(0xfff7f7f7),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
color: const Color(0xfff7f7f7),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
CupertinoButton(
child: Text(LocaleKeys.userID.tr(), style: textStyle(context)),
onPressed: () {
Navigator.pop(context);
},
),
CupertinoButton(
child: Text(
LocaleKeys.userID.tr(),
style: textStyle(context),
),
onPressed: () {
Navigator.pop(context);
onSelectFun(cupertinoPickerIndex);
},
)
],
),
),
Container(height: 3.h, color: const Color(0xfff7f7f7), child: buildPickerItems(context, items, onSelectFun))
],
),
);
});
}
}

@ -2,10 +2,11 @@ import 'package:flutter/material.dart';
import 'package:hmg_nurses/classes/colors.dart';
import 'package:hmg_nurses/extensions/int_extensions.dart';
import 'package:hmg_nurses/extensions/widget_extensions.dart';
import 'package:sizer/sizer.dart';
class InputWidget extends StatefulWidget {
class CustomTextField extends StatefulWidget {
final String labelText;
final String hintText;
final String? hintText;
final TextEditingController controller;
final VoidCallback? suffixTap;
final bool isEnable;
@ -18,19 +19,21 @@ class InputWidget extends StatefulWidget {
final double verticalPadding;
final double horizontalPadding;
final Function(String)? onChange;
final Function? onClick;
InputWidget(
const CustomTextField(
this.labelText,
this.hintText,
this.controller, {
Key? key,
this.isTextIsPassword = false,
this.suffixTap,
this.hintText,
this.isEnable = true,
this.hasSelection = false,
this.isEnableBorder = true,
this.lines = 1,
this.onChange,
this.onClick,
this.isInputTypeNum = false,
this.isBackgroundEnable = false,
this.verticalPadding = 15,
@ -38,12 +41,10 @@ class InputWidget extends StatefulWidget {
}) : super(key: key);
@override
_InputWidgetState createState() {
return _InputWidgetState();
}
CustomTextFieldState createState() => CustomTextFieldState();
}
class _InputWidgetState extends State<InputWidget> {
class CustomTextFieldState extends State<CustomTextField> {
late bool isObscureText;
@override
@ -64,27 +65,29 @@ class _InputWidgetState extends State<InputWidget> {
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: widget.isBackgroundEnable ? Color(0xffF7F7F7) : Colors.white,
border: Border.all(
color: widget.isEnableBorder ? Color(0xffefefef) : Colors.transparent,
width: 1,
),
color: widget.isBackgroundEnable ? const Color(0xffF7F7F7) : Colors.white,
border: Border.all(color: widget.isEnableBorder ? Colors.grey.shade300 : Colors.transparent, width: 1),
),
child: InkWell(
onTap: widget.hasSelection ? () {} : null,
onTap: widget.hasSelection
? () {
widget.onClick!();
}
: null,
child: Row(
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
widget.labelText,
style: const TextStyle(
fontSize: 11,
style: TextStyle(
fontSize: 9.sp,
fontWeight: FontWeight.w600,
color: Color(0xff2B353E),
color: const Color(0xff2B353E),
letterSpacing: -0.44,
),
),
@ -133,7 +136,7 @@ class _InputWidgetState extends State<InputWidget> {
});
})
],
if (widget.hasSelection) Icon(Icons.keyboard_arrow_down_outlined),
if (widget.hasSelection) const Icon(Icons.keyboard_arrow_down_outlined),
],
),
),

@ -116,6 +116,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.7"
flutter_svg:
dependency: "direct main"
description:
@ -182,6 +189,41 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
local_auth:
dependency: "direct main"
description:
name: local_auth
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
local_auth_android:
dependency: transitive
description:
name: local_auth_android
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.15"
local_auth_ios:
dependency: transitive
description:
name: local_auth_ios
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.10"
local_auth_platform_interface:
dependency: transitive
description:
name: local_auth_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
local_auth_windows:
dependency: transitive
description:
name: local_auth_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
logger:
dependency: "direct main"
description:

@ -49,6 +49,7 @@ dependencies:
auto_size_text: ^3.0.0
shimmer: ^2.0.0
sizer: ^2.0.15
local_auth: ^2.1.2
dev_dependencies:
flutter_test:
@ -74,4 +75,25 @@ flutter:
assets:
- assets/
- assets/langs/
- assets/langs/
- assets/images/login/
- assets/images/patient/
fonts:
- family: Poppins
fonts:
- asset: assets/fonts/Poppins/Poppins-Regular.ttf
weight: 400
- asset: assets/fonts/Poppins/Poppins-Medium.ttf
weight: 500
- asset: assets/fonts/Poppins/Poppins-SemiBold.ttf
weight: 600
- asset: assets/fonts/Poppins/Poppins-Bold.ttf
weight: 700
- asset: assets/fonts/Poppins/Poppins-Bold.ttf
weight: 800
- asset: assets/fonts/Poppins/Poppins-Bold.ttf
weight: 900

Loading…
Cancel
Save