From cd36d61640288619fb349839340010c7617da33b Mon Sep 17 00:00:00 2001 From: Aamir Muhammad Date: Tue, 15 Jul 2025 10:34:01 +0300 Subject: [PATCH 1/3] logins apis --- android/app/build.gradle | 49 +- android/build.gradle | 108 +++- android/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- android/settings.gradle | 49 +- ios/Runner.xcodeproj/project.pbxproj | 36 +- .../xcshareddata/xcschemes/Runner.xcscheme | 3 + lib/api/dashboard_api_client.dart | 58 +- lib/classes/consts.dart | 6 +- lib/classes/inAppWebView.dart | 33 + lib/classes/utils.dart | 146 ++--- lib/models/generic_response_model.dart | 581 +++++++++--------- lib/models/sso_auth_model.dart | 65 ++ lib/provider/dashboard_provider_model.dart | 59 +- lib/ui/landing/widget/services_widget.dart | 249 +++++--- .../offers_and_discounts_details.dart | 6 +- lib/widgets/mark_attendance_widget.dart | 1 - pubspec.yaml | 34 +- 18 files changed, 955 insertions(+), 534 deletions(-) create mode 100644 lib/classes/inAppWebView.dart create mode 100644 lib/models/sso_auth_model.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 512fe2a..217706e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,25 +1,12 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} +plugins { + id "com.android.application" + id "kotlin-android" + id "com.google.gms.google-services" + id "dev.flutter.flutter-gradle-plugin" + id "com.google.firebase.crashlytics" -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' } -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') @@ -27,19 +14,11 @@ if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'com.google.gms.google-services' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" -apply plugin: 'com.huawei.agconnect' -android { - compileSdkVersion 34 - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } +android { + namespace 'hmg.cloudSolutions.mohem' + compileSdk 36 kotlinOptions { jvmTarget = '1.8' @@ -52,10 +31,10 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "hmg.cloudSolutions.mohem" - minSdkVersion 28 - targetSdkVersion 34 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + minSdkVersion 30 + targetSdk = flutter.targetSdkVersion + versionCode flutter.versionCode + versionName flutter.versionName } signingConfigs { @@ -84,5 +63,5 @@ flutter { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.1.20" } diff --git a/android/build.gradle b/android/build.gradle index 2c90dbd..c1b6ff6 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,34 +1,110 @@ -buildscript { - ext.kotlin_version = '1.9.10' +//buildscript { +// ext.kotlin_version = '1.9.10' +// repositories { +// google() +// mavenCentral() +// maven { url 'https://developer.huawei.com/repo/' } +// } +// +// dependencies { +// classpath 'com.android.tools.build:gradle:7.1.3' +// classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" +// classpath 'com.google.gms:google-services:4.3.8' +// classpath 'com.huawei.agconnect:agcp:1.8.0.300' +// classpath "com.android.tools:r8:8.2.33" +// } +//} +// +//allprojects { +// repositories { +// google() +// mavenCentral() +// maven { url 'https://developer.huawei.com/repo/' } +// } +//} +// +//rootProject.buildDir = '../build' +//subprojects { +// project.buildDir = "${rootProject.buildDir}/${project.name}" +// project.evaluationDependsOn(':app') +//} +// +//tasks.register("clean", Delete) { +// delete rootProject.buildDir +//} + + +allprojects { repositories { google() mavenCentral() - maven { url 'https://developer.huawei.com/repo/' } + maven { + url 'https://developer.huawei.com/repo/' + } + maven { + url "https://artifactory.ess-dev.com/artifactory/gradle-dev-local" + } } - dependencies { - classpath 'com.android.tools.build:gradle:7.1.3' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.8' - classpath 'com.huawei.agconnect:agcp:1.8.0.300' - classpath "com.android.tools:r8:8.2.33" + // Exclude old BouncyCastle globally to avoid duplicate classes + configurations.all { + exclude group: 'org.bouncycastle', module: 'bcprov-jdk16' } -} -allprojects { - repositories { - google() - mavenCentral() - maven { url 'https://developer.huawei.com/repo/' } + tasks.withType(JavaCompile).configureEach { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } + + tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions { + jvmTarget = "21" + } + } + + subprojects { + afterEvaluate { project -> + if (project.hasProperty('android')) { + project.android { + if (namespace == null) { + namespace project.group + } + + buildFeatures { + if (buildConfig == null) { + buildConfig true + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 + } + } + } + // Force Java 17 for all JavaCompile tasks in all subprojects (including plugins) + project.tasks.withType(JavaCompile).configureEach { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } + // Force Kotlin JVM target for all subprojects + project.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions { + jvmTarget = "21" + } + } + } } } + rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { project.evaluationDependsOn(':app') } tasks.register("clean", Delete) { - delete rootProject.buildDir + delete rootProject.layout.buildDirectory } diff --git a/android/gradle.properties b/android/gradle.properties index 54e1a43..8310efa 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx2048M android.useAndroidX=true android.enableJetifier=true -org.gradle.java.home=/Users/user/Library/Java/JavaVirtualMachines/jbr-17.0.12/Contents/Home/ \ No newline at end of file +#org.gradle.java.home=/Users/amirs/Library/Java/JavaVirtualMachines/jbr-17.0.12/Contents/Home/ \ No newline at end of file diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 1e830b7..941ceb1 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Mar 06 11:40:30 AST 2025 +#Tue Jul 08 11:08:34 AST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bc..15303ee 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,44 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" + repositories { + google() + mavenCentral() + gradlePluginPortal() + maven { url 'https://developer.huawei.com/repo/' } + + } + + dependencyResolutionManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + maven { url 'https://developer.huawei.com/repo/' } + maven { + url "https://artifactory.ess-dev.com/artifactory/gradle-dev-local" + } + } + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version '8.11.0' apply false + id("org.jetbrains.kotlin.android") version "2.2.0" apply false + id("com.google.gms.google-services") version "4.4.3" apply false + id("com.google.firebase.crashlytics") version "3.0.4" apply false + id('org.gradle.toolchains.foojay-resolver-convention') version '0.9.0' apply false + +} + +include ":app" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 97a5b37..ea4aec9 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -144,7 +144,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, C4CFBC4C5CAC00182015ACD5 /* [CP] Embed Pods Frameworks */, - EF29CE25BB57F5AA48CE1136 /* [CP] Copy Pods Resources */, + 6C6E76E4FB19FAF11C24005D /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -242,6 +242,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 6C6E76E4FB19FAF11C24005D /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -274,23 +291,6 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - EF29CE25BB57F5AA48CE1136 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 5e31d3d..9c12df5 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 145b039..e8a94cd 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -1,6 +1,8 @@ import 'dart:async'; import 'dart:convert'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:http/http.dart' as http; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -12,7 +14,8 @@ import 'package:mohem_flutter_app/models/dashboard/list_menu.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; -import 'package:platform_device_id/platform_device_id.dart'; +import 'package:mohem_flutter_app/models/sso_auth_model.dart'; +import 'package:platform_device_id_plus/platform_device_id.dart'; // import 'package:platform_device_id/platform_device_id.dart'; import 'package:uuid/uuid.dart'; @@ -153,6 +156,59 @@ class DashboardApiClient { ); } + Future getTicketBookingRedirection() async { + String url = "${ApiConsts.erpRest}GET_PORTAL_REDIRECTION"; + Map postParams = {"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); + } + + Future getBookingSSOAuthRedirection({required String clientID}) async { + String url = "${ApiConsts.ssoAuthRedirection}?grantType=mohemm"; + //https://sso-uat.hmg.com/api/auth/connect?grantType=mohemm' + // Map postParams = {"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER}; + Map postParams = { + "ClientId": clientID, + // "ClientId": "a9f4d1a0596d4aea8f830992ec4bdac1", + "PersonId": AppState().memberInformationList?.eMPLOYEENUMBER, + "Username": AppState().memberInformationList?.eMPLOYEENUMBER, + "Language": "en", + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + SSOAuthModel responseData = SSOAuthModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); + } + + Future getBookingSSOFinalRedirection({required String token}) async { + token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhjZTE2OWM0YjIwYjQ2ZWM5YTQyOTU3Y2ZhODUzNzQ1IiwidHlwIjoiSldUIn0.eyJ0ZW5hbnRfaWQiOiJhOWY0ZDFhMDU5NmQ0YWVhOGY4MzA5OTJlYzRiZGFjMSIsImVpZCI6IjExNzkzMCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3NpZCI6Ijk2MDI0OGM1NzA3YzQ3MmFhYTEzM2I1N2ZhODE1ZmVhIiwibGFuZ3VhZ2UiOiJVUyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6IjExNzkzMEBobWcuY29tIiwiZXhwIjoxNzgyNDc1NzY5LCJpc3MiOiJodHRwczovL3Nzby11YXQuaG1nLmNvbSIsImF1ZCI6ImE5ZjRkMWEwNTk2ZDRhZWE4ZjgzMDk5MmVjNGJkYWMxIn0.rJcLVsG8D0XECyLERCTD2uqGeWyvp-OBVGE9uL2qKrX4etFUHgdFt_5kYF6edFTtGy-0PIZadHDmv7e-IOhVWHm5HVMClaukiXoRXR8cDN8XA1wfme3Kd-U5PXN-IRh49AyRTzLO0rYNPvH81ScosWGlsFSkOvA-0hJNa2adHdtvgNvB8wJshSU5p7sAmF8mjdDY6aInG19etu2iEuUDwHHA4ZY_ts4hboHo8fE392hFaYGonExoD7bpW5RMx5xKWeRCmWpG_PK8Aw_z1jGzdB9PANus4pteRGuln1J-kmo2lQC9pVrSyZATAKp1HfgfyZ_vUhaHEfM69cMWaCslJQ"; + var request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG')); + request.fields.addAll({'JWTToken': token}); + + // request.headers.addAll(headers); + + http.StreamedResponse response = await request.send(); + if (response.statusCode == 302) { + print("================== post =========="); + var res = await response.stream.bytesToString(); + return response.headers["location"]; + } else { + print(response.reasonPhrase); + } + } + //Mark Attendance Future markAttendance({ String lat = "0", diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 0214199..c7f62d8 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -6,12 +6,12 @@ class ApiConsts { // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver // static String baseUrl = "http://10.201.204.101:2024"; - static String baseUrl = "https://webservices.hmg.com"; // PreProd + // static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://hmgwebservices.com"; // Live server // static String baseUrl = "https://mohemm.hmg.com"; // New Live server // - // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver + static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver // static String baseUrl = "http://10.20.200.111:1010/"; // static String baseUrl = "https://webservices.hmg.com"; // PreProd @@ -27,6 +27,8 @@ class ApiConsts { static String user = baseUrlServices + "api/User/"; static String cocRest = baseUrlServices + "COCWS.svc/REST/"; + static String ssoAuthRedirection = "https://sso-uat.hmg.com/api/auth/connect"; + //Chat static String chatServerBaseUrl = "https://apiderichat.hmg.com/"; static String chatServerBaseApiUrl = chatServerBaseUrl + "api/"; diff --git a/lib/classes/inAppWebView.dart b/lib/classes/inAppWebView.dart new file mode 100644 index 0000000..ccb24fd --- /dev/null +++ b/lib/classes/inAppWebView.dart @@ -0,0 +1,33 @@ +import 'dart:developer'; + +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; + +class MyInAppBrowser extends InAppBrowser { + final Function onExitCallback; + final Function(String) onLoadStartCallback; + + MyInAppBrowser({ + required this.onExitCallback, + required this.onLoadStartCallback, + }); + + @override + Future onBrowserCreated() async { + log("\n\nBrowser Created!\n\n"); + } + + @override + Future onLoadStart(Uri? url) async { + onLoadStartCallback(url.toString()); + } + + @override + Future onLoadStop(Uri? url) async { + log("\n\nStopped $url\n\n"); + } + + @override + void onLoadError(Uri? url, int code, String message) { + log("Can't load $url.. Error: $message"); + } +} diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 1838cb8..0245bbf 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -31,13 +31,14 @@ class Utils { static void showToast(String message, {bool longDuration = true}) { Fluttertoast.showToast( - msg: message, - toastLength: longDuration ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - timeInSecForIosWeb: 1, - backgroundColor: Colors.black54, - textColor: Colors.white, - fontSize: 13.0); + msg: message, + toastLength: longDuration ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + timeInSecForIosWeb: 1, + backgroundColor: Colors.black54, + textColor: Colors.white, + fontSize: 13.0, + ); } static dynamic getNotNullValue(List list, int index) { @@ -63,12 +64,7 @@ class Utils { static void showLoading(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) { _isLoadingVisible = true; - showDialog( - context: context, - barrierColor: Colors.black.withOpacity(0.5), - useRootNavigator: false, - builder: (BuildContext context) => LoadingDialog(), - ).then((value) { + showDialog(context: context, barrierColor: Colors.black.withOpacity(0.5), useRootNavigator: false, builder: (BuildContext context) => LoadingDialog()).then((value) { _isLoadingVisible = false; }); }); @@ -118,13 +114,14 @@ class Utils { showDialog( barrierDismissible: false, context: cxt, - builder: (cxt) => ConfirmDialog( - message: errorMessage, - onTap: () { - Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route route) => false); - }, - onCloseTap: () {}, - ), + builder: + (cxt) => ConfirmDialog( + message: errorMessage, + onTap: () { + Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route route) => false); + }, + onCloseTap: () {}, + ), ); } else { if (cxt != null) { @@ -138,33 +135,18 @@ class Utils { } static Future showErrorDialog({required BuildContext context, required VoidCallback onOkTapped, required String message}) async { - return showDialog( - context: context, - builder: (BuildContext context) => ConfirmDialog( - message: message, - onTap: onOkTapped, - ), - ); + return showDialog(context: context, builder: (BuildContext context) => ConfirmDialog(message: message, onTap: onOkTapped)); } static void confirmDialog(cxt, String message, {VoidCallback? onTap}) { - showDialog( - context: cxt, - builder: (BuildContext cxt) => ConfirmDialog( - message: message, - onTap: onTap, - ), - ); + showDialog(context: cxt, builder: (BuildContext cxt) => ConfirmDialog(message: message, onTap: onTap)); } static Widget getNoDataWidget(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SvgPicture.asset('assets/images/not_found.svg', width: 110.0, height: 110.0), - LocaleKeys.noDataAvailable.tr().toText16().paddingOnly(top: 15), - ], + children: [SvgPicture.asset('assets/images/not_found.svg', width: 110.0, height: 110.0), LocaleKeys.noDataAvailable.tr().toText16().paddingOnly(top: 15)], ).center; } @@ -172,10 +154,7 @@ class Utils { return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SvgPicture.asset('assets/images/not_found.svg', width: 110.0, height: 110.0), - LocaleKeys.noDataAvailable.tr().toText16().paddingOnly(top: 15), - ], + children: [SvgPicture.asset('assets/images/not_found.svg', width: 110.0, height: 110.0), LocaleKeys.noDataAvailable.tr().toText16().paddingOnly(top: 15)], ).center; } @@ -209,17 +188,7 @@ class Utils { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, - children: [ - 6.height, - alignCenter ? text.toText12().center : text.toText12(), - 5.height, - if (showDivider) - const Divider( - height: 1, - color: Color(0xff2E303A), - thickness: 1, - ) - ], + children: [6.height, alignCenter ? text.toText12().center : text.toText12(), 5.height, if (showDivider) const Divider(height: 1, color: Color(0xff2E303A), thickness: 1)], ); } @@ -227,17 +196,15 @@ class Utils { return BoxDecoration( color: background, border: Border.all( - width: 1, // - color: background // <--- border width here - ), + width: 1, // + color: background, // <--- border width here + ), borderRadius: BorderRadius.circular(radius), ); } static Widget mHeight(double h) { - return Container( - height: h, - ); + return Container(height: h); } static Widget mDivider(Color color) { @@ -352,20 +319,21 @@ class Utils { if (!Platform.isIOS) { await showCupertinoModalPopup( context: context, - builder: (BuildContext cxt) => Container( - height: 250, - color: Colors.white, - child: CupertinoDatePicker( - backgroundColor: Colors.white, - mode: CupertinoDatePickerMode.date, - onDateTimeChanged: (DateTime value) { - if (value != null && value != selectedDate) { - selectedDate = value; - } - }, - initialDateTime: selectedDate, - ), - ), + builder: + (BuildContext cxt) => Container( + height: 250, + color: Colors.white, + child: CupertinoDatePicker( + backgroundColor: Colors.white, + mode: CupertinoDatePickerMode.date, + onDateTimeChanged: (DateTime value) { + if (value != null && value != selectedDate) { + selectedDate = value; + } + }, + initialDateTime: selectedDate, + ), + ), ); } else { DateTime? picked = await showDatePicker(context: context, initialDate: selectedDate, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101)); @@ -377,19 +345,25 @@ class Utils { } static void readNFc({required Function(String) onRead}) { - NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async { - MifareUltralight f; - if (Platform.isAndroid) { - f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); - } else { - f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); - } - String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); - NfcManager.instance.stopSession(); - onRead(identifier); - }).catchError((err) { - print(err); - }); + NfcManager.instance + .startSession( + onDiscovered: (NfcTag tag) async { + MifareUltralight f; + if (Platform.isAndroid) { + print(tag); + f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + } else { + f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + } + String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); + NfcManager.instance.stopSession(); + onRead(identifier); + }, + pollingOptions: {NfcPollingOption.iso14443}, + ) + .catchError((err) { + print(err); + }); } //HUAWEI DECISION MAKING diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index ba48836..74cef13 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:mohem_flutter_app/models/add_att_success_list_model.dart'; import 'package:mohem_flutter_app/models/add_attachment_list_model.dart'; import 'package:mohem_flutter_app/models/basic_member_information_model.dart'; @@ -391,275 +393,278 @@ class GenericResponseModel { String? ePharmacyGetItemOnHandList; bool? isActiveCode; bool? isSMSSent; - - GenericResponseModel( - {this.date, - this.languageID, - this.serviceName, - this.time, - this.androidLink, - this.authenticationTokenID, - this.data, - this.dataw, - this.dietType, - this.dietTypeID, - this.errorCode, - this.errorEndUserMessage, - this.errorEndUserMessageN, - this.errorMessage, - this.errorType, - this.foodCategory, - this.iOSLink, - this.isAuthenticated, - this.mealOrderStatus, - this.mealType, - this.messageStatus, - this.numberOfResultRecords, - this.patientBlodType, - this.successMsg, - this.successMsgN, - this.vidaUpdatedResponse, - this.addAttSuccessList, - this.addAttachmentList, - this.bCDomain, - this.bCLogo, - this.basicMemberInformation, - this.businessCardPrivilege, - this.calculateAbsenceDuration, - this.cancelHRTransactionLIst, - this.chatEmployeeLoginList, - this.companyBadge, - this.companyImage, - this.companyImageDescription, - this.companyImageURL, - this.companyMainCompany, - this.countryList, - this.createVacationRuleList, - this.deleteAttachmentList, - this.deleteVacationRuleList, - this.disableSessionList, - this.employeeQR, - this.employeeDocumentsList, - this.forgetPasswordTokenID, - this.getAbsenceAttachmentsList, - this.getAbsenceAttendanceTypesList, - this.getAbsenceCollectionNotificationBodyList, - this.getAbsenceDffStructureList, - this.getAbsenceTransactionList, - this.getAccrualBalancesList, - this.getActionHistoryList, - this.getPRActionHistoryList, - this.getAddressDffStructureList, - this.getAddressNotificationBodyList, - this.getApprovesList, - this.getAttachementList, - this.getPRAttachmentList, - this.getAttendanceTrackingList, - this.getBasicDetColsStructureList, - this.getBasicDetDffStructureList, - this.getBasicDetNtfBodyList, - this.getCEICollectionNotificationBodyList, - this.getCEIDFFStructureList, - this.getCEITransactionList, - this.getCcpTransactionsList, - this.getCcpTransactionsListNew, - this.getConcurrentProgramsList, - this.getContactColsStructureList, - this.getContactDetailsList, - this.getContactDffStructureList, - this.getContactNotificationBodyList, - this.getCountriesList, - this.getDayHoursTypeDetailsList, - this.getDeductionsList, - this.getDefaultValueList, - this.getEITCollectionNotificationBodyList, - this.getEITDFFStructureList, - this.getEITTransactionList, - this.getEarningsList, - this.getEmployeeAddressList, - this.getEmployeeBasicDetailsList, - this.getEmployeeContactsList, - this.getEmployeePhonesList, - this.getEmployeeSubordinatesList, - this.getFliexfieldStructureList, - this.getHrCollectionNotificationBodyList, - this.getHrTransactionList, - this.getItemCreationNtfBodyList, - this.getItemTypeNotificationsList, - this.getItemTypesList, - this.getLookupValuesList, - this.getMenuEntriesList, - this.getEventActivityList, - this.getMoItemHistoryList, - this.getMoNotificationBodyList, - this.getNotificationButtonsList, - this.getNotificationReassignModeList, - this.getObjectValuesList, - this.getOpenMissingSwipesList, - this.getOpenNotificationsList, - this.getOpenNotificationsNumList, - this.getOpenPeriodDatesList, - this.getOrganizationsSalariesList, - this.getPaymentInformationList, - this.getPayslipList, - this.getPerformanceAppraisalList, - this.getPhonesNotificationBodyList, - this.getPoItemHistoryList, - this.getPoNotificationBodyList, - this.getPrNotificationBodyList, - this.getPaymentNotificationBodyList, - this.getPRInformationList, - this.getQuotationAnalysisList, - this.getRFCEmployeeListList, - this.getRespondAttributeValueList, - this.getSITCollectionNotificationBodyList, - this.getSITDFFStructureList, - this.getSITTransactionList, - this.getScheduleShiftsDetailsList, - this.getShiftTypesList, - this.getStampMsNotificationBodyList, - this.getStampNsNotificationBodyList, - this.getSubordinatesAttdStatusList, - this.getSubordinatesLeavesList, - this.getSubordinatesLeavesTotalVacationsList, - this.getSummaryOfPaymentList, - this.getSwipesList, - this.getTermColsStructureList, - this.getTermDffStructureList, - this.getTermNotificationBodyList, - this.getTimeCardSummaryList, - this.getTicketsByEmployeeList, - this.getTicketDetailsByEmployee, - this.getTicketTransactions, - this.getTicketTypes, - this.getSectionTopics, - this.getMowadhafhiProjects, - this.getProjectDepartments, - this.getDepartmentSections, - this.getPendingTransactionsFunctions, - this.getPendingTransactionsDetails, - this.getConcurrentProgramsModel, - this.getCCPTransactionsModel, - this.getCCPOutputModel, - this.getCCPDFFStructureModel, - this.getUserItemTypesList, - this.getVacationRulesList, - this.getVaccinationOnHandList, - this.getVaccinationsList, - this.getValueSetValuesList, - this.getWorkList, - this.hRCertificateTemplate, - this.imgURLsList, - this.insertApInv, - this.insertBooked, - this.insertEmpSwipesList, - this.insertJournal, - this.insertOrders, - this.intPortalGetEmployeeList, - this.isDeviceTokenEmpty, - this.isPasswordExpired, - this.isRegisterAllowed, - this.isRequriedValueSetEmpty, - this.isUserSMSExcluded, - this.itemOnHand, - this.languageAvailable, - this.listSupplier, - this.listUserAgreement, - this.listEITStrucrure, - this.listItemImagesDetails, - this.listItemMaster, - this.listMedicineDetails, - this.listMenu, - this.listNewEmployees, - this.listRadScreen, - this.logInTokenID, - this.memberInformationList, - this.memberLoginList, - this.mohemmGetBusinessCardEnabledList, - this.mohemmGetFavoriteReplacementsList, - this.mohemmGetMobileDeviceInfobyEmpInfoList, - this.mohemmGetMobileLoginInfoList, - this.mohemmGetPatientIDList, - this.mohemmITGResponseItem, - this.mohemmIsChangeIsActiveBusinessCardEnable, - this.mohemmIsInsertBusinessCardEnable, - this.mohemmWifiPassword, - this.mohemmWifiSSID, - this.notificationAction, - this.notificationGetRespondAttributesList, - this.notificationRespondRolesList, - this.oracleOutPutNumber, - this.pASSWORDEXPIREDMSG, - this.pCOUNTRYCODE, - this.pCOUNTRYNAME, - this.pDESCFLEXCONTEXTCODE, - this.pDESCFLEXCONTEXTNAME, - this.pForm, - this.pINFORMATION, - this.pMBLID, - this.pNUMOFSUBORDINATES, - this.pOPENNTFNUMBER, - this.pQUESTION, - this.pSESSIONID, - this.pSchema, - this.pharmacyStockAddPharmacyStockList, - this.pharmacyStockGetOnHandList, - this.privilegeList, - this.processTransactions, - this.registerUserNameList, - this.replacementList, - this.respondAttributesList, - this.respondRolesList, - this.resubmitAbsenceTransactionList, - this.resubmitEITTransactionList, - this.resubmitHrTransactionList, - this.sFHGetPoNotificationBodyList, - this.sFHGetPrNotificationBodyList, - this.startAbsenceApprovalProccess, - this.startAddressApprovalProcessList, - this.startBasicDetApprProcessList, - this.startCeiApprovalProcess, - this.startContactApprovalProcessList, - this.startEitApprovalProcess, - this.startHrApprovalProcessList, - this.startPhonesApprovalProcessList, - this.startSitApprovalProcess, - this.startTermApprovalProcessList, - this.submitAddressTransactionList, - this.submitBasicDetTransactionList, - this.submitCEITransactionList, - this.submitCcpTransactionList, - this.submitContactTransactionList, - this.submitEITTransactionList, - this.submitHrTransactionList, - this.submitPhonesTransactionList, - this.submitSITTransactionList, - this.submitTermTransactionList, - this.subordinatesOnLeavesList, - this.sumbitAbsenceTransactionList, - this.tokenID, - this.updateAttachmentList, - this.updateEmployeeImageList, - this.updateItemTypeSuccessList, - this.updateUserItemTypesList, - this.updateVacationRuleList, - this.vHREmployeeLoginList, - this.vHRGetEmployeeDetailsList, - this.vHRGetManagersDetailsList, - this.vHRGetProjectByCodeList, - this.vHRIsVerificationCodeValid, - this.validateAbsenceTransactionList, - this.validateEITTransactionList, - this.validatePhonesTransactionList, - this.vrItemTypesList, - this.wFLookUpList, - this.eLearningGETEMPLOYEEPROFILEList, - this.eLearningLOGINList, - this.eLearningValidateLoginList, - this.eLearningValidate_LoginList, - this.ePharmacyGetItemOnHandList, - this.isActiveCode, - this.isSMSSent}); + PortalDirectionData? portalDirectionData; + + GenericResponseModel({ + this.date, + this.languageID, + this.portalDirectionData, + this.serviceName, + this.time, + this.androidLink, + this.authenticationTokenID, + this.data, + this.dataw, + this.dietType, + this.dietTypeID, + this.errorCode, + this.errorEndUserMessage, + this.errorEndUserMessageN, + this.errorMessage, + this.errorType, + this.foodCategory, + this.iOSLink, + this.isAuthenticated, + this.mealOrderStatus, + this.mealType, + this.messageStatus, + this.numberOfResultRecords, + this.patientBlodType, + this.successMsg, + this.successMsgN, + this.vidaUpdatedResponse, + this.addAttSuccessList, + this.addAttachmentList, + this.bCDomain, + this.bCLogo, + this.basicMemberInformation, + this.businessCardPrivilege, + this.calculateAbsenceDuration, + this.cancelHRTransactionLIst, + this.chatEmployeeLoginList, + this.companyBadge, + this.companyImage, + this.companyImageDescription, + this.companyImageURL, + this.companyMainCompany, + this.countryList, + this.createVacationRuleList, + this.deleteAttachmentList, + this.deleteVacationRuleList, + this.disableSessionList, + this.employeeQR, + this.employeeDocumentsList, + this.forgetPasswordTokenID, + this.getAbsenceAttachmentsList, + this.getAbsenceAttendanceTypesList, + this.getAbsenceCollectionNotificationBodyList, + this.getAbsenceDffStructureList, + this.getAbsenceTransactionList, + this.getAccrualBalancesList, + this.getActionHistoryList, + this.getPRActionHistoryList, + this.getAddressDffStructureList, + this.getAddressNotificationBodyList, + this.getApprovesList, + this.getAttachementList, + this.getPRAttachmentList, + this.getAttendanceTrackingList, + this.getBasicDetColsStructureList, + this.getBasicDetDffStructureList, + this.getBasicDetNtfBodyList, + this.getCEICollectionNotificationBodyList, + this.getCEIDFFStructureList, + this.getCEITransactionList, + this.getCcpTransactionsList, + this.getCcpTransactionsListNew, + this.getConcurrentProgramsList, + this.getContactColsStructureList, + this.getContactDetailsList, + this.getContactDffStructureList, + this.getContactNotificationBodyList, + this.getCountriesList, + this.getDayHoursTypeDetailsList, + this.getDeductionsList, + this.getDefaultValueList, + this.getEITCollectionNotificationBodyList, + this.getEITDFFStructureList, + this.getEITTransactionList, + this.getEarningsList, + this.getEmployeeAddressList, + this.getEmployeeBasicDetailsList, + this.getEmployeeContactsList, + this.getEmployeePhonesList, + this.getEmployeeSubordinatesList, + this.getFliexfieldStructureList, + this.getHrCollectionNotificationBodyList, + this.getHrTransactionList, + this.getItemCreationNtfBodyList, + this.getItemTypeNotificationsList, + this.getItemTypesList, + this.getLookupValuesList, + this.getMenuEntriesList, + this.getEventActivityList, + this.getMoItemHistoryList, + this.getMoNotificationBodyList, + this.getNotificationButtonsList, + this.getNotificationReassignModeList, + this.getObjectValuesList, + this.getOpenMissingSwipesList, + this.getOpenNotificationsList, + this.getOpenNotificationsNumList, + this.getOpenPeriodDatesList, + this.getOrganizationsSalariesList, + this.getPaymentInformationList, + this.getPayslipList, + this.getPerformanceAppraisalList, + this.getPhonesNotificationBodyList, + this.getPoItemHistoryList, + this.getPoNotificationBodyList, + this.getPrNotificationBodyList, + this.getPaymentNotificationBodyList, + this.getPRInformationList, + this.getQuotationAnalysisList, + this.getRFCEmployeeListList, + this.getRespondAttributeValueList, + this.getSITCollectionNotificationBodyList, + this.getSITDFFStructureList, + this.getSITTransactionList, + this.getScheduleShiftsDetailsList, + this.getShiftTypesList, + this.getStampMsNotificationBodyList, + this.getStampNsNotificationBodyList, + this.getSubordinatesAttdStatusList, + this.getSubordinatesLeavesList, + this.getSubordinatesLeavesTotalVacationsList, + this.getSummaryOfPaymentList, + this.getSwipesList, + this.getTermColsStructureList, + this.getTermDffStructureList, + this.getTermNotificationBodyList, + this.getTimeCardSummaryList, + this.getTicketsByEmployeeList, + this.getTicketDetailsByEmployee, + this.getTicketTransactions, + this.getTicketTypes, + this.getSectionTopics, + this.getMowadhafhiProjects, + this.getProjectDepartments, + this.getDepartmentSections, + this.getPendingTransactionsFunctions, + this.getPendingTransactionsDetails, + this.getConcurrentProgramsModel, + this.getCCPTransactionsModel, + this.getCCPOutputModel, + this.getCCPDFFStructureModel, + this.getUserItemTypesList, + this.getVacationRulesList, + this.getVaccinationOnHandList, + this.getVaccinationsList, + this.getValueSetValuesList, + this.getWorkList, + this.hRCertificateTemplate, + this.imgURLsList, + this.insertApInv, + this.insertBooked, + this.insertEmpSwipesList, + this.insertJournal, + this.insertOrders, + this.intPortalGetEmployeeList, + this.isDeviceTokenEmpty, + this.isPasswordExpired, + this.isRegisterAllowed, + this.isRequriedValueSetEmpty, + this.isUserSMSExcluded, + this.itemOnHand, + this.languageAvailable, + this.listSupplier, + this.listUserAgreement, + this.listEITStrucrure, + this.listItemImagesDetails, + this.listItemMaster, + this.listMedicineDetails, + this.listMenu, + this.listNewEmployees, + this.listRadScreen, + this.logInTokenID, + this.memberInformationList, + this.memberLoginList, + this.mohemmGetBusinessCardEnabledList, + this.mohemmGetFavoriteReplacementsList, + this.mohemmGetMobileDeviceInfobyEmpInfoList, + this.mohemmGetMobileLoginInfoList, + this.mohemmGetPatientIDList, + this.mohemmITGResponseItem, + this.mohemmIsChangeIsActiveBusinessCardEnable, + this.mohemmIsInsertBusinessCardEnable, + this.mohemmWifiPassword, + this.mohemmWifiSSID, + this.notificationAction, + this.notificationGetRespondAttributesList, + this.notificationRespondRolesList, + this.oracleOutPutNumber, + this.pASSWORDEXPIREDMSG, + this.pCOUNTRYCODE, + this.pCOUNTRYNAME, + this.pDESCFLEXCONTEXTCODE, + this.pDESCFLEXCONTEXTNAME, + this.pForm, + this.pINFORMATION, + this.pMBLID, + this.pNUMOFSUBORDINATES, + this.pOPENNTFNUMBER, + this.pQUESTION, + this.pSESSIONID, + this.pSchema, + this.pharmacyStockAddPharmacyStockList, + this.pharmacyStockGetOnHandList, + this.privilegeList, + this.processTransactions, + this.registerUserNameList, + this.replacementList, + this.respondAttributesList, + this.respondRolesList, + this.resubmitAbsenceTransactionList, + this.resubmitEITTransactionList, + this.resubmitHrTransactionList, + this.sFHGetPoNotificationBodyList, + this.sFHGetPrNotificationBodyList, + this.startAbsenceApprovalProccess, + this.startAddressApprovalProcessList, + this.startBasicDetApprProcessList, + this.startCeiApprovalProcess, + this.startContactApprovalProcessList, + this.startEitApprovalProcess, + this.startHrApprovalProcessList, + this.startPhonesApprovalProcessList, + this.startSitApprovalProcess, + this.startTermApprovalProcessList, + this.submitAddressTransactionList, + this.submitBasicDetTransactionList, + this.submitCEITransactionList, + this.submitCcpTransactionList, + this.submitContactTransactionList, + this.submitEITTransactionList, + this.submitHrTransactionList, + this.submitPhonesTransactionList, + this.submitSITTransactionList, + this.submitTermTransactionList, + this.subordinatesOnLeavesList, + this.sumbitAbsenceTransactionList, + this.tokenID, + this.updateAttachmentList, + this.updateEmployeeImageList, + this.updateItemTypeSuccessList, + this.updateUserItemTypesList, + this.updateVacationRuleList, + this.vHREmployeeLoginList, + this.vHRGetEmployeeDetailsList, + this.vHRGetManagersDetailsList, + this.vHRGetProjectByCodeList, + this.vHRIsVerificationCodeValid, + this.validateAbsenceTransactionList, + this.validateEITTransactionList, + this.validatePhonesTransactionList, + this.vrItemTypesList, + this.wFLookUpList, + this.eLearningGETEMPLOYEEPROFILEList, + this.eLearningLOGINList, + this.eLearningValidateLoginList, + this.eLearningValidate_LoginList, + this.ePharmacyGetItemOnHandList, + this.isActiveCode, + this.isSMSSent, + }); GenericResponseModel.fromJson(Map json) { date = json['Date']; @@ -688,6 +693,7 @@ class GenericResponseModel { successMsg = json['SuccessMsg']; successMsgN = json['SuccessMsgN']; vidaUpdatedResponse = json['VidaUpdatedResponse']; + portalDirectionData = json["PortalDirectionData"] == null ? null : PortalDirectionData.fromJson(json["PortalDirectionData"]); if (json['AddAttSuccessList'] != null) { addAttSuccessList = []; @@ -848,9 +854,10 @@ class GenericResponseModel { }); } - getCEICollectionNotificationBodyList = json["GetCEICollectionNotificationBodyList"] == null - ? null - : List.from(json["GetCEICollectionNotificationBodyList"].map((x) => GetEitCollectionNotificationBodyList.fromJson(x))); + getCEICollectionNotificationBodyList = + json["GetCEICollectionNotificationBodyList"] == null + ? null + : List.from(json["GetCEICollectionNotificationBodyList"].map((x) => GetEitCollectionNotificationBodyList.fromJson(x))); if (json['GetCEIDFFStructureList'] != null) { getCEIDFFStructureList = []; @@ -909,9 +916,10 @@ class GenericResponseModel { }); } getDefaultValueList = json['GetDefaultValueList'] != null ? GetDefaultValueList.fromJson(json['GetDefaultValueList']) : null; - getEITCollectionNotificationBodyList = json["GetEITCollectionNotificationBodyList"] == null - ? null - : List.from(json["GetEITCollectionNotificationBodyList"].map((x) => GetEitCollectionNotificationBodyList.fromJson(x))); + getEITCollectionNotificationBodyList = + json["GetEITCollectionNotificationBodyList"] == null + ? null + : List.from(json["GetEITCollectionNotificationBodyList"].map((x) => GetEitCollectionNotificationBodyList.fromJson(x))); if (json['GetEITDFFStructureList'] != null) { getEITDFFStructureList = []; json['GetEITDFFStructureList'].forEach((v) { @@ -1475,6 +1483,7 @@ class GenericResponseModel { data['SuccessMsg'] = this.successMsg; data['SuccessMsgN'] = this.successMsgN; data['VidaUpdatedResponse'] = this.vidaUpdatedResponse; + data['PortalDirectionData'] = portalDirectionData?.toJson(); if (this.addAttSuccessList != null) { data['AddAttSuccessList'] = this.addAttSuccessList!.map((v) => v.toJson()).toList(); @@ -1930,3 +1939,25 @@ class GenericResponseModel { return data; } } + +class PortalDirectionData { + String? pRedirection; + String? clientID; + + PortalDirectionData({this.pRedirection, this.clientID}); + + factory PortalDirectionData.fromRawJson(String str) => PortalDirectionData.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory PortalDirectionData.fromJson(Map json) => PortalDirectionData(pRedirection: json["P_REDIRECTION"], clientID: json["ClientID"]); + + Map toJson() => {"P_REDIRECTION": pRedirection, "ClientID": clientID}; +} + + +class TicketBookingResult { + final bool success; + final String? clientId; + TicketBookingResult(this.success, this.clientId); +} \ No newline at end of file diff --git a/lib/models/sso_auth_model.dart b/lib/models/sso_auth_model.dart new file mode 100644 index 0000000..0ee9b98 --- /dev/null +++ b/lib/models/sso_auth_model.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +class SSOAuthModel { + String? status; + List? message; + Data? data; + + SSOAuthModel({ + this.status, + this.message, + this.data, + }); + + factory SSOAuthModel.fromRawJson(String str) => SSOAuthModel.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory SSOAuthModel.fromJson(Map json) => SSOAuthModel( + status: json["status"], + message: json["message"] == null ? [] : List.from(json["message"]!.map((x) => x)), + data: json["data"] == null ? null : Data.fromJson(json["data"]), + ); + + Map toJson() => { + "status": status, + "message": message == null ? [] : List.from(message!.map((x) => x)), + "data": data?.toJson(), + }; +} + +class Data { + String? accessToken; + String? idToken; + int? expiresIn; + String? refreshToken; + String? postBackUrl; + + Data({ + this.accessToken, + this.idToken, + this.expiresIn, + this.refreshToken, + this.postBackUrl, + }); + + factory Data.fromRawJson(String str) => Data.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Data.fromJson(Map json) => Data( + accessToken: json["accessToken"], + idToken: json["idToken"], + expiresIn: json["expiresIn"], + refreshToken: json["refreshToken"], + postBackUrl: json["postBackUrl"], + ); + + Map toJson() => { + "accessToken": accessToken, + "idToken": idToken, + "expiresIn": expiresIn, + "refreshToken": refreshToken, + "postBackUrl": postBackUrl, + }; +} diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 36a9f81..0dcebed 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -21,6 +21,7 @@ import 'package:mohem_flutter_app/models/dashboard/mohemm_itg_pending_task_respo import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; +import 'package:mohem_flutter_app/models/sso_auth_model.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; /// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool @@ -239,6 +240,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { homeMenus = parseMenus(getMenuEntriesList ?? []); if (homeMenus!.isNotEmpty) { homeMenus!.first.menuEntiesList.insert(0, GetMenuEntriesList(requestType: "MONTHLY_ATTENDANCE", prompt: LocaleKeys.monthlyAttendance.tr())); + // homeMenus!.first.menuEntiesList.insert(1, GetMenuEntriesList(requestType: "TICKET_BOOKING", prompt: "Ticket Booking")); homeMenus!.first.menuEntiesList.add(GetMenuEntriesList(requestType: "VACATION_RULE", prompt: LocaleKeys.vacationRule.tr())); } isServicesMenusLoading = false; @@ -283,6 +285,61 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } + Future fetchTicketBooking() async { + try { + GenericResponseModel? genericResponseModel = await DashboardApiClient().getTicketBookingRedirection(); + if (genericResponseModel?.portalDirectionData?.pRedirection!.toLowerCase() == "alma") { + return TicketBookingResult(true, genericResponseModel?.portalDirectionData?.clientID); + } + return TicketBookingResult(false, null); + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + Utils.handleException(ex, null, null); + return TicketBookingResult(false, null); // Ensure a return value in case of an exception + } + } + + Future fetchSSOAuthRedirection({String? clientID}) async { + try { + SSOAuthModel? ssoResponse = await DashboardApiClient().getBookingSSOAuthRedirection(clientID: clientID!); + logger.d("SSO Response: ${ssoResponse!.toJson()}"); + if (ssoResponse.status == "Success") { + return ssoResponse; + } else { + Utils.showToast(ssoResponse.message!.first ?? "Failed to fetch SSO Auth Token"); + return null; + } + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + Utils.handleException(ex, null, null); + return null; // Ensure a return value in case of an exception + } + } + + Future fetchURLRedirection({required String token}) async { + try { + dynamic res = await DashboardApiClient().getBookingSSOFinalRedirection(token: token); + logger.d("SSO URL: $res"); + return res; + // if (ssoResponse.status == "Success") { + // return ssoResponse; + // } else { + // Utils.showToast(ssoResponse.message!.first ?? "Failed to fetch SSO Auth Token"); + // return null; + // } + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + Utils.handleException(ex, null, null); + return null; // Ensure a return value in case of an exception + } + } + List parseMenus(List getMenuEntriesList) { List menus = []; for (int i = 0; i < getMenuEntriesList.length; i++) { @@ -316,8 +373,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return res; } - - void notify() { notifyListeners(); } diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 7c19b58..7589317 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -1,20 +1,55 @@ +import 'dart:convert'; +import 'dart:developer'; + import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_svg/svg.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/inAppWebView.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart'; +import 'package:mohem_flutter_app/models/generic_response_model.dart'; +import 'package:mohem_flutter_app/models/sso_auth_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/services_menu_list_screen.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; class ServicesWidget extends StatelessWidget { + MyInAppBrowser? myInAppBrowser; + var inAppBrowserOptions = InAppBrowserClassSettings( + webViewSettings: InAppWebViewSettings( + useShouldOverrideUrlLoading: false, + transparentBackground: false, + isInspectable: false, + applePayAPIEnabled: true, + cacheEnabled: false, + allowsBackForwardNavigationGestures: false, + ), + browserSettings: InAppBrowserSettings( + hideUrlBar: true, + hideTitleBar: true, + hideDefaultMenuItems: true, + hideToolbarBottom: true, + hideToolbarTop: false, + hideCloseButton: false, + allowGoBackWithBackButton: false, + toolbarBottomBackgroundColor: Colors.black, + closeButtonColor: Colors.white, + presentationStyle: ModalPresentationStyle.FULL_SCREEN, + // toolbarTopBackgroundColor: Colors.black + ), + ); + @override Widget build(BuildContext context) { List namesT = [LocaleKeys.monthlyAttendance.tr(), LocaleKeys.workFromHome.tr(), LocaleKeys.ticketRequest.tr(), LocaleKeys.monthlyAttendance.tr()]; @@ -26,7 +61,7 @@ class ServicesWidget extends StatelessWidget { "assets/images/vacation_rule.svg", "assets/images/ticket_request.svg", "assets/images/ticket_request.svg", - "assets/images/ticket_request.svg" + "assets/images/ticket_request.svg", ]; return Consumer( @@ -34,72 +69,69 @@ class ServicesWidget extends StatelessWidget { return data.isServicesMenusLoading ? whileLoading() : ListView.separated( - padding: const EdgeInsets.only(top: 0), - itemBuilder: (context, parentIndex) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - data.homeMenus![parentIndex].menuEntry.prompt!.toSectionHeading().paddingOnly(left: 21, right: 21), - SizedBox( - height: 105 + 26, - child: ListView.separated( - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.only(left: 21, right: 21, top: 13, bottom: 13), - scrollDirection: Axis.horizontal, - itemBuilder: (cxt, index) { - return AspectRatio( - aspectRatio: 105 / 105, - child: data.isServicesMenusLoading + padding: const EdgeInsets.only(top: 0), + itemBuilder: (context, parentIndex) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + data.homeMenus![parentIndex].menuEntry.prompt!.toSectionHeading().paddingOnly(left: 21, right: 21), + SizedBox( + height: 105 + 26, + child: ListView.separated( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.only(left: 21, right: 21, top: 13, bottom: 13), + scrollDirection: Axis.horizontal, + itemBuilder: (cxt, index) { + return AspectRatio( + aspectRatio: 105 / 105, + child: + data.isServicesMenusLoading ? ServicesMenuShimmer() : Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SvgPicture.asset(AppState().isArabic(context) + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + boxShadow: [BoxShadow(color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3))], + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + AppState().isArabic(context) ? getMenuIconAr(data.homeMenus![parentIndex].menuEntiesList[index].prompt!) - : getMenuIconEn(data.homeMenus![parentIndex].menuEntiesList[index].prompt!)), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: data.homeMenus![parentIndex].menuEntiesList[index].prompt!.toText11(isBold: true), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 10, top: 12), - ).onPress(() { - handleOnPress(context, data.homeMenus![parentIndex].menuEntiesList[index]); - }), - ); - }, - separatorBuilder: (cxt, index) => 9.width, - itemCount: data.homeMenus![parentIndex].menuEntiesList.length), + : getMenuIconEn(data.homeMenus![parentIndex].menuEntiesList[index].prompt!), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded(child: data.homeMenus![parentIndex].menuEntiesList[index].prompt!.toText11(isBold: true)), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 10, top: 12), + ).onPress(() { + handleOnPress(context, data.homeMenus![parentIndex].menuEntiesList[index]); + }), + ); + }, + separatorBuilder: (cxt, index) => 9.width, + itemCount: data.homeMenus![parentIndex].menuEntiesList.length, ), - ], - ); - }, - separatorBuilder: (context, index) { - return 12.height; - }, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: data.homeMenus!.length); + ), + ], + ); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: data.homeMenus!.length, + ); }, ); } @@ -196,7 +228,7 @@ class ServicesWidget extends StatelessWidget { return returnImage; } - void handleOnPress(context, GetMenuEntriesList menuEntry) { + Future handleOnPress(context, GetMenuEntriesList menuEntry) async { var pro = Provider.of(context, listen: false); if (menuEntry.requestType == "MONTHLY_ATTENDANCE") { Navigator.pushNamed(context, AppRoutes.monthlyAttendance); @@ -220,9 +252,87 @@ class ServicesWidget extends StatelessWidget { Navigator.pushNamed(context, AppRoutes.monthlyPaySlip); } } else { - List _menuList = - pro.getMenuEntriesList?.where((element) => element.parentMenuName == menuEntry.menuName && (element.menuEntryType == "FUNCTION" || element.menuEntryType == "MENU")).toList() ?? []; - Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(menuEntry.prompt!, _menuList.isEmpty ? menuList : _menuList)); + if (menuEntry.menuName == "HMG_TICKET_REQUESTS") { + Utils.showLoading(context); + print("========="); + TicketBookingResult response = await pro.fetchTicketBooking(); + Utils.hideLoading(context); + if (response.success) { + print("============ Allowed ============"); + SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: response.clientId); + if (ssoToken != null) { + logger.d(ssoToken.data!.toJson()); + logger.d(ssoToken.data!.accessToken); + + dynamic valu = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); + + myInAppBrowser = MyInAppBrowser( + onExitCallback: () { + log("Browser Exited"); + }, + onLoadStartCallback: (String url) { + log("Browser LoadStart for : $url"); + if (url.contains("https://ek.techmaster.in/")) { + // Handle the URL as needed + log("SSO URL Loaded: $url"); + } + }, + ); + + await myInAppBrowser!.openUrlRequest( + urlRequest: URLRequest( + url: WebUri(valu, forceToStringRawValue: true), + allowsCellularAccess: true, + allowsConstrainedNetworkAccess: true, + allowsExpensiveNetworkAccess: true, + // headers: {'Authorization': 'Bearer ${ssoToken.data!.accessToken}'}, + ), + settings: inAppBrowserOptions, + ); + + // Navigator.of(context).push( + // MaterialPageRoute( + // builder: + // (context) => WebViewWidget( + // controller: + // WebViewController() + // ..setJavaScriptMode(JavaScriptMode.unrestricted) + // ..setNavigationDelegate( + // NavigationDelegate( + // onNavigationRequest: (NavigationRequest request) { + // return NavigationDecision.navigate; + // }, + // onHttpError: (HttpResponseError response) { + // print(response.response!.statusCode); + // }, + // onProgress: (int value) { + // print(value); + // }, + // onWebResourceError: (WebResourceError error) { + // print(error.errorCode); + // print(error.description); + // }, + // ), + // ) + // ..loadRequest(Uri.parse("https://ek.techmaster.in/SSO/HMG"), headers: {'Authorization': 'Bearer ${ssoToken.data!.accessToken}'}), + // ), + // ), + // ); + + // launchUrl(Uri.parse("https://ek.techmaster.in/SSO/HMG"),headers: {'Authorization': 'Bearer ${ssoToken.data!.accessToken}'}, mode: LaunchMode.inAppBrowserView); + // ddv + print("============ Token Fetched ============"); + } + } else { + List _menuList = + pro.getMenuEntriesList?.where((element) => element.parentMenuName == menuEntry.menuName && (element.menuEntryType == "FUNCTION" || element.menuEntryType == "MENU")).toList() ?? []; + Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(menuEntry.prompt!, _menuList.isEmpty ? menuList : _menuList)); + } + } else { + List _menuList = + pro.getMenuEntriesList?.where((element) => element.parentMenuName == menuEntry.menuName && (element.menuEntryType == "FUNCTION" || element.menuEntryType == "MENU")).toList() ?? []; + Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(menuEntry.prompt!, _menuList.isEmpty ? menuList : _menuList)); + } } return; } @@ -253,10 +363,7 @@ class ServicesWidget extends StatelessWidget { padding: const EdgeInsets.only(left: 21, right: 21, top: 13, bottom: 13), scrollDirection: Axis.horizontal, itemBuilder: (cxt, index) { - return AspectRatio( - aspectRatio: 105 / 105, - child: ServicesMenuShimmer(), - ); + return AspectRatio(aspectRatio: 105 / 105, child: ServicesMenuShimmer()); }, separatorBuilder: (cxt, index) => 9.width, itemCount: 4, diff --git a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart index 30a9fa2..d791a18 100644 --- a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart +++ b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart @@ -16,7 +16,7 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:share/share.dart'; +import 'package:share_plus/share_plus.dart'; import 'package:url_launcher/url_launcher.dart'; class OffersAndDiscountsDetails extends StatefulWidget { @@ -127,7 +127,7 @@ class _OffersAndDiscountsDetailsState extends State { Directory tempDir = await getTemporaryDirectory(); File file = await File('${tempDir.path}/${DateTime.now().toString()}.png').create(); await file.writeAsBytes(pngBytes); - await Share.shareFiles([(file.path)], text: AppState().isArabic(context) ? getOffersList[0].titleAr : getOffersList[0].titleEn); + await SharePlus.instance.share(ShareParams(files: [(XFile(file.path))], text: AppState().isArabic(context) ? getOffersList[0].titleAr : getOffersList[0].titleEn)); } catch (ex) { debugPrint(ex.toString()); } @@ -155,7 +155,7 @@ class _OffersAndDiscountsDetailsState extends State { mainAxisSize: MainAxisSize.min, children: [ Hero( - tag: "ItemImage" + getOffersList.offersDiscountId.toString()!, + tag: "ItemImage" + getOffersList.offersDiscountId.toString(), transitionOnUserGestures: true, child: AspectRatio( aspectRatio: 148 / 127, diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 508ed00..ee258e1 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -24,7 +24,6 @@ import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart'; import 'package:mohem_flutter_app/widgets/qr_scanner_dialog.dart'; import 'package:nfc_manager/nfc_manager.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:platform_device_id/platform_device_id.dart'; import 'package:wifi_iot/wifi_iot.dart'; class MarkAttendanceWidget extends StatefulWidget { diff --git a/pubspec.yaml b/pubspec.yaml index 27f23f2..24bb5c2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,7 +41,7 @@ dependencies: provider: ^6.0.1 easy_localization: ^3.0.0 http: ^1.3.0 - permission_handler: ^10.2.0 + permission_handler: ^12.0.1 flutter_svg: any sizer: ^2.0.15 local_auth: ^2.3.0 @@ -50,19 +50,16 @@ dependencies: # flutter_calendar_carousel: ^2.1.0 pie_chart: ^5.1.0 shared_preferences: ^2.0.12 - firebase_messaging: ^13.0.4 + firebase_messaging: ^15.2.9 shimmer: ^2.0.0 logger: ^1.1.0 flutter_countdown_timer: ^4.1.0 - nfc_manager: ^3.2.0 - # uuid: ^3.0.6 - # device_info_plus: ^4.0.0 - # android_id: ^0.1.3+1 - platform_device_id: ^1.0.1 + + platform_device_id_plus: ^1.0.7 image_picker: ^0.8.5+3 file_picker: ^8.3.1 geolocator: ^9.0.2 - month_year_picker: ^0.4.0+1 + month_year_picker: ^0.5.0+1 month_picker_dialog: ^6.0.3 # open_file: ^3.2.1 open_filex: ^4.6.0 @@ -72,7 +69,7 @@ dependencies: qr_code_scanner: ^1.0.1 # qr_flutter: ^4.0.0 url_launcher: ^6.0.15 - share: 2.0.4 + share_plus: ^11.0.0 flutter_rating_bar: ^4.0.1 auto_size_text: ^3.0.0 pull_to_refresh: ^2.0.0 @@ -112,17 +109,27 @@ dependencies: # huawei_hmsavailability: ^6.6.0+300 # huawei_location: 6.0.0+302 huawei_location: ^6.11.0+301 - huawei_push: ^6.7.0+300 - firebase_crashlytics: ^2.9.0 +# huawei_push: ^6.7.0+300 + + huawei_map: + git: + url: https://github.com/fleoparra/hms-flutter-plugin.git + path: flutter-hms-map + huawei_push: + git: + url: https://github.com/crasowas/hms-flutter-plugin.git + path: flutter-hms-push + firebase_crashlytics: ^4.3.9 #Items for sale Image Carousel Slider carousel_slider: ^5.0.0 #Huawei Specified # store_checker: ^1.1.0 - google_api_availability: ^3.0.1 + google_api_availability: ^5.0.1 in_app_update: 4.1.0 + flutter_inappwebview: ^6.1.5 #todo its for temporary purpose, later will remove this. dotted_border: ^2.0.0+3 @@ -131,7 +138,8 @@ dependencies: dependency_overrides: - firebase_core_platform_interface: 4.5.1 + nfc_manager: ^3.2.0 +# firebase_core_platform_interface: 4.5.1 dev_dependencies: From f61817937bfc16488652c123a95a3eeaf4b0e880 Mon Sep 17 00:00:00 2001 From: Aamir Muhammad Date: Tue, 22 Jul 2025 10:31:33 +0300 Subject: [PATCH 2/3] tickt booking implementation --- lib/api/dashboard_api_client.dart | 2 +- lib/ui/landing/widget/services_widget.dart | 52 +++++++++--------- lib/widgets/sso_webview_widget.dart | 61 ++++++++++++++++++++++ pubspec.yaml | 1 + 4 files changed, 90 insertions(+), 26 deletions(-) create mode 100644 lib/widgets/sso_webview_widget.dart diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index e8a94cd..28226ce 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -179,7 +179,7 @@ class DashboardApiClient { // "ClientId": "a9f4d1a0596d4aea8f830992ec4bdac1", "PersonId": AppState().memberInformationList?.eMPLOYEENUMBER, "Username": AppState().memberInformationList?.eMPLOYEENUMBER, - "Language": "en", + "Language": "US", }; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 7589317..7bb9bd4 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -21,6 +21,7 @@ import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/services_menu_list_screen.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; +import 'package:mohem_flutter_app/widgets/sso_webview_widget.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -263,32 +264,33 @@ class ServicesWidget extends StatelessWidget { if (ssoToken != null) { logger.d(ssoToken.data!.toJson()); logger.d(ssoToken.data!.accessToken); + dynamic url = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); + Navigator.push(context, MaterialPageRoute(builder: (context) => SsoLoginWebView(url: url ?? "", jwtToken: ssoToken.data!.accessToken!))); - dynamic valu = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); - - myInAppBrowser = MyInAppBrowser( - onExitCallback: () { - log("Browser Exited"); - }, - onLoadStartCallback: (String url) { - log("Browser LoadStart for : $url"); - if (url.contains("https://ek.techmaster.in/")) { - // Handle the URL as needed - log("SSO URL Loaded: $url"); - } - }, - ); - - await myInAppBrowser!.openUrlRequest( - urlRequest: URLRequest( - url: WebUri(valu, forceToStringRawValue: true), - allowsCellularAccess: true, - allowsConstrainedNetworkAccess: true, - allowsExpensiveNetworkAccess: true, - // headers: {'Authorization': 'Bearer ${ssoToken.data!.accessToken}'}, - ), - settings: inAppBrowserOptions, - ); + // + // myInAppBrowser = MyInAppBrowser( + // onExitCallback: () { + // log("Browser Exited"); + // }, + // onLoadStartCallback: (String url) { + // log("Browser LoadStart for : $url"); + // if (url.contains("https://ek.techmaster.in/")) { + // // Handle the URL as needed + // log("SSO URL Loaded: $url"); + // } + // }, + // ); + // + // await myInAppBrowser!.openUrlRequest( + // urlRequest: URLRequest( + // url: WebUri(valu, forceToStringRawValue: true), + // allowsCellularAccess: true, + // allowsConstrainedNetworkAccess: true, + // allowsExpensiveNetworkAccess: true, + // // headers: {'Authorization': 'Bearer ${ssoToken.data!.accessToken}'}, + // ), + // settings: inAppBrowserOptions, + // ); // Navigator.of(context).push( // MaterialPageRoute( diff --git a/lib/widgets/sso_webview_widget.dart b/lib/widgets/sso_webview_widget.dart new file mode 100644 index 0000000..e5f2759 --- /dev/null +++ b/lib/widgets/sso_webview_widget.dart @@ -0,0 +1,61 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +class SsoLoginWebView extends StatefulWidget { + final String url; + final String jwtToken; + + SsoLoginWebView({required this.url, required this.jwtToken}); + + @override + State createState() => _SsoLoginWebViewState(); +} + +class _SsoLoginWebViewState extends State { + late final WebViewController _controller; + + @override + void initState() { + // TODO: implement initState + super.initState(); + _controller = + WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setNavigationDelegate( + NavigationDelegate( + onProgress: (int progress) { + print("WebView is loading (progress: $progress%)"); + }, + onPageStarted: (String url) { + print("Page started loading: $url"); + }, + onPageFinished: (String url) { + print("Page finished loading: $url"); + }, + onHttpError: (HttpResponseError error) { + print("HTTP error: ${error.toString()} for URL: ${error.response!.statusCode}"); + }, + onWebResourceError: (WebResourceError error) { + print("Web resource error: ${error.description} for URL: ${error.errorType}"); + }, + ), + ) + ..loadHtmlString(''' + + + +
+ +
+

Redirecting...

+ +'''); + } + + @override + Widget build(BuildContext context) { + return Scaffold(appBar: AppBar(title: Text('Logging in...')), body: WebViewWidget(controller: _controller)); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 24bb5c2..54d313f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -133,6 +133,7 @@ dependencies: #todo its for temporary purpose, later will remove this. dotted_border: ^2.0.0+3 + webview_flutter: ^4.13.0 # saf: ^1.0.3+4 From 515ffef14ea72653273cb4fd08239729a635990d Mon Sep 17 00:00:00 2001 From: Aamir Muhammad Date: Tue, 22 Jul 2025 10:32:21 +0300 Subject: [PATCH 3/3] tickt booking implementation --- lib/ui/landing/widget/services_widget.dart | 60 ---------------------- 1 file changed, 60 deletions(-) diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 7bb9bd4..7d2c2b2 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -255,75 +255,15 @@ class ServicesWidget extends StatelessWidget { } else { if (menuEntry.menuName == "HMG_TICKET_REQUESTS") { Utils.showLoading(context); - print("========="); TicketBookingResult response = await pro.fetchTicketBooking(); Utils.hideLoading(context); if (response.success) { - print("============ Allowed ============"); SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: response.clientId); if (ssoToken != null) { logger.d(ssoToken.data!.toJson()); logger.d(ssoToken.data!.accessToken); dynamic url = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); Navigator.push(context, MaterialPageRoute(builder: (context) => SsoLoginWebView(url: url ?? "", jwtToken: ssoToken.data!.accessToken!))); - - // - // myInAppBrowser = MyInAppBrowser( - // onExitCallback: () { - // log("Browser Exited"); - // }, - // onLoadStartCallback: (String url) { - // log("Browser LoadStart for : $url"); - // if (url.contains("https://ek.techmaster.in/")) { - // // Handle the URL as needed - // log("SSO URL Loaded: $url"); - // } - // }, - // ); - // - // await myInAppBrowser!.openUrlRequest( - // urlRequest: URLRequest( - // url: WebUri(valu, forceToStringRawValue: true), - // allowsCellularAccess: true, - // allowsConstrainedNetworkAccess: true, - // allowsExpensiveNetworkAccess: true, - // // headers: {'Authorization': 'Bearer ${ssoToken.data!.accessToken}'}, - // ), - // settings: inAppBrowserOptions, - // ); - - // Navigator.of(context).push( - // MaterialPageRoute( - // builder: - // (context) => WebViewWidget( - // controller: - // WebViewController() - // ..setJavaScriptMode(JavaScriptMode.unrestricted) - // ..setNavigationDelegate( - // NavigationDelegate( - // onNavigationRequest: (NavigationRequest request) { - // return NavigationDecision.navigate; - // }, - // onHttpError: (HttpResponseError response) { - // print(response.response!.statusCode); - // }, - // onProgress: (int value) { - // print(value); - // }, - // onWebResourceError: (WebResourceError error) { - // print(error.errorCode); - // print(error.description); - // }, - // ), - // ) - // ..loadRequest(Uri.parse("https://ek.techmaster.in/SSO/HMG"), headers: {'Authorization': 'Bearer ${ssoToken.data!.accessToken}'}), - // ), - // ), - // ); - - // launchUrl(Uri.parse("https://ek.techmaster.in/SSO/HMG"),headers: {'Authorization': 'Bearer ${ssoToken.data!.accessToken}'}, mode: LaunchMode.inAppBrowserView); - // ddv - print("============ Token Fetched ============"); } } else { List _menuList =