diff --git a/android/app/build.gradle b/android/app/build.gradle index 92ec20d..0236a3b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,35 +1,12 @@ plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' - id "dev.flutter.flutter-gradle-plugin" + id "com.android.application" + id "kotlin-android" id "com.google.gms.google-services" -// id "com.huawei.agconnect" //todo this will be done - -} - - -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.") -} + 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') @@ -37,27 +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 { - namespace 'hmg.cloudSolutions.mohem' - compileSdkVersion 35 - - defaultConfig { - multiDexEnabled true - } - compileOptions { - // Flag to enable support for the new language APIs - coreLibraryDesugaringEnabled true - // Sets Java compatibility to Java 8 - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } +android { + namespace 'hmg.cloudSolutions.mohem' + compileSdk 36 kotlinOptions { jvmTarget = '1.8' @@ -70,11 +31,12 @@ 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 35 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + minSdkVersion 30 + targetSdk = flutter.targetSdkVersion + versionCode flutter.versionCode + versionName flutter.versionName } + buildFeatures{ buildConfig true } @@ -106,57 +68,5 @@ flutter { dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2' -// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.1.20" } - - -def targetProjects = ["huawei_push", "in_app_update", "qr_code_scanner"] - -subprojects { - afterEvaluate { subproject -> - if (targetProjects.contains(subproject.name) && subproject.extensions.findByName("android") != null) { - // Register the fix task only for target projects - def fixTask = subproject.tasks.register("fixManifestsAndNamespace") { - doLast { - def buildGradleFile = file("build.gradle") - def manifestFile = file("src/main/AndroidManifest.xml") - - // Step 1: Set namespace from package if not already present - if (manifestFile.exists()) { - def manifestContent = manifestFile.getText("UTF-8") - def matcher = (manifestContent =~ /package\s*=\s*"([^"]+)"/) - def packageName = matcher.find() ? matcher.group(1) : null - - if (packageName != null && !buildGradleFile.getText().contains("namespace")) { - println "Setting namespace in ${buildGradleFile.path}" - def updatedBuildGradle = buildGradleFile.getText().replaceFirst( - /android\s*\{/, - "android {\n namespace = \"${packageName}\"" - ) - buildGradleFile.write(updatedBuildGradle, "UTF-8") - } - } - - // Step 2: Remove `package` from all AndroidManifest.xml files in the project - def manifestFiles = fileTree("src/main") { - include "**/AndroidManifest.xml" - } - - manifestFiles.each { file -> - def content = file.getText() - if (content.contains("package=")) { - println "Removing package attribute from ${file.path}" - def updated = content.replaceAll(/package\s*=\s*"[^"]*"/, "") - file.write(updated) - } - } - } - } - - // Ensure the task runs before preBuild - subproject.tasks.matching { it.name.startsWith("preBuild") }.configureEach { - dependsOn fixTask - } - } - } -} \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 7536277..c1b6ff6 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,6 +1,6 @@ //buildscript { -// ext.kotlin_version = '`1.9.10' -// repositories {` +// ext.kotlin_version = '1.9.10' +// repositories { // google() // mavenCentral() // maven { url 'https://developer.huawei.com/repo/' } @@ -14,21 +14,97 @@ // 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" + } + } + + // Exclude old BouncyCastle globally to avoid duplicate classes + configurations.all { + exclude group: 'org.bouncycastle', module: 'bcprov-jdk16' + } + + 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 69c440c..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 7a00584..941ceb1 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Jul 09 13:30:59 AST 2025 +#Tue Jul 08 11:08:34 AST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-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 3a4691e..f29151d 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -7,6 +7,7 @@ pluginManagement { return flutterSdkPath }() + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") repositories { @@ -14,27 +15,31 @@ pluginManagement { mavenCentral() gradlePluginPortal() maven { url 'https://developer.huawei.com/repo/' } + } - resolutionStrategy { - eachPlugin { - if (requested.id.id == "com.huawei.agconnect") { - //https://flutter.dev/go/flutter-gradle-plugin-apply - //https://forums.developer.huawei.com/forumPortal/en/topic/0201148914110187023 - //https://stackoverflow.com/questions/78339717/huawei-agcp-plugin-cannot-be-applied - useModule("com.huawei.agconnect:agcp:1.9.1.304") + + 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 'com.android.application' version "8.3.2" apply false - id 'dev.flutter.flutter-plugin-loader' version "1.0.0" // apply true - id "org.jetbrains.kotlin.android" version "2.0.0" apply false - id "com.google.gms.google-services" version "4.4.0" apply false -// id "com.google.gms.google-services" version "4.4.0" apply false - id "com.huawei.agconnect" version "1.9.1.304" apply false -// classpath 'com.huawei.agconnect:agcp:1.8.0.300' + 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 + id("com.huawei.agconnect") version "1.9.1.304" apply false + } -include ":app" \ No newline at end of file +include ":app" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 98a3328..d990020 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -144,6 +144,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, C4CFBC4C5CAC00182015ACD5 /* [CP] Embed Pods Frameworks */, + EF29CE25BB57F5AA48CE1136 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -241,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; 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 5908de4..b2ee4c2 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -2,6 +2,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:http/http.dart' as http; import 'package:device_info_plus/device_info_plus.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; @@ -14,6 +16,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: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:platform_device_id/platform_device_id.dart'; @@ -155,6 +159,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": "US", + }; + 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 9753744..be3f840 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -3,16 +3,10 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; class ApiConsts { // static String baseUrl = "http://10.200.204.11"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - // 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 - // static String baseUrl = "https://mohemm.hmg.com"; - // static String baseUrl = "https://hmgwebservices.com"; // 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.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 @@ -20,7 +14,7 @@ class ApiConsts { // 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 + // static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://mohemm.hmg.com"; // static String baseUrl = "https://hmgwebservices.com"; // Live server @@ -33,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/"; @@ -72,6 +68,8 @@ class ApiConsts { static String marathonGetMarathonersCount = marathonBaseUrl + "Participant/GetRemainingParticipants"; static String marathonGetTutorial = marathonBaseUrl + "tutorial/GetTutorialNotification"; + + //DummyCards for the UI static int tabletMinLength = 500; 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 e644aa0..fc53773 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 319c36d..7d2c2b2 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -229,7 +229,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); @@ -253,9 +253,28 @@ 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); + TicketBookingResult response = await pro.fetchTicketBooking(); + Utils.hideLoading(context); + if (response.success) { + 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!))); + } + } 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; } @@ -286,10 +305,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 c2fc9b8..70eecd2 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 @@ -128,12 +128,7 @@ class _OffersAndDiscountsDetailsState extends State { Directory tempDir = await getTemporaryDirectory(); File file = await File('${tempDir.path}/${DateTime.now().toString()}.png').create(); await file.writeAsBytes(pngBytes); - - var params = ShareParams( - text: AppState().isArabic(context) ? getOffersList[0].titleAr : getOffersList[0].titleEn, - files: [XFile('${tempDir.path}/${DateTime.now().toString()}.png')], - ); - await SharePlus.instance.share(params); + await SharePlus.instance.share(ShareParams(files: [(XFile(file.path))], text: AppState().isArabic(context) ? getOffersList[0].titleAr : getOffersList[0].titleEn)); } catch (ex) { debugPrint(ex.toString()); } @@ -161,7 +156,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 f5c8fb0..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/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 03634cb..084364a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,12 +16,11 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html - -version: 3.6.6+300076 -#version: 3.8.999+2 +#version: 3.3.01+300040 +version: 3.7.98+3 environment: - sdk: ">=3.0.0 <4.0.0" + sdk: ^3.7.0 # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -42,10 +41,10 @@ dependencies: provider: ^6.0.1 easy_localization: ^3.0.0 http: ^1.4.0 - permission_handler: ^10.2.0 + permission_handler: ^12.0.1 flutter_svg: any sizer: ^2.0.15 - local_auth: ^2.2.0 + local_auth: ^2.3.0 fluttertoast: ^8.0.8 syncfusion_flutter_calendar: ^29.1.38 # flutter_calendar_carousel: ^2.1.0 @@ -55,20 +54,16 @@ dependencies: 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 device_info_plus: ^9.0.0 image_picker: ^0.8.5+3 - file_picker: 8.1.3 - geolocator: ^11.1.0 - month_year_picker: ^0.4.0+1 + file_picker: ^8.3.1 + geolocator: ^9.0.2 + month_year_picker: ^0.5.0+1 month_picker_dialog: ^6.0.3 -# month_picker_dialog: ^6.2.3 - # open_file: ^3.2.1 - open_filex: ^4.4.0 +# open_file: ^3.2.1 + open_filex: ^4.6.0 wifi_iot: ^0.3.19+1 flutter_html: ^3.0.0-alpha.6 mobile_scanner: ^6.0.10 @@ -80,7 +75,7 @@ dependencies: flutter_rating_bar: ^4.0.1 auto_size_text: ^3.0.0 pull_to_refresh: ^2.0.0 - fl_chart: ^0.66.0 + fl_chart: ^0.70.2 # lottie json animations lottie: any # Marathon Card Swipe @@ -89,19 +84,19 @@ dependencies: safe_device: ^1.1.9 # networkImage -# cached_network_image: ^3.2.2 + cached_network_image: ^3.2.2 #Chat signalr_netcore: ^1.3.3 logging: ^1.0.1 swipe_to: ^1.0.2 - flutter_webrtc: ^0.9.17 + flutter_webrtc: ^0.12.11 camera: ^0.10.3 - flutter_local_notifications: ^18.0.0 + flutter_local_notifications: ^18.0.1 #firebase_analytics: any #Chat Voice Message Recoding & Play - audio_waveforms: ^1.3.0 + audio_waveforms: ^0.1.5+1 rxdart: ^0.27.7 #Encryption @@ -114,12 +109,17 @@ dependencies: #Huawei Dependencies # huawei_hmsavailability: ^6.6.0+300 - # huawei_location: 6.0.0+302 +# huawei_location: 6.0.0+302 huawei_location: ^6.11.0+301 -# huawei_push: ^6.13.0+300 - huawei_push: +# 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 @@ -130,18 +130,21 @@ dependencies: # store_checker: ^1.1.0 google_api_availability: ^5.0.1 google_maps_flutter_web: ^0.5.4 - in_app_update: 4.2.3 - cached_network_image: ^3.3.0 # or newer - flutter_blurhash: ^0.8.0 # + in_app_update: 4.1.0 + flutter_inappwebview: ^6.1.5 + flutter_blurhash: ^0.8.0 + #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 -#dependency_overrides: +dependency_overrides: + nfc_manager: ^3.2.0 # firebase_core_platform_interface: 4.5.1 -# cached_network_image: ^3.2.0 + dev_dependencies: flutter_test: @@ -237,4 +240,4 @@ flutter: # see https://flutter.dev/custom-fonts/#from-packages -# Adding this to test the push from iMac \ No newline at end of file +# Adding this to test the push from iMac