diff --git a/android/app/build.gradle b/android/app/build.gradle index 807f7fad..300075a5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -23,6 +23,7 @@ if (flutterVersionName == null) { apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { @@ -60,4 +61,5 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "com.google.firebase:firebase-messaging:20.1.0" } diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 00000000..f86832ad --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,42 @@ +{ + "project_info": { + "project_number": "815750722565", + "firebase_url": "https://api-project-815750722565.firebaseio.com", + "project_id": "api-project-815750722565", + "storage_bucket": "api-project-815750722565.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", + "android_client_info": { + "package_name": "com.cloud.diplomaticquarterapp" + } + }, + "oauth_client": [ + { + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 1, + "other_platform_oauth_client": [] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b88d5204..02c26fa6 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -33,15 +33,22 @@ android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" /> + + + + + + + diff --git a/android/build.gradle b/android/build.gradle index 3100ad2d..70b3637d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.5.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.google.gms:google-services:4.3.2' } } diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle new file mode 100644 index 00000000..e7b4def4 --- /dev/null +++ b/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/assets/images/habib-logo.png b/assets/images/habib-logo.png new file mode 100644 index 00000000..bcb6a42b Binary files /dev/null and b/assets/images/habib-logo.png differ diff --git a/assets/images/id_card_icon.png b/assets/images/id_card_icon.png new file mode 100644 index 00000000..96650604 Binary files /dev/null and b/assets/images/id_card_icon.png differ diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 00000000..0d9e4a56 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/assets/images/my_file_white_icon.png b/assets/images/my_file_white_icon.png new file mode 100644 index 00000000..6bd9b935 Binary files /dev/null and b/assets/images/my_file_white_icon.png differ diff --git a/lib/config/config.dart b/lib/config/config.dart index d8246358..389e49f3 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -1,11 +1,6 @@ -import 'dart:io'; -import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; -import 'package:diplomaticquarterapp/models/Request.dart'; -import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; - const MAX_SMALL_SCREEN = 660; -const BASE_URL = 'https://uat.hmgwebservices.com/Services'; +const BASE_URL = 'https://hmgwebservices.com/Services'; const GET_PROJECT = '/Lists.svc/REST/GetProject'; //const BASE_URL = 'https://hmgwebservices.com/'; // Production Environment @@ -18,7 +13,6 @@ const GET_CLINICS_LIST_URL = "Services/lists.svc/REST/GetClinicCentralized"; //URL to get doctors list const GET_DOCTORS_LIST_URL = "Services/Doctors.svc/REST/SearchDoctorsByTime"; - class AppGlobal { static var context; AppSharedPreferences sharedPref = AppSharedPreferences(); @@ -39,3 +33,8 @@ class AppGlobal { } } + +const CHANNEL = 3; +const GENERAL_ID = 'Cs2020@2016\$2958'; +const IP_ADDRESS = '10.20.10.20'; +const VERSION_ID = 5.5; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 3fc65bf2..66cc2c3f 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -42,4 +42,41 @@ const Map> localizedValues = { 'appoActions': {'en': 'Appointment Actions', 'ar': 'إجراءات الموعد'}, + 'login': {'en': 'Login', 'ar': 'تسجيل الدخول'}, + 'loginregister': {'en': 'Login / Register', 'ar': 'دخولتسجيل'}, + 'welcome': {'en': 'Welcome', 'ar': 'أهلا بك'}, + 'welcome_text': { + 'en': 'Dr. Sulaiman Al Habib Mobile Application ', + 'ar': 'الدكتور سليمان الحبيب لتطبيقات الهاتف المتحرك' + }, + 'welcome_text2': { + 'en': 'Have you visited AlHabib Medical Group before? ', + 'ar': 'الدكتور سليمان الحبيب لتطبيقات الهاتف المتحرك' + }, + 'yes': {'en': 'Yes', 'ar': 'نعم'}, + 'no': {'en': 'No', 'ar': 'لا'}, + "logintyperadio": { + "en": "Choose from below options to login to your medical file.", + "ar": "اختر من الخيارات أدناه لتسجيل الدخول إلى ملفك الطبي." + }, + "registernow": {"en": "Register Now", "ar": "تسجيل الان"}, + "nationalID": {"en": "National ID", "ar": "رقم الهوية"}, + "fileNo": {"en": "File Number", "ar": "رقم الملف"}, + "forgotFileNo": {"en": "Forgot file Number?", "ar": "نسيت رقم الملف الطبي؟"}, + "enter-national-id": { + "en": "Please enter mobile number and national ID / Iqama", + "ar": "الرجاء إدخال رقم الجوال والهوية الوطنية / الاقامة" + }, + "profile-info": { + "en": "Please enter profile information", + "ar": "الرجاء إدخال معلومات الملف الشخصي" + }, + "submit": {"en": "Submit", "ar": "ارسال"}, + "forgot-desc": { + "en": "Enter the mobile number to receive the Medical file Number via SMS", + "ar": "أدخل رقم الجوال المسجل لاستلام رقم الملف عن طريق الرسائل النصية" + }, + "dob": {"en": "Birth Date:", "ar": "تاريخ الميلاد"}, + "hijri-date": {"en": "Hijri Date", "ar": "التاريخ الهجري"}, + "gregorian-date": {"en": "Gregorian Date", "ar": "التاريخ الميلادي"}, }; diff --git a/lib/config/shared_pref_kay.dart b/lib/config/shared_pref_kay.dart index 8c03fcce..1e75a802 100644 --- a/lib/config/shared_pref_kay.dart +++ b/lib/config/shared_pref_kay.dart @@ -1,3 +1,7 @@ const TOKEN = 'token'; const APP_LANGUAGE = 'language'; - +const USER_PROFILE = 'user-profile'; +const PUSH_TOKEN = 'push-token'; +const REGISTER_DATA_FOR_REGISTER = 'register-data-for-register'; +const LOGIN_TOKEN_ID = 'register-data-for-register'; +const REGISTER_DATA_FOR_LOGIIN = 'register-data-for-login'; diff --git a/lib/core/model/auth/check_paitent_authentication_req.dart b/lib/core/model/auth/check_paitent_authentication_req.dart new file mode 100644 index 00000000..2846c1fc --- /dev/null +++ b/lib/core/model/auth/check_paitent_authentication_req.dart @@ -0,0 +1,76 @@ +class CheckPatientAuthenticationReq { + int patientMobileNumber; + String zipCode; + bool isRegister; + String tokenID; + int searchType; + String patientIdentificationID; + int patientID; + double versionID; + int channel; + int languageID; + String iPAdress; + String generalid; + int patientOutSA; + Null sessionID; + bool isDentalAllowedBackend; + int deviceTypeID; + + CheckPatientAuthenticationReq( + {this.patientMobileNumber, + this.zipCode, + this.isRegister, + this.tokenID, + this.searchType, + this.patientIdentificationID, + this.patientID, + this.versionID, + this.channel, + this.languageID, + this.iPAdress, + this.generalid, + this.patientOutSA, + this.sessionID, + this.isDentalAllowedBackend, + this.deviceTypeID}); + + CheckPatientAuthenticationReq.fromJson(Map json) { + patientMobileNumber = json['PatientMobileNumber']; + zipCode = json['ZipCode']; + isRegister = json['isRegister']; + tokenID = json['TokenID']; + searchType = json['SearchType']; + patientIdentificationID = json['PatientIdentificationID']; + patientID = json['PatientID']; + versionID = json['VersionID']; + channel = json['Channel']; + languageID = json['LanguageID']; + iPAdress = json['IPAdress']; + generalid = json['generalid']; + patientOutSA = json['PatientOutSA']; + sessionID = json['SessionID']; + isDentalAllowedBackend = json['isDentalAllowedBackend']; + deviceTypeID = json['DeviceTypeID']; + } + + Map toJson() { + final Map data = new Map(); + data['PatientMobileNumber'] = this.patientMobileNumber; + data['ZipCode'] = this.zipCode; + data['isRegister'] = this.isRegister; + data['TokenID'] = this.tokenID; + data['SearchType'] = this.searchType; + data['PatientIdentificationID'] = this.patientIdentificationID; + data['PatientID'] = this.patientID; + data['VersionID'] = this.versionID; + data['Channel'] = this.channel; + data['LanguageID'] = this.languageID; + data['IPAdress'] = this.iPAdress; + data['generalid'] = this.generalid; + data['PatientOutSA'] = this.patientOutSA; + data['SessionID'] = this.sessionID; + data['isDentalAllowedBackend'] = this.isDentalAllowedBackend; + data['DeviceTypeID'] = this.deviceTypeID; + return data; + } +} diff --git a/lib/core/model/auth/select_device_imei_res.dart b/lib/core/model/auth/select_device_imei_res.dart new file mode 100644 index 00000000..14444279 --- /dev/null +++ b/lib/core/model/auth/select_device_imei_res.dart @@ -0,0 +1,68 @@ +class SelectDeviceIMEIRES { + bool biometricEnabled; + String createdOn; + String editedOn; + int iD; + String iMEI; + String identificationNo; + int logInType; + String mobile; + String name; + String nameN; + bool outSA; + int patientID; + int patientType; + int preferredLanguage; + + SelectDeviceIMEIRES( + {this.biometricEnabled, + this.createdOn, + this.editedOn, + this.iD, + this.iMEI, + this.identificationNo, + this.logInType, + this.mobile, + this.name, + this.nameN, + this.outSA, + this.patientID, + this.patientType, + this.preferredLanguage}); + + SelectDeviceIMEIRES.fromJson(Map json) { + biometricEnabled = json['BiometricEnabled']; + createdOn = json['CreatedOn']; + editedOn = json['EditedOn']; + iD = json['ID']; + iMEI = json['IMEI']; + identificationNo = json['IdentificationNo']; + logInType = json['LogInType']; + mobile = json['Mobile']; + name = json['Name']; + nameN = json['NameN']; + outSA = json['OutSA']; + patientID = json['PatientID']; + patientType = json['PatientType']; + preferredLanguage = json['PreferredLanguage']; + } + + Map toJson() { + final Map data = new Map(); + data['BiometricEnabled'] = this.biometricEnabled; + data['CreatedOn'] = this.createdOn; + data['EditedOn'] = this.editedOn; + data['ID'] = this.iD; + data['IMEI'] = this.iMEI; + data['IdentificationNo'] = this.identificationNo; + data['LogInType'] = this.logInType; + data['Mobile'] = this.mobile; + data['Name'] = this.name; + data['NameN'] = this.nameN; + data['OutSA'] = this.outSA; + data['PatientID'] = this.patientID; + data['PatientType'] = this.patientType; + data['PreferredLanguage'] = this.preferredLanguage; + return data; + } +} diff --git a/lib/core/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart index 72c38568..57686824 100644 --- a/lib/core/service/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -14,7 +14,7 @@ AppSharedPreferences sharedPref = new AppSharedPreferences(); /// body: null); class BaseAppClient { - post( + post( String endPoint, { Map body, Function(dynamic response, int statusCode) onSuccess, @@ -22,7 +22,6 @@ class BaseAppClient { }) async { String url = BASE_URL + endPoint; try { - //Map profile = await sharedPref.getObj(DOCTOR_PROFILE); // String token = await sharedPref.getString(TOKEN); diff --git a/lib/main.dart b/lib/main.dart index 2eb5dd26..06cf9652 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -71,8 +72,8 @@ class MyApp extends StatelessWidget { ), ), ), - initialRoute: '/', - routes: {'/': (context) => LandingPage()}, + initialRoute: HOME, + routes: routes, debugShowCheckedModeBanner: false, ), ), diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 68cf8ce9..b3039be6 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -1,12 +1,13 @@ -import 'package:diplomaticquarterapp/pages/BookAppointment/BookingOptions.dart'; -import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/auth/select_device_imei_res.dart'; import 'package:diplomaticquarterapp/pages/landing/replay_page.dart'; +import 'package:diplomaticquarterapp/providers/auth_provider.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/bottom_navigation/bottom_nav_bar.dart'; import 'package:diplomaticquarterapp/widgets/drawer/app_drawer_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; - +import 'package:firebase_messaging/firebase_messaging.dart'; import 'home_page.dart'; class LandingPage extends StatefulWidget { @@ -17,7 +18,8 @@ class LandingPage extends StatefulWidget { class _LandingPageState extends State { int currentTab = 0; PageController pageController; - + final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); + final authService = new AuthProvider(); _changeCurrentTab(int tab) { setState(() { currentTab = tab; @@ -29,6 +31,14 @@ class _LandingPageState extends State { void initState() { super.initState(); pageController = PageController(keepPage: true); + _firebaseMessaging.getToken().then((String token) { + sharedPref.setString(PUSH_TOKEN, token); + if (token != null) { + checkUserStatus(token); + } + + //assert(token != null); + }); } @override @@ -36,6 +46,7 @@ class _LandingPageState extends State { return Scaffold( appBar: AppBar( elevation: 0, + backgroundColor: Colors.grey, textTheme: TextTheme( headline6: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), @@ -77,4 +88,10 @@ class _LandingPageState extends State { return TranslationBase.of(context).bookAppo; } } + + void checkUserStatus(token) { + authService + .selectDeviceImei(token) + .then((SelectDeviceIMEIRES value) => print(value)); + } } diff --git a/lib/pages/login/forgot-password.dart b/lib/pages/login/forgot-password.dart new file mode 100644 index 00000000..c1fa7b18 --- /dev/null +++ b/lib/pages/login/forgot-password.dart @@ -0,0 +1,95 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; +import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class ForgotPassword extends StatefulWidget { + @override + _ForgotPassword createState() => _ForgotPassword(); +} + +class _ForgotPassword extends State { + String selectedType = 'Saudi Arabia'; + final TextEditingController nationalIDorFile = null; + final TextEditingController mobileNo = null; + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).forgotPassword, + isShowAppBar: true, + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top: 10, left: 20, right: 20), + height: SizeConfig.realScreenHeight * .8, + width: SizeConfig.realScreenWidth, + child: Column(children: [ + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context).forgotDesc, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + )), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + // add Expanded to have your dropdown button fill remaining space + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + value: selectedType, + iconSize: 40, + elevation: 16, + onChanged: (String newValue) => { + setState(() { + selectedType = newValue; + }) + }, + items: [ + 'Saudi Arabia', + 'Dubai', + ].map>( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList()))), + ], + ), + MobileNo(controller: mobileNo), + ], + ), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: Colors.grey, + textColor: Colors.white, + child: Text(TranslationBase.of(context).submit), + onPressed: () => {}, + )) + ], + ), + ], + )) + ]), + ))); + } +} diff --git a/lib/pages/login/login-type.dart b/lib/pages/login/login-type.dart new file mode 100644 index 00000000..c0697099 --- /dev/null +++ b/lib/pages/login/login-type.dart @@ -0,0 +1,162 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/routes.dart'; + +class LoginType extends StatelessWidget { + static int loginType = 0; + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).welcome, + isShowAppBar: true, + body: Padding( + padding: EdgeInsets.all(20), + child: Column( + children: [ + Expanded( + flex: 4, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + 'assets/images/habib-logo.png', + height: 80, + width: 80, + ), + AppText( + TranslationBase.of(context).logintypeRadio, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: InkWell( + onTap: () => { + LoginType.loginType = 1, + Navigator.of(context) + .pushNamed(LOGIN_PAGE) + }, + child: RoundedContainer( + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB( + 20, 10, 20, 10), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/id_card_icon.png', + height: SizeConfig + .imageSizeMultiplier * + 12, + width: SizeConfig + .imageSizeMultiplier * + 15, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context) + .nationalID, + fontSize: + SizeConfig.textMultiplier * + 2, + ) + ], + ), + )))), + Expanded( + child: InkWell( + onTap: () => { + LoginType.loginType = 2, + Navigator.of(context) + .pushNamed(LOGIN_PAGE) + }, + child: RoundedContainer( + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB( + 25, 10, 25, 10), + child: Column( + children: [ + Image.asset( + 'assets/images/my_file_white_icon.png', + height: SizeConfig + .imageSizeMultiplier * + 12, + width: SizeConfig + .imageSizeMultiplier * + 15, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context) + .fileNo, + fontSize: + SizeConfig.textMultiplier * + 2, + ) + ], + ), + )))) + ], + ), + Divider( + color: Colors.grey, + height: 2, + ), + Center( + child: InkWell( + onTap: () => { + Navigator.of(context) + .pushNamed(FORGOT_PASSWORD) + }, + child: AppText( + TranslationBase.of(context).forgotPassword, + fontSize: SizeConfig.textMultiplier * 3, + margin: 10, + underline: true))) + ]), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: Colors.grey, + textColor: Colors.white, + child: + Text(TranslationBase.of(context).registerNow), + onPressed: () => { + Navigator.of(context).pushNamed( + REGISTER, + ) + }, + )) + ], + ), + ], + )) + ], + ))); + } +} diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart new file mode 100644 index 00000000..7bb61da5 --- /dev/null +++ b/lib/pages/login/login.dart @@ -0,0 +1,163 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/model/auth/check_paitent_authentication_req.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; +import 'package:diplomaticquarterapp/pages/login/login-type.dart'; +import 'package:diplomaticquarterapp/providers/auth_provider.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; +import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class Login extends StatefulWidget { + @override + _Login createState() => _Login(); +} + +class _Login extends State { + final util = Utils(); + final nationalIDorFile = TextEditingController(); + final int loginType = LoginType.loginType; + String mobileNo; + String countryCode = '966'; + bool isButtonDisabled = true; + final authService = new AuthProvider(); + var sharedPref = new AppSharedPreferences(); + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).login, + isShowAppBar: true, + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top: 10, left: 20, right: 20), + height: SizeConfig.realScreenHeight * .8, + width: SizeConfig.realScreenWidth, + child: Column(children: [ + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context).enterNationalId, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + )), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + MobileNo( + onNumberChange: (value) => + {mobileNo = value, validateForm()}, + onCountryChange: (value) => countryCode = value), + Container( + child: TextFields( + controller: nationalIDorFile, + onChanged: (value) => {validateForm()}, + prefixIcon: Icon( + loginType == 1 + ? Icons.chrome_reader_mode + : Icons.receipt, + color: Colors.red), + padding: EdgeInsets.only( + top: 20, bottom: 20, left: 10, right: 10), + hintText: loginType == 1 + ? TranslationBase.of(context).nationalID + : TranslationBase.of(context).fileNo, + )) + ], + ), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: isButtonDisabled == true + ? Colors.grey + : Colors.grey[600], + textColor: Colors.white, + child: Text(TranslationBase.of(context).login), + onPressed: () => {this.startLogin()}, + )) + ], + ), + ], + )) + ]), + ))); + } + + startLogin() { + if (isButtonDisabled == false) { + checkUserAuthentication(); + } + } + + void validateForm() { + if (validateIDBox(nationalIDorFile.text) == true && + mobileNo != null && + util.isSAUDIIDValid(nationalIDorFile.text) == true) { + setState(() { + isButtonDisabled = false; + }); + } else { + setState(() { + isButtonDisabled = true; + }); + } + } + + bool validateIDBox(String value) { + Pattern pattern = loginIDPattern(); //r'^\d+(?:\.\d+)?$'; + + RegExp regex = new RegExp(pattern); + return regex.hasMatch(value); + } + + String loginIDPattern() { + var length = loginType == 1 ? 10 : 7; + return "([0-9]{" + length.toString() + "})"; + } + + checkUserAuthentication() { + var request = CheckPatientAuthenticationReq(); + request.isRegister = false; + request.patientMobileNumber = int.parse(mobileNo); + request.zipCode = countryCode; + request.searchType = this.loginType; + request.deviceTypeID = this.loginType; + if (this.loginType == 1) { + request.patientIdentificationID = this.nationalIDorFile.text; + request.patientID = 0; + } else { + request.patientIdentificationID = ''; + request.patientID = int.parse(nationalIDorFile.text); + } + sharedPref.setObject(REGISTER_DATA_FOR_REGISTER, request); + authService.checkPatientAuthentication(request).then((value) => { + if (value.isSMSSent) + { + sharedPref.setString(LOGIN_TOKEN_ID, value.LogInTokenID), + sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), + } + else + { + if (value.IsAuthenticated) {this.checkActivationCode()} + } + }); + } + + checkActivationCode() {} +} diff --git a/lib/pages/login/register.dart b/lib/pages/login/register.dart new file mode 100644 index 00000000..6c58ba72 --- /dev/null +++ b/lib/pages/login/register.dart @@ -0,0 +1,139 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/pages/login/login-type.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; +import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class Register extends StatefulWidget { + @override + _Register createState() => _Register(); +} + +class _Register extends State { + final TextEditingController nationalIDorFile = null; + final int loginType = LoginType.loginType; + final TextEditingController mobileNo = null; + var isHijri; + + DateTime selectedDate; + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).login, + isShowAppBar: true, + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top: 10, left: 20, right: 20), + height: SizeConfig.realScreenHeight * .8, + width: SizeConfig.realScreenWidth, + child: Column(children: [ + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context).enterNationalId, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + )), + Expanded( + flex: 4, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + MobileNo(controller: mobileNo), + Container( + child: TextFields( + controller: nationalIDorFile, + prefixIcon: + Icon(Icons.chrome_reader_mode, color: Colors.red), + padding: EdgeInsets.only( + top: 20, bottom: 20, left: 10, right: 10), + hintText: TranslationBase.of(context).nationalID, + )), + Row( + children: [ + Expanded( + child: Row( + children: [ + Radio( + value: 1, + groupValue: isHijri, + onChanged: (value) { + setState(() { + isHijri = value; + }); + }, + ), + Text(TranslationBase.of(context).hijriDate), + ], + ), + ), + Expanded( + child: Row( + children: [ + Radio( + value: 0, + groupValue: isHijri, + onChanged: (value) { + setState(() { + isHijri = value; + }); + }, + ), + Text(TranslationBase.of(context).gregorianDate), + ], + ), + ), + ], + ), + Row(children: [ + Expanded( + child: RaisedButton.icon( + onPressed: () => {_selectDate(context)}, + icon: Icon(Icons.date_range), + label: Text(selectedDate != null + ? "${selectedDate.toLocal()}".split(' ')[0] + : TranslationBase.of(context).dob))) + ]) + ], + ), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: Colors.grey, + textColor: Colors.white, + child: Text(TranslationBase.of(context).login), + onPressed: () => {}, + )) + ], + ), + ], + )) + ]), + ))); + } + + Future _selectDate(BuildContext context) async { + final DateTime picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2015, 8), + lastDate: DateTime(2101)); + if (picked != null && picked != selectedDate) + setState(() { + selectedDate = picked; + }); + } +} diff --git a/lib/pages/login/welcome.dart b/lib/pages/login/welcome.dart new file mode 100644 index 00000000..978ff449 --- /dev/null +++ b/lib/pages/login/welcome.dart @@ -0,0 +1,85 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/routes.dart'; + +class WelcomeLogin extends StatelessWidget { + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).welcome, + isShowAppBar: true, + body: Padding( + padding: EdgeInsets.all(20), + child: Column( + children: [ + Expanded( + flex: 3, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + 'assets/images/habib-logo.png', + height: 80, + width: 80, + ), + Text( + TranslationBase.of(context).welcome, + style: TextStyle(fontSize: 30), + textAlign: TextAlign.left, + ), + Text( + TranslationBase.of(context).welcomeText, + style: TextStyle(fontSize: 24), + textAlign: TextAlign.left, + ), + Text( + TranslationBase.of(context).welcomeText2, + style: TextStyle(fontSize: 24), + textAlign: TextAlign.left, + ) + ]), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: Colors.red[900], + textColor: Colors.white, + child: Text(TranslationBase.of(context).yes), + onPressed: () => { + Navigator.of(context).pushNamed( + LOGIN_TYPE, + ) + }, + )) + ], + ), + Row( + children: [ + Expanded( + child: RaisedButton( + child: Text(TranslationBase.of(context).no), + onPressed: () => { + Navigator.of(context).pushNamed( + REGISTER, + ) + }, + )) + ], + ), + ], + )) + ], + ))); + } +} diff --git a/lib/providers/auth_provider.dart b/lib/providers/auth_provider.dart new file mode 100644 index 00000000..3590355b --- /dev/null +++ b/lib/providers/auth_provider.dart @@ -0,0 +1,124 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/auth/check_paitent_authentication_req.dart'; +import 'package:diplomaticquarterapp/core/model/auth/select_device_imei_res.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:flutter/cupertino.dart'; + +// SharedPreferences sharedPref = new SharedPreferences(); +enum APP_STATUS { LOADING, UNAUTHENTICATED, AUTHENTICATED } +AppSharedPreferences sharedPref = new AppSharedPreferences(); + +const String INSERT_DEVICE_IMEI = '/Patients.svc/REST/Patient_INSERTDeviceIMEI'; +const String SELECT_DEVICE_IMEI = + '/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; +const String CHECK_PATIENT_AUTH = + '/Authentication.svc/REST/CheckPatientAuthentication'; + +class AuthProvider with ChangeNotifier { + bool isLogin = false; + bool isLoading = true; + AuthProvider() { + getUserAuthentication(); + } + + void getUserAuthentication() async { + Map profile = await sharedPref.getObject(USER_PROFILE); + if (profile != null) { + isLoading = false; + isLogin = true; + } else { + isLoading = false; + isLogin = false; + } + notifyListeners(); + } + + APP_STATUS get stutas { + if (isLoading) { + return APP_STATUS.LOADING; + } else { + if (this.isLogin) { + return APP_STATUS.AUTHENTICATED; + } else { + return APP_STATUS.UNAUTHENTICATED; + } + } + } + + // Future login(UserModel userInfo) async { + // try { + // dynamic localRes; + + // await BaseAppClient.post(LOGIN_URL, + // onSuccess: (dynamic response, int statusCode) { + // localRes = response; + // }, onFailure: (String error, int statusCode) { + // throw error; + // }, body: userInfo.toJson()); + + // return Future.value(localRes); + // } catch (error) { + // print(error); + // throw error; + // } + // } + + Future insertDeviceImei(imei) async { + try { + dynamic localRes; + + await new BaseAppClient().post(INSERT_DEVICE_IMEI, + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: imei); + return Future.value(localRes); + } catch (error) { + print(error); + throw error; + } + } + + Future selectDeviceImei(imei) async { + try { + dynamic localRes; + await new BaseAppClient().post(SELECT_DEVICE_IMEI, + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: imei); + return Future.value(localRes); + } catch (error) { + print(error); + throw error; + } + } + + Future checkPatientAuthentication( + CheckPatientAuthenticationReq request) async { + request.versionID = VERSION_ID; + request.channel = CHANNEL; + request.iPAdress = IP_ADDRESS; + request.generalid = GENERAL_ID; + request.languageID = 2; + request.patientOutSA = request.zipCode == '966' ? 0 : 1; + try { + dynamic localRes; + await new BaseAppClient().post(CHECK_PATIENT_AUTH, + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request.toJson()); + return Future.value(localRes); + } catch (error) { + print(error); + throw error; + } + } +} diff --git a/lib/routes.dart b/lib/routes.dart new file mode 100644 index 00000000..8b3d1d4b --- /dev/null +++ b/lib/routes.dart @@ -0,0 +1,25 @@ +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; +import 'package:diplomaticquarterapp/pages/login/forgot-password.dart'; +import 'package:diplomaticquarterapp/pages/login/welcome.dart'; +import 'package:diplomaticquarterapp/pages/login/login-type.dart'; +import 'package:diplomaticquarterapp/pages/login/login.dart'; +import 'package:diplomaticquarterapp/pages/login/register.dart'; + +const String INIT_ROUTE = '/'; +const String ROOT = 'root'; +const String HOME = '/'; +const String LOGIN = 'login'; +const String WELCOME_LOGIN = 'welcome-login'; +const String LOGIN_TYPE = 'login-type'; +const String LOGIN_PAGE = 'login-page'; +const String FORGOT_PASSWORD = 'forgot-password'; +const String REGISTER = 'register'; +var routes = { + // ROOT: (_) => RootPage(), + HOME: (_) => LandingPage(), + WELCOME_LOGIN: (_) => WelcomeLogin(), + LOGIN_TYPE: (_) => LoginType(), + LOGIN_PAGE: (_) => Login(), + FORGOT_PASSWORD: (_) => ForgotPassword(), + REGISTER: (_) => Register() +}; diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 056258c1..bbeef4e0 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -95,6 +95,33 @@ class TranslationBase { String get appoActions => localizedValues['appoActions'][locale.languageCode]; String get appointment => localizedValues['appointment'][locale.languageCode]; + String get login => localizedValues['login'][locale.languageCode]; + String get loginregister => + localizedValues['loginregister'][locale.languageCode]; + String get welcome => localizedValues['welcome'][locale.languageCode]; + String get welcomeText => + localizedValues['welcome_text'][locale.languageCode]; + String get welcomeText2 => + localizedValues['welcome_text2'][locale.languageCode]; + String get yes => localizedValues['yes'][locale.languageCode]; + String get no => localizedValues['no'][locale.languageCode]; + String get logintypeRadio => + localizedValues['logintyperadio'][locale.languageCode]; + String get registerNow => localizedValues['registernow'][locale.languageCode]; + String get nationalID => localizedValues['nationalID'][locale.languageCode]; + String get fileNo => localizedValues['fileNo'][locale.languageCode]; + String get forgotPassword => + localizedValues['forgotFileNo'][locale.languageCode]; + String get enterNationalId => + localizedValues['enter-national-id'][locale.languageCode]; + String get profileInfo => + localizedValues['profile-info'][locale.languageCode]; + String get submit => localizedValues['submit'][locale.languageCode]; + String get forgotDesc => localizedValues['forgot-desc'][locale.languageCode]; + String get dob => localizedValues['dob'][locale.languageCode]; + String get hijriDate => localizedValues['hijri-date'][locale.languageCode]; + String get gregorianDate => + localizedValues['gregorian-date'][locale.languageCode]; } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/uitl/utils.dart b/lib/uitl/utils.dart index 1c2da2b6..ac586b7d 100644 --- a/lib/uitl/utils.dart +++ b/lib/uitl/utils.dart @@ -42,4 +42,42 @@ class Utils { static hideKeyboard(BuildContext context) { FocusScope.of(context).unfocus(); } + + bool isSAUDIIDValid(String id) { + if (id == null) { + return false; + } + try { + id = id.toString(); + id = id.trim(); + var returnValue = int.parse(id); + var sum = 0; + if (returnValue > 0) { + var type = int.parse(id[0]); + + if (id.length != 10) { + return false; + } + if (type != 2 && type != 1) { + return false; + } + + for (var i = 0; i < 10; i++) { + if (i % 2 == 0) { + var a = id[i]; + var x = int.parse(a) * 2; + var b = x.toString(); + if (b.length == 1) { + b = "0" + b; + } + sum += int.parse(b[0]) + int.parse(b[1]); + } else { + sum += int.parse(id[i]); + } + } + return sum % 10 == 0; + } + } catch (err) {} + return false; + } } diff --git a/lib/widgets/card/rounded_container.dart b/lib/widgets/card/rounded_container.dart new file mode 100644 index 00000000..a6cb36e2 --- /dev/null +++ b/lib/widgets/card/rounded_container.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; + +// OWNER : Ibrahim albitar +// DATE : 05-04-2020 +// DESCRIPTION : Custom widget for rounded container and custom decoration + +class RoundedContainer extends StatefulWidget { + final double width; + final double height; + final double raduis; + final Color backgroundColor; + final double margin; + final double elevation; + final bool showBorder; + final Color borderColor; + final bool customCornerRaduis; + final double topLeft; + final double bottomRight; + final double topRight; + final double bottomLeft; + final Widget child; + final double borderWidth; + + RoundedContainer( + {@required this.child, + this.width, + this.height, + this.raduis = 10, + this.backgroundColor = Colors.white, + this.margin = 10, + this.elevation = 1, + this.showBorder = false, + this.borderColor = Colors.red, + this.customCornerRaduis = false, + this.topLeft = 0, + this.topRight = 0, + this.bottomRight = 0, + this.bottomLeft = 0, + this.borderWidth = 1}); + + @override + _RoundedContainerState createState() => _RoundedContainerState(); +} + +class _RoundedContainerState extends State { + @override + Widget build(BuildContext context) { + return Container( + width: widget.width, + height: widget.height, + margin: EdgeInsets.all(widget.margin), + decoration: widget.showBorder == true + ? BoxDecoration( + color: Theme.of(context).primaryColor, + border: Border.all( + color: widget.borderColor, width: widget.borderWidth), + borderRadius: widget.customCornerRaduis + ? BorderRadius.only( + topLeft: Radius.circular(widget.topLeft), + topRight: Radius.circular(widget.topRight), + bottomRight: Radius.circular(widget.bottomRight), + bottomLeft: Radius.circular(widget.bottomLeft)) + : BorderRadius.circular(widget.raduis), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 10, + blurRadius: 5, + offset: Offset(0, 5), // changes position of shadow + ), + ]) + : null, + child: Card( + margin: EdgeInsets.all(0), + shape: RoundedRectangleBorder( + borderRadius: widget.customCornerRaduis + ? BorderRadius.only( + topLeft: Radius.circular(widget.topLeft), + topRight: Radius.circular(widget.topRight), + bottomRight: Radius.circular(widget.bottomRight), + bottomLeft: Radius.circular(widget.bottomLeft)) + : BorderRadius.circular(widget.raduis), + ), + color: widget.backgroundColor, + child: widget.child, + )); + } +} diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index c1e92443..4a5071d1 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/list/flexible_container.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; @@ -6,8 +7,6 @@ import 'package:flutter/material.dart'; import '../../config/size_config.dart'; import 'drawer_item_widget.dart'; - - class AppDrawer extends StatefulWidget { @override _AppDrawerState createState() => _AppDrawerState(); @@ -32,11 +31,11 @@ class _AppDrawerState extends State { child: InkWell( child: DrawerHeader( child: Column( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( child: Image.asset('assets/images/logo.png'), - margin: EdgeInsets.only(top: 10, bottom: 15), + margin: EdgeInsets.all(20), ), SizedBox( height: 1, @@ -45,36 +44,18 @@ class _AppDrawerState extends State { ), ), SizedBox(height: 15), - CircleAvatar( - radius: SizeConfig.imageSizeMultiplier * 12, - backgroundColor: Colors.white, - //TODO add backgroundImage: NetworkImage(''), - ), - Padding( - padding: EdgeInsets.only(top: 10), - child: Texts( - 'Patient', - color: Colors.black, - fontSize: SizeConfig.textMultiplier * 2, - )), - Texts("Director of medical records", - //TODO: Make The Dr Title Dynamic and check overflow issue. - - color: Colors.black87), - RaisedButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), - side: BorderSide(color: Colors.red), - ), - child: Texts( - TranslationBase.of(context).logout, - color: Colors.white, - ), - onPressed: () async { - Navigator.pop(context); - //TODO add await helpers.logout(); - }, - ), + // CircleAvatar( + // radius: SizeConfig.imageSizeMultiplier * 12, + // backgroundColor: Colors.white, + // //TODO add backgroundImage: NetworkImage(''), + // ), + // Padding( + // padding: EdgeInsets.only(top: 10), + // child: Texts( + // 'Patient', + // color: Colors.black, + // fontSize: SizeConfig.textMultiplier * 2, + // )), ], ), ), @@ -85,10 +66,12 @@ class _AppDrawerState extends State { ), InkWell( child: DrawerItem( - TranslationBase.of(context).settings, Icons.settings), + TranslationBase.of(context).loginregister, + Icons.lock), onTap: () { - Navigator.pop(context); - //TODO add fun + Navigator.of(context).pushNamed( + WELCOME_LOGIN, + ); }, ), ], diff --git a/lib/widgets/drawer/drawer_item_widget.dart b/lib/widgets/drawer/drawer_item_widget.dart index 06dcd170..3357ef8d 100644 --- a/lib/widgets/drawer/drawer_item_widget.dart +++ b/lib/widgets/drawer/drawer_item_widget.dart @@ -25,7 +25,7 @@ class _DrawerItemState extends State { @override Widget build(BuildContext context) { return Container( - margin: EdgeInsets.only(top: 5, bottom: 5, left: 10, right: 10), + margin: EdgeInsets.only(top: 5, bottom: 15, left: 10, right: 10), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -34,21 +34,26 @@ class _DrawerItemState extends State { color: widget.iconColor, size: SizeConfig.imageSizeMultiplier * 5, ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts( - widget.title, - color: widget.textColor, - fontSize: SizeConfig.textMultiplier * 2.3, - ), - Texts( - widget.subTitle, - color: widget.textColor, - fontSize: SizeConfig.textMultiplier * 2.5, - ), - ], - ), + Padding( + padding: widget.subTitle == '' + ? EdgeInsets.only(top: 20) + : EdgeInsets.only(top: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts( + widget.title, + color: widget.textColor, + fontSize: SizeConfig.textMultiplier * 2.3, + ), + Texts( + widget.subTitle, + color: widget.textColor, + fontSize: SizeConfig.textMultiplier * 2.5, + ), + ], + ), + ) ], ), ); diff --git a/lib/widgets/input/text_field.dart b/lib/widgets/input/text_field.dart index 900c3401..5429dd39 100644 --- a/lib/widgets/input/text_field.dart +++ b/lib/widgets/input/text_field.dart @@ -46,7 +46,7 @@ class TextFields extends StatefulWidget { this.suffixIcon, this.autoFocus, this.onChanged, - this.initialValue, + // this.initialValue, this.minLines, this.maxLines, this.inputFormatters, @@ -68,18 +68,20 @@ class TextFields extends StatefulWidget { this.maxLength, this.prefixIcon, this.bare = false, + this.onTap, this.fontSize = 16.0, this.fontWeight = FontWeight.w700, this.autoValidate = false}) : super(key: key); final String hintText; - final String initialValue; + // final String initialValue; final String type; final bool autoFocus; final IconData suffixIcon; final Color suffixIconColor; - final IconData prefixIcon; + final Icon prefixIcon; + final VoidCallback onTap; final TextEditingController controller; final TextInputType keyboardType; final FormFieldValidator validator; @@ -196,6 +198,10 @@ class _TextFieldsState extends State { decoration: widget.bare ? null : BoxDecoration(boxShadow: [ + // BoxShadow( + // color: Color.fromRGBO(70, 68, 167, focus ? 0.20 : 0), + // offset: Offset(0.0, 13.0), + // blurRadius: focus ? 34.0 : 12.0) BoxShadow( color: Color.fromRGBO(110, 68, 80, focus ? 0.20 : 0), offset: Offset(0.0, 13.0), @@ -217,7 +223,7 @@ class _TextFieldsState extends State { minLines: widget.minLines ?? 1, maxLines: widget.maxLines ?? 1, maxLengthEnforced: widget.maxLengthEnforced, - initialValue: widget.initialValue, + // initialValue: widget.initialValue, onChanged: widget.onChanged, focusNode: _focusNode, maxLength: widget.maxLength ?? null, @@ -255,19 +261,7 @@ class _TextFieldsState extends State { ? Colors.transparent : Theme.of(context).backgroundColor, suffixIcon: _buildSuffixIcon(), - prefixIcon: widget.type != "search" - ? widget.prefixIcon != null - ? Padding( - padding: EdgeInsets.only( - left: 28.0, top: 14.0, bottom: 14.0, right: 0), - child: Text( - "\$", - style: TextStyle( - fontSize: 14, fontWeight: FontWeight.w800), - ), - ) - : null - : Icon(EvaIcons.search, size: 20.0, color: Colors.grey[500]), + prefixIcon: widget.prefixIcon, errorStyle: TextStyle( fontSize: 14.0, fontWeight: widget.fontWeight, @@ -277,35 +271,23 @@ class _TextFieldsState extends State { color: Theme.of(context) .errorColor .withOpacity(widget.bare ? 0.0 : 0.5), - width: 2.0), + width: 1.0), borderRadius: BorderRadius.circular(widget.bare ? 0.0 : 8.0)), focusedErrorBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context) .errorColor .withOpacity(widget.bare ? 0.0 : 0.5), - width: 2.0), + width: 1.0), borderRadius: BorderRadius.circular(widget.bare ? 0.0 : 8.0)), focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context) - .dividerColor - .withOpacity(widget.bare ? 0.0 : 1.0), - width: 2.0), + borderSide: BorderSide(color: Colors.grey, width: 1.0), borderRadius: BorderRadius.circular(widget.bare ? 0.0 : 8.0)), disabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context) - .dividerColor - .withOpacity(widget.bare ? 0.0 : 1.0), - width: 2.0), + borderSide: BorderSide(color: Colors.grey, width: 1.0), borderRadius: BorderRadius.circular(widget.bare ? 0.0 : 8.0)), enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context) - .dividerColor - .withOpacity(widget.bare ? 0.0 : 1.0), - width: 2.0), + borderSide: BorderSide(color: Colors.grey, width: 1.0), borderRadius: BorderRadius.circular(widget.bare ? 0.0 : 8.0), ), ), diff --git a/lib/widgets/mobile-no/mobile_no.dart b/lib/widgets/mobile-no/mobile_no.dart new file mode 100644 index 00000000..2c17a669 --- /dev/null +++ b/lib/widgets/mobile-no/mobile_no.dart @@ -0,0 +1,125 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +// OWNER : Ibrahim albitar +// DATE : 12-04-2020 +// DESCRIPTION : Customization for Texts in app + +class MobileNo extends StatefulWidget { + final bool disabled; + // final String data; + final List countries = [ + new Countries(name: 'Saudi Arabia', code: '966'), + new Countries(name: 'Dubai', code: '971'), + ]; + final double margin; + final double marginTop; + final double marginRight; + final double marginBottom; + final double marginLeft; + final TextEditingController controller; + final Function onNumberChange; + final Function onCountryChange; + MobileNo( + {this.disabled = false, + this.marginTop = 0, + this.marginRight = 0, + this.marginBottom = 0, + this.controller, + this.marginLeft = 0, + this.onNumberChange, + this.onCountryChange, + this.margin = 0}); + + @override + _MobileNo createState() => _MobileNo(); +} + +class _MobileNo extends State { + var _selectedType = '966'; + String countryCode = '966'; + @override + Widget build(BuildContext context) { + return Visibility( + child: Column(children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + // add Expanded to have your dropdown button fill remaining space + child: Padding( + padding: EdgeInsets.all(10), + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + value: _selectedType, + iconSize: 40, + elevation: 16, + onChanged: (value) => { + widget.onCountryChange(value), + setState(() { + countryCode = value; + _selectedType = value; + }) + }, + items: widget.countries + .map>((Countries value) { + return DropdownMenuItem( + value: value.code, + child: Text(value.name), + ); + }).toList())))), + ], + ), + Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(10)), + child: Row(children: [ + Expanded( + flex: 1, + child: Icon( + Icons.phone, + color: Colors.red, + )), + Expanded( + flex: 1, + child: Text( + countryCode, + overflow: TextOverflow.clip, + )), + Expanded( + flex: 4, + child: Container( + margin: widget.margin != null + ? EdgeInsets.all(widget.margin) + : EdgeInsets.only( + top: widget.marginTop, + right: widget.marginRight, + bottom: widget.marginBottom, + left: widget.marginLeft), + child: TextField( + controller: widget.controller, + keyboardType: TextInputType.phone, + // onChanged: (value) { + // widget.controller.text = countryCode; + // }, + onChanged: (value) => widget.onNumberChange(value), + decoration: InputDecoration( + border: InputBorder.none, hintText: '5xxxxxxxx'), + ), + ), + ) + ]), + ) + ])); + } +} + +class Countries { + final String name; + final String code; + Countries({this.name, this.code}); +} diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index 89bb4336..062b40d8 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -1,4 +1,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import '../progress_indicator/app_loader_widget.dart'; +import 'arrow_back.dart'; import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; import 'package:diplomaticquarterapp/widgets/progress_indicator/app_loader_widget.dart'; import 'package:flutter/material.dart'; diff --git a/lib/widgets/text/app_texts_widget.dart b/lib/widgets/text/app_texts_widget.dart new file mode 100644 index 00000000..e3989719 --- /dev/null +++ b/lib/widgets/text/app_texts_widget.dart @@ -0,0 +1,74 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +// OWNER : Ibrahim albitar +// DATE : 12-04-2020 +// DESCRIPTION : Customization for Texts in app + +class AppText extends StatefulWidget { + final String data; + final Color color; + final FontWeight fontWeight; + final double fontSize; + final String fontFamily; + final double margin; + final double marginTop; + final double marginRight; + final double marginBottom; + final double marginLeft; + final bool visibility; + final TextAlign textAlign; + final Color backGroundcolor; + final bool underline; + AppText(this.data, + {this.color = Colors.black, + this.fontWeight = FontWeight.normal, + this.fontSize, + this.fontFamily = 'WorkSans', + this.margin, + this.marginTop = 0, + this.marginRight = 0, + this.marginBottom = 0, + this.marginLeft = 0, + this.visibility = true, + this.textAlign, + this.underline = false, + this.backGroundcolor = Colors.white}); + + @override + _AppTextState createState() => _AppTextState(); +} + +class _AppTextState extends State { + @override + Widget build(BuildContext context) { + return Visibility( + visible: widget.visibility, + child: Container( + margin: widget.margin != null + ? EdgeInsets.all(widget.margin) + : EdgeInsets.only( + top: widget.marginTop, + right: widget.marginRight, + bottom: widget.marginBottom, + left: widget.marginLeft), + child: Text( + widget.data, + textAlign: widget.textAlign, + overflow: TextOverflow.clip, + style: TextStyle( + color: widget.color, + fontWeight: widget.fontWeight, + fontSize: widget.fontSize ?? (SizeConfig.textMultiplier * 2), + fontFamily: widget.fontFamily, + decoration: widget.underline == true + ? TextDecoration.underline + : TextDecoration.none + // backgroundColor:widget.backGroundcolor + ), + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 62ce8f3f..9a13dcdd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,7 +38,8 @@ dependencies: url_launcher: ^5.5.0 shared_preferences: ^0.5.8 flutter_flexible_toast: ^0.1.4 - + firebase_messaging: ^6.0.16 + # Progress bar progress_hud_v2: ^2.0.0 percent_indicator: ^2.1.5