From 3aec62dceb24e28590de29fc9112fc487aeaffea Mon Sep 17 00:00:00 2001 From: Elham Rababah Date: Tue, 18 Aug 2020 15:18:12 +0300 Subject: [PATCH 1/7] First step from login page --- ios/Podfile | 87 ++++++ lib/app-icons/config.json | 24 ++ lib/app-icons/driver_app_icons.dart | 25 ++ lib/app-icons/fonts/DriverApp.ttf | Bin 0 -> 2116 bytes lib/config/shared_pref_kay.dart | 2 + .../authentication/authenticated_user.dart | 282 ++++++++++++++++++ lib/core/service/authentication_service.dart | 29 ++ lib/core/service/base_service.dart | 19 +- .../viewModels/authentication_view_model.dart | 30 ++ lib/core/viewModels/base_view_model.dart | 18 +- lib/locator.dart | 4 + lib/main.dart | 7 +- lib/pages/authentication/login_page.dart | 85 ++++++ lib/root_page.dart | 36 +++ lib/widgets/buttons/secondary_button.dart | 27 +- lib/widgets/others/app_scaffold_widget.dart | 66 ++-- lib/widgets/others/network_base_view.dart | 3 +- pubspec.yaml | 4 + 18 files changed, 702 insertions(+), 46 deletions(-) create mode 100644 ios/Podfile create mode 100644 lib/app-icons/config.json create mode 100644 lib/app-icons/driver_app_icons.dart create mode 100644 lib/app-icons/fonts/DriverApp.ttf create mode 100644 lib/core/model/authentication/authenticated_user.dart create mode 100644 lib/core/service/authentication_service.dart create mode 100644 lib/core/viewModels/authentication_view_model.dart create mode 100644 lib/pages/authentication/login_page.dart create mode 100644 lib/root_page.dart diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..6697f0a --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,87 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + generated_key_values = {} + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) do |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + generated_key_values[podname] = podpath + else + puts "Invalid plugin specification: #{line}" + end + end + generated_key_values +end + +target 'Runner' do + use_frameworks! + use_modular_headers! + + # Flutter Pod + + copied_flutter_dir = File.join(__dir__, 'Flutter') + copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') + copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') + unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) + # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. + # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. + # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. + + generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') + unless File.exist?(generated_xcode_build_settings_path) + raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) + cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; + + unless File.exist?(copied_framework_path) + FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) + end + unless File.exist?(copied_podspec_path) + FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) + end + end + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'Flutter', :path => 'Flutter' + + # Plugin Pods + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.each do |name, path| + symlink = File.join('.symlinks', 'plugins', name) + File.symlink(path, symlink) + pod name, :path => File.join(symlink, 'ios') + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/lib/app-icons/config.json b/lib/app-icons/config.json new file mode 100644 index 0000000..cca5b07 --- /dev/null +++ b/lib/app-icons/config.json @@ -0,0 +1,24 @@ +{ + "name": "DriverApp", + "css_prefix_text": "", + "css_use_suffix": false, + "hinting": true, + "units_per_em": 1000, + "ascent": 850, + "glyphs": [ + { + "uid": "6b13cdbdada31c1cc88c63aedc146a9c", + "css": "logo", + "code": 59393, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M1572.1 336.4A308.4 308.4 0 0 0 1008.4 436.3C1007 443.1 1005.5 449.9 1003.6 458.7 972.3 454.4 941.8 450.3 911.4 446.1S850.1 437.4 818 432.8C818.4 426.5 818.3 421 819.2 415.9A498.9 498.9 0 1 1 1532.6 947.1 489.1 489.1 0 0 1 1117.1 960 21.8 21.8 0 0 1 1101 931.9C1116.5 824.5 1160.3 502.5 1164.7 470 1172.6 412.1 1179.8 354 1189 296.4A37.2 37.2 0 0 1 1207.3 272.1 252.3 252.3 0 0 1 1362.2 255.7C1379.3 259 1385.5 264.7 1382.3 283.6 1374.2 331.4 1368.2 379.7 1362.4 427.9 1361.1 438.9 1326.1 693.4 1309.7 810 1331.9 807.6 1351.9 806.7 1371.5 803.2A308.6 308.6 0 0 0 1619 493.2C1618.7 485.7 1616.7 459.2 1615.7 452.9A436.5 436.5 0 0 0 1590.8 372C1588.7 368.6 1577.1 344.3 1572.1 336.4ZM237.6 663.6A308.4 308.4 0 0 0 801.2 563.8C802.7 557 804.2 550.2 806.1 541.4 837.4 545.6 867.9 549.7 898.3 554S959.6 562.7 991.7 567.3C991.3 573.6 991.3 579.1 990.5 584.2A498.9 498.9 0 1 1 277 53 489.1 489.1 0 0 1 692.6 40.1 21.8 21.8 0 0 1 708.6 68.2C693.2 175.5 649.4 497.6 645 530.1 637.1 588 629.9 646 620.7 703.7A37.2 37.2 0 0 1 602.4 728 252.4 252.4 0 0 1 447.5 744.4C430.5 741.1 424.2 735.3 427.4 716.5 435.5 668.6 441.6 620.4 447.3 572.1 448.7 561.2 483.6 306.7 500 190.1 477.8 192.4 457.8 193.4 438.2 196.9A308.6 308.6 0 0 0 190.7 506.9C191 514.3 193 540.9 194.1 547.2A436.5 436.5 0 0 0 218.9 628.1C221 631.4 232.6 655.5 237.6 663.6Z", + "width": 1810 + }, + "search": [ + "logo" + ] + } + ] +} \ No newline at end of file diff --git a/lib/app-icons/driver_app_icons.dart b/lib/app-icons/driver_app_icons.dart new file mode 100644 index 0000000..f66e96e --- /dev/null +++ b/lib/app-icons/driver_app_icons.dart @@ -0,0 +1,25 @@ +/// Flutter icons DriverApp +/// Copyright (C) 2020 by original authors @ fluttericon.com, fontello.com +/// This font was generated by FlutterIcon.com, which is derived from Fontello. +/// +/// To use this font, place it in your fonts/ directory and include the +/// following in your pubspec.yaml +/// +/// flutter: +/// fonts: +/// - family: DriverApp +/// fonts: +/// - asset: fonts/DriverApp.ttf +/// +/// +/// +import 'package:flutter/widgets.dart'; + +class DriverApp { + DriverApp._(); + + static const _kFontFam = 'DriverApp'; + static const _kFontPkg = null; + + static const IconData logo = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); +} diff --git a/lib/app-icons/fonts/DriverApp.ttf b/lib/app-icons/fonts/DriverApp.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a9e0e9fc83c193bb1212377594424a3275f8043d GIT binary patch literal 2116 zcmd^A&u<%55T4n!*K0d*ev$+z&1;p!4M}ass+Q@A%9#@vI97rpaY!X3qzE|lQ1iX@Hci#^FW{}7-#6cU zGjHDPdY71pqI82)N-bP^=ZyGt@H!DsfL&g^luS(<4{fUjK)p>aJAWGu-bUuZS&#gqnq|lOkCRnMt9Kd|R>+Ttp2_Iix>A zDVic>ZvM?>idlwRrI#q+d7J)&n5}ZrK>ntOp_5()!=ycCgCFo`6vW2Y71^1XW)KWfN}Yi4Wa zLfDgpZLDazo)8h6i~$(s+>i|5Wy_Vu2fFB$jp;fNYO{z^m( z#0D4Rtr1m^G7rXLqWukLT4CmJyB2x)WBL|y1YgdSpOYf`VqZWCO52v7g}%Y}Hm-mdFPOYG!(y8h@d zlU22C<->E`?SWV0EnSa(xQHyPy#YNIiX5I~;qEubCZD8v?cENp98BWfDC(qN{d-0< z52|_pn8L7{SfLOt`d9^@^>G0BijRYMo0fd6fv@{GLL>CPkE7H@U(0`7AdG!>=#Gz> zI(gp53dQ)ck5%vm9|wT9d>o`6{=~-`_%D4Np)7yv<0uU&`m9~scFM()D^AP~i*zcT z5?8l{4XRuQY*)otBDK#gm{rp;Tr)4XtZx?6u3HcV$F7KZKewnk_PUvK6D8NJO(v5E z_oP{}sYcu6P??J8tV@DUfE~t~#`{-JL06#=P&QR%s**t#7=tztQSv->*fW>~cqHqR z>FIOuR`E5FYXxsWsgR8HTe$3f-<+r4^x{sVsv0c;7m>}vP7Xcmf0oI5(RG|g?jdLl z*;9u^E$HhI)7}XRUbT)_xxjP!bln0KO5Zy2(!9VMAesRSH;k(U$K20HxnM(*OVf literal 0 HcmV?d00001 diff --git a/lib/config/shared_pref_kay.dart b/lib/config/shared_pref_kay.dart index 8c03fcc..b1bfbc9 100644 --- a/lib/config/shared_pref_kay.dart +++ b/lib/config/shared_pref_kay.dart @@ -1,3 +1,5 @@ const TOKEN = 'token'; const APP_LANGUAGE = 'language'; +const USER_PROFILE = 'user-profile'; + diff --git a/lib/core/model/authentication/authenticated_user.dart b/lib/core/model/authentication/authenticated_user.dart new file mode 100644 index 0000000..7ca3a3e --- /dev/null +++ b/lib/core/model/authentication/authenticated_user.dart @@ -0,0 +1,282 @@ +class AuthenticatedUser { + String setupID; + int patientType; + int patientID; + String firstName; + String middleName; + String lastName; + String firstNameN; + String middleNameN; + String lastNameN; + int relationshipID; + int gender; + String dateofBirth; + dynamic dateofBirthN; + String nationalityID; + dynamic phoneResi; + dynamic phoneOffice; + String mobileNumber; + dynamic faxNumber; + String emailAddress; + dynamic bloodGroup; + dynamic rHFactor; + bool isEmailAlertRequired; + bool isSMSAlertRequired; + String preferredLanguage; + bool isPrivilegedMember; + dynamic memberID; + dynamic expiryDate; + dynamic isHmgEmployee; + dynamic employeeID; + dynamic emergencyContactName; + dynamic emergencyContactNo; + int patientPayType; + dynamic dHCCPatientRefID; + bool isPatientDummy; + int status; + dynamic isStatusCleared; + int patientIdentificationType; + String patientIdentificationNo; + int projectID; + int infoSourceID; + dynamic address; + int age; + String ageDesc; + int areaID; + int createdBy; + String genderDescription; + dynamic iR; + dynamic iSOCityID; + dynamic iSOCountryID; + List listPrivilege; + dynamic marital; + int outSA; + dynamic pOBox; + bool receiveHealthSummaryReport; + int sourceType; + dynamic strDateofBirth; + dynamic tempAddress; + dynamic zipCode; + // dynamic patientPayType; + // dynamic patientType; + // dynamic status; + + AuthenticatedUser({ + this.setupID, + this.patientType, + this.patientID, + this.firstName, + this.middleName, + this.lastName, + this.firstNameN, + this.middleNameN, + this.lastNameN, + this.relationshipID, + this.gender, + this.dateofBirth, + this.dateofBirthN, + this.nationalityID, + this.phoneResi, + this.phoneOffice, + this.mobileNumber, + this.faxNumber, + this.emailAddress, + this.bloodGroup, + this.rHFactor, + this.isEmailAlertRequired, + this.isSMSAlertRequired, + this.preferredLanguage, + this.isPrivilegedMember, + this.memberID, + this.expiryDate, + this.isHmgEmployee, + this.employeeID, + this.emergencyContactName, + this.emergencyContactNo, + this.patientPayType, + this.dHCCPatientRefID, + this.isPatientDummy, + this.status, + this.isStatusCleared, + this.patientIdentificationType, + this.patientIdentificationNo, + this.projectID, + this.infoSourceID, + this.address, + this.age, + this.ageDesc, + this.areaID, + this.createdBy, + this.genderDescription, + this.iR, + this.iSOCityID, + this.iSOCountryID, + this.listPrivilege, + this.marital, + this.outSA, + this.pOBox, + this.receiveHealthSummaryReport, + this.sourceType, + this.strDateofBirth, + this.tempAddress, + this.zipCode, + }); + + AuthenticatedUser.fromJson(Map json) { + setupID = json['SetupID']; + patientType = json['PatientType']; + patientID = json['PatientID']; + firstName = json['FirstName']; + middleName = json['MiddleName']; + lastName = json['LastName']; + firstNameN = json['FirstNameN']; + middleNameN = json['MiddleNameN']; + lastNameN = json['LastNameN']; + relationshipID = json['RelationshipID']; + gender = json['Gender']; + dateofBirth = json['DateofBirth']; + dateofBirthN = json['DateofBirthN']; + nationalityID = json['NationalityID']; + phoneResi = json['PhoneResi']; + phoneOffice = json['PhoneOffice']; + mobileNumber = json['MobileNumber']; + faxNumber = json['FaxNumber']; + emailAddress = json['EmailAddress']; + bloodGroup = json['BloodGroup']; + rHFactor = json['RHFactor']; + isEmailAlertRequired = json['IsEmailAlertRequired']; + isSMSAlertRequired = json['IsSMSAlertRequired']; + preferredLanguage = json['PreferredLanguage']; + isPrivilegedMember = json['IsPrivilegedMember']; + memberID = json['MemberID']; + expiryDate = json['ExpiryDate']; + isHmgEmployee = json['IsHmgEmployee']; + employeeID = json['EmployeeID']; + emergencyContactName = json['EmergencyContactName']; + emergencyContactNo = json['EmergencyContactNo']; + patientPayType = json['PatientPayType']; + dHCCPatientRefID = json['DHCCPatientRefID']; + isPatientDummy = json['IsPatientDummy']; + status = json['Status']; + isStatusCleared = json['IsStatusCleared']; + patientIdentificationType = json['PatientIdentificationType']; + patientIdentificationNo = json['PatientIdentificationNo']; + projectID = json['ProjectID']; + infoSourceID = json['InfoSourceID']; + address = json['Address']; + age = json['Age']; + ageDesc = json['AgeDesc']; + areaID = json['AreaID']; + createdBy = json['CreatedBy']; + genderDescription = json['GenderDescription']; + iR = json['IR']; + iSOCityID = json['ISOCityID']; + iSOCountryID = json['ISOCountryID']; + if (json['ListPrivilege'] != null) { + listPrivilege = new List(); + json['ListPrivilege'].forEach((v) { + listPrivilege.add(new ListPrivilege.fromJson(v)); + }); + } + marital = json['Marital']; + outSA = json['OutSA']; + pOBox = json['POBox']; + receiveHealthSummaryReport = json['ReceiveHealthSummaryReport']; + sourceType = json['SourceType']; + strDateofBirth = json['StrDateofBirth']; + tempAddress = json['TempAddress']; + zipCode = json['ZipCode']; + } + + Map toJson() { + final Map data = new Map(); + data['SetupID'] = this.setupID; + data['PatientType'] = this.patientType; + data['PatientID'] = this.patientID; + data['FirstName'] = this.firstName; + data['MiddleName'] = this.middleName; + data['LastName'] = this.lastName; + data['FirstNameN'] = this.firstNameN; + data['MiddleNameN'] = this.middleNameN; + data['LastNameN'] = this.lastNameN; + data['RelationshipID'] = this.relationshipID; + data['Gender'] = this.gender; + data['DateofBirth'] = this.dateofBirth; + data['DateofBirthN'] = this.dateofBirthN; + data['NationalityID'] = this.nationalityID; + data['PhoneResi'] = this.phoneResi; + data['PhoneOffice'] = this.phoneOffice; + data['MobileNumber'] = this.mobileNumber; + data['FaxNumber'] = this.faxNumber; + data['EmailAddress'] = this.emailAddress; + data['BloodGroup'] = this.bloodGroup; + data['RHFactor'] = this.rHFactor; + data['IsEmailAlertRequired'] = this.isEmailAlertRequired; + data['IsSMSAlertRequired'] = this.isSMSAlertRequired; + data['PreferredLanguage'] = this.preferredLanguage; + data['IsPrivilegedMember'] = this.isPrivilegedMember; + data['MemberID'] = this.memberID; + data['ExpiryDate'] = this.expiryDate; + data['IsHmgEmployee'] = this.isHmgEmployee; + data['EmployeeID'] = this.employeeID; + data['EmergencyContactName'] = this.emergencyContactName; + data['EmergencyContactNo'] = this.emergencyContactNo; + data['PatientPayType'] = this.patientPayType; + data['DHCCPatientRefID'] = this.dHCCPatientRefID; + data['IsPatientDummy'] = this.isPatientDummy; + data['Status'] = this.status; + data['IsStatusCleared'] = this.isStatusCleared; + data['PatientIdentificationType'] = this.patientIdentificationType; + data['PatientIdentificationNo'] = this.patientIdentificationNo; + data['ProjectID'] = this.projectID; + data['InfoSourceID'] = this.infoSourceID; + data['Address'] = this.address; + data['Age'] = this.age; + data['AgeDesc'] = this.ageDesc; + data['AreaID'] = this.areaID; + data['CreatedBy'] = this.createdBy; + data['GenderDescription'] = this.genderDescription; + data['IR'] = this.iR; + data['ISOCityID'] = this.iSOCityID; + data['ISOCountryID'] = this.iSOCountryID; + if (this.listPrivilege != null) { + data['ListPrivilege'] = + this.listPrivilege.map((v) => v.toJson()).toList(); + } + data['Marital'] = this.marital; + data['OutSA'] = this.outSA; + data['POBox'] = this.pOBox; + data['ReceiveHealthSummaryReport'] = this.receiveHealthSummaryReport; + data['SourceType'] = this.sourceType; + data['StrDateofBirth'] = this.strDateofBirth; + data['TempAddress'] = this.tempAddress; + data['ZipCode'] = this.zipCode; + + return data; + } +} + +class ListPrivilege { + int iD; + String serviceName; + bool previlege; + dynamic region; + + ListPrivilege({this.iD, this.serviceName, this.previlege, this.region}); + + ListPrivilege.fromJson(Map json) { + iD = json['ID']; + serviceName = json['ServiceName']; + previlege = json['Previlege']; + region = json['Region']; + } + + Map toJson() { + final Map data = new Map(); + data['ID'] = this.iD; + data['ServiceName'] = this.serviceName; + data['Previlege'] = this.previlege; + data['Region'] = this.region; + return data; + } +} diff --git a/lib/core/service/authentication_service.dart b/lib/core/service/authentication_service.dart new file mode 100644 index 0000000..ae26b38 --- /dev/null +++ b/lib/core/service/authentication_service.dart @@ -0,0 +1,29 @@ + +import 'package:driverapp/core/service/base_service.dart'; +import 'package:flutter/cupertino.dart'; + + +class AuthenticationService extends BaseService { + String selectedClinicName; + bool isLogin = false; + bool isLoading = true; + + AuthenticationService() { +// getUserAuthentication(); + } + +// void getUserAuthentication() async { +// if (profile != null) { +//// doctorProfile = new DoctorProfileModel.fromJson(profile); +// isLoading = false; +// isLogin = true; +// } else { +// isLoading = false; +// isLogin = false; +// } +// notifyListeners(); +// } + + + +} diff --git a/lib/core/service/base_service.dart b/lib/core/service/base_service.dart index 828420c..33ce779 100644 --- a/lib/core/service/base_service.dart +++ b/lib/core/service/base_service.dart @@ -1,9 +1,26 @@ +import 'package:driverapp/config/shared_pref_kay.dart'; +import 'package:driverapp/core/model/authentication/authenticated_user.dart'; +import 'package:driverapp/uitl/app_shared_preferences.dart'; import 'client/base_app_client.dart'; -class BaseService{ +class BaseService { String error; bool hasError = false; BaseAppClient baseAppClient = BaseAppClient(); + AuthenticatedUser user; + AppSharedPreferences sharedPref = AppSharedPreferences(); + + BaseService() { + getUser(); + } + + getUser() async { + var userProfile = await sharedPref.getObject(USER_PROFILE); + if (userProfile != null) { + user = + AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); + } + } } \ No newline at end of file diff --git a/lib/core/viewModels/authentication_view_model.dart b/lib/core/viewModels/authentication_view_model.dart new file mode 100644 index 0000000..53aed7b --- /dev/null +++ b/lib/core/viewModels/authentication_view_model.dart @@ -0,0 +1,30 @@ +import 'package:driverapp/core/enum/viewstate.dart'; +import 'package:driverapp/core/service/authentication_service.dart'; +import 'package:driverapp/core/viewModels/base_view_model.dart'; + +import '../../locator.dart'; + +enum APP_STATUS { LOADING, UNAUTHENTICATED, AUTHENTICATED } + +class AuthenticationViewModel extends BaseViewModel { + AuthenticationService _authenticationService = locator(); + + APP_STATUS get status { + if (state == ViewState.Busy || state == ViewState.BusyLocal) { + return APP_STATUS.LOADING; + } else { + if (user != null) { + return APP_STATUS.AUTHENTICATED; + } else { + return APP_STATUS.UNAUTHENTICATED; + } + } + } + + login({String userName,String password}){ + setState(ViewState.BusyLocal); + // call api +// if() +// setState(viewState) + } +} diff --git a/lib/core/viewModels/base_view_model.dart b/lib/core/viewModels/base_view_model.dart index f48bc1b..2af07b6 100644 --- a/lib/core/viewModels/base_view_model.dart +++ b/lib/core/viewModels/base_view_model.dart @@ -1,4 +1,7 @@ +import 'package:driverapp/config/shared_pref_kay.dart'; import 'package:driverapp/core/enum/viewstate.dart'; +import 'package:driverapp/core/model/authentication/authenticated_user.dart'; +import 'package:driverapp/uitl/app_shared_preferences.dart'; import 'package:flutter/material.dart'; class BaseViewModel extends ChangeNotifier { @@ -6,8 +9,21 @@ class BaseViewModel extends ChangeNotifier { bool isInternetConnection = true; ViewState get state => _state; - + AuthenticatedUser user; String error = ""; + AppSharedPreferences sharedPref = AppSharedPreferences(); + + BaseViewModel(){ + getUser(); + } + + getUser() async { + var userProfile = await sharedPref.getObject(USER_PROFILE); + if (userProfile != null) { + user = + AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); + } + } //TODO load user details from SP diff --git a/lib/locator.dart b/lib/locator.dart index 3d44f4c..b7f1052 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -1,6 +1,8 @@ import 'package:get_it/get_it.dart'; +import 'core/service/authentication_service.dart'; import 'core/service/hospital_service.dart'; +import 'core/viewModels/authentication_view_model.dart'; import 'core/viewModels/hospital_view_model.dart'; GetIt locator = GetIt.instance; @@ -9,7 +11,9 @@ GetIt locator = GetIt.instance; void setupLocator() { /// Services locator.registerLazySingleton(() => HospitalService()); + locator.registerLazySingleton(() => AuthenticationService()); /// View Model locator.registerFactory(() => HospitalViewModel()); + locator.registerFactory(() => AuthenticationViewModel()); } diff --git a/lib/main.dart b/lib/main.dart index 930ca7d..c93225c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,11 @@ +import 'package:driverapp/root_page.dart'; import 'package:driverapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:provider/provider.dart'; import 'config/size_config.dart'; +import 'core/service/authentication_service.dart'; import 'core/viewModels/project_view_model.dart'; import 'locator.dart'; import 'pages/landing/landing_page.dart'; @@ -25,7 +27,7 @@ class MyApp extends StatelessWidget { providers: [ ChangeNotifierProvider( create: (context) => ProjectViewModel(), - ), + ) ], child: Consumer( builder: (context, projectProvider, child) => MaterialApp( @@ -51,6 +53,7 @@ class MyApp extends StatelessWidget { TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), }, ), + scaffoldBackgroundColor:Color.fromRGBO(239, 245, 245, 1) , hintColor: Colors.grey[400], disabledColor: Colors.grey[300], errorColor: Color.fromRGBO(235, 80, 60, 1.0), @@ -73,7 +76,7 @@ class MyApp extends StatelessWidget { ), ), initialRoute: '/', - routes: {'/': (context) => LandingPage()}, + routes: {'/': (context) => RootPage()}, debugShowCheckedModeBanner: false, ), ), diff --git a/lib/pages/authentication/login_page.dart b/lib/pages/authentication/login_page.dart new file mode 100644 index 0000000..0f860e7 --- /dev/null +++ b/lib/pages/authentication/login_page.dart @@ -0,0 +1,85 @@ +import 'package:driverapp/app-icons/driver_app_icons.dart'; +import 'package:driverapp/core/viewModels/authentication_view_model.dart'; +import 'package:driverapp/pages/base/base_view.dart'; +import 'package:driverapp/widgets/buttons/secondary_button.dart'; +import 'package:driverapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class LoginPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return AnimatedSwitcher( + duration: Duration(microseconds: 350), + child: BaseView( + builder: (_, model, widget) => AppScaffold( + baseViewModel: model, + body: Center( + child: Column( + + children: [ + FractionallySizedBox( + widthFactor: 0.9, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(DriverApp.logo, + size: 60, + color: Colors.red,), + ], + ), + Column(), + new Container( + height: 22.28, + width: 139.13, + decoration: BoxDecoration( + color: Color(0xffffffff), + border: Border.all( + width: 1.00, + color: Color(0xff707070), + ), + borderRadius: BorderRadius.circular(6.00), + ), + ), + Container( + height: 22.28, + width: 139.13, + decoration: BoxDecoration( + color: Color(0xffffffff), + border: Border.all( + width: 1.00, + color: Color(0xff707070), + ), + borderRadius: BorderRadius.circular(6.00), + ), + ), + new Container( + height: 22.28, + width: 139.13, + decoration: BoxDecoration( + color: Color(0xffffffff), + border: Border.all( + width: 1.00, + color: Color(0xff707070), + ), + borderRadius: BorderRadius.circular(6.00), + ), + ) + ], + ), + ), + FractionallySizedBox( + widthFactor: 0.90, + child: SecondaryButton(label: "DFDf"), + ) + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/root_page.dart b/lib/root_page.dart new file mode 100644 index 0000000..6e3125e --- /dev/null +++ b/lib/root_page.dart @@ -0,0 +1,36 @@ +import 'package:driverapp/pages/authentication/login_page.dart'; +import 'package:driverapp/pages/base/base_view.dart'; +import 'package:driverapp/pages/landing/landing_page.dart'; +import 'package:driverapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'core/viewModels/authentication_view_model.dart'; + +class RootPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + Widget buildRoot(APP_STATUS status) { + switch (status) { + case APP_STATUS.UNAUTHENTICATED: + return LoginPage(); + break; + case APP_STATUS.AUTHENTICATED: + return LandingPage(); + break; + } + } + + return AnimatedSwitcher( + duration: Duration(microseconds: 350), + child: BaseView( + builder: (_, model, widget) => AppScaffold( + baseViewModel: model, + body: buildRoot((model.status)), + ), + ), + ); + } +} + + diff --git a/lib/widgets/buttons/secondary_button.dart b/lib/widgets/buttons/secondary_button.dart index a63f027..dc88f3d 100644 --- a/lib/widgets/buttons/secondary_button.dart +++ b/lib/widgets/buttons/secondary_button.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:hexcolor/hexcolor.dart'; /// SecondaryButton widget /// [label] button label @@ -87,6 +88,7 @@ class _SecondaryButtonState extends State _rippleSize = _rippleAnimation.value; }); }); + super.initState(); } @@ -160,17 +162,22 @@ class _SecondaryButtonState extends State child: ClipRRect( borderRadius: widget.noBorderRadius ? BorderRadius.all(Radius.circular(0.0)) - : BorderRadius.all(Radius.circular(10.0)), + : BorderRadius.all(Radius.circular(40.0)), child: Stack( children: [ Positioned( left: 0, bottom: 0, child: Container( - width: MediaQuery.of(context).size.width, + width: MediaQuery + .of(context) + .size + .width, height: 100, decoration: BoxDecoration( - color: Theme.of(context).disabledColor, + color: Theme + .of(context) + .disabledColor, ), ), ), @@ -184,7 +191,8 @@ class _SecondaryButtonState extends State height: MediaQuery.of(context).size.width * 2.2, decoration: BoxDecoration( shape: BoxShape.circle, - color: widget.color, + color: widget.color != null ? widget.color : Hexcolor( + "#1CA4AA"), ), ), ), @@ -193,8 +201,8 @@ class _SecondaryButtonState extends State padding: widget.iconOnly ? EdgeInsets.symmetric(vertical: 4.0, horizontal: 5.0) : EdgeInsets.only( - top: widget.small ? 8.0 : 14.0, - bottom: widget.small ? 6.0 : 14.0, + top: widget.small ? 8.0 : 12.0, + bottom: widget.small ? 6.0 : 12.0, left: 18.0, right: 18.0), child: Stack( @@ -223,12 +231,13 @@ class _SecondaryButtonState extends State ) : Padding( padding: EdgeInsets.only( - bottom: widget.small ? 4.0 : 3.0), + bottom: widget.small ? 4.0 : 2.0), child: Text(widget.label, style: TextStyle( - color: widget.textColor, + color: widget.textColor != null + ? widget.textColor + : Colors.white, fontSize: 17.0, - fontWeight: FontWeight.w800, fontFamily: "WorkSans")), ) ], diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index d5e9c51..3005588 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -24,40 +24,42 @@ class AppScaffold extends StatelessWidget { @override Widget build(BuildContext context) { AppGlobal.context = context; - return Scaffold( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - appBar: isShowAppBar - ? AppBar( - elevation: 0, - backgroundColor: Theme.of(context).appBarTheme.color, - textTheme: TextTheme( - headline6: - TextStyle(color: Colors.white, fontWeight: FontWeight.bold), - ), - title: Text(appBarTitle.toUpperCase()), - leading: Builder( - builder: (BuildContext context) { - return ArrowBack(); - }, - ), - centerTitle: true, - actions: [ - IconButton( - icon: Icon(FontAwesomeIcons.home), - color: Colors.white, - onPressed: () { - // TODO add navigator to home page + return SafeArea( + child: Scaffold( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + appBar: isShowAppBar + ? AppBar( + elevation: 0, + backgroundColor: Theme.of(context).appBarTheme.color, + textTheme: TextTheme( + headline6: + TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + ), + title: Text(appBarTitle.toUpperCase()), + leading: Builder( + builder: (BuildContext context) { + return ArrowBack(); }, ), - ], - ) - : null, - body: baseViewModel != null - ? NetworkBaseView( - child: buildBodyWidget(), - baseViewModel: baseViewModel, - ) - : buildBodyWidget(), + centerTitle: true, + actions: [ + IconButton( + icon: Icon(FontAwesomeIcons.home), + color: Colors.white, + onPressed: () { + // TODO add navigator to home page + }, + ), + ], + ) + : null, + body: baseViewModel != null + ? NetworkBaseView( + child: buildBodyWidget(), + baseViewModel: baseViewModel, + ) + : buildBodyWidget(), + ), ); } diff --git a/lib/widgets/others/network_base_view.dart b/lib/widgets/others/network_base_view.dart index 5776e84..fe409bc 100644 --- a/lib/widgets/others/network_base_view.dart +++ b/lib/widgets/others/network_base_view.dart @@ -20,6 +20,8 @@ class NetworkBaseView extends StatelessWidget { buildBaseViewWidget() { switch (baseViewModel.state) { case ViewState.Idle: + case ViewState.BusyLocal: + case ViewState.ErrorLocal: return child; break; case ViewState.Busy: @@ -31,7 +33,6 @@ class NetworkBaseView extends StatelessWidget { error: baseViewModel.error, ), ); - break; } } } diff --git a/pubspec.yaml b/pubspec.yaml index fefcf54..358a44e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -92,3 +92,7 @@ flutter: - asset: assets/fonts/Work_Sans/WorkSans-Bold.ttf - asset: assets/fonts/Work_Sans/WorkSans-Bold.ttf weight: 700 + + - family: DriverApp + fonts: + - asset: lib/app-icons/fonts/DriverApp.ttf From 8a8dd6457dfefc57aa60b7c9345198a064bcf9be Mon Sep 17 00:00:00 2001 From: Elham Rababah Date: Wed, 19 Aug 2020 12:08:16 +0300 Subject: [PATCH 2/7] Finish login page --- lib/main.dart | 10 +- lib/pages/authentication/login_page.dart | 212 +++++++++++---- lib/widgets/input/text_field.dart | 331 +++++++++++++---------- 3 files changed, 364 insertions(+), 189 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index c93225c..9626777 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,10 +5,10 @@ import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:provider/provider.dart'; import 'config/size_config.dart'; -import 'core/service/authentication_service.dart'; import 'core/viewModels/project_view_model.dart'; import 'locator.dart'; -import 'pages/landing/landing_page.dart'; + + void main() { setupLocator(); @@ -56,6 +56,9 @@ class MyApp extends StatelessWidget { scaffoldBackgroundColor:Color.fromRGBO(239, 245, 245, 1) , hintColor: Colors.grey[400], disabledColor: Colors.grey[300], + bottomSheetTheme: BottomSheetThemeData( + backgroundColor: Color.fromRGBO(239, 245, 245, 1) + ), errorColor: Color.fromRGBO(235, 80, 60, 1.0), textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), textSelectionHandleColor: Color.fromRGBO(80, 100, 253, 1.0), @@ -63,9 +66,10 @@ class MyApp extends StatelessWidget { backgroundColor: Color.fromRGBO(255, 255, 255, 1), highlightColor: Colors.grey[100].withOpacity(0.4), splashColor: Colors.transparent, - primaryColor: Colors.grey, + primaryColor: Color.fromRGBO(69, 183, 174, 1.0), cursorColor: Color.fromRGBO(78, 62, 253, 1.0), iconTheme: IconThemeData(), + dividerColor: Color.fromRGBO(112, 112, 112, 1.0), appBarTheme: AppBarTheme( color: Colors.grey, brightness: Brightness.light, diff --git a/lib/pages/authentication/login_page.dart b/lib/pages/authentication/login_page.dart index 0f860e7..f5dd638 100644 --- a/lib/pages/authentication/login_page.dart +++ b/lib/pages/authentication/login_page.dart @@ -2,9 +2,11 @@ import 'package:driverapp/app-icons/driver_app_icons.dart'; import 'package:driverapp/core/viewModels/authentication_view_model.dart'; import 'package:driverapp/pages/base/base_view.dart'; import 'package:driverapp/widgets/buttons/secondary_button.dart'; -import 'package:driverapp/widgets/others/app_scaffold_widget.dart'; +import 'package:driverapp/widgets/input/text_field.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:hexcolor/hexcolor.dart'; class LoginPage extends StatelessWidget { @override @@ -12,74 +14,192 @@ class LoginPage extends StatelessWidget { return AnimatedSwitcher( duration: Duration(microseconds: 350), child: BaseView( - builder: (_, model, widget) => AppScaffold( - baseViewModel: model, + builder: (_, model, widget) => Scaffold( + //baseViewModel: model, body: Center( child: Column( - + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ FractionallySizedBox( - widthFactor: 0.9, + widthFactor: 0.80, child: Column( - crossAxisAlignment: CrossAxisAlignment.center, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, + SizedBox( + height: 40, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Icon(DriverApp.logo, - size: 60, - color: Colors.red,), + Container( + child: Icon( + DriverApp.logo, + size: 70, + color: Theme.of(context).primaryColor, + ), + margin: EdgeInsets.only( + right: + MediaQuery.of(context).size.width * 0.15), + ), ], ), - Column(), - new Container( - height: 22.28, - width: 139.13, - decoration: BoxDecoration( - color: Color(0xffffffff), - border: Border.all( - width: 1.00, - color: Color(0xff707070), + SizedBox( + height: 20, + ), + Column( + children: [ + Text( + "Driver", + style: TextStyle( + fontSize: 50, fontWeight: FontWeight.bold), + ), + Text( + "Delivery", + style: TextStyle(fontSize: 36, letterSpacing: 1), + ), + Text( + "APP", + style: TextStyle( + fontSize: 33, + letterSpacing: 33, + fontWeight: FontWeight.w400), ), - borderRadius: BorderRadius.circular(6.00), - ), + ], + ), + SizedBox( + height: 30, ), - Container( - height: 22.28, - width: 139.13, - decoration: BoxDecoration( - color: Color(0xffffffff), - border: Border.all( - width: 1.00, - color: Color(0xff707070), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircleContainer( + child: Text( + "English", + style: TextStyle( + fontSize: 12, color: Colors.white), + ), + color: Theme.of(context).primaryColor, borderWidth: 0,borderColor: Colors.transparent,), + SizedBox( + width: 20, ), - borderRadius: BorderRadius.circular(6.00), - ), + CircleContainer( + child: Text( + "Arabic", + style: TextStyle( + fontSize: 12, color: Colors.black), + ), + color: Colors.transparent, borderColor: Theme.of(context).primaryColor,borderWidth: 3,), + ], + ), + SizedBox( + height: 10, ), - new Container( - height: 22.28, - width: 139.13, - decoration: BoxDecoration( - color: Color(0xffffffff), - border: Border.all( - width: 1.00, - color: Color(0xff707070), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "Please insert username and password to login", + style: TextStyle( + fontSize: 13, color: Colors.grey), + ), + SizedBox( + height: 10, + ) + ], + ), + ), + SizedBox( + height: 10, ), - borderRadius: BorderRadius.circular(6.00), - ), - ) + Container( + child: TextFields( + onChanged: (value) => {}, + hintText: "User Name", + ), + ), + SizedBox( + height: 20, + ), + Container( + child: TextFields( + borderRadiusValue: 6, + onChanged: (value) => {}, + hintText: "Password", + ), + ), + SizedBox( + height: 25, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "Forgot Password?", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).primaryColor), + ), + ], + ), + ], + ), ], ), ), - FractionallySizedBox( - widthFactor: 0.90, - child: SecondaryButton(label: "DFDf"), + SizedBox( + height: 20, + ), + SizedBox( + height: 10, ) ], ), ), + bottomSheet: Container( + margin: EdgeInsets.all(10), + height: MediaQuery.of(context).size.height * 0.12, + child: Column( + children: [ + SecondaryButton(label: "Login"), + SizedBox( + height: 30, + ) + ], + )), ), ), ); } } + +class CircleContainer extends StatelessWidget { + const CircleContainer( + {this.child, + this.color = Colors.white, + this.borderColor, + this.borderWidth = 2.0}); + + final Widget child; + final Color color; + final Color borderColor; + final double borderWidth; + + @override + Widget build(BuildContext context) { + return Container( + child: Center(child: child), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: color, + border: Border.all( + color: borderColor ?? Hexcolor("#707070"), + width: borderWidth)), + height: 60, + width: 60, + ); + } +} diff --git a/lib/widgets/input/text_field.dart b/lib/widgets/input/text_field.dart index 900c340..12b0adc 100644 --- a/lib/widgets/input/text_field.dart +++ b/lib/widgets/input/text_field.dart @@ -39,38 +39,44 @@ class NumberTextInputFormatter extends TextInputFormatter { final _mobileFormatter = NumberTextInputFormatter(); class TextFields extends StatefulWidget { - TextFields( - {Key key, - this.type, - this.hintText, - this.suffixIcon, - this.autoFocus, - this.onChanged, - this.initialValue, - this.minLines, - this.maxLines, - this.inputFormatters, - this.padding, - this.focus = false, - this.maxLengthEnforced = true, - this.suffixIconColor, - this.inputAction, - this.onSubmit, - this.keepPadding = true, - this.textCapitalization = TextCapitalization.none, - this.controller, - this.keyboardType, - this.validator, - this.borderOnlyError = false, - this.onSaved, - this.onSuffixTap, - this.readOnly: false, - this.maxLength, - this.prefixIcon, - this.bare = false, - this.fontSize = 16.0, - this.fontWeight = FontWeight.w700, - this.autoValidate = false}) + TextFields({Key key, + this.type, + this.hintText, + this.suffixIcon, + this.autoFocus, + this.onChanged, + this.initialValue, + this.minLines, + this.maxLines, + this.inputFormatters, + this.padding, + this.focus = false, + this.maxLengthEnforced = true, + this.suffixIconColor, + this.inputAction, + this.onSubmit, + this.keepPadding = true, + this.textCapitalization = TextCapitalization.none, + this.onTap, + this.controller, + this.keyboardType, + this.validator, + this.borderOnlyError = false, + this.onSaved, + this.onSuffixTap, + this.readOnly: false, + this.maxLength, + this.prefixIcon, + this.bare = false, + this.fontSize = 14.0, + this.color = Colors.black, + this.fontWeight = FontWeight.w600, + this.autoValidate = false, + this.borderRadiusValue = 8.0, + this.borderWidth = 1.5, + this.fieldTextColor, + this.textAlign = TextAlign.start, + this.borderRadius}) : super(key: key); final String hintText; @@ -80,6 +86,7 @@ class TextFields extends StatefulWidget { final IconData suffixIcon; final Color suffixIconColor; final IconData prefixIcon; + final VoidCallback onTap; final TextEditingController controller; final TextInputType keyboardType; final FormFieldValidator validator; @@ -96,6 +103,7 @@ class TextFields extends StatefulWidget { final TextInputAction inputAction; final double fontSize; final FontWeight fontWeight; + final Color color; final bool keepPadding; final TextCapitalization textCapitalization; final List inputFormatters; @@ -103,6 +111,11 @@ class TextFields extends StatefulWidget { final EdgeInsets padding; final bool focus; final bool borderOnlyError; + final double borderRadiusValue; + final BorderRadius borderRadius; + final double borderWidth; + final Color fieldTextColor; + final TextAlign textAlign; @override _TextFieldsState createState() => _TextFieldsState(); @@ -138,43 +151,46 @@ class _TextFieldsState extends State { Widget _buildSuffixIcon() { switch (widget.type) { case "password": - return Padding( - padding: const EdgeInsets.only(right: 8.0), - child: view - ? InkWell( + { + return Padding( + padding: const EdgeInsets.only(right: 8.0), + child: view + ? InkWell( onTap: () { - this.setState( - () { - view = false; - }, - ); + this.setState(() { + view = false; + }); }, - child: Icon( - EvaIcons.eye, - size: 24.0, - color: Color.fromRGBO(78, 62, 253, 1.0), - ), - ) - : InkWell( + child: Icon(EvaIcons.eye, + size: 24.0, color: Theme + .of(context) + .primaryColor)) + : InkWell( onTap: () { this.setState(() { view = true; }); }, child: Icon(EvaIcons.eyeOff, - size: 24.0, color: Colors.grey[500]), - ), - ); + size: 24.0, color: Colors.grey[500]))); + } + case "hourly": + return Align( + alignment: Alignment.centerRight, + child: Text( + '/ hr ', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700), + )); + break; default: if (widget.suffixIcon != null) return InkWell( - onTap: widget.onSuffixTap, - child: Icon(widget.suffixIcon, - size: 22.0, - color: widget.suffixIconColor != null - ? widget.suffixIconColor - : Colors.grey[500]), - ); + onTap: widget.onSuffixTap, + child: Icon(widget.suffixIcon, + size: 22.0, + color: widget.suffixIconColor != null + ? widget.suffixIconColor + : Colors.grey[500])); else return null; } @@ -196,22 +212,26 @@ class _TextFieldsState extends State { decoration: widget.bare ? null : BoxDecoration(boxShadow: [ - BoxShadow( - color: Color.fromRGBO(110, 68, 80, focus ? 0.20 : 0), - offset: Offset(0.0, 13.0), - blurRadius: focus ? 34.0 : 12.0) - ]), + BoxShadow( + color: Color.fromRGBO(70, 68, 167, focus ? 0.20 : 0), + offset: Offset(0.0, 13.0), + blurRadius: focus ? 34.0 : 12.0) + ]), child: TextFormField( - keyboardAppearance: Theme.of(context).brightness, + keyboardAppearance: Theme + .of(context) + .brightness, scrollPhysics: BouncingScrollPhysics(), autovalidate: widget.autoValidate, + onTap: widget.onTap, + textAlign: widget.textAlign, textCapitalization: widget.textCapitalization, onFieldSubmitted: widget.inputAction == TextInputAction.next ? (widget.onSubmit != null - ? widget.onSubmit - : (val) { - _focusNode.nextFocus(); - }) + ? widget.onSubmit + : (val) { + _focusNode.nextFocus(); + }) : widget.onSubmit, textInputAction: widget.inputAction, minLines: widget.minLines ?? 1, @@ -228,87 +248,118 @@ class _TextFieldsState extends State { autofocus: widget.autoFocus ?? false, validator: widget.validator, onSaved: widget.onSaved, - style: Theme.of(context) + style: Theme + .of(context) .textTheme .body2 - .copyWith(fontSize: widget.fontSize, fontWeight: widget.fontWeight), + .copyWith( + fontSize: widget.fontSize, + fontWeight: widget.fontWeight, + color: widget.color), inputFormatters: widget.keyboardType == TextInputType.phone ? [ - WhitelistingTextInputFormatter.digitsOnly, - _mobileFormatter, - ] + WhitelistingTextInputFormatter.digitsOnly, + _mobileFormatter, + ] : widget.inputFormatters, decoration: InputDecoration( - counterText: "", - hintText: widget.hintText, - hintStyle: TextStyle( - fontSize: widget.fontSize, - fontWeight: widget.fontWeight, - color: Theme.of(context).hintColor), - contentPadding: widget.padding != null - ? widget.padding - : EdgeInsets.symmetric( - vertical: (widget.bare && !widget.keepPadding) ? 0.0 : 10.0, - horizontal: 16.0), - filled: true, - fillColor: widget.bare - ? 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]), - errorStyle: TextStyle( - fontSize: 14.0, - fontWeight: widget.fontWeight, - height: widget.borderOnlyError ? 0.0 : null), - errorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context) - .errorColor - .withOpacity(widget.bare ? 0.0 : 0.5), - width: 2.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), - 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), - borderRadius: BorderRadius.circular(widget.bare ? 0.0 : 8.0)), - disabledBorder: OutlineInputBorder( + counterText: "", + hintText: widget.hintText, + hintStyle: TextStyle( + fontSize: widget.fontSize, + fontWeight: widget.fontWeight, + color: Theme + .of(context) + .hintColor), + contentPadding: widget.padding != null + ? widget.padding + : EdgeInsets.symmetric( + vertical: (widget.bare && !widget.keepPadding) ? 0.0 : 10.0, + horizontal: 16.0), + filled: true, + fillColor: widget.bare + ? Colors.transparent + : widget.fieldTextColor != null + ? widget.fieldTextColor + : 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]), + errorStyle: TextStyle( + fontSize: 14.0, + fontWeight: widget.fontWeight, + height: widget.borderOnlyError ? 0.0 : null), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Theme + .of(context) + .errorColor + .withOpacity(widget.bare ? 0.0 : 0.5), + width: widget.borderWidth), + borderRadius: widget.bare + ? BorderRadius.circular(0.0) + : widget.borderRadius != null + ? widget.borderRadius + : BorderRadius.circular(widget.borderRadiusValue)), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Theme + .of(context) + .errorColor + .withOpacity(widget.bare ? 0.0 : 0.5), + width: widget.borderWidth), + borderRadius: widget.bare + ? BorderRadius.circular(0.0) + : widget.borderRadius != null + ? widget.borderRadius + : BorderRadius.circular(widget.borderRadiusValue)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Theme + .of(context) + .dividerColor + .withOpacity(widget.bare ? 0.0 : 1.0), + width: widget.borderWidth), + borderRadius: widget.bare + ? BorderRadius.circular(0.0) + : widget.borderRadius != null + ? widget.borderRadius + : BorderRadius.circular(widget.borderRadiusValue)), + disabledBorder: + OutlineInputBorder(borderSide: BorderSide(color: Theme + .of(context) + .dividerColor + .withOpacity(widget.bare ? 0.0 : 1.0), + width: widget.borderWidth), + borderRadius: widget.bare ? BorderRadius.circular(0.0) : widget + .borderRadius != null ? widget.borderRadius : BorderRadius + .circular(widget.borderRadiusValue)), + enabledBorder: OutlineInputBorder( borderSide: BorderSide( - color: Theme.of(context) + color: Theme + .of(context) .dividerColor .withOpacity(widget.bare ? 0.0 : 1.0), - width: 2.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), - borderRadius: BorderRadius.circular(widget.bare ? 0.0 : 8.0), - ), - ), + width: widget.borderWidth), + borderRadius: widget.bare + ? BorderRadius.circular(0.0) + : widget.borderRadius != null + ? widget.borderRadius + : BorderRadius.circular(widget.borderRadiusValue), + )), ), )); } From 7e50545dd181637df6c3142e21ba61bfa71f4c91 Mon Sep 17 00:00:00 2001 From: Elham Rababah Date: Sun, 23 Aug 2020 15:17:39 +0300 Subject: [PATCH 3/7] Finish login Functionality --- lib/config/config.dart | 2 + lib/config/localized_values.dart | 24 +- .../authentication/authenticated_user.dart | 318 +++--------------- .../model/authentication/login_request.dart | 18 + lib/core/service/authentication_service.dart | 40 ++- .../viewModels/authentication_view_model.dart | 18 +- lib/pages/authentication/login_page.dart | 228 ++++++++----- lib/uitl/translations_delegate_base.dart | 13 + .../data_display/circle-container.dart | 34 ++ 9 files changed, 320 insertions(+), 375 deletions(-) create mode 100644 lib/core/model/authentication/login_request.dart create mode 100644 lib/widgets/data_display/circle-container.dart diff --git a/lib/config/config.dart b/lib/config/config.dart index e6ae40e..2e70bf9 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -6,6 +6,8 @@ const MAX_SMALL_SCREEN = 660; const BASE_URL = 'https://uat.hmgwebservices.com/Services'; const GET_PROJECT = '/Lists.svc/REST/GetProject'; +const LOGIN = "/Authentication.svc/REST/CheckDriverAuthentication"; + class AppGlobal { diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 5916d90..5cfdfbe 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -11,6 +11,28 @@ const Map> localizedValues = { 'services': {'en': 'SERVICES', 'ar': 'الخدمات'}, 'mySchedule': {'en': 'My Schedule', 'ar': 'جدولي'}, 'logout': {'en': 'Logout', 'ar': 'تسجيل خروج'}, - 'booking':{'en': 'Booking','ar':'حجز'} + 'booking':{'en': 'Booking','ar':'حجز'}, + 'enterId': {'en': 'User Name', 'ar': 'اسم المستخدم'}, + 'pleaseEnterYourID': { + 'en': 'Please enter your ', + 'ar': 'الرجاء ادخال اسم المستخدم' + }, + 'enterPassword': {'en': 'Password', 'ar': 'كلمه السر'}, + 'pleaseEnterPassword': { + 'en': 'Please Enter Your Password', + 'ar': 'الرجاء ادخال كلمه السر' + }, + 'enterCredentialsMsg': { + 'en': 'Please insert username and password to login', + 'ar': 'الرجاء إدخال اسم المستخدم وكلمة المرور لتسجيل الدخول' + }, + 'forgotPassword': { + 'en': 'Forgot Password?', + 'ar': 'هل نسيت كلمة المرور ؟' + }, + 'login': { + 'en': 'Login', + 'ar': 'تسجيل الدخول' + } }; diff --git a/lib/core/model/authentication/authenticated_user.dart b/lib/core/model/authentication/authenticated_user.dart index 7ca3a3e..0329bd5 100644 --- a/lib/core/model/authentication/authenticated_user.dart +++ b/lib/core/model/authentication/authenticated_user.dart @@ -1,282 +1,64 @@ class AuthenticatedUser { - String setupID; - int patientType; - int patientID; - String firstName; - String middleName; - String lastName; - String firstNameN; - String middleNameN; - String lastNameN; - int relationshipID; - int gender; - String dateofBirth; - dynamic dateofBirthN; - String nationalityID; - dynamic phoneResi; - dynamic phoneOffice; - String mobileNumber; - dynamic faxNumber; - String emailAddress; - dynamic bloodGroup; - dynamic rHFactor; - bool isEmailAlertRequired; - bool isSMSAlertRequired; - String preferredLanguage; - bool isPrivilegedMember; - dynamic memberID; - dynamic expiryDate; - dynamic isHmgEmployee; - dynamic employeeID; - dynamic emergencyContactName; - dynamic emergencyContactNo; - int patientPayType; - dynamic dHCCPatientRefID; - bool isPatientDummy; - int status; - dynamic isStatusCleared; - int patientIdentificationType; - String patientIdentificationNo; - int projectID; - int infoSourceID; - dynamic address; - int age; - String ageDesc; - int areaID; + int iD; + int userID; + String password; + String userName; + int roleID; + String name; + bool active; + String createdOn; int createdBy; - String genderDescription; - dynamic iR; - dynamic iSOCityID; - dynamic iSOCountryID; - List listPrivilege; - dynamic marital; - int outSA; - dynamic pOBox; - bool receiveHealthSummaryReport; - int sourceType; - dynamic strDateofBirth; - dynamic tempAddress; - dynamic zipCode; - // dynamic patientPayType; - // dynamic patientType; - // dynamic status; + Null editedOn; + Null editedBy; + String mobileNumber; + int realRoleID; - AuthenticatedUser({ - this.setupID, - this.patientType, - this.patientID, - this.firstName, - this.middleName, - this.lastName, - this.firstNameN, - this.middleNameN, - this.lastNameN, - this.relationshipID, - this.gender, - this.dateofBirth, - this.dateofBirthN, - this.nationalityID, - this.phoneResi, - this.phoneOffice, - this.mobileNumber, - this.faxNumber, - this.emailAddress, - this.bloodGroup, - this.rHFactor, - this.isEmailAlertRequired, - this.isSMSAlertRequired, - this.preferredLanguage, - this.isPrivilegedMember, - this.memberID, - this.expiryDate, - this.isHmgEmployee, - this.employeeID, - this.emergencyContactName, - this.emergencyContactNo, - this.patientPayType, - this.dHCCPatientRefID, - this.isPatientDummy, - this.status, - this.isStatusCleared, - this.patientIdentificationType, - this.patientIdentificationNo, - this.projectID, - this.infoSourceID, - this.address, - this.age, - this.ageDesc, - this.areaID, - this.createdBy, - this.genderDescription, - this.iR, - this.iSOCityID, - this.iSOCountryID, - this.listPrivilege, - this.marital, - this.outSA, - this.pOBox, - this.receiveHealthSummaryReport, - this.sourceType, - this.strDateofBirth, - this.tempAddress, - this.zipCode, - }); + AuthenticatedUser( + {this.iD, + this.userID, + this.password, + this.userName, + this.roleID, + this.name, + this.active, + this.createdOn, + this.createdBy, + this.editedOn, + this.editedBy, + this.mobileNumber, + this.realRoleID}); AuthenticatedUser.fromJson(Map json) { - setupID = json['SetupID']; - patientType = json['PatientType']; - patientID = json['PatientID']; - firstName = json['FirstName']; - middleName = json['MiddleName']; - lastName = json['LastName']; - firstNameN = json['FirstNameN']; - middleNameN = json['MiddleNameN']; - lastNameN = json['LastNameN']; - relationshipID = json['RelationshipID']; - gender = json['Gender']; - dateofBirth = json['DateofBirth']; - dateofBirthN = json['DateofBirthN']; - nationalityID = json['NationalityID']; - phoneResi = json['PhoneResi']; - phoneOffice = json['PhoneOffice']; - mobileNumber = json['MobileNumber']; - faxNumber = json['FaxNumber']; - emailAddress = json['EmailAddress']; - bloodGroup = json['BloodGroup']; - rHFactor = json['RHFactor']; - isEmailAlertRequired = json['IsEmailAlertRequired']; - isSMSAlertRequired = json['IsSMSAlertRequired']; - preferredLanguage = json['PreferredLanguage']; - isPrivilegedMember = json['IsPrivilegedMember']; - memberID = json['MemberID']; - expiryDate = json['ExpiryDate']; - isHmgEmployee = json['IsHmgEmployee']; - employeeID = json['EmployeeID']; - emergencyContactName = json['EmergencyContactName']; - emergencyContactNo = json['EmergencyContactNo']; - patientPayType = json['PatientPayType']; - dHCCPatientRefID = json['DHCCPatientRefID']; - isPatientDummy = json['IsPatientDummy']; - status = json['Status']; - isStatusCleared = json['IsStatusCleared']; - patientIdentificationType = json['PatientIdentificationType']; - patientIdentificationNo = json['PatientIdentificationNo']; - projectID = json['ProjectID']; - infoSourceID = json['InfoSourceID']; - address = json['Address']; - age = json['Age']; - ageDesc = json['AgeDesc']; - areaID = json['AreaID']; - createdBy = json['CreatedBy']; - genderDescription = json['GenderDescription']; - iR = json['IR']; - iSOCityID = json['ISOCityID']; - iSOCountryID = json['ISOCountryID']; - if (json['ListPrivilege'] != null) { - listPrivilege = new List(); - json['ListPrivilege'].forEach((v) { - listPrivilege.add(new ListPrivilege.fromJson(v)); - }); - } - marital = json['Marital']; - outSA = json['OutSA']; - pOBox = json['POBox']; - receiveHealthSummaryReport = json['ReceiveHealthSummaryReport']; - sourceType = json['SourceType']; - strDateofBirth = json['StrDateofBirth']; - tempAddress = json['TempAddress']; - zipCode = json['ZipCode']; - } - - Map toJson() { - final Map data = new Map(); - data['SetupID'] = this.setupID; - data['PatientType'] = this.patientType; - data['PatientID'] = this.patientID; - data['FirstName'] = this.firstName; - data['MiddleName'] = this.middleName; - data['LastName'] = this.lastName; - data['FirstNameN'] = this.firstNameN; - data['MiddleNameN'] = this.middleNameN; - data['LastNameN'] = this.lastNameN; - data['RelationshipID'] = this.relationshipID; - data['Gender'] = this.gender; - data['DateofBirth'] = this.dateofBirth; - data['DateofBirthN'] = this.dateofBirthN; - data['NationalityID'] = this.nationalityID; - data['PhoneResi'] = this.phoneResi; - data['PhoneOffice'] = this.phoneOffice; - data['MobileNumber'] = this.mobileNumber; - data['FaxNumber'] = this.faxNumber; - data['EmailAddress'] = this.emailAddress; - data['BloodGroup'] = this.bloodGroup; - data['RHFactor'] = this.rHFactor; - data['IsEmailAlertRequired'] = this.isEmailAlertRequired; - data['IsSMSAlertRequired'] = this.isSMSAlertRequired; - data['PreferredLanguage'] = this.preferredLanguage; - data['IsPrivilegedMember'] = this.isPrivilegedMember; - data['MemberID'] = this.memberID; - data['ExpiryDate'] = this.expiryDate; - data['IsHmgEmployee'] = this.isHmgEmployee; - data['EmployeeID'] = this.employeeID; - data['EmergencyContactName'] = this.emergencyContactName; - data['EmergencyContactNo'] = this.emergencyContactNo; - data['PatientPayType'] = this.patientPayType; - data['DHCCPatientRefID'] = this.dHCCPatientRefID; - data['IsPatientDummy'] = this.isPatientDummy; - data['Status'] = this.status; - data['IsStatusCleared'] = this.isStatusCleared; - data['PatientIdentificationType'] = this.patientIdentificationType; - data['PatientIdentificationNo'] = this.patientIdentificationNo; - data['ProjectID'] = this.projectID; - data['InfoSourceID'] = this.infoSourceID; - data['Address'] = this.address; - data['Age'] = this.age; - data['AgeDesc'] = this.ageDesc; - data['AreaID'] = this.areaID; - data['CreatedBy'] = this.createdBy; - data['GenderDescription'] = this.genderDescription; - data['IR'] = this.iR; - data['ISOCityID'] = this.iSOCityID; - data['ISOCountryID'] = this.iSOCountryID; - if (this.listPrivilege != null) { - data['ListPrivilege'] = - this.listPrivilege.map((v) => v.toJson()).toList(); - } - data['Marital'] = this.marital; - data['OutSA'] = this.outSA; - data['POBox'] = this.pOBox; - data['ReceiveHealthSummaryReport'] = this.receiveHealthSummaryReport; - data['SourceType'] = this.sourceType; - data['StrDateofBirth'] = this.strDateofBirth; - data['TempAddress'] = this.tempAddress; - data['ZipCode'] = this.zipCode; - - return data; - } -} - -class ListPrivilege { - int iD; - String serviceName; - bool previlege; - dynamic region; - - ListPrivilege({this.iD, this.serviceName, this.previlege, this.region}); - - ListPrivilege.fromJson(Map json) { iD = json['ID']; - serviceName = json['ServiceName']; - previlege = json['Previlege']; - region = json['Region']; + userID = json['UserID']; + password = json['password']; + userName = json['UserName']; + roleID = json['RoleID']; + name = json['Name']; + active = json['Active']; + createdOn = json['CreatedOn']; + createdBy = json['CreatedBy']; + editedOn = json['EditedOn']; + editedBy = json['EditedBy']; + mobileNumber = json['MobileNumber']; + realRoleID = json['RealRoleID']; } Map toJson() { final Map data = new Map(); data['ID'] = this.iD; - data['ServiceName'] = this.serviceName; - data['Previlege'] = this.previlege; - data['Region'] = this.region; + data['UserID'] = this.userID; + data['password'] = this.password; + data['UserName'] = this.userName; + data['RoleID'] = this.roleID; + data['Name'] = this.name; + data['Active'] = this.active; + data['CreatedOn'] = this.createdOn; + data['CreatedBy'] = this.createdBy; + data['EditedOn'] = this.editedOn; + data['EditedBy'] = this.editedBy; + data['MobileNumber'] = this.mobileNumber; + data['RealRoleID'] = this.realRoleID; return data; } } diff --git a/lib/core/model/authentication/login_request.dart b/lib/core/model/authentication/login_request.dart new file mode 100644 index 0000000..0e08b82 --- /dev/null +++ b/lib/core/model/authentication/login_request.dart @@ -0,0 +1,18 @@ +class LoginRequest { + int userID; + String password; + + LoginRequest({this.userID, this.password}); + + LoginRequest.fromJson(Map json) { + userID = json['UserID']; + password = json['Password']; + } + + Map toJson() { + final Map data = new Map(); + data['UserID'] = this.userID; + data['Password'] = this.password; + return data; + } +} \ No newline at end of file diff --git a/lib/core/service/authentication_service.dart b/lib/core/service/authentication_service.dart index ae26b38..266f2ae 100644 --- a/lib/core/service/authentication_service.dart +++ b/lib/core/service/authentication_service.dart @@ -1,29 +1,35 @@ - +import 'package:driverapp/config/config.dart'; +import 'package:driverapp/core/model/authentication/authenticated_user.dart'; +import 'package:driverapp/core/model/authentication/login_request.dart'; import 'package:driverapp/core/service/base_service.dart'; -import 'package:flutter/cupertino.dart'; - class AuthenticationService extends BaseService { String selectedClinicName; bool isLogin = false; bool isLoading = true; + AuthenticatedUser authenticatedUser; + String token; AuthenticationService() { // getUserAuthentication(); } -// void getUserAuthentication() async { -// if (profile != null) { -//// doctorProfile = new DoctorProfileModel.fromJson(profile); -// isLoading = false; -// isLogin = true; -// } else { -// isLoading = false; -// isLogin = false; -// } -// notifyListeners(); -// } - - - + login(LoginRequest loginRequest) async { + hasError = false; + try { + await baseAppClient.post(LOGIN, + onSuccess: (dynamic response, int statusCode) { + authenticatedUser = + AuthenticatedUser.fromJson(response['PatientER_DriverFile']); + token = response['LogInTokenID']; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: loginRequest.toJson()); + } catch (error) { + hasError = true; + super.error = error; + throw error; + } + } } diff --git a/lib/core/viewModels/authentication_view_model.dart b/lib/core/viewModels/authentication_view_model.dart index 53aed7b..32b7df8 100644 --- a/lib/core/viewModels/authentication_view_model.dart +++ b/lib/core/viewModels/authentication_view_model.dart @@ -1,5 +1,8 @@ +import 'package:driverapp/config/shared_pref_kay.dart'; import 'package:driverapp/core/enum/viewstate.dart'; +import 'package:driverapp/core/model/authentication/login_request.dart'; import 'package:driverapp/core/service/authentication_service.dart'; +import 'package:driverapp/core/service/client/base_app_client.dart'; import 'package:driverapp/core/viewModels/base_view_model.dart'; import '../../locator.dart'; @@ -21,10 +24,17 @@ class AuthenticationViewModel extends BaseViewModel { } } - login({String userName,String password}){ + login(LoginRequest loginRequest) async { setState(ViewState.BusyLocal); - // call api -// if() -// setState(viewState) + await _authenticationService.login(loginRequest); + if (_authenticationService.hasError) { + error = _authenticationService.error; + setState(ViewState.ErrorLocal); + } else { + sharedPref.setObject( + USER_PROFILE, _authenticationService.authenticatedUser); + sharedPref.setString(TOKEN, _authenticationService.token); + setState(ViewState.Idle); + } } } diff --git a/lib/pages/authentication/login_page.dart b/lib/pages/authentication/login_page.dart index f5dd638..10fb9b6 100644 --- a/lib/pages/authentication/login_page.dart +++ b/lib/pages/authentication/login_page.dart @@ -1,21 +1,34 @@ import 'package:driverapp/app-icons/driver_app_icons.dart'; +import 'package:driverapp/core/enum/viewstate.dart'; +import 'package:driverapp/core/model/authentication/login_request.dart'; import 'package:driverapp/core/viewModels/authentication_view_model.dart'; +import 'package:driverapp/core/viewModels/project_view_model.dart'; import 'package:driverapp/pages/base/base_view.dart'; +import 'package:driverapp/pages/landing/landing_page.dart'; +import 'package:driverapp/uitl/translations_delegate_base.dart'; +import 'package:driverapp/uitl/utils.dart'; import 'package:driverapp/widgets/buttons/secondary_button.dart'; +import 'package:driverapp/widgets/data_display/circle-container.dart'; import 'package:driverapp/widgets/input/text_field.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; -import 'package:hexcolor/hexcolor.dart'; +import 'package:provider/provider.dart'; class LoginPage extends StatelessWidget { + LoginRequest loginRequest = LoginRequest(); + final loginFormKey = GlobalKey(); + ProjectViewModel projectViewModel; + @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); return AnimatedSwitcher( duration: Duration(microseconds: 350), child: BaseView( builder: (_, model, widget) => Scaffold( //baseViewModel: model, + body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -37,8 +50,12 @@ class LoginPage extends StatelessWidget { color: Theme.of(context).primaryColor, ), margin: EdgeInsets.only( - right: - MediaQuery.of(context).size.width * 0.15), + right: projectViewModel.isArabic + ? 0 + : MediaQuery.of(context).size.width * 0.15, + left: !projectViewModel.isArabic + ? 0 + : MediaQuery.of(context).size.width * 0.15), ), ], ), @@ -72,80 +89,127 @@ class LoginPage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ CircleContainer( - child: Text( - "English", - style: TextStyle( - fontSize: 12, color: Colors.white), - ), - color: Theme.of(context).primaryColor, borderWidth: 0,borderColor: Colors.transparent,), + onTap: () => projectViewModel.changeLanguage('en'), + child: Text( + TranslationBase.of(context).lanEnglish, + style: TextStyle( + fontSize: 12, + color: projectViewModel.isArabic + ? Colors.black + : Colors.white), + ), + color: projectViewModel.isArabic + ? Colors.transparent + : Theme.of(context).primaryColor, + borderWidth: projectViewModel.isArabic ? 3 : 0, + borderColor: projectViewModel.isArabic + ? Theme.of(context).primaryColor + : Colors.transparent, + ), SizedBox( width: 20, ), CircleContainer( + onTap: () => + projectViewModel.changeLanguage('ar'), child: Text( - "Arabic", + TranslationBase.of(context).lanArabic, style: TextStyle( - fontSize: 12, color: Colors.black), + fontSize: 12, + color: !projectViewModel.isArabic + ? Colors.black + : Colors.white), ), - color: Colors.transparent, borderColor: Theme.of(context).primaryColor,borderWidth: 3,), + color: !projectViewModel.isArabic + ? Colors.transparent + : Theme.of(context).primaryColor, + borderWidth: !projectViewModel.isArabic ? 3 : 0, + borderColor: !projectViewModel.isArabic + ? Theme.of(context).primaryColor + : Colors.transparent), ], ), SizedBox( height: 10, ), - Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( + Form( + key: loginFormKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + TranslationBase.of(context).enterCredentialsMsg, + style: TextStyle( + fontSize: 13, color: Colors.grey), + ), + SizedBox( + height: 10, + ) + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + child: TextFields( + onChanged: (value) => {}, + hintText: TranslationBase.of(context).enterId, + validator: (value) { + if (value.isEmpty) { + return TranslationBase.of(context) + .pleaseEnterYourID; + } + return null; + }, + onSaved: (value) { + loginRequest.userID = int.parse(value.trim()); + }, + ), + ), + SizedBox( + height: 20, + ), + Container( + child: TextFields( + borderRadiusValue: 6, + onChanged: (value) => {}, + hintText: + TranslationBase.of(context).enterPassword, + validator: (value) { + if (value.isEmpty) { + return TranslationBase.of(context) + .pleaseEnterPassword; + } + return null; + }, + onSaved: (value) { + loginRequest.password = value; + }, + ), + ), + SizedBox( + height: 25, + ), + Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( - "Please insert username and password to login", + TranslationBase.of(context).forgotPassword, style: TextStyle( - fontSize: 13, color: Colors.grey), + fontSize: 14, + color: Theme.of(context).primaryColor), ), - SizedBox( - height: 10, - ) ], ), - ), - SizedBox( - height: 10, - ), - Container( - child: TextFields( - onChanged: (value) => {}, - hintText: "User Name", - ), - ), - SizedBox( - height: 20, - ), - Container( - child: TextFields( - borderRadiusValue: 6, - onChanged: (value) => {}, - hintText: "Password", - ), - ), - SizedBox( - height: 25, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - "Forgot Password?", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).primaryColor), - ), - ], - ), - ], + ], + ), ), ], ), @@ -164,7 +228,14 @@ class LoginPage extends StatelessWidget { height: MediaQuery.of(context).size.height * 0.12, child: Column( children: [ - SecondaryButton(label: "Login"), + SecondaryButton( + label: TranslationBase.of(context).login, + onTap: () { + login(model, context); + }, + disabled: model.state == ViewState.BusyLocal, + loading: model.state == ViewState.BusyLocal, + ), SizedBox( height: 30, ) @@ -174,32 +245,19 @@ class LoginPage extends StatelessWidget { ), ); } -} - -class CircleContainer extends StatelessWidget { - const CircleContainer( - {this.child, - this.color = Colors.white, - this.borderColor, - this.borderWidth = 2.0}); - final Widget child; - final Color color; - final Color borderColor; - final double borderWidth; - - @override - Widget build(BuildContext context) { - return Container( - child: Center(child: child), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: color, - border: Border.all( - color: borderColor ?? Hexcolor("#707070"), - width: borderWidth)), - height: 60, - width: 60, - ); + login(AuthenticationViewModel model, BuildContext context) async { + if (loginFormKey.currentState.validate()) { + loginFormKey.currentState.save(); + await model.login(loginRequest); + if (model.state == ViewState.ErrorLocal) { + Utils.showErrorToast(model.error); + // Show error + } else { + Navigator.push( + context, MaterialPageRoute(builder: (context) => LandingPage())); + } + } } } + diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 1a61090..400292e 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -39,6 +39,19 @@ class TranslationBase { String get logout => localizedValues['logout'][locale.languageCode]; String get booking => localizedValues['booking'][locale.languageCode]; + String get enterId => localizedValues['enterId'][locale.languageCode]; + String get pleaseEnterYourID => + localizedValues['pleaseEnterYourID'][locale.languageCode]; + String get enterPassword => + localizedValues['enterPassword'][locale.languageCode]; + String get pleaseEnterPassword => + localizedValues['pleaseEnterPassword'][locale.languageCode]; + String get english => localizedValues['english'][locale.languageCode]; + + String get arabic => localizedValues['arabic'][locale.languageCode]; + String get enterCredentialsMsg => localizedValues['enterCredentialsMsg'][locale.languageCode]; + String get forgotPassword => localizedValues['forgotPassword'][locale.languageCode]; + String get login => localizedValues['login'][locale.languageCode]; } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/widgets/data_display/circle-container.dart b/lib/widgets/data_display/circle-container.dart new file mode 100644 index 0000000..bb0ebdd --- /dev/null +++ b/lib/widgets/data_display/circle-container.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:hexcolor/hexcolor.dart'; + +class CircleContainer extends StatelessWidget { + const CircleContainer( + {this.child, + this.color = Colors.white, + this.borderColor, + this.borderWidth = 2.0, + this.onTap}); + + final Widget child; + final Color color; + final Color borderColor; + final double borderWidth; + final Function onTap; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Container( + child: Center(child: child), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: color, + border: Border.all( + color: borderColor ?? Hexcolor("#707070"), width: borderWidth)), + height: 60, + width: 60, + ), + ); + } +} From 57e60178a30d0ef6e04b362bfb0a45746a442f1a Mon Sep 17 00:00:00 2001 From: Elham Rababah Date: Sun, 23 Aug 2020 16:49:08 +0300 Subject: [PATCH 4/7] Finish login Functionality --- ios/Runner.xcodeproj/project.pbxproj | 43 +- .../viewModels/authentication_view_model.dart | 6 +- lib/pages/authentication/login_page.dart | 382 +++++++++--------- 3 files changed, 235 insertions(+), 196 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 90398e9..dd7be69 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -225,12 +225,47 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework", + "${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework", + "${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework", + "${BUILT_PRODUCTS_DIR}/TOCropViewController/TOCropViewController.framework", + "${BUILT_PRODUCTS_DIR}/barcode_scan/barcode_scan.framework", + "${BUILT_PRODUCTS_DIR}/connectivity/connectivity.framework", + "${BUILT_PRODUCTS_DIR}/device_info/device_info.framework", + "${BUILT_PRODUCTS_DIR}/flutter_flexible_toast/flutter_flexible_toast.framework", + "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework", + "${BUILT_PRODUCTS_DIR}/flutter_plugin_android_lifecycle/flutter_plugin_android_lifecycle.framework", + "${BUILT_PRODUCTS_DIR}/hexcolor/hexcolor.framework", + "${BUILT_PRODUCTS_DIR}/image_cropper/image_cropper.framework", + "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework", + "${BUILT_PRODUCTS_DIR}/local_auth/local_auth.framework", + "${BUILT_PRODUCTS_DIR}/maps_launcher/maps_launcher.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", ); name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TOCropViewController.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/barcode_scan.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_flexible_toast.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_plugin_android_lifecycle.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hexcolor.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_cropper.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/maps_launcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/lib/core/viewModels/authentication_view_model.dart b/lib/core/viewModels/authentication_view_model.dart index 32b7df8..b91b228 100644 --- a/lib/core/viewModels/authentication_view_model.dart +++ b/lib/core/viewModels/authentication_view_model.dart @@ -16,7 +16,7 @@ class AuthenticationViewModel extends BaseViewModel { if (state == ViewState.Busy || state == ViewState.BusyLocal) { return APP_STATUS.LOADING; } else { - if (user != null) { + if ( user != null) { return APP_STATUS.AUTHENTICATED; } else { return APP_STATUS.UNAUTHENTICATED; @@ -24,6 +24,10 @@ class AuthenticationViewModel extends BaseViewModel { } } + AuthenticationViewModel(){ + sharedPref.clear(); + } + login(LoginRequest loginRequest) async { setState(ViewState.BusyLocal); await _authenticationService.login(loginRequest); diff --git a/lib/pages/authentication/login_page.dart b/lib/pages/authentication/login_page.dart index 10fb9b6..634f6e4 100644 --- a/lib/pages/authentication/login_page.dart +++ b/lib/pages/authentication/login_page.dart @@ -12,6 +12,7 @@ import 'package:driverapp/widgets/data_display/circle-container.dart'; import 'package:driverapp/widgets/input/text_field.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; @@ -27,220 +28,220 @@ class LoginPage extends StatelessWidget { duration: Duration(microseconds: 350), child: BaseView( builder: (_, model, widget) => Scaffold( - //baseViewModel: model, - - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - FractionallySizedBox( - widthFactor: 0.80, - child: Column( - children: [ - SizedBox( - height: 40, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - child: Icon( - DriverApp.logo, - size: 70, - color: Theme.of(context).primaryColor, + body: SingleChildScrollView( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + FractionallySizedBox( + widthFactor: 0.80, + child: Column( + children: [ + SizedBox( + height: 40, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Icon( + DriverApp.logo, + size: 70, + color: Theme.of(context).primaryColor, + ), + margin: EdgeInsets.only( + right: projectViewModel.isArabic + ? 0 + : MediaQuery.of(context).size.width * 0.15, + left: !projectViewModel.isArabic + ? 0 + : MediaQuery.of(context).size.width * 0.15), ), - margin: EdgeInsets.only( - right: projectViewModel.isArabic - ? 0 - : MediaQuery.of(context).size.width * 0.15, - left: !projectViewModel.isArabic - ? 0 - : MediaQuery.of(context).size.width * 0.15), - ), - ], - ), - SizedBox( - height: 20, - ), - Column( - children: [ - Text( - "Driver", - style: TextStyle( - fontSize: 50, fontWeight: FontWeight.bold), - ), - Text( - "Delivery", - style: TextStyle(fontSize: 36, letterSpacing: 1), - ), - Text( - "APP", - style: TextStyle( - fontSize: 33, - letterSpacing: 33, - fontWeight: FontWeight.w400), - ), - ], - ), - SizedBox( - height: 30, - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CircleContainer( - onTap: () => projectViewModel.changeLanguage('en'), - child: Text( - TranslationBase.of(context).lanEnglish, + ], + ), + SizedBox( + height: 20, + ), + Column( + children: [ + Text( + "Driver", style: TextStyle( - fontSize: 12, - color: projectViewModel.isArabic - ? Colors.black - : Colors.white), + fontSize: 50, fontWeight: FontWeight.bold), ), - color: projectViewModel.isArabic - ? Colors.transparent - : Theme.of(context).primaryColor, - borderWidth: projectViewModel.isArabic ? 3 : 0, - borderColor: projectViewModel.isArabic - ? Theme.of(context).primaryColor - : Colors.transparent, - ), - SizedBox( - width: 20, - ), - CircleContainer( - onTap: () => - projectViewModel.changeLanguage('ar'), + Text( + "Delivery", + style: TextStyle(fontSize: 36, letterSpacing: 1), + ), + Text( + "APP", + style: TextStyle( + fontSize: 33, + letterSpacing: 33, + fontWeight: FontWeight.w400), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircleContainer( + onTap: () => projectViewModel.changeLanguage('en'), child: Text( - TranslationBase.of(context).lanArabic, + TranslationBase.of(context).lanEnglish, style: TextStyle( fontSize: 12, - color: !projectViewModel.isArabic + color: projectViewModel.isArabic ? Colors.black : Colors.white), ), - color: !projectViewModel.isArabic + color: projectViewModel.isArabic ? Colors.transparent : Theme.of(context).primaryColor, - borderWidth: !projectViewModel.isArabic ? 3 : 0, - borderColor: !projectViewModel.isArabic + borderWidth: projectViewModel.isArabic ? 3 : 0, + borderColor: projectViewModel.isArabic ? Theme.of(context).primaryColor - : Colors.transparent), - ], - ), - SizedBox( - height: 10, - ), - Form( - key: loginFormKey, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 20), - child: Row( + : Colors.transparent, + ), + SizedBox( + width: 20, + ), + CircleContainer( + onTap: () => + projectViewModel.changeLanguage('ar'), + child: Text( + TranslationBase.of(context).lanArabic, + style: TextStyle( + fontSize: 12, + color: !projectViewModel.isArabic + ? Colors.black + : Colors.white), + ), + color: !projectViewModel.isArabic + ? Colors.transparent + : Theme.of(context).primaryColor, + borderWidth: !projectViewModel.isArabic ? 3 : 0, + borderColor: !projectViewModel.isArabic + ? Theme.of(context).primaryColor + : Colors.transparent), + ], + ), + SizedBox( + height: 10, + ), + Form( + key: loginFormKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: Text( + TranslationBase.of(context).enterCredentialsMsg, + style: TextStyle( + fontSize: 13, color: Colors.grey), + ), + ), + SizedBox( + height: 10, + ) + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + child: TextFields( + hintText: TranslationBase.of(context).enterId, + validator: (value) { + if (value.isEmpty) { + return TranslationBase.of(context) + .pleaseEnterYourID; + } + return null; + }, + onSaved: (value) { + loginRequest.userID = int.parse(value.trim()); + }, + ), + ), + SizedBox( + height: 20, + ), + Container( + child: TextFields( + borderRadiusValue: 6, + hintText: + TranslationBase.of(context).enterPassword, + validator: (value) { + if (value.isEmpty) { + return TranslationBase.of(context) + .pleaseEnterPassword; + } + return null; + }, + onSaved: (value) { + loginRequest.password = value; + }, + ), + ), + SizedBox( + height: 25, + ), + Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( - TranslationBase.of(context).enterCredentialsMsg, + TranslationBase.of(context).forgotPassword, style: TextStyle( - fontSize: 13, color: Colors.grey), + fontSize: 14, + color: Theme.of(context).primaryColor), ), - SizedBox( - height: 10, - ) ], ), - ), - SizedBox( - height: 10, - ), - Container( - child: TextFields( - onChanged: (value) => {}, - hintText: TranslationBase.of(context).enterId, - validator: (value) { - if (value.isEmpty) { - return TranslationBase.of(context) - .pleaseEnterYourID; - } - return null; - }, - onSaved: (value) { - loginRequest.userID = int.parse(value.trim()); - }, - ), - ), - SizedBox( - height: 20, - ), - Container( - child: TextFields( - borderRadiusValue: 6, - onChanged: (value) => {}, - hintText: - TranslationBase.of(context).enterPassword, - validator: (value) { - if (value.isEmpty) { - return TranslationBase.of(context) - .pleaseEnterPassword; - } - return null; - }, - onSaved: (value) { - loginRequest.password = value; - }, - ), - ), - SizedBox( - height: 25, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - TranslationBase.of(context).forgotPassword, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).primaryColor), - ), - ], - ), - ], + ], + ), ), - ), - ], + ], + ), ), - ), - SizedBox( - height: 20, - ), - SizedBox( - height: 10, - ) - ], - ), - ), - bottomSheet: Container( - margin: EdgeInsets.all(10), - height: MediaQuery.of(context).size.height * 0.12, - child: Column( - children: [ - SecondaryButton( - label: TranslationBase.of(context).login, - onTap: () { - login(model, context); - }, - disabled: model.state == ViewState.BusyLocal, - loading: model.state == ViewState.BusyLocal, + SizedBox( + height: 20, ), SizedBox( - height: 30, - ) + height: 10, + ),Container( + margin: EdgeInsets.all(10), + height: MediaQuery.of(context).size.height * 0.22, + child: Column( + children: [ + SecondaryButton( + label: TranslationBase.of(context).login, + onTap: () { + login(model, context); + }, + disabled: model.state == ViewState.BusyLocal, + loading: model.state == ViewState.BusyLocal, + ), + SizedBox( + height: 30, + ) + ], + )) ], - )), + ), + ), + ), + ), ), ); @@ -252,7 +253,6 @@ class LoginPage extends StatelessWidget { await model.login(loginRequest); if (model.state == ViewState.ErrorLocal) { Utils.showErrorToast(model.error); - // Show error } else { Navigator.push( context, MaterialPageRoute(builder: (context) => LandingPage())); From 5dc27562750cd30758228770ff21180fa75d8efb Mon Sep 17 00:00:00 2001 From: hussam al-habibeh Date: Mon, 24 Aug 2020 09:59:57 +0300 Subject: [PATCH 5/7] Dashboaed page --- assets/images/closed_box.png | Bin 0 -> 4983 bytes assets/images/driver.png | Bin 0 -> 34583 bytes assets/images/location.png | Bin 0 -> 1586 bytes assets/images/open_box.png | Bin 0 -> 6073 bytes assets/images/qr_code.png | Bin 0 -> 7041 bytes lib/app-icons/config.json | 70 ++++ lib/app-icons/driver_app_icons.dart | 5 + lib/app-icons/fonts/DriverApp.ttf | Bin 2116 -> 6964 bytes lib/config/config.dart | 3 +- .../pending_orders/pending_orders_model.dart | 51 +++ lib/core/service/pending_orders_service.dart | 31 ++ .../viewModels/pending_orders_view_model.dart | 21 + lib/locator.dart | 4 + lib/pages/dashboard/dashboard_screen.dart | 395 ++++++++++++++++++ lib/pages/landing/landing_page.dart | 4 +- lib/pages/orders/pending_orders_page.dart | 31 ++ lib/root_page.dart | 5 +- lib/widgets/others/rounded_container.dart | 84 ++++ 18 files changed, 697 insertions(+), 7 deletions(-) create mode 100644 assets/images/closed_box.png create mode 100644 assets/images/driver.png create mode 100644 assets/images/location.png create mode 100644 assets/images/open_box.png create mode 100644 assets/images/qr_code.png create mode 100644 lib/core/model/pending_orders/pending_orders_model.dart create mode 100644 lib/core/service/pending_orders_service.dart create mode 100644 lib/core/viewModels/pending_orders_view_model.dart create mode 100644 lib/pages/dashboard/dashboard_screen.dart create mode 100644 lib/pages/orders/pending_orders_page.dart create mode 100644 lib/widgets/others/rounded_container.dart diff --git a/assets/images/closed_box.png b/assets/images/closed_box.png new file mode 100644 index 0000000000000000000000000000000000000000..3f7844f6cf270f7de85e0b13305de944af960dd6 GIT binary patch literal 4983 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 literal 0 HcmV?d00001 diff --git a/assets/images/driver.png b/assets/images/driver.png new file mode 100644 index 0000000000000000000000000000000000000000..9bf0a56585c8e1db62b63e7aef21ff6e9375925d GIT binary patch literal 34583 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

