Merge issue 1.0
@ -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.
|
||||
|
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 |
|
After Width: | Height: | Size: 549 B |
|
After Width: | Height: | Size: 453 B |
|
After Width: | Height: | Size: 453 B |
|
After Width: | Height: | Size: 988 B |
|
After Width: | Height: | Size: 652 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 733 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 940 B |
|
After Width: | Height: | Size: 417 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 995 B |
|
After Width: | Height: | Size: 854 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 399 B |
@ -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"
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_nurses/classes/enums.dart';
|
||||
|
||||
class BaseViewModel extends ChangeNotifier {
|
||||
|
||||
ViewState _state = ViewState.idle;
|
||||
bool isInternetConnection = true;
|
||||
|
||||
ViewState get state => _state;
|
||||
|
||||
String error = "";
|
||||
|
||||
//TODO add the user login model when we need it
|
||||
|
||||
void setState(ViewState viewState) {
|
||||
_state = viewState;
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
enum APPSTATUS { loading, unAuthenticated, authenticated, unverified }
|
||||
enum AuthMethodTypes { sms, whatsApp, fingerPrint, faceID, moreOptions }
|
||||
enum ViewState { idle, busy, error, busyLocal, errorLocal }
|
||||
@ -0,0 +1,103 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:hmg_nurses/classes/consts.dart';
|
||||
|
||||
class SizeConfig {
|
||||
static double _blockWidth = 0;
|
||||
static double _blockHeight = 0;
|
||||
|
||||
static double? realScreenWidth;
|
||||
static double? realScreenHeight;
|
||||
static double? screenWidth;
|
||||
static double? screenHeight;
|
||||
static double? textMultiplier;
|
||||
static double? imageSizeMultiplier;
|
||||
static double? heightMultiplier;
|
||||
static bool isPortrait = true;
|
||||
static double? widthMultiplier;
|
||||
static bool isMobilePortrait = false;
|
||||
static bool isMobile = false;
|
||||
static bool isHeightShort = false;
|
||||
static bool isHeightVeryShort = false;
|
||||
static bool isHeightMiddle = false;
|
||||
static bool isHeightLarge = false;
|
||||
static bool isWidthLarge = false;
|
||||
|
||||
void init(BoxConstraints constraints, Orientation orientation) {
|
||||
realScreenHeight = constraints.maxHeight;
|
||||
realScreenWidth = constraints.maxWidth;
|
||||
if (constraints.maxWidth <= ApiConsts.MAX_SMALL_SCREEN) {
|
||||
isMobile = true;
|
||||
}
|
||||
if (constraints.maxHeight < 600) {
|
||||
isHeightVeryShort = true;
|
||||
} else if (constraints.maxHeight < 800) {
|
||||
isHeightShort = true;
|
||||
} else if (constraints.maxHeight < 1000) {
|
||||
isHeightMiddle = true;
|
||||
} else {
|
||||
isHeightLarge = true;
|
||||
}
|
||||
|
||||
if (constraints.maxWidth > 600) {
|
||||
isWidthLarge = true;
|
||||
}
|
||||
|
||||
if (orientation == Orientation.portrait) {
|
||||
isPortrait = true;
|
||||
if (realScreenWidth! < 450) {
|
||||
isMobilePortrait = true;
|
||||
}
|
||||
// textMultiplier = _blockHeight;
|
||||
// imageSizeMultiplier = _blockWidth;
|
||||
screenHeight = realScreenHeight;
|
||||
screenWidth = realScreenWidth;
|
||||
} else {
|
||||
isPortrait = false;
|
||||
isMobilePortrait = false;
|
||||
// textMultiplier = _blockWidth;
|
||||
// imageSizeMultiplier = _blockHeight;
|
||||
screenHeight = realScreenWidth;
|
||||
screenWidth = realScreenHeight;
|
||||
}
|
||||
_blockWidth = screenWidth! / 100;
|
||||
_blockHeight = screenHeight! / 100;
|
||||
|
||||
textMultiplier = _blockHeight;
|
||||
imageSizeMultiplier = _blockWidth;
|
||||
heightMultiplier = _blockHeight;
|
||||
widthMultiplier = _blockWidth;
|
||||
|
||||
print('realScreenWidth $realScreenWidth');
|
||||
print('realScreenHeight $realScreenHeight');
|
||||
print('textMultiplier $textMultiplier');
|
||||
print('imageSizeMultiplier $imageSizeMultiplier');
|
||||
print('heightMultiplier$heightMultiplier');
|
||||
print('widthMultiplier $widthMultiplier');
|
||||
print('isPortrait $isPortrait');
|
||||
print('isMobilePortrait $isMobilePortrait');
|
||||
}
|
||||
|
||||
static getTextMultiplierBasedOnWidth({double? width}) {
|
||||
// TODO handel LandScape case
|
||||
if (width != null) {
|
||||
return width / 100;
|
||||
}
|
||||
return widthMultiplier;
|
||||
}
|
||||
|
||||
static getWidthMultiplier({double? width}) {
|
||||
// TODO handel LandScape case
|
||||
if (width != null) {
|
||||
return width / 100;
|
||||
}
|
||||
return widthMultiplier;
|
||||
}
|
||||
|
||||
static getHeightMultiplier({double? height}) {
|
||||
// TODO handel LandScape case
|
||||
if (height != null) {
|
||||
return height / 100;
|
||||
}
|
||||
return heightMultiplier;
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AppProvider extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
AppProvider({required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return child;
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
// ChangeNotifierProvider(create: (_) => Counter()),
|
||||
],
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:hmg_nurses/ui/login/login_vm.dart';
|
||||
|
||||
GetIt getIt = GetIt.instance;
|
||||
|
||||
|
||||
void initDependencies () {
|
||||
// TODO; WE WILL REGISTER ALL THE SERVICES HERE AS LAZY SINGLETON
|
||||
|
||||
|
||||
|
||||
//TODO: WE WILL REGISTER ALL THE VIEW MODELS AS FACTORY HERE
|
||||
|
||||
/// View Model
|
||||
getIt.registerFactory(() => LoginViewModel());
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import 'package:hmg_nurses/classes/enums.dart';
|
||||
|
||||
extension SelectedAuthMethodTypesService on AuthMethodTypes {
|
||||
int getTypeIdService() {
|
||||
switch (this) {
|
||||
case AuthMethodTypes.sms:
|
||||
return 1;
|
||||
case AuthMethodTypes.whatsApp:
|
||||
return 2;
|
||||
case AuthMethodTypes.fingerPrint:
|
||||
return 3;
|
||||
case AuthMethodTypes.faceID:
|
||||
return 4;
|
||||
case AuthMethodTypes.moreOptions:
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
static getMethodsTypeService(int typeId) {
|
||||
switch (typeId) {
|
||||
case 1:
|
||||
return AuthMethodTypes.sms;
|
||||
case 2:
|
||||
return AuthMethodTypes.whatsApp;
|
||||
case 3:
|
||||
return AuthMethodTypes.fingerPrint;
|
||||
case 4:
|
||||
return AuthMethodTypes.faceID;
|
||||
case 5:
|
||||
return AuthMethodTypes.moreOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
class GetMobileLoginInfoListModel {
|
||||
int? iD;
|
||||
int? employeeID;
|
||||
int? channelID;
|
||||
int? companyID;
|
||||
String? deviceType;
|
||||
String? deviceToken;
|
||||
int? language;
|
||||
int? gender;
|
||||
int? loginType;
|
||||
String? createdOn;
|
||||
String? editedOn;
|
||||
String? employeeName;
|
||||
bool? businessCardPrivilege;
|
||||
|
||||
GetMobileLoginInfoListModel(
|
||||
{this.iD,
|
||||
this.employeeID,
|
||||
this.channelID,
|
||||
this.companyID,
|
||||
this.deviceType,
|
||||
this.deviceToken,
|
||||
this.language,
|
||||
this.gender,
|
||||
this.loginType,
|
||||
this.createdOn,
|
||||
this.editedOn,
|
||||
this.employeeName,
|
||||
this.businessCardPrivilege});
|
||||
|
||||
GetMobileLoginInfoListModel.fromJson(Map<String, dynamic> json) {
|
||||
iD = json['ID'];
|
||||
employeeID = json['EmployeeID'];
|
||||
channelID = json['ChannelID'];
|
||||
companyID = json['CompanyID'];
|
||||
deviceType = json['DeviceType'];
|
||||
deviceToken = json['DeviceToken'];
|
||||
language = json['Language'];
|
||||
gender = json['Gender'];
|
||||
loginType = json['LoginType'];
|
||||
createdOn = json['CreatedOn'];
|
||||
editedOn = json['EditedOn'];
|
||||
employeeName = json['EmployeeName'];
|
||||
businessCardPrivilege = json['BusinessCardPrivilege'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> data = Map<String, dynamic>();
|
||||
data['ID'] = iD;
|
||||
data['EmployeeID'] = employeeID;
|
||||
data['ChannelID'] = channelID;
|
||||
data['CompanyID'] = companyID;
|
||||
data['DeviceType'] = deviceType;
|
||||
data['DeviceToken'] = deviceToken;
|
||||
data['Language'] = language;
|
||||
data['Gender'] = gender;
|
||||
data['LoginType'] = loginType;
|
||||
data['CreatedOn'] = createdOn;
|
||||
data['EditedOn'] = editedOn;
|
||||
data['EmployeeName'] = employeeName;
|
||||
data['BusinessCardPrivilege'] = businessCardPrivilege;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,310 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hexcolor/hexcolor.dart';
|
||||
import 'package:hmg_nurses/classes/colors.dart';
|
||||
import 'package:hmg_nurses/classes/enums.dart';
|
||||
import 'package:hmg_nurses/classes/size_config.dart';
|
||||
import 'package:hmg_nurses/extensions/string_extensions.dart';
|
||||
import 'package:hmg_nurses/extensions/util_extensions.dart';
|
||||
import 'package:hmg_nurses/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_nurses/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_nurses/ui/login/login_vm.dart';
|
||||
import 'package:hmg_nurses/ui/login/widgets/verification_method_card.dart';
|
||||
import 'package:hmg_nurses/widgets/button/default_button.dart';
|
||||
import 'package:provider/provider.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> {
|
||||
bool isMoreOption = false;
|
||||
bool onlySMSBox = false;
|
||||
late AuthMethodTypes fingerPrintBefore;
|
||||
late AuthMethodTypes selectedOption;
|
||||
late LoginViewModel loginViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
loginViewModel = context.read<LoginViewModel>();
|
||||
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: SingleChildScrollView(
|
||||
child: Center(
|
||||
child: FractionallySizedBox(
|
||||
widthFactor: 0.9,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
SizedBox(height: 1.h),
|
||||
if (loginViewModel.isFromLogin)
|
||||
InkWell(
|
||||
onTap: () {
|
||||
loginViewModel.setUnverified(false, isFromLogin: false);
|
||||
loginViewModel.setAppStatus(APPSTATUS.unAuthenticated);
|
||||
},
|
||||
child: const Icon(Icons.arrow_back_ios, color: MyColors.darkTextColor)),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
isMoreOption != null && isMoreOption == false
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
LocaleKeys.welcomeBack.tr().toText12(),
|
||||
SizedBox(height: 1.h),
|
||||
"Faiz Hashmi".toText24(isBold: true),
|
||||
SizedBox(height: 3.h),
|
||||
LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText18(),
|
||||
SizedBox(height: 3.h),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
border: Border.all(color: HexColor('#707070'), width: 0.1),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
LocaleKeys.lastLoginDetails.tr(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Poppins',
|
||||
fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * 4.8,
|
||||
color: Color(0xFF2E303A),
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.4),
|
||||
),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.55,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
text: "${LocaleKeys.verificationType.tr()} ",
|
||||
style: TextStyle(
|
||||
color: const Color(0xFF575757),
|
||||
fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * 3.5,
|
||||
fontFamily: 'Poppins',
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.4),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: loginViewModel.getType(1),
|
||||
style: TextStyle(
|
||||
color: MyColors.darkTextColor,
|
||||
fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * 3.5,
|
||||
fontFamily: 'Poppins',
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.48),
|
||||
)
|
||||
]),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"12 NOV, 2022",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Poppins',
|
||||
fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * 4.2,
|
||||
color: Color(0xFF2E303A),
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: -0.4),
|
||||
),
|
||||
|
||||
Text(
|
||||
"09:56 AM",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Poppins',
|
||||
fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * 3.5,
|
||||
color: Color(0xFF2E303A),
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.4),
|
||||
),
|
||||
// AppText(
|
||||
// loginViewModel.user.editedOn != null
|
||||
// ? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(loginViewModel.user.editedOn), isMonthShort: true)
|
||||
// : loginViewModel.user.createdOn != null
|
||||
// ? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(loginViewModel.user.createdOn), isMonthShort: true)
|
||||
// : '--',
|
||||
// textAlign: TextAlign.right,
|
||||
// fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * 4.5,
|
||||
// color: Color(0xFF2E303A),
|
||||
// fontWeight: FontWeight.w700,
|
||||
// letterSpacing: -0.48,
|
||||
// ),
|
||||
// AppText(
|
||||
// loginViewModel.user.editedOn != null
|
||||
// ? AppDateUtils.getHour(AppDateUtils.convertStringToDate(loginViewModel.user.editedOn))
|
||||
// : loginViewModel.user.createdOn != null
|
||||
// ? AppDateUtils.getHour(AppDateUtils.convertStringToDate(loginViewModel.user.createdOn))
|
||||
// : '--',
|
||||
// textAlign: TextAlign.right,
|
||||
// fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * 3.5,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// letterSpacing: -0.48,
|
||||
// color: Color(0xFF575757),
|
||||
// )
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: SizeConfig.heightMultiplier! * 3),
|
||||
Row(
|
||||
children: [
|
||||
//todo add translation
|
||||
LocaleKeys.pleaseVerify.tr().toText18().paddingOnly(left: 8),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: SizeConfig.heightMultiplier! * 2,
|
||||
),
|
||||
],
|
||||
)
|
||||
: Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
|
||||
onlySMSBox == true
|
||||
? Container(
|
||||
margin: const EdgeInsets.only(bottom: 20, top: 30),
|
||||
child: LocaleKeys.pleaseVerify.tr().toText16(),
|
||||
)
|
||||
: LocaleKeys.pleaseVerify.tr().toText16(),
|
||||
]),
|
||||
isMoreOption != null && isMoreOption == false
|
||||
? Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
|
||||
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
|
||||
Expanded(
|
||||
child: VerificationMethodsList(
|
||||
loginViewModel: loginViewModel,
|
||||
authMethodType: SelectedAuthMethodTypesService.getMethodsTypeService(1),
|
||||
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
|
||||
loginViewModel.startSMSService(authMethodType, context: context);
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: VerificationMethodsList(
|
||||
loginViewModel: loginViewModel,
|
||||
authMethodType: AuthMethodTypes.moreOptions,
|
||||
onShowMore: () {
|
||||
setState(() {
|
||||
isMoreOption = true;
|
||||
});
|
||||
},
|
||||
))
|
||||
]),
|
||||
])
|
||||
: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
|
||||
onlySMSBox == false
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: VerificationMethodsList(
|
||||
loginViewModel: loginViewModel,
|
||||
authMethodType: AuthMethodTypes.fingerPrint,
|
||||
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
|
||||
loginViewModel.startSMSService(authMethodType, context: context);
|
||||
},
|
||||
)),
|
||||
Expanded(
|
||||
child: VerificationMethodsList(
|
||||
loginViewModel: loginViewModel,
|
||||
authMethodType: AuthMethodTypes.faceID,
|
||||
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
|
||||
loginViewModel.startSMSService(authMethodType, context: context);
|
||||
},
|
||||
))
|
||||
],
|
||||
)
|
||||
: const SizedBox(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: VerificationMethodsList(
|
||||
loginViewModel: loginViewModel,
|
||||
authMethodType: AuthMethodTypes.sms,
|
||||
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
|
||||
loginViewModel.startSMSService(authMethodType, context: context);
|
||||
},
|
||||
)),
|
||||
Expanded(
|
||||
child: VerificationMethodsList(
|
||||
loginViewModel: loginViewModel,
|
||||
authMethodType: AuthMethodTypes.whatsApp,
|
||||
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
|
||||
loginViewModel.startSMSService(authMethodType, context: context);
|
||||
},
|
||||
))
|
||||
],
|
||||
),
|
||||
]),
|
||||
|
||||
// )
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomSheet: !isMoreOption
|
||||
? null
|
||||
: Container(
|
||||
height: 10.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.useAnotherAccount.tr(), () {}, colors: const [MyColors.redColor, MyColors.redColor]),
|
||||
),
|
||||
SizedBox(height: 3.h)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
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,141 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hmg_nurses/base/base_vm.dart';
|
||||
import 'package:hmg_nurses/classes/enums.dart';
|
||||
import 'package:hmg_nurses/classes/utils.dart';
|
||||
import 'package:hmg_nurses/dialogs/otp_dialog.dart';
|
||||
import 'package:hmg_nurses/generated/locale_keys.g.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
|
||||
class LoginViewModel extends BaseViewModel {
|
||||
bool isLogin = false;
|
||||
bool unverified = false;
|
||||
bool isFromLogin = false;
|
||||
APPSTATUS appStatus = APPSTATUS.loading;
|
||||
String localToken = "";
|
||||
|
||||
String nurseProfile = "";
|
||||
|
||||
final LocalAuthentication auth = LocalAuthentication();
|
||||
late List<BiometricType> _availableBiometrics;
|
||||
|
||||
LoginViewModel();
|
||||
|
||||
/// get type name based on id.
|
||||
getType(type) {
|
||||
switch (type) {
|
||||
case 1:
|
||||
return LocaleKeys.sms.tr();
|
||||
case 3:
|
||||
return LocaleKeys.fingerPrint.tr();
|
||||
case 4:
|
||||
return LocaleKeys.face.tr();
|
||||
case 2:
|
||||
return LocaleKeys.whatsapp.tr();
|
||||
default:
|
||||
return LocaleKeys.sms.tr();
|
||||
}
|
||||
}
|
||||
|
||||
/// ask user to add his biometric
|
||||
showIOSAuthMessages() async {
|
||||
try {
|
||||
await auth.authenticate(
|
||||
localizedReason: 'Scan your fingerprint to authenticate',
|
||||
);
|
||||
} on PlatformException catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// check specific biometric if it available or not
|
||||
Future<bool> checkIfBiometricAvailable(BiometricType biometricType) async {
|
||||
bool isAvailable = false;
|
||||
await _getAvailableBiometrics();
|
||||
if (_availableBiometrics != null) {
|
||||
for (var i = 0; i < _availableBiometrics.length; i++) {
|
||||
if (biometricType == _availableBiometrics[i]) isAvailable = true;
|
||||
}
|
||||
}
|
||||
return isAvailable;
|
||||
}
|
||||
|
||||
/// get all available biometric on the device for local Auth service
|
||||
Future<void> _getAvailableBiometrics() async {
|
||||
try {
|
||||
_availableBiometrics = await auth.getAvailableBiometrics();
|
||||
} on PlatformException catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// determine the status of the app
|
||||
APPSTATUS get status {
|
||||
if (state == ViewState.busy) {
|
||||
appStatus = APPSTATUS.loading;
|
||||
} else {
|
||||
if (nurseProfile != null) {
|
||||
appStatus = APPSTATUS.authenticated;
|
||||
} else if (unverified) {
|
||||
appStatus = APPSTATUS.unverified;
|
||||
} else if (isLogin) {
|
||||
appStatus = APPSTATUS.authenticated;
|
||||
} else {
|
||||
appStatus = APPSTATUS.unAuthenticated;
|
||||
}
|
||||
}
|
||||
return appStatus;
|
||||
}
|
||||
|
||||
setAppStatus(APPSTATUS status) {
|
||||
appStatus = status;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
setUnverified(bool unverified, {bool isFromLogin = false}) {
|
||||
this.unverified = unverified;
|
||||
this.isFromLogin = isFromLogin;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// logout function
|
||||
logout({bool isFromLogin = false}) async {
|
||||
// localToken = "";
|
||||
// String lang = await sharedPref.getString(APP_Language);
|
||||
// await Utils.clearSharedPref();
|
||||
// doctorProfile = null;
|
||||
// sharedPref.setString(APP_Language, lang);
|
||||
// deleteUser();
|
||||
// await getDeviceInfoFromFirebase();
|
||||
// this.isFromLogin = isFromLogin;
|
||||
// appStatus = APPSTATUS.unAuthenticated;
|
||||
// setState(ViewState.Idle);
|
||||
}
|
||||
|
||||
deleteUser() {
|
||||
// user = null;
|
||||
// unverified = false;
|
||||
// isLogin = false;
|
||||
}
|
||||
|
||||
startSMSService(AuthMethodTypes type, {isSilentLogin = false, required BuildContext context}) {
|
||||
OtpDialog(
|
||||
type: 1,
|
||||
mobileNo: 0504278212,
|
||||
onSuccess: (String otpCode, TextEditingController pinPut) {
|
||||
Utils.showLoading();
|
||||
//TODO: API CALL
|
||||
// performDirectApiCall(_title, _icon, _flag, value);
|
||||
},
|
||||
onFailure: () => Navigator.pop(context),
|
||||
onResendCode: () {})
|
||||
.displayDialog(context);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,135 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:hexcolor/hexcolor.dart';
|
||||
import 'package:hmg_nurses/classes/colors.dart';
|
||||
import 'package:hmg_nurses/classes/enums.dart';
|
||||
import 'package:hmg_nurses/classes/size_config.dart';
|
||||
import 'package:hmg_nurses/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_nurses/ui/login/login_vm.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
|
||||
class VerificationMethodsList extends StatefulWidget {
|
||||
final AuthMethodTypes authMethodType;
|
||||
final Function(AuthMethodTypes type, bool isActive)? authenticateUser;
|
||||
final Function? onShowMore;
|
||||
final LoginViewModel loginViewModel;
|
||||
|
||||
const VerificationMethodsList({Key? key, required this.authMethodType, this.authenticateUser, this.onShowMore, required this.loginViewModel}) : super(key: key);
|
||||
|
||||
@override
|
||||
VerificationMethodsListState createState() => VerificationMethodsListState();
|
||||
}
|
||||
|
||||
class VerificationMethodsListState extends State<VerificationMethodsList> {
|
||||
final LocalAuthentication auth = LocalAuthentication();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
switch (widget.authMethodType) {
|
||||
case AuthMethodTypes.whatsApp:
|
||||
return MethodTypeCard(
|
||||
assetPath: 'assets/images/login/verify_whatsapp.svg',
|
||||
onTap: () => {widget.authenticateUser!(AuthMethodTypes.whatsApp, true)},
|
||||
label: LocaleKeys.verifyThroughWhatsapp.tr(),
|
||||
);
|
||||
case AuthMethodTypes.sms:
|
||||
return MethodTypeCard(
|
||||
assetPath: "assets/images/login/verify_sms.svg",
|
||||
onTap: () => {widget.authenticateUser!(AuthMethodTypes.sms, true)},
|
||||
label: LocaleKeys.verifyThroughSMS.tr(),
|
||||
);
|
||||
case AuthMethodTypes.fingerPrint:
|
||||
return MethodTypeCard(
|
||||
assetPath: 'assets/images/login/verify_thumb.svg',
|
||||
onTap: () => {widget.authenticateUser!(AuthMethodTypes.fingerPrint, true)},
|
||||
label: LocaleKeys.verifyThroughFingerprint.tr(),
|
||||
);
|
||||
case AuthMethodTypes.faceID:
|
||||
return MethodTypeCard(
|
||||
assetPath: 'assets/images/login/verify_face.svg',
|
||||
onTap: () => {widget.authenticateUser!(AuthMethodTypes.faceID, true)},
|
||||
label: LocaleKeys.verifyThroughFace.tr(),
|
||||
);
|
||||
|
||||
default:
|
||||
return MethodTypeCard(
|
||||
assetPath: 'assets/images/login/more_icon.png',
|
||||
onTap: () {
|
||||
widget.onShowMore!();
|
||||
},
|
||||
isSvg: false,
|
||||
label: LocaleKeys.moreVerificationOpts.tr(),
|
||||
height: 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MethodTypeCard extends StatelessWidget {
|
||||
const MethodTypeCard({
|
||||
Key? key,
|
||||
required this.assetPath,
|
||||
required this.onTap,
|
||||
required this.label,
|
||||
this.height = 20,
|
||||
this.isSvg = true,
|
||||
}) : super(key: key);
|
||||
final String assetPath;
|
||||
final GestureTapCallback onTap;
|
||||
final String label;
|
||||
final double height;
|
||||
final bool isSvg;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double cardHeight = SizeConfig.heightMultiplier! *
|
||||
(SizeConfig.isHeightVeryShort
|
||||
? 22
|
||||
: SizeConfig.isHeightLarge
|
||||
? 25
|
||||
: 20);
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
border: Border.all(color: HexColor('#707070'), width: 0.1),
|
||||
),
|
||||
height: cardHeight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
isSvg
|
||||
? SvgPicture.asset(assetPath, width: SizeConfig.widthMultiplier! * (14), height: cardHeight * 0.20)
|
||||
: Image.asset(
|
||||
assetPath,
|
||||
width: SizeConfig.widthMultiplier! * (12),
|
||||
height: cardHeight * 0.35,
|
||||
// height: ,
|
||||
),
|
||||
SizedBox(
|
||||
height: height,
|
||||
),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * (SizeConfig.isHeightVeryShort ? 3 : 3.7),
|
||||
color: MyColors.darkTextColor,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.48,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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))
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||