SBV^OfB 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 AssI20 literal 0 HcmV?d00001 diff --git a/assets/images/qr_code.png b/assets/images/qr_code.png new file mode 100644 index 0000000000000000000000000000000000000000..e50e92b9b28ecb487474782310ac3a3baef80a6e GIT binary patch literal 7041 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 St8hCtJS{btYNhgjq5lWv;$$cQ literal 0 HcmV?d00001 diff --git a/lib/app-icons/config.json b/lib/app-icons/config.json index cca5b07..331f146 100644 --- a/lib/app-icons/config.json +++ b/lib/app-icons/config.json @@ -19,6 +19,76 @@ "search": [ "logo" ] + }, + { + "uid": "633ab939f7378584b7fdcdf73ddc3187", + "css": "closed_box", + "code": 59395, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M786 1000L0 753.1V167.4L786 334.7ZM1260.2 730.4L786 1000V334.7L1260.2 106.5ZM0 167.4L479.7 0 1260.1 106.5 785.9 334.8ZM228.1 87.8L968.9 250 984.1 515.3 1010.2 553.3 1023.1 504.4 1040.6 519.6 1058 484.8 1071.1 504.6 1054.3 205.8 293.5 65.2ZM322.9 236.1L786 41.8 864.9 52.6 420.6 256.9ZM322.9 236.1V854.5L420.5 885.2V256.9ZM960.1 831.5C960.1 838.8 954.8 841.2 947.1 844.6L866.7 885.2C855.8 890.6 853.6 879.4 853.6 872.1V748.2C853.6 741 858.3 739.3 866.7 735.2L947.1 694.5C964.1 685.8 959 703.5 960.1 736.9ZM861.9 760.4L941.7 721.6V726.1L861.9 766.2ZM861.9 775.8L941.7 737V741.5L861.9 781.6ZM861.9 792.9L941.7 754.1V758.5L861.9 798.7ZM863.7 839.9L914.2 815.4 914.8 820 863.7 845.7ZM863.7 851.5L914.2 827 914.8 831.6 863.7 857.3ZM863.7 863.3L914.2 838.8 914.8 843.4 863.7 869.1Z", + "width": 1260 + }, + "search": [ + "closed_box" + ] + }, + { + "uid": "5ec8c041511a6ad70c313085226140a7", + "css": "location", + "code": 59396, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M359.3 267.2A91.9 91.9 0 1 1 267.4 175.4 92 92 0 0 1 359.3 267.2ZM534.7 267.2A266.2 266.2 0 0 1 517.5 361C482.4 465.1 250.5 1000.1 250.5 1000.1S32.1 416.8 13.1 349.9A267.3 267.3 0 1 1 534.7 267.2ZM437.9 268.3A170.5 170.5 0 1 0 267.4 438.9 170.5 170.5 0 0 0 437.9 268.3Z", + "width": 535 + }, + "search": [ + "location" + ] + }, + { + "uid": "dcd3318a238870bf147ea27335dad4ca", + "css": "open_box", + "code": 59397, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M1055.8 759.9L537.7 1000 541 412.4 1057.3 247.2ZM152.3 270.8L541 412.4 1055.8 247.2 579.4 153.1ZM579.4 153.1L763 61.5 1185.9 153.1 1057.2 247.2ZM579.4 153.1V403.7L682.1 367.1 1057.2 247.2ZM540.9 412.4L537.6 1000 152.1 840.7V270.8ZM540.9 412.4L660 623.6 1185.8 414.6 1057.2 247.2ZM540.9 412.4L419.9 608.7 0 426.2 152.3 270.8ZM152.3 270.8L37.7 84 476.4 0 579.4 153.1Z", + "width": 1186 + }, + "search": [ + "open_box" + ] + }, + { + "uid": "d755ac5bb912e95877e670a67bf4528d", + "css": "phone_call", + "code": 59398, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M907.5 618.9L829.1 540.7A45.6 45.6 0 0 0 764.4 540.7L764.4 540.7 719.7 585.5A9.9 9.9 0 0 1 707 586.6 517.6 517.6 0 0 1 586 467.8 9.9 9.9 0 0 1 586.9 455.1L633 409A45.7 45.7 0 0 0 633 344.4L554.6 265.9A46.7 46.7 0 0 0 489.9 265.9L465.1 290.8A139.5 139.5 0 0 0 430.3 433.2 417.6 417.6 0 0 0 481.3 536.8 544.9 544.9 0 0 0 638.1 690.9 400.4 400.4 0 0 0 754.2 742.5 134.2 134.2 0 0 0 786.7 746.4 141.4 141.4 0 0 0 886.1 704.6L907.4 683.2A45.6 45.6 0 0 0 907.5 618.9Z", + "width": 1344 + }, + "search": [ + "phone_call" + ] + }, + { + "uid": "bf7916a50afc43e4ef26fe098b6c10f3", + "css": "qr", + "code": 59399, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M9.6 167.1A9.6 9.6 0 0 1 0 157.5V9.6A9.6 9.6 0 0 1 9.6 0H161.2A9.6 9.6 0 0 1 161.2 19.2H19.2V157.5A9.6 9.6 0 0 1 9.6 167.1ZM161.2 1000H9.6A9.6 9.6 0 0 1 0 990.4V843A9.6 9.6 0 1 1 19.2 843V980.8H161.2A9.6 9.6 0 0 1 161.2 1000ZM990.3 167.1A9.6 9.6 0 0 1 980.7 157.5V19.2H845.5A9.6 9.6 0 1 1 845.5 0H990.3A9.6 9.6 0 0 1 999.9 9.6V157.5A9.6 9.6 0 0 1 990.3 167.1ZM990.3 1000H845.6A9.6 9.6 0 1 1 845.6 980.8H980.7V843A9.6 9.6 0 1 1 999.9 843V990.4A9.6 9.6 0 0 1 990.3 1000ZM396.9 180.7A5.9 5.9 0 0 0 402.8 174.8V180.7ZM430.5 174.8V158.9A5.9 5.9 0 0 0 424.6 152.9H408.7A5.9 5.9 0 0 0 402.8 158.9H402.8V180.7H430.5ZM535.6 180.7A5.9 5.9 0 0 0 541.5 174.8V180.7ZM569.3 174.8V158.9A5.9 5.9 0 0 0 563.4 152.9H547.4A5.9 5.9 0 0 0 541.5 158.9H541.5V180.7H569.3ZM396.9 180.7H380.9A5.9 5.9 0 0 0 375 186.6H375V202.6A5.9 5.9 0 0 0 380.9 208.5H402.8V180.7ZM452.4 208.5A5.9 5.9 0 0 0 458.3 202.6V208.5ZM436.4 208.5A5.9 5.9 0 0 1 430.5 202.6V208.5ZM464.2 180.7A5.9 5.9 0 0 0 458.3 186.6H458.3V208.5H486.1V180.7ZM569.3 202.6A5.9 5.9 0 0 1 563.4 208.5H541.5V180.7H569.3ZM402.8 214.4V208.5H396.9A5.9 5.9 0 0 1 402.8 214.4ZM396.9 236.2A5.9 5.9 0 0 0 402.8 230.3V236.2ZM492 208.5H486.1V214.4A5.9 5.9 0 0 1 492 208.5ZM396.9 236.2H380.9A5.9 5.9 0 0 0 375 242.2H375V258.1A5.9 5.9 0 0 0 380.9 264H402.8V236.2ZM430.5 258.1A5.9 5.9 0 0 1 424.6 264H402.8V236.2H430.5ZM436.4 236.2H430.5V242.2A5.9 5.9 0 0 1 436.4 236.2ZM458.3 242.2V236.2H452.4A5.9 5.9 0 0 1 458.3 242.2ZM458.3 258.1A5.9 5.9 0 0 0 464.2 264H480.2A5.9 5.9 0 0 0 486.1 258.1V236.2H458.3ZM575.2 236.2A5.9 5.9 0 0 0 569.4 242.2H569.4V264H597.1V236.2ZM619 236.2A5.9 5.9 0 0 1 624.9 242.2V264H597.1V236.2ZM458.3 285.9V269.9A5.9 5.9 0 0 0 452.4 264H436.4A5.9 5.9 0 0 0 430.5 269.9H430.5V291.8H458.3ZM563.5 291.8A5.9 5.9 0 0 0 569.4 285.9V291.8ZM624.9 285.9A5.9 5.9 0 0 1 619 291.8H597.1V263.9H624.9ZM402.8 313.6V297.6A5.9 5.9 0 0 0 396.9 291.6H380.9A5.9 5.9 0 0 0 375 297.6H375V319.4H402.8ZM535.6 291.8H519.7A5.9 5.9 0 0 0 513.8 297.7H513.8V313.6A5.9 5.9 0 0 0 519.7 319.5H541.5V291.8ZM597.1 313.6A5.9 5.9 0 0 1 591.2 319.5H569.4V291.8H597.1ZM602.9 291.8H597V297.7A5.9 5.9 0 0 1 602.9 291.8ZM375 341.4A5.9 5.9 0 0 0 380.9 347.3H396.9A5.9 5.9 0 0 0 402.8 341.4V319.5H375ZM430.5 341.4A5.9 5.9 0 0 0 436.4 347.3H452.4A5.9 5.9 0 0 0 458.3 341.4V319.5H430.5ZM513.8 341.4V325.4A5.9 5.9 0 0 0 507.9 319.5H492A5.9 5.9 0 0 0 486.1 325.4H486.1V347.3H513.8ZM541.6 325.4V319.5H535.6A5.9 5.9 0 0 1 541.6 325.4ZM541.6 341.4A5.9 5.9 0 0 0 547.5 347.3H563.5A5.9 5.9 0 0 0 569.4 341.4V319.5H541.6ZM575.2 319.5H569.3V325.4A5.9 5.9 0 0 1 575.2 319.5ZM624.9 341.4V325.4A5.9 5.9 0 0 0 619 319.5H602.9A5.9 5.9 0 0 0 597 325.4H597V347.3H624.8ZM519.7 375.1A5.9 5.9 0 0 1 513.8 369.2V375.1ZM597.1 369.2A5.9 5.9 0 0 0 603 375.1H619A5.9 5.9 0 0 0 624.9 369.2V347.3H597.1ZM174.7 375.1H158.8A5.9 5.9 0 0 0 152.9 381H152.9V396.9A5.9 5.9 0 0 0 158.8 402.8H180.7V375.1ZM269.8 402.8H285.8A5.9 5.9 0 0 0 291.7 396.9V381A5.9 5.9 0 0 0 285.8 375.1H264V402.8ZM341.3 375.1H325.4A5.9 5.9 0 0 0 319.5 381H319.5V396.9A5.9 5.9 0 0 0 325.4 402.8H347.2V375.1ZM436.4 402.8H452.4A5.9 5.9 0 0 0 458.3 396.9V381A5.9 5.9 0 0 0 452.4 375.1H430.5V402.8ZM486.1 396.9A5.9 5.9 0 0 0 492 402.8H513.8V375.1H486.1ZM519.7 402.8H535.7A5.9 5.9 0 0 0 541.6 396.9V381A5.9 5.9 0 0 0 535.7 375.1H513.8V402.8ZM597.1 396.9V381A5.9 5.9 0 0 0 591.2 375.1H575.2A5.9 5.9 0 0 0 569.4 381H569.4V402.8H597.1ZM619 402.8A5.9 5.9 0 0 0 624.9 396.9V402.8ZM602.9 402.8A5.9 5.9 0 0 1 597 396.9V402.8ZM652.7 396.9V381A5.9 5.9 0 0 0 646.8 375.1H630.8A5.9 5.9 0 0 0 624.9 381H624.9V402.8H652.7ZM708.2 396.9V381A5.9 5.9 0 0 0 702.3 375.1H686.3A5.9 5.9 0 0 0 680.4 381H680.4V402.8H708.2ZM714.1 402.8A5.9 5.9 0 0 1 708.2 396.9V402.8ZM180.7 408.7V402.8H174.7A5.9 5.9 0 0 1 180.7 408.7ZM180.7 424.7A5.9 5.9 0 0 0 186.5 430.6H202.5A5.9 5.9 0 0 0 208.4 424.7V402.8H180.7ZM214.3 402.8H208.4V408.7A5.9 5.9 0 0 1 214.3 402.8ZM347.2 408.7V402.8H341.3A5.9 5.9 0 0 1 347.2 408.7ZM347.2 424.7A5.9 5.9 0 0 0 353.1 430.6H375V402.8H347.2ZM436.4 402.8H430.5V408.7A5.9 5.9 0 0 1 436.4 402.8ZM563.5 430.6A5.9 5.9 0 0 0 569.4 424.7V430.6ZM658.5 430.6A5.9 5.9 0 0 1 652.7 424.7V430.6ZM680.4 424.7A5.9 5.9 0 0 0 686.3 430.6H708.2V402.8H680.4ZM730 402.8A5.9 5.9 0 0 1 735.9 408.7V430.6H708.2V402.8ZM214.3 430.6A5.9 5.9 0 0 0 208.4 436.5H208.4V458.4H236.2V430.6ZM269.8 458.4H285.8A5.9 5.9 0 0 0 291.7 452.4V436.5A5.9 5.9 0 0 0 285.8 430.6H264V458.4ZM375 436.5V430.6H369.1A5.9 5.9 0 0 1 375 436.5ZM452.4 458.4A5.9 5.9 0 0 0 458.3 452.4V458.4ZM436.4 458.4A5.9 5.9 0 0 1 430.5 452.4V458.4ZM464.2 430.6A5.9 5.9 0 0 0 458.3 436.5H458.3V458.4H486.1V430.6ZM597.1 452.4A5.9 5.9 0 0 1 591.2 458.4H569.4V430.6H597.1ZM602.9 430.6H597V436.5A5.9 5.9 0 0 1 602.9 430.6ZM624.9 436.5V430.6H619A5.9 5.9 0 0 1 624.9 436.5ZM619 458.4A5.9 5.9 0 0 0 624.9 452.4V458.4ZM658.5 458.4H674.5A5.9 5.9 0 0 0 680.4 452.4V436.5A5.9 5.9 0 0 0 674.5 430.6H652.7V458.4ZM708.2 436.5V430.6H702.3A5.9 5.9 0 0 1 708.2 436.5ZM708.2 452.4A5.9 5.9 0 0 0 714.1 458.4H730A5.9 5.9 0 0 0 735.9 452.4V430.6H708.2ZM242.1 458.4H236.2V464.3A5.9 5.9 0 0 1 242.1 458.4ZM375 480.3A5.9 5.9 0 0 0 380.9 486.2H402.8V458.4H375ZM492 458.4H486.1V464.3A5.9 5.9 0 0 1 492 458.4ZM619 458.4H602.9A5.9 5.9 0 0 0 597 464.3H597V480.2A5.9 5.9 0 0 0 602.9 486.1H624.8V458.4ZM652.7 480.3A5.9 5.9 0 0 1 646.8 486.2H624.9V458.4H652.7ZM658.5 458.4H652.7V464.3A5.9 5.9 0 0 1 658.5 458.4ZM208.4 508A5.9 5.9 0 0 0 214.3 513.9H230.3A5.9 5.9 0 0 0 236.2 508V486.1H208.4ZM402.8 492V486.1H396.9A5.9 5.9 0 0 1 402.8 492ZM402.8 508A5.9 5.9 0 0 0 408.7 513.9H424.6A5.9 5.9 0 0 0 430.5 508V486.1H402.8ZM436.4 486.1H430.5V492A5.9 5.9 0 0 1 436.4 486.1ZM458.3 492V486.1H452.4A5.9 5.9 0 0 1 458.3 492ZM458.3 508A5.9 5.9 0 0 0 464.2 513.9H480.2A5.9 5.9 0 0 0 486.1 508V486.1H458.3ZM646.8 513.9A5.9 5.9 0 0 0 652.7 508V513.9ZM658.5 486.1A5.9 5.9 0 0 0 652.7 492H652.7V513.9H680.4V486.1ZM741.8 513.9H757.8A5.9 5.9 0 0 0 763.7 508V492A5.9 5.9 0 0 0 757.8 486.2H735.9V513.9ZM813.3 486.1H797.4A5.9 5.9 0 0 0 791.5 492H791.5V508A5.9 5.9 0 0 0 797.4 513.9H819.2V486.1ZM825.1 513.9H841.1A5.9 5.9 0 0 0 847 508V492A5.9 5.9 0 0 0 841.1 486.2H819.3V513.9ZM180.7 535.7V519.8A5.9 5.9 0 0 0 174.7 513.9H158.8A5.9 5.9 0 0 0 152.9 519.8H152.9V541.7H180.7ZM230.3 541.7A5.9 5.9 0 0 0 236.2 535.7V541.7ZM264 535.7V519.8A5.9 5.9 0 0 0 258.1 513.9H242.1A5.9 5.9 0 0 0 236.2 519.8H236.2V541.7H264ZM269.8 541.7A5.9 5.9 0 0 1 264 535.7V541.7ZM341.3 541.7A5.9 5.9 0 0 0 347.2 535.7V541.7ZM375 535.7V519.8A5.9 5.9 0 0 0 369.1 513.9H353.1A5.9 5.9 0 0 0 347.2 519.8H347.2V541.7H375ZM535.6 541.7A5.9 5.9 0 0 0 541.5 535.7V541.7ZM569.3 535.7V519.8A5.9 5.9 0 0 0 563.4 513.9H547.4A5.9 5.9 0 0 0 541.5 519.8H541.5V541.7H569.3ZM619 513.9H602.9A5.9 5.9 0 0 0 597 519.8H597V535.8A5.9 5.9 0 0 0 602.9 541.7H624.8V513.9ZM741.8 513.9H735.9V519.8A5.9 5.9 0 0 1 741.8 513.9ZM214.3 541.7A5.9 5.9 0 0 0 208.4 547.6H208.4V569.4H236.2V541.7ZM396.9 569.4A5.9 5.9 0 0 0 402.8 563.5V569.4ZM380.9 569.4A5.9 5.9 0 0 1 375 563.5V569.4ZM430.5 563.5V547.6A5.9 5.9 0 0 0 424.6 541.7H408.7A5.9 5.9 0 0 0 402.8 547.6H402.8V569.5H430.5ZM535.6 541.7H519.7A5.9 5.9 0 0 0 513.8 547.6H513.8V563.5A5.9 5.9 0 0 0 519.7 569.4H541.5V541.7ZM624.9 547.6V541.7H619A5.9 5.9 0 0 1 624.9 547.6ZM680.4 563.5A5.9 5.9 0 0 1 674.5 569.4H652.7V541.7H680.4ZM686.3 541.7H680.4V547.6A5.9 5.9 0 0 1 686.3 541.7ZM708.2 547.6V541.7H702.3A5.9 5.9 0 0 1 708.2 547.6ZM708.2 563.5A5.9 5.9 0 0 0 714.1 569.4H730A5.9 5.9 0 0 0 735.9 563.5V541.7H708.2ZM785.6 541.7H769.7A5.9 5.9 0 0 0 763.8 547.6H763.8V563.5A5.9 5.9 0 0 0 769.7 569.4H791.6V541.7ZM841.1 541.7A5.9 5.9 0 0 1 847 547.6V569.4H819.3V541.7ZM208.4 591.3A5.9 5.9 0 0 0 214.3 597.2H230.3A5.9 5.9 0 0 0 236.2 591.3V569.4H208.4ZM242.1 569.4H236.2V575.3A5.9 5.9 0 0 1 242.1 569.4ZM347.2 575.3V569.4H341.3A5.9 5.9 0 0 1 347.2 575.3ZM341.3 597.2A5.9 5.9 0 0 0 347.2 591.3V597.2ZM436.4 597.2A5.9 5.9 0 0 1 430.5 591.3V597.2ZM513.8 591.3V575.3A5.9 5.9 0 0 0 507.9 569.4H492A5.9 5.9 0 0 0 486.1 575.3H486.1V597.2H513.8ZM541.6 575.3V569.4H535.6A5.9 5.9 0 0 1 541.6 575.3ZM575.2 597.2A5.9 5.9 0 0 1 569.4 591.3V597.2ZM619 597.2A5.9 5.9 0 0 0 624.9 591.3V597.2ZM658.5 569.4H652.7V575.3A5.9 5.9 0 0 1 658.5 569.4ZM658.5 597.2A5.9 5.9 0 0 1 652.7 591.3V597.2ZM791.5 575.3V569.4H785.6A5.9 5.9 0 0 1 791.5 575.3ZM791.5 591.3A5.9 5.9 0 0 0 797.4 597.2H819.2V569.4H791.5ZM152.9 619A5.9 5.9 0 0 0 158.8 625H174.7A5.9 5.9 0 0 0 180.7 619V597.2H152.9ZM341.3 597.2H325.4A5.9 5.9 0 0 0 319.5 603.1H319.5V619A5.9 5.9 0 0 0 325.4 625H347.2V597.2ZM375 619A5.9 5.9 0 0 1 369.1 625H347.2V597.2H375ZM380.9 597.2H375V603.1A5.9 5.9 0 0 1 380.9 597.2ZM402.8 603.1V597.2H396.9A5.9 5.9 0 0 1 402.8 603.1ZM396.9 625A5.9 5.9 0 0 0 402.8 619V625ZM436.4 625H452.4A5.9 5.9 0 0 0 458.3 619V603.1A5.9 5.9 0 0 0 452.4 597.2H430.5V625ZM486.1 619A5.9 5.9 0 0 0 492 625H507.9A5.9 5.9 0 0 0 513.8 619V597.2H486.1ZM741.8 625H757.8A5.9 5.9 0 0 0 763.7 619V603.1A5.9 5.9 0 0 0 757.8 597.2H735.9V625ZM819.3 603.1V597.2H813.4A5.9 5.9 0 0 1 819.3 603.1ZM380.9 625A5.9 5.9 0 0 0 375 630.8H375V652.7H402.8V625ZM430.5 646.8A5.9 5.9 0 0 1 424.6 652.7H402.8V625H430.5ZM436.4 625H430.5V630.8A5.9 5.9 0 0 1 436.4 625ZM575.2 625H569.3V630.8A5.9 5.9 0 0 1 575.2 625ZM597.1 630.8V625H591.2A5.9 5.9 0 0 1 597.1 630.8ZM630.8 625H624.9V630.8A5.9 5.9 0 0 1 630.8 625ZM708.2 630.8V625H702.3A5.9 5.9 0 0 1 708.2 630.8ZM741.8 625H735.9V630.8A5.9 5.9 0 0 1 741.8 625ZM813.3 652.7A5.9 5.9 0 0 0 819.2 646.8V652.7ZM375 674.6A5.9 5.9 0 0 0 380.9 680.5H396.9A5.9 5.9 0 0 0 402.8 674.6V652.7H375ZM408.7 652.7H402.8V658.6A5.9 5.9 0 0 1 408.7 652.7ZM464.2 652.7A5.9 5.9 0 0 0 458.3 658.6H458.3V680.5H486.1V652.7ZM492 680.5H507.9A5.9 5.9 0 0 0 513.8 674.6V658.6A5.9 5.9 0 0 0 507.9 652.7H486.1V680.5ZM541.6 674.6A5.9 5.9 0 0 0 547.5 680.5H563.5A5.9 5.9 0 0 0 569.4 674.6V652.7H541.6ZM741.8 680.5A5.9 5.9 0 0 1 735.9 674.6V680.5ZM785.6 652.7H769.7A5.9 5.9 0 0 0 763.8 658.6H763.8V674.6A5.9 5.9 0 0 0 769.7 680.5H791.6V652.7ZM847 674.6A5.9 5.9 0 0 1 841.1 680.5H819.3V652.7H847.1ZM452.4 708.2A5.9 5.9 0 0 0 458.3 702.3V708.2ZM492 680.5H486.1V686.4A5.9 5.9 0 0 1 492 680.5ZM492 708.2A5.9 5.9 0 0 1 486.1 702.3V708.2ZM630.8 708.2A5.9 5.9 0 0 1 624.9 702.3V708.2ZM702.3 708.2A5.9 5.9 0 0 0 708.2 702.3V708.2ZM757.8 680.5A5.9 5.9 0 0 1 763.7 686.4V708.2H735.9V680.5ZM402.8 730.1V714.1A5.9 5.9 0 0 0 396.9 708.2H380.9A5.9 5.9 0 0 0 375 714.1H375V736H402.8ZM452.4 708.2H436.4A5.9 5.9 0 0 0 430.5 714.1H430.5V730.1A5.9 5.9 0 0 0 436.4 736H458.3V708.2ZM507.9 708.2A5.9 5.9 0 0 1 513.8 714.1V736H486.1V708.2ZM591.2 736A5.9 5.9 0 0 0 597.1 730.1V736ZM763.7 730.1A5.9 5.9 0 0 1 757.8 736H735.9V708.2H763.7ZM408.7 763.8A5.9 5.9 0 0 1 402.8 757.9V763.8ZM486.1 741.9V736H480.2A5.9 5.9 0 0 1 486.1 741.9ZM591.2 736H575.2A5.9 5.9 0 0 0 569.4 741.9H569.4V757.9A5.9 5.9 0 0 0 575.2 763.8H597.1V736ZM624.9 757.9A5.9 5.9 0 0 1 619 763.8H597.1V736H624.9ZM630.8 736H624.9V741.9A5.9 5.9 0 0 1 630.8 736ZM652.7 741.9V736H646.8A5.9 5.9 0 0 1 652.7 741.9ZM652.7 757.9A5.9 5.9 0 0 0 658.5 763.8H674.5A5.9 5.9 0 0 0 680.4 757.9V736H652.7ZM686.3 736H680.4V741.9A5.9 5.9 0 0 1 686.3 736ZM708.2 741.9V736H702.3A5.9 5.9 0 0 1 708.2 741.9ZM741.8 736H735.9V741.9A5.9 5.9 0 0 1 741.8 736ZM813.3 736H797.4A5.9 5.9 0 0 0 791.5 741.9H791.5V757.9A5.9 5.9 0 0 0 797.4 763.8H819.2V736ZM841.1 736A5.9 5.9 0 0 1 847 741.9V763.8H819.3V736ZM436.4 791.5H452.4A5.9 5.9 0 0 0 458.3 785.6V769.7A5.9 5.9 0 0 0 452.4 763.8H430.5V791.5ZM535.6 791.5A5.9 5.9 0 0 0 541.5 785.6V791.5ZM519.7 791.5A5.9 5.9 0 0 1 513.8 785.6V791.5ZM569.3 785.6V769.6A5.9 5.9 0 0 0 563.4 763.7H547.4A5.9 5.9 0 0 0 541.5 769.6H541.5V791.5H569.3ZM702.3 791.5A5.9 5.9 0 0 0 708.2 785.6V791.5ZM741.8 791.5A5.9 5.9 0 0 1 735.9 785.6V791.5ZM819.3 769.7V763.8H813.4A5.9 5.9 0 0 1 819.3 769.7ZM819.3 785.6A5.9 5.9 0 0 0 825.2 791.5H841.1A5.9 5.9 0 0 0 847.1 785.6V763.7H819.3ZM408.7 791.5H402.8V797.4A5.9 5.9 0 0 1 408.7 791.5ZM569.3 813.4A5.9 5.9 0 0 1 563.4 819.3H541.5V791.5H569.3ZM619 791.5H602.9A5.9 5.9 0 0 0 597 797.4H597V813.4A5.9 5.9 0 0 0 602.9 819.3H624.8V791.5ZM741.8 819.2H757.8A5.9 5.9 0 0 0 763.7 813.3V797.4A5.9 5.9 0 0 0 757.8 791.5H735.9V819.2ZM785.6 819.2A5.9 5.9 0 0 0 791.6 813.3V819.2ZM819.3 813.4V797.4A5.9 5.9 0 0 0 813.4 791.5H797.4A5.9 5.9 0 0 0 791.5 797.4H791.5V819.3H819.3ZM825.1 819.2A5.9 5.9 0 0 1 819.2 813.3V819.2ZM375 841.2A5.9 5.9 0 0 0 380.9 847.1H396.9A5.9 5.9 0 0 0 402.8 841.2V819.3H375ZM486.1 841.2A5.9 5.9 0 0 0 492 847.1H513.8V819.2H486.1ZM541.6 841.2A5.9 5.9 0 0 1 535.7 847.1H513.8V819.2H541.6ZM547.5 819.2H541.6V825.1A5.9 5.9 0 0 1 547.5 819.2ZM785.6 819.2H769.7A5.9 5.9 0 0 0 763.8 825.1H763.8V841.1A5.9 5.9 0 0 0 769.7 847H791.6V819.2ZM825.1 847.1H841.1A5.9 5.9 0 0 0 847 841.2V825.2A5.9 5.9 0 0 0 841.1 819.3H819.3V847.1ZM341.3 152.9H158.8A6 6 0 0 0 152.8 158.8V341.5A5.9 5.9 0 0 0 158.8 347.4H341.3A5.9 5.9 0 0 0 347.2 341.5V158.8A5.9 5.9 0 0 0 341.3 152.9ZM319.5 316.1A3.4 3.4 0 0 1 316.1 319.5H184A3.4 3.4 0 0 1 180.6 316.1V184.1A3.4 3.4 0 0 1 184 180.7H316.1A3.4 3.4 0 0 1 319.5 184.1ZM291.7 263.9V214.3A5.9 5.9 0 0 0 285.8 208.4H214.3A5.9 5.9 0 0 0 208.4 214.3V285.8A5.9 5.9 0 0 0 214.3 291.7H285.8A5.9 5.9 0 0 0 291.7 285.8ZM841.1 152.9H658.4A6 6 0 0 0 652.5 158.8V341.5A5.9 5.9 0 0 0 658.4 347.4H841.1A5.9 5.9 0 0 0 847 341.5V158.8A5.9 5.9 0 0 0 841.1 152.9ZM819.2 316.1A3.4 3.4 0 0 1 815.8 319.5H683.8A3.4 3.4 0 0 1 680.4 316.1V184.1A3.4 3.4 0 0 1 683.8 180.7H815.8A3.4 3.4 0 0 1 819.2 184.1ZM791.5 263.9V214.3A5.9 5.9 0 0 0 785.6 208.4H714.1A5.9 5.9 0 0 0 708.2 214.3V285.8A5.9 5.9 0 0 0 714.1 291.7H785.6A5.9 5.9 0 0 0 791.6 285.8ZM341.3 652.7H158.8A5.9 5.9 0 0 0 152.8 658.6V841.3A5.9 5.9 0 0 0 158.8 847.2H341.3A5.9 5.9 0 0 0 347.2 841.3V658.6A5.9 5.9 0 0 0 341.3 652.7ZM319.5 815.9A3.4 3.4 0 0 1 316.1 819.3H184A3.4 3.4 0 0 1 180.6 815.9V683.9A3.4 3.4 0 0 1 184 680.5H316.1A3.4 3.4 0 0 1 319.5 683.9ZM291.7 763.8V714.1A5.9 5.9 0 0 0 285.8 708.2H214.3A5.9 5.9 0 0 0 208.4 714.1V785.6A5.9 5.9 0 0 0 214.3 791.5H285.8A5.9 5.9 0 0 0 291.7 785.6Z", + "width": 1000 + }, + "search": [ + "qr" + ] } ] } \ No newline at end of file diff --git a/lib/app-icons/driver_app_icons.dart b/lib/app-icons/driver_app_icons.dart index f66e96e..d6bbfb8 100644 --- a/lib/app-icons/driver_app_icons.dart +++ b/lib/app-icons/driver_app_icons.dart @@ -22,4 +22,9 @@ class DriverApp { static const _kFontPkg = null; static const IconData logo = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData closed_box = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData location = IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData open_box = IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData phone_call = IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData qr = IconData(0xe807, fontFamily: _kFontFam, fontPackage: _kFontPkg); } diff --git a/lib/app-icons/fonts/DriverApp.ttf b/lib/app-icons/fonts/DriverApp.ttf index a9e0e9fc83c193bb1212377594424a3275f8043d..9b039c2d077be09003c85b5c5c10c8dcdfd19988 100644 GIT binary patch literal 6964 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 KCO$R^pZ^Cj%GK@w delta 413 zcmdmDc0^!;QoXkz0|R3Z0|P@?a&BV5OU>PDf&4c>T#%kqnWm{OZ@|F7oC4%8$w*C1 zk@=#_3sn06h|My90$k~Ag+TTmAXdr9Evex8_5Tx4?GqrMBPTyOk>L`M#lRc`B-nBj zD+(C-7$yScC4hW|yu{qpHPUB=)EO99Ie?0I3i69favL&AfqF%N3iKxKQFdlxU<5LO z_`a3Bc09k$R|an87eEn)+leLHVD$e_|I^qNn8Sd44hANWC=h`3F)_33&zhM0TA4UTCK%ESXn-iFL8D(XFOb`Go0x5y8fg~_wHeX;~%DDNcxDGQv R6C)ENGXqObetJGgIRMw{P-XxC diff --git a/lib/config/config.dart b/lib/config/config.dart index e6ae40e..f0692b1 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -1,4 +1,3 @@ - import 'package:flutter/cupertino.dart'; const MAX_SMALL_SCREEN = 660; @@ -6,7 +5,7 @@ const MAX_SMALL_SCREEN = 660; const BASE_URL = 'https://uat.hmgwebservices.com/Services'; const GET_PROJECT = '/Lists.svc/REST/GetProject'; - +const GET_ALL_ORDERS = '/Patients.svc/REST/PatientER_Delivery_GetAllOrder'; class AppGlobal { static BuildContext context; diff --git a/lib/core/model/pending_orders/pending_orders_model.dart b/lib/core/model/pending_orders/pending_orders_model.dart new file mode 100644 index 0000000..c2ef9e3 --- /dev/null +++ b/lib/core/model/pending_orders/pending_orders_model.dart @@ -0,0 +1,51 @@ +import 'dart:ffi'; + +class PendingOrders { + int driverID; + String searchKey; + int pageSize; + int pageIndex; + String tokenID; + String userID; + String mobileNo; + String firstName; + String lastName; + String mobileNumber; + + PendingOrders( + {this.driverID, + this.searchKey, + this.pageSize, + this.pageIndex, + this.tokenID, + this.userID, + this.mobileNo, + this.firstName, + this.lastName, + this.mobileNumber}); + + PendingOrders.fromJson(Map json) { + driverID = json['DriverID']; + searchKey = json['SearchKey']; + pageSize = json['PageSize']; + pageIndex = json['PageIndex']; + tokenID = json['TokenID']; + userID = json['UserID']; + mobileNo = json['MobileNo']; + firstName = json['FirstName']; + lastName = json['LastName']; + mobileNumber = json['MobileNumber']; + } + + Map toJson() { + final Map data = new Map(); + data['DriverID'] = this.driverID; + data['SearchKey'] = this.searchKey; + data['PageSize'] = this.pageSize; + data['PageIndex'] = this.pageIndex; + data['TokenID'] = this.tokenID; + data['UserID'] = this.userID; + data['MobileNo'] = this.mobileNo; + return data; + } +} diff --git a/lib/core/service/pending_orders_service.dart b/lib/core/service/pending_orders_service.dart new file mode 100644 index 0000000..f4024a3 --- /dev/null +++ b/lib/core/service/pending_orders_service.dart @@ -0,0 +1,31 @@ +import 'package:driverapp/config/config.dart'; +import 'package:driverapp/core/model/pending_orders/pending_orders_model.dart'; +import 'package:driverapp/core/service/base_service.dart'; + +class PendingOrdersService extends BaseService { + List _orders = List(); + List get orders => _orders; + + PendingOrders _requestGetPendingOrders = PendingOrders( + driverID: 1111, + searchKey: "", + pageSize: 0, + pageIndex: 0, + tokenID: "@dm!n", + userID: "1111", + mobileNo: "0541710575", + ); + + Future getPendingOrders() async { + await baseAppClient.post(GET_ALL_ORDERS, + onSuccess: (dynamic response, int statusCode) { + _orders.clear(); + response['PatientER_Delivery_GetAllOrderList'].forEach((order) { + _orders.add(PendingOrders.fromJson(order)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: _requestGetPendingOrders.toJson()); + } +} diff --git a/lib/core/viewModels/pending_orders_view_model.dart b/lib/core/viewModels/pending_orders_view_model.dart new file mode 100644 index 0000000..0f66bba --- /dev/null +++ b/lib/core/viewModels/pending_orders_view_model.dart @@ -0,0 +1,21 @@ +import 'package:driverapp/core/enum/viewstate.dart'; +import 'package:driverapp/core/service/pending_orders_service.dart'; +import 'package:driverapp/core/model/pending_orders/pending_orders_model.dart'; +import '../../locator.dart'; +import 'base_view_model.dart'; + +class PendingOrdersViewModel extends BaseViewModel { + PendingOrdersService _pendingOrdersService = locator(); + + List get orders => _pendingOrdersService.orders; + + Future getPendingOrders() async { + setState(ViewState.Busy); + await _pendingOrdersService.getPendingOrders(); + if (_pendingOrdersService.hasError) { + error = _pendingOrdersService.error; + setState(ViewState.Error); + } else + setState(ViewState.Idle); + } +} diff --git a/lib/locator.dart b/lib/locator.dart index b7f1052..e12abbf 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -2,7 +2,9 @@ import 'package:get_it/get_it.dart'; import 'core/service/authentication_service.dart'; import 'core/service/hospital_service.dart'; +import 'core/service/pending_orders_service.dart'; import 'core/viewModels/authentication_view_model.dart'; +import 'core/viewModels/pending_orders_view_model.dart'; import 'core/viewModels/hospital_view_model.dart'; GetIt locator = GetIt.instance; @@ -12,8 +14,10 @@ void setupLocator() { /// Services locator.registerLazySingleton(() => HospitalService()); locator.registerLazySingleton(() => AuthenticationService()); + locator.registerLazySingleton(() => PendingOrdersService()); /// View Model locator.registerFactory(() => HospitalViewModel()); locator.registerFactory(() => AuthenticationViewModel()); + locator.registerFactory(() => PendingOrdersViewModel()); } diff --git a/lib/pages/dashboard/dashboard_screen.dart b/lib/pages/dashboard/dashboard_screen.dart new file mode 100644 index 0000000..94ff6ae --- /dev/null +++ b/lib/pages/dashboard/dashboard_screen.dart @@ -0,0 +1,395 @@ +import 'package:driverapp/config/size_config.dart'; +import 'package:driverapp/core/viewModels/pending_orders_view_model.dart'; +import 'package:flutter/material.dart'; +import '../base/base_view.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:driverapp/app-icons/driver_app_icons.dart'; +import 'package:driverapp/widgets/others/rounded_container.dart'; +import 'package:driverapp/pages/orders/pending_orders_page.dart'; + +class DashboardScreen extends StatefulWidget { + @override + _DashboardScreenState createState() => _DashboardScreenState(); +} + +class _DashboardScreenState extends State { + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getPendingOrders(), + builder: + (BuildContext context, PendingOrdersViewModel model, Widget child) => + Scaffold( + backgroundColor: Color(0xffF4F9FA), + body: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.all(16.0), + child: Column( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Have a great day ,', + style: TextStyle(fontSize: 12.5), + ), + Padding( + padding: EdgeInsets.only(top: 4.5), + child: Text( + 'Driver Name', + style: TextStyle( + fontWeight: FontWeight.w400, fontSize: 25.0), + ), + ), + ], + ), + ], + ), + ), + Padding( + padding: EdgeInsets.all(16.0), + child: Column( + children: [ + CircleAvatar( + radius: 25.5, + backgroundColor: Color(0xff30B7B9), + child: CircleAvatar( + backgroundColor: Color(0xff30B7B9), + maxRadius: 26.0, + child: Image.asset( + 'assets/images/driver.png', + fit: BoxFit.contain, + ), + ), + ), + ], + ), + ), + ], + ), + Row( + children: [ + Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.0), + child: Container( + height: MediaQuery.of(context).size.height * 0.15, + width: MediaQuery.of(context).size.width * 0.43, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.0), + gradient: LinearGradient( + colors: [Color(0xff17AFB8), Color(0xff49C1BC)]), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.all(12.0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Text( + 'You Have', + style: TextStyle( + color: Colors.white, fontSize: 10.0), + ), + Text( + '5', + style: TextStyle( + color: Colors.white, fontSize: 25.0), + ), + Text( + 'Undelivered \n Packages', + style: TextStyle( + color: Colors.white, fontSize: 10.0), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.all(4.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(right: 9.5), + child: Image.asset( + 'assets/images/closed_box.png', + height: + MediaQuery.of(context).size.height * + 0.09, + width: + MediaQuery.of(context).size.width * + 0.20, + //fit: BoxFit.cover, + )), + ], + ), + ) + ], + ), + ), + ) + ], + ), + Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.0), + child: Container( + height: MediaQuery.of(context).size.height * 0.15, + width: MediaQuery.of(context).size.width * 0.43, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.0), + gradient: LinearGradient( + colors: [Color(0xff17AFB8), Color(0xff49C1BC)]), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.all(12.0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Text( + 'You Have', + style: TextStyle( + color: Colors.white, fontSize: 10.0), + ), + Text( + '25', + style: TextStyle( + color: Colors.white, fontSize: 25.0), + ), + Text( + 'unWanted\n Packge', + style: TextStyle( + color: Colors.white, fontSize: 10.0), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.only(right: 9.5), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/open_box.png', + height: MediaQuery.of(context).size.height * + 0.11, + width: MediaQuery.of(context).size.width * + 0.24, + scale: 0.9, + fit: BoxFit.cover, + ), + ], + ), + ), + ], + ), + ), + ) + ], + ), + ], + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 12.0), + child: Row( + children: [ + Expanded( + child: InkWell( + child: Container( + height: 140, + width: 350, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.0), + gradient: LinearGradient(colors: [ + Color(0xff48C0BC), + Color(0xff17AFB8) + ])), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/qr_code.png', + width: + MediaQuery.of(context).size.width * 0.25, + height: + MediaQuery.of(context).size.height * 0.14, + fit: BoxFit.fitHeight, + ) + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'SCAN', + style: TextStyle( + fontSize: 35.0, color: Colors.white), + ), + Padding( + padding: EdgeInsets.only(top: 6.0), + child: Text( + 'To add package to que ', + style: TextStyle( + fontSize: 12.0, + color: Colors.white, + letterSpacing: 0.5, + wordSpacing: 5.5, + ), + ), + ), + ], + ) + ], + ), + ), + ), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Text( + 'Nearest Drop-Offs', + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + child: Row( + children: [ + Text( + 'See All', + style: TextStyle(fontSize: 14.5), + ), + Icon( + Icons.arrow_forward_ios, + size: 15.0, + ), + ], + ), + onTap: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => OrdersListScreen()), + )), + ], + ), + ], + ), + ), + Column( + children: [ + ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + itemCount: //model.orders == null ? 0 : model.orders.length, + 2, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 12.0), + child: RoundedContainer( + height: SizeConfig.heightMultiplier * 10.5, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(left: 22.0), + child: Image.asset( + 'assets/images/location.png'), + ) + ], + ), + if (model.orders.length != 0) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + model.orders[index].firstName + + ' ' + + model.orders[index].lastName, + style: TextStyle(fontSize: 20.0), + ), + Text( + model.orders[index].mobileNumber, + style: TextStyle( + color: Color(0xff30B7B9), + fontWeight: FontWeight.w600, + fontSize: 15.0), + ), + Text( + 'Olaya ST, Behind kfc next to king-\ndom tower 2nd floor n.o 247', + style: TextStyle(color: Colors.black45), + ) + ], + ), + Padding( + padding: EdgeInsets.all(10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircleAvatar( + backgroundColor: Colors.black45, + radius: 30.0, + child: CircleAvatar( + backgroundColor: Colors.white, + maxRadius: 28.9, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + '3 K.m \n away', + style: TextStyle( + color: Color(0xff30B7B9), + fontSize: 14.0), + ), + ), + ), + ) + ], + ), + ) + ], + ), + ), + ); + }) + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index a14e9eb..6239d50 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -4,7 +4,7 @@ import 'package:driverapp/widgets/bottom_navigation/bottom_nav_bar.dart'; import 'package:driverapp/widgets/drawer/app_drawer_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; - +import 'package:driverapp/pages/dashboard/dashboard_screen.dart'; import 'home_page.dart'; class LandingPage extends StatefulWidget { @@ -55,7 +55,7 @@ class _LandingPageState extends State { body: PageView( physics: NeverScrollableScrollPhysics(), controller: pageController, - children: [HomePage(), ReplayPage(), Container(), Container()], + children: [HomePage(), ReplayPage(), DashboardScreen(), Container()], ), bottomNavigationBar: BottomNavBar(changeIndex: _changeCurrentTab), ); diff --git a/lib/pages/orders/pending_orders_page.dart b/lib/pages/orders/pending_orders_page.dart new file mode 100644 index 0000000..f7caff9 --- /dev/null +++ b/lib/pages/orders/pending_orders_page.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:driverapp/config/size_config.dart'; +import 'package:driverapp/core/viewModels/pending_orders_view_model.dart'; +import '../base/base_view.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:driverapp/widgets/others/rounded_container.dart'; + +class OrdersListScreen extends StatefulWidget { + @override + _OrdersListScreenState createState() => _OrdersListScreenState(); +} + +class _OrdersListScreenState extends State { + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getPendingOrders(), + builder: + (BuildContext context, PendingOrdersViewModel model, Widget child) => + Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: Color(0xffF4F9FA), + title: Text( + 'Your Delivery Que', + ), + ), + ), + ); + } +} diff --git a/lib/root_page.dart b/lib/root_page.dart index 6e3125e..342f7ca 100644 --- a/lib/root_page.dart +++ b/lib/root_page.dart @@ -4,6 +4,7 @@ import 'package:driverapp/pages/landing/landing_page.dart'; import 'package:driverapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:driverapp/pages/dashboard/dashboard_screen.dart'; import 'core/viewModels/authentication_view_model.dart'; @@ -13,7 +14,7 @@ class RootPage extends StatelessWidget { Widget buildRoot(APP_STATUS status) { switch (status) { case APP_STATUS.UNAUTHENTICATED: - return LoginPage(); + return DashboardScreen(); break; case APP_STATUS.AUTHENTICATED: return LandingPage(); @@ -32,5 +33,3 @@ class RootPage extends StatelessWidget { ); } } - - diff --git a/lib/widgets/others/rounded_container.dart b/lib/widgets/others/rounded_container.dart new file mode 100644 index 0000000..93dc6cc --- /dev/null +++ b/lib/widgets/others/rounded_container.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; + +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, + )); + } +} From b36ec7f49071ba80b315d1cfd20df50c4d3ece6f Mon Sep 17 00:00:00 2001 From: Elham Rababah Date: Mon, 24 Aug 2020 10:44:35 +0300 Subject: [PATCH 6/7] Merge dashboard into dev --- ios/Runner.xcodeproj/project.pbxproj | 43 +++++++++++++++++++++--- lib/pages/authentication/login_page.dart | 3 +- lib/root_page.dart | 4 +-- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 90398e9..dd7be69 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -225,12 +225,47 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework", + "${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework", + "${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework", + "${BUILT_PRODUCTS_DIR}/TOCropViewController/TOCropViewController.framework", + "${BUILT_PRODUCTS_DIR}/barcode_scan/barcode_scan.framework", + "${BUILT_PRODUCTS_DIR}/connectivity/connectivity.framework", + "${BUILT_PRODUCTS_DIR}/device_info/device_info.framework", + "${BUILT_PRODUCTS_DIR}/flutter_flexible_toast/flutter_flexible_toast.framework", + "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework", + "${BUILT_PRODUCTS_DIR}/flutter_plugin_android_lifecycle/flutter_plugin_android_lifecycle.framework", + "${BUILT_PRODUCTS_DIR}/hexcolor/hexcolor.framework", + "${BUILT_PRODUCTS_DIR}/image_cropper/image_cropper.framework", + "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework", + "${BUILT_PRODUCTS_DIR}/local_auth/local_auth.framework", + "${BUILT_PRODUCTS_DIR}/maps_launcher/maps_launcher.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", ); name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TOCropViewController.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/barcode_scan.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_flexible_toast.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_plugin_android_lifecycle.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hexcolor.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_cropper.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/maps_launcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/lib/pages/authentication/login_page.dart b/lib/pages/authentication/login_page.dart index 10fb9b6..31a4958 100644 --- a/lib/pages/authentication/login_page.dart +++ b/lib/pages/authentication/login_page.dart @@ -4,6 +4,7 @@ import 'package:driverapp/core/model/authentication/login_request.dart'; import 'package:driverapp/core/viewModels/authentication_view_model.dart'; import 'package:driverapp/core/viewModels/project_view_model.dart'; import 'package:driverapp/pages/base/base_view.dart'; +import 'package:driverapp/pages/dashboard/dashboard_screen.dart'; import 'package:driverapp/pages/landing/landing_page.dart'; import 'package:driverapp/uitl/translations_delegate_base.dart'; import 'package:driverapp/uitl/utils.dart'; @@ -255,7 +256,7 @@ class LoginPage extends StatelessWidget { // Show error } else { Navigator.push( - context, MaterialPageRoute(builder: (context) => LandingPage())); + context, MaterialPageRoute(builder: (context) => DashboardScreen())); } } } diff --git a/lib/root_page.dart b/lib/root_page.dart index 342f7ca..3e1dbff 100644 --- a/lib/root_page.dart +++ b/lib/root_page.dart @@ -14,10 +14,10 @@ class RootPage extends StatelessWidget { Widget buildRoot(APP_STATUS status) { switch (status) { case APP_STATUS.UNAUTHENTICATED: - return DashboardScreen(); + return LoginPage (); break; case APP_STATUS.AUTHENTICATED: - return LandingPage(); + return DashboardScreen(); break; } } From 5e983bd77d0b9f3357f4ec417c433524722b9f5e Mon Sep 17 00:00:00 2001 From: Elham Rababah Date: Mon, 24 Aug 2020 11:17:09 +0300 Subject: [PATCH 7/7] remove clear Shared pref code --- lib/core/viewModels/authentication_view_model.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/core/viewModels/authentication_view_model.dart b/lib/core/viewModels/authentication_view_model.dart index b91b228..b64f49c 100644 --- a/lib/core/viewModels/authentication_view_model.dart +++ b/lib/core/viewModels/authentication_view_model.dart @@ -24,10 +24,6 @@ class AuthenticationViewModel extends BaseViewModel { } } - AuthenticationViewModel(){ - sharedPref.clear(); - } - login(LoginRequest loginRequest) async { setState(ViewState.BusyLocal); await _authenticationService.login(loginRequest);