diff --git a/.vscode/settings.json b/.vscode/settings.json index af7c712..6558ca6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "cSpell.words": [ "MPLOYEEIMAGE" - ] + ], + "java.configuration.updateBuildConfiguration": "disabled" } \ No newline at end of file diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/100.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/100.png new file mode 100644 index 0000000..8583b24 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/100.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/1024.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000..fffa7bf Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/114.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/114.png new file mode 100644 index 0000000..ba1ac90 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/114.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/120.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000..3adedb4 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/144.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/144.png new file mode 100644 index 0000000..2dd8969 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/144.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/152.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000..3e1f94e Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/167.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000..7ee129e Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/180.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 0000000..ad74bdc Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/20.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/20.png new file mode 100644 index 0000000..1d84d69 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/29.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000..c9f0362 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/40.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000..b6f2d2d Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/50.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/50.png new file mode 100644 index 0000000..01ececa Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/50.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/57.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/57.png new file mode 100644 index 0000000..feda456 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/57.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/58.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000..0f1dd24 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/60.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000..889d976 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/72.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/72.png new file mode 100644 index 0000000..4aab906 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/72.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/76.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/76.png new file mode 100644 index 0000000..b04a92f Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/80.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 0000000..86e69f2 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/87.png b/AppIcons/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000..6110508 Binary files /dev/null and b/AppIcons/Assets.xcassets/AppIcon.appiconset/87.png differ diff --git a/AppIcons/Assets.xcassets/AppIcon.appiconset/Contents.json b/AppIcons/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..65b74d7 --- /dev/null +++ b/AppIcons/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1 @@ +{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} \ No newline at end of file diff --git a/AppIcons/appstore.png b/AppIcons/appstore.png new file mode 100644 index 0000000..fffa7bf Binary files /dev/null and b/AppIcons/appstore.png differ diff --git a/AppIcons/playstore.png b/AppIcons/playstore.png new file mode 100644 index 0000000..b34ffe6 Binary files /dev/null and b/AppIcons/playstore.png differ diff --git a/android/agconnect-services.json b/android/agconnect-services.json new file mode 100644 index 0000000..20a7546 --- /dev/null +++ b/android/agconnect-services.json @@ -0,0 +1,57 @@ +{ + "agcgw_all":{ + "CN":"connect-drcn.dbankcloud.cn", + "CN_back":"connect-drcn.hispace.hicloud.com", + "DE":"connect-dre.dbankcloud.cn", + "DE_back":"connect-dre.hispace.hicloud.com", + "RU":"connect-drru.hispace.dbankcloud.ru", + "RU_back":"connect-drru.hispace.dbankcloud.cn", + "SG":"connect-dra.dbankcloud.cn", + "SG_back":"connect-dra.hispace.hicloud.com" + }, + "websocketgw_all":{ + "CN":"connect-ws-drcn.hispace.dbankcloud.cn", + "CN_back":"connect-ws-drcn.hispace.dbankcloud.com", + "DE":"connect-ws-dre.hispace.dbankcloud.cn", + "DE_back":"connect-ws-dre.hispace.dbankcloud.com", + "RU":"connect-ws-drru.hispace.dbankcloud.ru", + "RU_back":"connect-ws-drru.hispace.dbankcloud.cn", + "SG":"connect-ws-dra.hispace.dbankcloud.cn", + "SG_back":"connect-ws-dra.hispace.dbankcloud.com" + }, + "client":{ + "cp_id":"2640966000002322881", + "product_id":"737518067793559971", + "client_id":"715996003571874624", + "client_secret":"B5B89A56A53847C6BB9D216A8747E75952760DF9A8232239D8744CD847A8FFDA", + "project_id":"737518067793559971", + "app_id":"104737117", + "api_key":"DAEDACKDrYgyco9mjPV9ZUjCSh1kCr/GBV0nseHH0z2mnxlZ41RksOKmyTi+PUTwmGEPK+VxCup4F9oUf4VbDnCsjB7aNBShYcjR+g==", + "package_name":"hmg.cloudSolutions.mohem" + }, + "oauth_client":{ + "client_id":"104737117", + "client_type":1 + }, + "app_info":{ + "app_id":"104737117", + "package_name":"hmg.cloudSolutions.mohem" + }, + "configuration_version":"3.0", + "appInfos":[ + { + "package_name":"hmg.cloudSolutions.mohem", + "client":{ + "app_id":"104737117" + }, + "app_info":{ + "package_name":"hmg.cloudSolutions.mohem", + "app_id":"104737117" + }, + "oauth_client":{ + "client_type":1, + "client_id":"104737117" + } + } + ] +} \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 5279c1f..1901f3a 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.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' +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" + id "com.huawei.agconnect" } -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,13 @@ 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 33 + namespace 'hmg.cloudSolutions.mohem' + compileSdk 36 + ndkVersion '28.2.13676358' - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } kotlinOptions { jvmTarget = '1.8' @@ -52,10 +33,20 @@ 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 33 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + minSdkVersion 30 + targetSdk 35 + targetSdk = flutter.targetSdkVersion + versionCode flutter.versionCode + versionName flutter.versionName + multiDexEnabled true + } + + compileOptions { + coreLibraryDesugaringEnabled true + } + + buildFeatures{ + buildConfig true } signingConfigs { @@ -84,5 +75,10 @@ flutter { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.1.20" + implementation 'androidx.multidex:multidex:2.0.1' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' + implementation 'com.huawei.hms:push:6.11.0.300' + + } diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 50ab38d..443c7bf 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,5 @@ + > diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 3f5e424..6d2f83f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,13 +1,26 @@ + xmlns:tools="http://schemas.android.com/tools" + > - + - + + + + + + + + + + + @@ -20,10 +33,21 @@ + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml index 50ab38d..443c7bf 100644 --- a/android/app/src/profile/AndroidManifest.xml +++ b/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,5 @@ + > diff --git a/android/build.gradle b/android/build.gradle index 5effa33..8a97f51 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,4 @@ buildscript { - ext.kotlin_version = '1.7.20' repositories { google() mavenCentral() @@ -7,10 +6,10 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.0.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.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10" + classpath 'com.google.gms:google-services:4.3.15' + classpath 'com.huawei.agconnect:agcp:1.9.1.304' } } @@ -20,14 +19,66 @@ allprojects { mavenCentral() maven { url 'https://developer.huawei.com/repo/' } } + + // 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 2260f45..8df3fe9 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,7 @@ -org.gradle.jvmargs=-Xmx1836M +org.gradle.jvmargs=-Xmx4096m +kotlin.daemon.jvmargs=-Xmx4096m android.useAndroidX=true android.enableJetifier=true +apmsInstrumentationEnabled=false + +#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 2f8758c..941ceb1 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 23 08:50:38 CEST 2017 +#Tue Jul 08 11:08:34 AST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip \ No newline at end of file diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bc..10a4a8d 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,56 @@ -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/' } + } + + resolutionStrategy { + eachPlugin { + if (requested.id.id == "com.huawei.agconnect") { + useModule("com.huawei.agconnect:agcp:1.9.1.304") + } + } + } + +} + + +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 + id "com.huawei.agconnect" version "1.9.1.304" apply false +} + + +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + maven { url 'https://developer.huawei.com/repo/' } + maven { + url "https://artifactory.ess-dev.com/artifactory/gradle-dev-local" + } + } +} + + + +include ":app" diff --git a/assets/icons/itg/alert.svg b/assets/icons/itg/alert.svg new file mode 100644 index 0000000..6f0f0ca --- /dev/null +++ b/assets/icons/itg/alert.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/itg/calendar-remove.svg b/assets/icons/itg/calendar-remove.svg new file mode 100644 index 0000000..965a40c --- /dev/null +++ b/assets/icons/itg/calendar-remove.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/itg/calendar.svg b/assets/icons/itg/calendar.svg new file mode 100644 index 0000000..2ac497c --- /dev/null +++ b/assets/icons/itg/calendar.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/icons/itg/coming-soon.svg b/assets/icons/itg/coming-soon.svg new file mode 100644 index 0000000..52d5ffc --- /dev/null +++ b/assets/icons/itg/coming-soon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/itg/finger-print-remove.svg b/assets/icons/itg/finger-print-remove.svg new file mode 100644 index 0000000..bc6fe65 --- /dev/null +++ b/assets/icons/itg/finger-print-remove.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/itg/knight-shield.svg b/assets/icons/itg/knight-shield.svg new file mode 100644 index 0000000..e0bf799 --- /dev/null +++ b/assets/icons/itg/knight-shield.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/itg/money-not-found.svg b/assets/icons/itg/money-not-found.svg new file mode 100644 index 0000000..01121a6 --- /dev/null +++ b/assets/icons/itg/money-not-found.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/itg/stethoscope.svg b/assets/icons/itg/stethoscope.svg new file mode 100644 index 0000000..31c4638 --- /dev/null +++ b/assets/icons/itg/stethoscope.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/itg/time-quarter-pass.svg b/assets/icons/itg/time-quarter-pass.svg new file mode 100644 index 0000000..5a8a758 --- /dev/null +++ b/assets/icons/itg/time-quarter-pass.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/icons/itg/time-quarter.svg b/assets/icons/itg/time-quarter.svg new file mode 100644 index 0000000..7eaf056 --- /dev/null +++ b/assets/icons/itg/time-quarter.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/icons/mazaya_brand.svg b/assets/icons/mazaya_brand.svg new file mode 100755 index 0000000..52fb265 --- /dev/null +++ b/assets/icons/mazaya_brand.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/images/EID_ARABIC_3.svg b/assets/images/EID_ARABIC_3.svg new file mode 100644 index 0000000..483a836 --- /dev/null +++ b/assets/images/EID_ARABIC_3.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/EID_Englsih_04.svg b/assets/images/EID_Englsih_04.svg new file mode 100644 index 0000000..c2a75b5 --- /dev/null +++ b/assets/images/EID_Englsih_04.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/images/asddasd.svg b/assets/images/asddasd.svg new file mode 100644 index 0000000..b91a675 --- /dev/null +++ b/assets/images/asddasd.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/images/biometrics.svg b/assets/images/biometrics.svg new file mode 100644 index 0000000..5d61575 --- /dev/null +++ b/assets/images/biometrics.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/drawer/car_parking_icon.svg b/assets/images/drawer/car_parking_icon.svg new file mode 100644 index 0000000..f77afa0 --- /dev/null +++ b/assets/images/drawer/car_parking_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/drawer/courses.svg b/assets/images/drawer/courses.svg new file mode 100644 index 0000000..d15e742 --- /dev/null +++ b/assets/images/drawer/courses.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/eid_banner.svg b/assets/images/eid_banner.svg new file mode 100644 index 0000000..f8e4adb --- /dev/null +++ b/assets/images/eid_banner.svg @@ -0,0 +1,606 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/xcellent.svg b/assets/images/excellent.svg similarity index 100% rename from assets/images/xcellent.svg rename to assets/images/excellent.svg diff --git a/assets/images/bad.svg b/assets/images/fair.svg similarity index 100% rename from assets/images/bad.svg rename to assets/images/fair.svg diff --git a/assets/images/greeting.svg b/assets/images/greeting.svg new file mode 100644 index 0000000..0682c60 --- /dev/null +++ b/assets/images/greeting.svg @@ -0,0 +1,605 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/logos/loading_mohemm_logo.gif b/assets/images/logos/loading_mohemm_logo.gif index ffefdb0..eb8b36f 100644 Binary files a/assets/images/logos/loading_mohemm_logo.gif and b/assets/images/logos/loading_mohemm_logo.gif differ diff --git a/assets/images/logos/loading_mohemm_logo_old.gif b/assets/images/logos/loading_mohemm_logo_old.gif new file mode 100644 index 0000000..ffefdb0 Binary files /dev/null and b/assets/images/logos/loading_mohemm_logo_old.gif differ diff --git a/assets/images/logos/main_mohemm_logo.png b/assets/images/logos/main_mohemm_logo.png index 5536c07..8ea04aa 100644 Binary files a/assets/images/logos/main_mohemm_logo.png and b/assets/images/logos/main_mohemm_logo.png differ diff --git a/assets/images/logos/main_mohemm_logo_old.png b/assets/images/logos/main_mohemm_logo_old.png new file mode 100644 index 0000000..5536c07 Binary files /dev/null and b/assets/images/logos/main_mohemm_logo_old.png differ diff --git a/assets/images/normal.svg b/assets/images/ok.svg similarity index 100% rename from assets/images/normal.svg rename to assets/images/ok.svg diff --git a/assets/images/ticket_bal.svg b/assets/images/ticket_bal.svg new file mode 100644 index 0000000..8fadde8 --- /dev/null +++ b/assets/images/ticket_bal.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/vacation_rule.svg b/assets/images/vacation_rule.svg new file mode 100644 index 0000000..0a536f7 --- /dev/null +++ b/assets/images/vacation_rule.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/images/worklist/approve.svg b/assets/images/worklist/approve.svg new file mode 100644 index 0000000..8d62ae9 --- /dev/null +++ b/assets/images/worklist/approve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/worklist/reject.svg b/assets/images/worklist/reject.svg new file mode 100644 index 0000000..cb5da34 --- /dev/null +++ b/assets/images/worklist/reject.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 8ff0ea3..f3552d5 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -4,7 +4,10 @@ "arabic": "عربي", "login": "تسجيل الدخول", "pleaseEnterLoginDetails": "الرجاء إدخال التفاصيل أدناه لتسجيل الدخول", + "userId": "UserID", "username": "اسم المستخدم", + "userName": "اسم المستخدم", + "userSearch": "User Search", "password": "كلمة المرور", "welcomeBack": "مرحبا بعودتك", "wouldYouLikeToLoginWithCurrentUsername": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟", @@ -88,7 +91,7 @@ "atLeastOneNumeric": "رقم واحد على الأقل", "minimum8Characters": "8 أحرف على الأقل", "doNotAddRepeatingLetters": "لا تقم بإضافة أحرف متكررة", - "itShouldContainSpecialCharacter": "يجب أن يحتوي على طابع خاص", + "itShouldContainSpecialCharacter": "يجب لا يحتوي على أحرف خاصة", "confirmPasswordMustMatch": "يجب أن يتطابق تأكيد كلمة المرور", "sms": "رسالة قصيرة", "fingerPrint": "بصمة", @@ -97,6 +100,7 @@ "reject": "يرفض", "approve": "يوافق", "cancel": "إلغاء", + "generate": "يولد", "requestedItems": "العناصر المطلوبة", "request": "طلب", "myRequest": "طلبي", @@ -160,6 +164,7 @@ "quotationAnalysis": "تحليل الاقتباس", "subject": "موضوعات", "description": "وصف", + "pleaseEnterDescription": "الرجاء إدخال الوصف", "supplier": "المورد", "site": "موقع", "buyer": "مشتر", @@ -254,6 +259,7 @@ "fullName": "الأسم الكامل", "remove": "حذف", "submit": "ارسال", + "submitAsAnonymous": "إرسال كمجهول", "areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟", "comments": "تعليقات", "writeComment": "أكتب تعليقا", @@ -527,7 +533,7 @@ "noWinner": "حزين! لم يفز أحد اليوم.", "myTeam": "فريقي", "youCanPlayDemo": "لكن يمكنك لعب العرض", - "group" : "مجموعة", + "group": "مجموعة", "searchGroup": "مجموعة البحث", "connectHmgWifi": "قم بتوصيل HMG WIFI", "connectedHmgWifi": "اتصال HMG WIFI", @@ -542,5 +548,128 @@ "uploadedDocuments": "المستندات التي تم تحميلها", "addAtLeastOneAttachment": "الرجاء إضافة مرفق واحد على الأقل.", "pleaseClickButtonToJoinMarathon": "الرجاء الضغط على الزر أدناه للانضمام إلى الماراثون", - "youCannotJoinTheMarathon": "لا يمكنك الانضمام إلى الماراثون لأنك تجاوزت الحد الزمني" -} \ No newline at end of file + "youCannotJoinTheMarathon": "لا يمكنك الانضمام إلى الماراثون لأنك تجاوزت الحد الزمني", + "open": "يفتح", + "youCannotJoinTheMarathon": "لا يمكنك الانضمام إلى الماراثون لأنك تجاوزت الحد الزمني", + "pleaseClickButtonToJoinMarathon": "الرجاء الضغط على الزر أدناه للانضمام إلى الماراثون", + "generate": "يولد", + "paymentRequest": "طلب الدفع", + "paymentDetails": "تفاصيل الدفع", + "requestNo": "رقم الطلب", + "requesterEmpNum": "رقم الموظف الذي قدم الطلب", + "requesterEmpName": "اسم الموظف مقدم الطلب", + "prepareEmpName": "إعداد اسم الموظف", + "requesterPositionName": "اسم الوظيفة لمقدم الطلب", + "preparePositionName": "إعداد اسم الوظيفة", + "requesterPayrollName": "اسم مقدم الطلب", + "payingORGName": "اسم المنظمة الدافعة", + "requestAmount": "مبلغ الطلب", + "typeofPayment": "نوع الدفع", + "beneficiaryDetails": "تفاصيل المستفيد", + "beneficiaryName": "اسم المستفيد", + "idIqama": "الهوية السعودية / الإقامة", + "beneficiaryBankName": "اسم البنك المستفيد", + "sadadNumber": "رقم سداد", + "beneficiaryIBAN": "رقم IBAN للمستفيد", + "purchaseOrders": "طلبات الشراء", + "approvalDate": "تاريخ الموافقة", + "pOAmount": "مبلغ الطلب", + "versionStatus": "حالة الإصدار", + "supplierNo": "رقم المورد", + "general": "عام", + "requesterOperatingUnit": "وحدة تشغيل مقدم الطلب", + "prepareEmpNum": "إعداد رقم الموظف", + "supplierInfo": "معلومات المورد", + "supplierAcNo": "رقم حساب المورد", + "supplierAcName": "اسم حساب المورد", + "supplierIBAN": "رقم IBAN للمورد", + "supplierCRNo": "رقم السجل التجاري", + "suppliedAcNo": "رقم الحساب المقدم", + "patientRefundInvoice": "فاتورة استرداد الأموال للمريض", + "patientNumber": "رقم المريض", + "patientName": "اسم المريض", + "invoiceDate": "تاريخ الفاتورة", + "refundInvoice": "فاتورة الاسترجاع", + "hospitalClinic": "عيادة المستشفى", + "graphicalAnalysis": "التحليل الرسومي", + "itemHistoryAnalysis": "تحليل تاريخ العنصر", + "pOno": "امر شراء #", + "oprUnit": "وحدة التشغيل", + "qtyOrdered": "الكمية المطلوبة", + "qtyReceived": "الكمية المستلمة", + "bonusQty": "كمية المكافأة", + "balQty": "كمية التوازن", + "videoCall": "مكالمة فيديو", + "addUsers": "إضافة مستخدمين إلى المجموعة", + "admin": "مشرف", + "areYouSureWantTodelete": "هل أنت متأكد أنك تريد الحذف؟", + "Attendance": "الحضور", + "audioCall": "مكالمة صوتية", + "editGroups": "تعديل المجموعة", + "enterGroupName": "يرجى إدخال اسم المجموعة الصحيح", + "enterGroupNamePlease": "يرجى إدخال اسم المجموعة", + "groupMembers": "أعضاء المجموعة", + "groupName": "اسم المجموعة", + "groupNameshouldbe": "يجب أن يتكون اسم المجموعة من 10 أحرف على الأقل", + "manage": "إدارة", + "manageGroup": "إدارة المجموعة", + "members": "الأعضاء", + "searchByUserName": "البحث بواسطة اسم المستخدم", + "shareScreen": "مشاركة الشاشة", + "start": "يبدأ", + "about": "عن", + "explore": "يستكشف", + "mazaya": "مازيا", + "benefits": "فوائد", + "mazayaDesc": "اكتشف الخصومات والعروض الخاصة المتاحة للموظفين", + "viewallofferMazaya": "أعرض كل المزايا", + "buyerName": "اسم المشتري", + "buyerNumber": "رقم المشتري", + "highestBidder": "أعلى مزايد", + "remarks": "ملاحظات", + "faHeader": "تفاصيل رأس الصفحة FA", + "bookTypeCode": "رمز نوع الكتاب", + "categoryCode": "رمز الفئة", + "categoryGroup": "مجموعة الفئات", + "faLINES": "تفاصيل الأصول", + "assetNumber": "رقم الأصول", + "assetDescription": "وصف الأصول", + "barCodeNumber": "رقم الباركود", + "datePlaceInService": "تاريخ وضعه في الخدمة", + "serialNumber": "رقم سري", + "disposedDate": "تاريخ التخلص", + "netBookValue": "القيمة الدفترية الصافية", + "purchasedPrice": "سعر الشراء", + "usefulLife": "العمر الإنتاجي", + "yearsUsed": "سنوات الاستخدام", + "faRequest": "طلب التخلص من FA", + "showMore": "عرض المزيد", + "ticketDetails": "تفاصيل التذكرة", + "currentTicketBalance": "رصيد التذكرة الحالي", + "ticketHistory": "تاريخ التذكرة", + "proceedBooking": "المتابعة للحجز", + "courses": "الدورات التدريبية", + "course": "دورة", + "status": "الحالة", + "deadline": "الموعد النهائي", + "overdue": "متأخر", + "noCoursesAvailable": "لا توجد دورات متاحة", + "pullToRefresh": "اسحب للتحديث", + "courseUrlNotAvailable": "رابط الدورة غير متوفر", + "buyerDetails": "تفاصيل المشتري", + "etqanOVR": "الإبلاغ عن حادثة", + "etqanRequest": "طلبات الحوادث", + "selectProject": "حدد المشروع", + "project": "مشروع", + "keen": "حريص", + "reportIncident": "الإبلاغ عن الحادث", + "myIncidents": "حوادثي", + "incidentDetails": "تفاصيل الحادث", + "ticketNumber": "رقم التذكرة", + "ticketId": "معرف التذكرة", + "pleaseSelectProject": "الرجاء اختيار مشروع", + "viewAttachment" : "عرض المرفق", + "parkingQr": "وقوف السيارات QR", + "startNow": "ابدأ الآن" +} + diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 2449802..a227a73 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -85,7 +85,7 @@ "atLeastOneNumeric": "At least one numeric", "minimum8Characters": "Minimum 8 characters", "doNotAddRepeatingLetters": "Do not add repeating letters", - "itShouldContainSpecialCharacter": "It should contain special character", + "itShouldContainSpecialCharacter": "It should not contain special characters", "confirmPasswordMustMatch": "Confirm password must match", "sms": "SMS", "fingerPrint": "Fingerprint", @@ -93,6 +93,7 @@ "whatsapp": "Whatsapp", "reject": "Reject", "approve": "Approve", + "generate": "Generate", "cancel": "Cancel", "requestedItems": "Requested Items", "request": "Request", @@ -157,6 +158,7 @@ "subject": "Subject", "quotationAnalysis": "Quotation Analysis", "description": "Description", + "pleaseEnterDescription": "Please enter description", "supplier": "Supplier", "site": "Site", "buyer": "Buyer", @@ -255,6 +257,7 @@ "remove": "Remove", "Attendance": "Attendance", "submit": "Submit", + "submitAsAnonymous": "Submit as Anonymous", "areYouSureYouWantToSubmit": "Are you sure you want to submit?", "comments": "Comments", "writeComment": "Write a comment", @@ -302,6 +305,7 @@ "section": "Section", "topic": "Topic", "actionBy": "Action By", + "pending": "Pending", "pendingTransactions": "Pending Transactions", "selectRequestType": "Please select request type", "dateFrom": "Date From", @@ -547,7 +551,7 @@ "manageGroup": "Manage Group", "admin": "Admin", "addUsers": "Add users to the group", - "editGroups":"Edit Group", + "editGroups": "Edit Group", "groupNameshouldbe": "Group name should be minimum 10 character long", "enterGroupName": "Please enter valid group Name", "groupName": "Group Name", @@ -559,7 +563,110 @@ "userSearch": "User Search", "userName": "User Name", "userId": "UserID", + "open": "open", "addAtLeastOneAttachment": "Please add at least one attachment.", "pleaseClickButtonToJoinMarathon": "Press the button below to join the Marathon.", - "youCannotJoinTheMarathon": "You cannot join the Marathon because you have exceeded the time limit." + "youCannotJoinTheMarathon": "You cannot join the Marathon because you have exceeded the time limit.", + "requesterOperatingUnit": "Requester Operating Unit", + "generate": "Generate", + "paymentRequest": "Pay Request", + "paymentDetails": "Payment Details", + "requestNo": "Request No", + "requesterEmpNum": "Requester Employee Num", + "requesterEmpName": "Requester Employee Name", + "prepareEmpName": "Prepare Employee Name", + "requesterPositionName": "Requester Position Name", + "preparePositionName": "Prepare Position Name", + "requesterPayrollName": "Requester Payroll Name", + "payingORGName": "Paying Organization Name", + "requestAmount": "Request Amount", + "typeofPayment": "Type of Payment", + "beneficiaryDetails": "Beneficiary Details", + "beneficiaryName": "Beneficiary Name", + "idIqama": "Saudi ID / Iqama", + "beneficiaryBankName": "Beneficiary Bank Name", + "sadadNumber": "Sadad Number", + "beneficiaryIBAN": "Beneficiary IBAN", + "purchaseOrders": "Purchase Orders", + "approvalDate": "Approval Date", + "pOAmount": "PO Amount", + "versionStatus": "Version Status", + "supplierNo": "Supplier No", + "general": "General", + "prepareEmpNum": "Prepare Employee Num", + "supplierInfo": "Supplier Information", + "supplierAcNo": "Supplier Account No", + "supplierAcName": "Supplier Account Name", + "supplierIBAN": "Supplier IBAN", + "supplierCRNo": "CR Number", + "suppliedAcNo": "Supplied Account No.", + "patientRefundInvoice": "Patient Refund Invoice", + "patientNumber": "Patient Number", + "patientName": "Patient Name", + "invoiceDate": "Invoice Date", + "refundInvoice": "Refund Invoice", + "hospitalClinic": "Hospital Clinic", + "graphicalAnalysis": "Graphical Analysis", + "itemHistoryAnalysis": "Item History Analysis", + "pOno": "P.O #", + "oprUnit": "Opr. Unit", + "qtyOrdered": "Qty. Ordered", + "qtyReceived": "Qty. Received", + "bonusQty": "Bonus Qty.", + "balQty": "Bal. Qty.", + "start": "Start", + "about": "About", + "explore": "Explore", + "mazaya": "MAZAYA", + "benefits": "Benefits", + "mazayaDesc": "Discover special Discounts and offers available to Employees", + "viewallofferMazaya": "View All Offers", + "buyerName": "Buyer Name", + "buyerNumber": "Buyer Number", + "highestBidder": "Highest Bidder", + "remarks": "Remarks", + "faHeader": "FA Header Details", + "bookTypeCode": "Book Type Code", + "categoryCode": "Category Code", + "categoryGroup": "Category Group", + "faLINES": "Asset Details", + "assetNumber": "Asset Number", + "assetDescription": "Asset Description", + "barCodeNumber": "BarCode Number", + "datePlaceInService": "Date place In Service", + "serialNumber": "Serial Number", + "disposedDate": "Disposed Date", + "netBookValue": "Net Book Value", + "purchasedPrice": "Purchased Price", + "usefulLife": "Useful Life", + "yearsUsed": "Years Used", + "faRequest": "FA Disposal Request", + "showMore": "Show More", + "ticketDetails": "Ticket Details", + "currentTicketBalance": "Current Ticket Balance", + "ticketHistory": "Ticket History", + "proceedBooking": "Proceed For Booking", + "courses": "Courses", + "course": "Course", + "status": "Status", + "deadline": "Deadline", + "overdue": "Overdue", + "noCoursesAvailable": "No Courses Available", + "pullToRefresh": "Pull to refresh", + "courseUrlNotAvailable": "Course URL not available", + "buyerDetails": "Buyer Details", + "etqanOVR": "Report An Incident", + "etqanRequest": "Incident Requests", + "selectProject": "Select Project", + "project": "Project", + "keen": "Keen", + "reportIncident": "Report Incident", + "myIncidents": "My Incidents", + "incidentDetails": "Incident Details", + "ticketNumber": "Ticket Number", + "ticketId": "Ticket ID", + "pleaseSelectProject": "Please select a project", + "viewAttachment" : "View Attachment", + "parkingQr": "Parking QR", + "startNow": "Start Now" } \ No newline at end of file diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 9625e10..7c56964 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 073c15f..6aac74d 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 = ( ); @@ -160,7 +161,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -232,6 +233,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -240,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; @@ -362,6 +381,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; @@ -371,12 +391,12 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.7.2; + MARKETING_VERSION = 3.7.95; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.mohemm; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -500,6 +520,7 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; @@ -509,12 +530,12 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.7.2; + MARKETING_VERSION = 3.7.95; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.mohemm; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -530,6 +551,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; @@ -539,12 +561,12 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.7.2; + MARKETING_VERSION = 3.7.95; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.mohemm; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a..9c12df5 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index b4ad5b3..be22807 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -4,7 +4,7 @@ import Firebase import flutter_local_notifications -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index e83c3bf..65b74d7 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,128 +1 @@ -{ - "images":[ - { - "idiom":"iphone", - "size":"20x20", - "scale":"2x", - "filename":"Icon-App-20x20@2x.png" - }, - { - "idiom":"iphone", - "size":"20x20", - "scale":"3x", - "filename":"Icon-App-20x20@3x.png" - }, - { - "idiom":"iphone", - "size":"29x29", - "scale":"1x", - "filename":"Icon-App-29x29@1x.png" - }, - { - "idiom":"iphone", - "size":"29x29", - "scale":"2x", - "filename":"Icon-App-29x29@2x.png" - }, - { - "idiom":"iphone", - "size":"29x29", - "scale":"3x", - "filename":"Icon-App-29x29@3x.png" - }, - { - "idiom":"iphone", - "size":"40x40", - "scale":"2x", - "filename":"Icon-App-40x40@2x.png" - }, - { - "idiom":"iphone", - "size":"40x40", - "scale":"3x", - "filename":"Icon-App-40x40@3x.png" - }, - { - "idiom":"iphone", - "size":"60x60", - "scale":"2x", - "filename":"Icon-App-60x60@2x.png" - }, - { - "idiom":"iphone", - "size":"60x60", - "scale":"3x", - "filename":"Icon-App-60x60@3x.png" - }, - { - "idiom":"iphone", - "size":"76x76", - "scale":"2x", - "filename":"Icon-App-76x76@2x.png" - }, - { - "idiom":"ipad", - "size":"20x20", - "scale":"1x", - "filename":"Icon-App-20x20@1x.png" - }, - { - "idiom":"ipad", - "size":"20x20", - "scale":"2x", - "filename":"Icon-App-20x20@2x.png" - }, - { - "idiom":"ipad", - "size":"29x29", - "scale":"1x", - "filename":"Icon-App-29x29@1x.png" - }, - { - "idiom":"ipad", - "size":"29x29", - "scale":"2x", - "filename":"Icon-App-29x29@2x.png" - }, - { - "idiom":"ipad", - "size":"40x40", - "scale":"1x", - "filename":"Icon-App-40x40@1x.png" - }, - { - "idiom":"ipad", - "size":"40x40", - "scale":"2x", - "filename":"Icon-App-40x40@2x.png" - }, - { - "idiom":"ipad", - "size":"76x76", - "scale":"1x", - "filename":"Icon-App-76x76@1x.png" - }, - { - "idiom":"ipad", - "size":"76x76", - "scale":"2x", - "filename":"Icon-App-76x76@2x.png" - }, - { - "idiom":"ipad", - "size":"83.5x83.5", - "scale":"2x", - "filename":"Icon-App-83.5x83.5@2x.png" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "scale" : "1x", - "filename" : "ItunesArtwork@2x.png" - } - ], - "info":{ - "version":1, - "author":"easyappicon" - } -} +{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index cb62b88..51a5801 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -13,7 +13,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - MOHEMM + MoheM CFBundlePackageType APPL CFBundleShortVersionString @@ -61,6 +61,8 @@ This app requires photo library access to select image as document & upload it. UIApplicationSupportsIndirectInputEvents + NSSpeechRecognitionUsageDescription + This app requires speech recognition access to access voice command features. UIBackgroundModes fetch diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index 3fbe57c..91fd28a 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -6,6 +6,8 @@ import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:http/io_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/exceptions/api_exception.dart'; import 'package:mohem_flutter_app/main.dart'; // ignore_for_file: avoid_annotating_with_dynamic @@ -13,16 +15,17 @@ import 'package:mohem_flutter_app/main.dart'; typedef FactoryConstructor = U Function(dynamic); class APIError { - int? errorCode; + dynamic errorCode; int? errorType; String? errorMessage; - - APIError(this.errorCode, this.errorMessage, this.errorType); + int? errorStatusCode; + APIError(this.errorCode, this.errorMessage, this.errorType, this.errorStatusCode); Map toJson() => { 'errorCode': errorCode, 'errorMessage': errorMessage, 'errorType': errorType, + 'ErrorStatusCode': errorStatusCode }; @override @@ -38,14 +41,14 @@ APIException _throwAPIException(Response response) { if (response.body != null && response.body.isNotEmpty) { var jsonError = jsonDecode(response.body); print(jsonError); - apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType']); + apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'], jsonError['ErrorStatusCode']); } return APIException(APIException.BAD_REQUEST, error: apiError); case 400: APIError? apiError; if (response.body != null && response.body.isNotEmpty) { var jsonError = jsonDecode(response.body); - apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType']); + apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'],jsonError['ErrorStatusCode']); } return APIException(APIException.BAD_REQUEST, error: apiError); case 401: @@ -85,6 +88,7 @@ class ApiClient { var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes, isFormData: isFormData); try { if (!kReleaseMode) { + logger.i("Url: " + url); logger.i("res: " + response.body); } @@ -92,11 +96,20 @@ class ApiClient { if (jsonData["IsAuthenticated"] != null) { AppState().setIsAuthenticated = jsonData["IsAuthenticated"]; } + + // if(url.contains("GetOfferDiscountsConfigData")) { + // jsonData["ErrorMessage"] = "Service Not Available"; + // jsonData["ErrorEndUserMessage"] = "Service Not Available"; + // } + if (jsonData["ErrorMessage"] == null) { return factoryConstructor(jsonData); - } else { + } else if (jsonData["MessageStatus"] == 2 && jsonData["IsOTPMaxLimitExceed"] == true) { + await Utils.performLogout(AppRoutes.navigatorKey.currentContext, null); + throw const APIException(APIException.UNAUTHORIZED, error: null); + } else { APIError? apiError; - apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage'], jsonData['ErrorType'] ?? 0); + apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage'], jsonData['ErrorType'] ?? 0, jsonData['ErrorStatusCode']); throw APIException(APIException.BAD_REQUEST, error: apiError); } } catch (ex) { @@ -146,7 +159,7 @@ class ApiClient { } var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 120)); - if (response.statusCode >= 200 && response.statusCode < 300) { + if (response. statusCode >= 200 && response.statusCode < 300) { return response; } else { throw _throwAPIException(response); diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index d077026..a9667ec 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -28,7 +28,8 @@ class ChatApiClient { factory ChatApiClient() => _instance; Future getUserLoginToken() async { - user.UserAutoLoginModel userLoginResponse = user.UserAutoLoginModel(); + user.UserAutoLoginModel userLoginResponse = user.UserAutoLoginModel(); + String? deviceToken = AppState().getIsHuawei ? AppState().getHuaweiPushToken : AppState().getDeviceToken; Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatLoginTokenUrl}externaluserlogin", { @@ -38,6 +39,7 @@ class ChatApiClient { "platform": Platform.isIOS ? "ios" : "android", "deviceToken": AppState().getIsHuawei ? AppState().getHuaweiPushToken : AppState().getDeviceToken, "isHuaweiDevice": AppState().getIsHuawei, + "voipToken": Platform.isIOS ? "80a3b01fc1ef2453eb4f1daa4fc31d8142d9cb67baf848e91350b607971fe2ba" : "", }, ); @@ -143,14 +145,14 @@ class ChatApiClient { } // Upload Chat Media - Future uploadMedia(String userId, File file) async { + Future uploadMedia(String userId, File file, String fileSource) async { if (kDebugMode) { print("${ApiConsts.chatMediaImageUploadUrl}upload"); print(AppState().chatDetails!.response!.token); } dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatMediaImageUploadUrl}upload')); - request.fields.addAll({'userId': userId, 'fileSource': '1'}); + request.fields.addAll({'userId': userId, 'fileSource': fileSource}); request.files.add(await MultipartFile.fromPath('files', file.path)); request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'}); StreamedResponse response = await request.send(); @@ -162,10 +164,10 @@ class ChatApiClient { } // Download File For Chat - Future downloadURL({required String fileName, required String fileTypeDescription}) async { + Future downloadURL({required String fileName, required String fileTypeDescription, required int fileSource}) async { Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatMediaImageUploadUrl}download", - {"fileType": fileTypeDescription, "fileName": fileName, "fileSource": 1}, + {"fileType": fileTypeDescription, "fileName": fileName, "fileSource": fileSource}, token: AppState().chatDetails!.response!.token, ); Uint8List data = Uint8List.fromList(response.bodyBytes); diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 77cc37d..87025f2 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -1,18 +1,28 @@ 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:mobile_device_identifier/mobile_device_identifier.dart'; 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'; import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; +import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart'; import 'package:mohem_flutter_app/models/dashboard/list_menu.dart'; +import 'package:mohem_flutter_app/models/dashboard/courses_response_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; +import 'package:mohem_flutter_app/models/get_employee_parking_details_model.dart'; +import 'package:mohem_flutter_app/models/greetings/greeting_card_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:uuid/uuid.dart'; class DashboardApiClient { @@ -26,40 +36,56 @@ class DashboardApiClient { String url = "${ApiConsts.erpRest}GET_Attendance_Tracking"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getAttendanceTrackingList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAttendanceTrackingList; + }, + url, + postParams, + ); } Future getOpenNotifications() async { String url = "${ApiConsts.erpRest}GET_OPEN_NOTIFICATIONS"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future getCOCNotifications() async { String url = "${ApiConsts.cocRest}Mohemm_ITG_ReviewerAdmin_Pending_Tasks"; Map postParams = {"Date": DateUtil.getISODateFormat(DateTime.now()), "EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future getItgFormsPendingTask() async { String url = "${ApiConsts.cocRest}ITGFormsPendingTasks"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future> getAccrualBalances(String effectiveDate, {String? empID}) async { @@ -67,20 +93,43 @@ class DashboardApiClient { Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; postParams.addAll(AppState().postParamsJson); if (empID != null) postParams["P_SELECTED_EMPLOYEE_NUMBER"] = empID; - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getAccrualBalancesList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAccrualBalancesList ?? []; + }, + url, + postParams, + ); + } + + Future> getTicketAccuralBalance(String effectiveDate, {String? empID}) async { + String url = "${ApiConsts.erpRest}GET_TICKET_ACCRUAL_BALANCES"; + Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; + postParams.addAll(AppState().postParamsJson); + if (empID != null) postParams["P_SELECTED_EMPLOYEE_NUMBER"] = empID; + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAccrualBalancesTicketList ?? []; + }, + url, + postParams, + ); } Future getOpenMissingSwipes() async { String url = "${ApiConsts.erpRest}GET_OPEN_MISSING_SWIPES"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } //Menus List @@ -88,10 +137,14 @@ class DashboardApiClient { String url = "${ApiConsts.erpRest}GET_MENU"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.listMenu ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.listMenu ?? []; + }, + url, + postParams, + ); } //GET_MENU_ENTRIES @@ -99,20 +152,129 @@ class DashboardApiClient { String url = "${ApiConsts.erpRest}GET_MENU_ENTRIES"; Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E"}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); + } + + Future getEventActivity() async { + String url = "${ApiConsts.erpRest}Get_EventActivity"; + Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E"}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); + } + + 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 getTicketBalance() async { + String url = "${ApiConsts.erpRest}GET_TICKET_BALANCE"; + 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", + "SessionId": AppState().postParamsObject?.pSessionId, + }; + 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')); + var request = http.MultipartRequest('POST', Uri.parse('https://Paxes-release.techmaster.in/SSO/HMG')); // UAT + // var request = http.MultipartRequest('POST', Uri.parse('https://paxes.com/sso/hmg')); // Prod + 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", String? long = "0", required int pointType, String nfcValue = "", bool isGpsRequired = false, String QRValue = ""}) async { + Future markAttendance({ + String lat = "0", + String? long = "0", + required int pointType, + String nfcValue = "", + bool isGpsRequired = false, + String QRValue = "", + String payrollCode = "", + }) async { + var _mobileDeviceIdentifierPlugin = MobileDeviceIdentifier(); + Codec stringToBase64 = utf8.fuse(base64); String url = "${ApiConsts.swpRest}AuthenticateAndSwipeUserSupportNFC"; var uuid = Uuid(); + String? deviceId = ""; // Generate a v4 (random) id - + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo; + deviceId = await _mobileDeviceIdentifierPlugin.getDeviceId() ?? androidInfo.id; + deviceId = stringToBase64.encode(deviceId); + deviceId = deviceId.length >= 50 ? deviceId.substring(0, 48) : deviceId; + } else if (Platform.isIOS) { + IosDeviceInfo iosInfo = await DeviceInfoPlugin().iosInfo; + deviceId = iosInfo.identifierForVendor; + } Map postParams = { - "UID": await PlatformDeviceId.getDeviceId, //uuid.v4(), //Mobile Id + "UID": deviceId, //uuid.v4(), //Mobile Id // "UID": uuid.v4(), //Mobile Id "Latitude": lat, "Longitude": long, @@ -120,13 +282,18 @@ class DashboardApiClient { "PointType": pointType, // NFC=2, Wifi = 3, QR= 1, "NFCValue": nfcValue, "WifiValue": pointType == 3 ? "100" : "", - "IsGpsRequired": isGpsRequired + "IsGpsRequired": isGpsRequired, + "PayrollCodeStr": AppState().postParamsObject?.payrollCodeStr.toString() ?? "", }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } //Mark Fake Location @@ -145,10 +312,14 @@ class DashboardApiClient { "EmployeeID": AppState().memberInformationList!.eMPLOYEENUMBER, }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } //Check ITG Type @@ -158,15 +329,19 @@ class DashboardApiClient { Map postParams = { "EmployeeNumber": AppState().getUserName, "ItgEnableAt": "After Service Submission", //Mobile Id - "ItgServiceName": "Login" + "ItgServiceName": "Login", }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - MohemmItgResponseItem res = MohemmItgResponseItem.fromJson(jsonDecode(responseData.mohemmITGResponseItem ?? "")); - // var jsonDecodedData = jsonDecode(jsonDecode(responseData.mohemmITGResponseItem!)['result']['data']); - return res; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + MohemmItgResponseItem res = MohemmItgResponseItem.fromJson(jsonDecode(responseData.mohemmITGResponseItem ?? "")); + // var jsonDecodedData = jsonDecode(jsonDecode(responseData.mohemmITGResponseItem!)['result']['data']); + return res; + }, + url, + postParams, + ); } //Submit ITG @@ -178,13 +353,17 @@ class DashboardApiClient { "ItgComments": comment, "ItgNotificationMasterId": masterId, "ItgQuestionResponses": itgList, - "ItgSurveyId": serviceId + "ItgSurveyId": serviceId, }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgMainRes responseData = ItgMainRes.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgMainRes responseData = ItgMainRes.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future getAdvertisementDetail(String masterID) async { @@ -195,10 +374,14 @@ class DashboardApiClient { "ItgNotificationMasterId": masterID, //Mobile Id }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgMainRes responseData = ItgMainRes.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgMainRes responseData = ItgMainRes.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future setAdvertisementViewed(String masterID, int advertisementId, String? ackValue) async { @@ -212,9 +395,80 @@ class DashboardApiClient { // "ItgAdvertisement": {"ItgAdvertisementId": advertisementId, "ItgAcknowledgment": ackValue} //Mobile Id }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - // ItgMainRes responseData = ItgMainRes.fromJson(json); - return json; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + // ItgMainRes responseData = ItgMainRes.fromJson(json); + return json; + }, + url, + postParams, + ); + } + + // Future getItgTimeCardDetails() async { + // String url = "${ApiConsts.cocRest}ITG_TimeCard_Get"; + // Map postParams = {}; + // postParams.addAll(AppState().postParamsJson); + // return await ApiClient().postJsonForObject( + // (json) { + // ItgTimeCardModel responseData = ItgTimeCardModel.fromJson(json); + // return responseData; + // }, + // url, + // postParams, + // ); + // } + + Future getEmployeeParkingQrCode() async { + String url = "${ApiConsts.erpRest}GET_Employee_Parking"; + Map postParams = {}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GetEmployeeParking responseData = GetEmployeeParking.fromJson(json); + return responseData; + }, + url, + postParams, + ); + } + + //Fetch All Courses Status + Future fetchAllCoursesStatus() async { + String url = "https://elearning.hmg.com/moodle_dev/api/Fetch_All_Courses_Status.php"; + + Map headers = { + 'x-api-key': 'bLi@mbXJeXTHd/)h&LFh%25+%25(Nbnaq6hBg%7d%5dyQbthY%7bv6ew6-5UT\$NASwucn%7d,_PSJpuwNCCen2%7djj%7b00HR2T-%5b,k7W%7d-0yepK?%258', + 'Content-Type': 'application/x-www-form-urlencoded', + }; + + Map postParams = { + "username": AppState().memberInformationList?.eMPLOYEENUMBER ?? "", + }; + + return await ApiClient().postJsonForObject( + (json) { + CoursesResponseModel responseData = CoursesResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + headers: headers, + isFormData: false, + ); + } + + Future getGreetingCards() async { + String url = "${ApiConsts.erpRest}Get_GreetingCards"; + Map postParams = {}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GetGreetingCardsModelResponse responseData = GetGreetingCardsModelResponse.fromJson(json); + return responseData; + }, + url, + postParams, + ); } } diff --git a/lib/api/eit_api_client.dart b/lib/api/eit_api_client.dart index 9e4f292..d473aaf 100644 --- a/lib/api/eit_api_client.dart +++ b/lib/api/eit_api_client.dart @@ -19,13 +19,26 @@ class EITApiClient { factory EITApiClient() => _instance; - Future?> getEITTransactions(String functionName) async { + Future getEITTransactions(String functionName, {bool isCompleteList = false}) async { String url = "${ApiConsts.erpRest}GET_EIT_TRANSACTIONS"; Map postParams = {'P_FUNCTION_NAME': functionName, "P_MENU_TYPE": "E", "P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - List? responseData = GetEitTransactionsModel.fromJson(json['GetEITTransactionList'][0]).collectionTransaction; - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + if (isCompleteList) { + List> responseData = []; + json['GetEITTransactionList'].forEach((element) { + var transactionList = GetEitTransactionsModel.fromJson(element).collectionTransaction; + if (transactionList != null) responseData.add(transactionList); + }); + return responseData; + } else { + List? responseData = GetEitTransactionsModel.fromJson(json['GetEITTransactionList'][0]).collectionTransaction; + return responseData; + } + }, + url, + postParams, + ); } } diff --git a/lib/api/etqan_ovr_api_client.dart b/lib/api/etqan_ovr_api_client.dart new file mode 100644 index 0000000..f7512cc --- /dev/null +++ b/lib/api/etqan_ovr_api_client.dart @@ -0,0 +1,140 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; +import 'package:intl/intl.dart'; +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'; +import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_employee_incident_report.dart'; +import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_requests_model.dart'; +import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart'; +import 'package:mohem_flutter_app/models/generic_response_model.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_department_sections.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_project_departments.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_projects.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_section_topics.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_details.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_types.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_tickets_list.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_transaction_attachment_model.dart'; + +class EtqanApiClient { + static final EtqanApiClient _instance = EtqanApiClient._internal(); + + EtqanApiClient._internal(); + + factory EtqanApiClient() => _instance; + + Future> getEtqanProjects() async { + String url = "${ApiConsts.cocRest}ETQAN_GetProjects"; + Map postParams = {"P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + List? responseData = []; + if (json["ETQAN_GetProjects_Response"] != null && json["ETQAN_GetProjects_Response"].isNotEmpty) { + json["ETQAN_GetProjects_Response"].forEach((element) { + responseData.add(EtqanGetProjectsResponse.fromJson(element)); + }); + } + return responseData; + }, + url, + postParams, + ); + } + + Future> getEmployeeEtqanRequests() async { + String url = "${ApiConsts.cocRest}ETQAN_GetEmployeeOVRRequests"; + Map postParams = { + "ETQAN_EmployeeID": AppState().memberInformationList?.eMPLOYEENUMBER, + "P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER, + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + List responseData = []; + if (json["ETQAN_GetEmployeeOVRRequests_Response"] != null && json["ETQAN_GetEmployeeOVRRequests_Response"].isNotEmpty) { + json["ETQAN_GetEmployeeOVRRequests_Response"].forEach((element) { + responseData.add(EtqanGetEmployeeOvrRequestsResponse.fromJson(element)); + }); + } + + if (responseData.isNotEmpty) { + responseData.sort((EtqanGetEmployeeOvrRequestsResponse a, EtqanGetEmployeeOvrRequestsResponse b) { + if (a.createdDate == null && b.createdDate == null) return 0; + if (a.createdDate == null) return 1; + if (b.createdDate == null) return -1; + + try { + // Parse dates in format "26-Feb-2026 12:54 PM" or "01-Mar-2026 02:45 PM" + DateFormat dateFormat = DateFormat("dd-MMM-yyyy hh:mm a", "en_US"); + DateTime dateA = dateFormat.parse(a.createdDate!); + DateTime dateB = dateFormat.parse(b.createdDate!); + return dateB.compareTo(dateA); // Descending order (newest first) + } catch (e) { + return (b.createdDate ?? '').compareTo(a.createdDate ?? ''); + } + }); + } + return responseData; + }, + url, + postParams, + ); + } + + Future> getEtqanIncidentRequests(String ticketNo) async { + String url = "${ApiConsts.cocRest}ETQAN_GetIncidentRequest"; + Map postParams = {"ETQAN_TicketNumber": ticketNo, "P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + List responseData = []; + if (json["ETQAN_GetIncidentRequest_Response"] != null && json["ETQAN_GetIncidentRequest_Response"].isNotEmpty) { + json["ETQAN_GetIncidentRequest_Response"].forEach((element) { + responseData.add(EtqanGetIncidentRequestResponse.fromJson(element)); + }); + } + return responseData; + }, + url, + postParams, + ); + } + + Future?> createRequest(String description, int? projectID, String? attachmentBase64, bool? isAnonymous) async { + String url = "${ApiConsts.cocRest}ETQAN_CreateIncident"; + Map postParams = { + "P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER, + "P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER, + "ETQAN_Emp_EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER, + "ETQAN_Description": description, + "ETQAN_ProjectId": projectID, + "ETQAN_FileInfoBase64": attachmentBase64, + "ETQAN_IsAnonymous": isAnonymous ?? false, + }; + + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + if (json["ETQAN_CreateIncident_Response"] != null) { + var response = json["ETQAN_CreateIncident_Response"]; + if (response["id"] != null && response["ticketNumber"] != null) { + return {"id": response["id"], "ticketNumber": response["ticketNumber"]}; + } + return null; + } + return null; + + // "ETQAN_CreateIncident_Response": { + // "id": "00adabe4-4a32-4b35-1f00-08de4d152e7c", + // "ticketNumber": "OVR/OLY/2026/224" + // }, + }, + url, + postParams, + ); + } +} diff --git a/lib/api/marathon/marathon_api_client.dart b/lib/api/marathon/marathon_api_client.dart index 428e586..d9021c6 100644 --- a/lib/api/marathon/marathon_api_client.dart +++ b/lib/api/marathon/marathon_api_client.dart @@ -11,6 +11,7 @@ import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_generic_model.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; import 'package:mohem_flutter_app/models/marathon/question_model.dart'; +import 'package:mohem_flutter_app/models/marathon/tutorial_notification_model.dart'; import 'package:mohem_flutter_app/models/marathon/winner_model.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:provider/provider.dart'; @@ -195,6 +196,24 @@ class MarathonApiClient { return null; } + Future getMarathonTutorial() async { + Response response = await ApiClient().getJsonForResponse( + // ApiConsts.marathonGetTutorial, + "https://marathoon.com/uatservice/api/tutorial/GetTutorialNotification", + token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken, + ); + try { + MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(jsonDecode(response.body)); + if (marathonModel.data is List) { + return TutorialNotificationModel.fromJson(marathonModel.data[0]); + } + } catch (ex) { + print(ex); + } + + return null; + } + // late HubConnection hubConnection; // Future buildHubConnection(BuildContext context, String prizeId) async { // HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); diff --git a/lib/api/mowadhafhi/mowadhafhi_api_client.dart b/lib/api/mowadhafhi/mowadhafhi_api_client.dart index e5ecc4b..d724c67 100644 --- a/lib/api/mowadhafhi/mowadhafhi_api_client.dart +++ b/lib/api/mowadhafhi/mowadhafhi_api_client.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + 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'; @@ -10,6 +12,7 @@ import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_details.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_types.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_tickets_list.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_transaction_attachment_model.dart'; class MowadhafhiApiClient { static final MowadhafhiApiClient _instance = MowadhafhiApiClient._internal(); @@ -51,6 +54,18 @@ class MowadhafhiApiClient { }, url, postParams); } + Future getTransactionAttachments(int? attachmentID) async { + String url = "${ApiConsts.cocRest}Mohemm_ITG_GetTicketAttachment"; + Map postParams = {"EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER, "ItgAttachmentId": attachmentID}; + + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + var jsonDecodedData = jsonDecode(responseData.mohemmITGResponseItem!); + return GetTransactionAttachmentModel.fromJson(jsonDecodedData); + }, url, postParams); + } + Future> getTicketTypes() async { String url = "${ApiConsts.cocRest}Mohemm_ITG_GetTicketTypes"; Map postParams = {"EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER}; diff --git a/lib/api/my_attendance_api_client.dart b/lib/api/my_attendance_api_client.dart index 78742a3..3978c2d 100644 --- a/lib/api/my_attendance_api_client.dart +++ b/lib/api/my_attendance_api_client.dart @@ -29,6 +29,21 @@ class MyAttendanceApiClient { }, url, postParams); } + Future?> getCeiTransaction(String pFunctionName, int? relationID) async { + String url = "${ApiConsts.erpRest}GET_CEI_TRANSACTIONS"; + Map postParams = {"P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1, "P_FUNCTION_NAME": pFunctionName}; + postParams.addAll(AppState().postParamsJson); + if (relationID != null) postParams["P_CONTACT_RELATIONSHIP_ID"] = relationID; + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + if (responseData.getCEITransactionList?.isNotEmpty ?? false) { + return responseData.getCEITransactionList!.map((e) => GetEITTransactionList(collectionTransaction: e.collectionTransaction)).toList(); + } else { + return []; + } + }, url, postParams); + } + Future getEitDffStructure(String pFunctionName, String? empID) async { String url = "${ApiConsts.erpRest}GET_EIT_DFF_STRUCTURE"; Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E", "P_FUNCTION_NAME": pFunctionName}; @@ -40,14 +55,55 @@ class MyAttendanceApiClient { }, url, postParams); } - Future> getValueSetValues(String pSegmentName, String pDescFlexContextCode, String pDescFlexName, List> list, {String? empID, String? parentValue}) async { + Future getCEIDffStructure(String pFunctionName, String? empID) async { + String url = "${ApiConsts.erpRest}GET_CEI_DFF_STRUCTURE"; + Map postParams = {"P_FUNCTION_NAME": pFunctionName}; + postParams.addAll(AppState().postParamsJson); + if (empID != null) postParams["P_SELECTED_EMPLOYEE_NUMBER"] = empID; + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + return responseData; + }, url, postParams); + } + + Future> getValueSetValues(String pSegmentName, String pDescFlexContextCode, String pDescFlexName, List> list, + {String? empID, String? parentValue, bool hasParent = false}) async { String url = "${ApiConsts.erpRest}GET_VALUE_SET_VALUES"; Map postParams = { "P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E", "P_PAGE_LIMIT": 1000, "P_PAGE_NUM": 1, - "P_PARENT_VALUE": empID != null ? parentValue : null, + "P_PARENT_VALUE": hasParent + ? parentValue + : empID != null + ? parentValue + : null, + "P_SEGMENT_NAME": pSegmentName, + "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, + "P_DESC_FLEX_NAME": pDescFlexName, + "GetValueSetValuesTBL": list, + }; + postParams.addAll(AppState().postParamsJson); + if (empID != null) postParams["P_SELECTED_EMPLOYEE_NUMBER"] = empID; + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + return responseData.getValueSetValuesList ?? []; + }, url, postParams); + } + Future> getValueSetValuesSearch(String pSegmentName, String pDescFlexContextCode, String pDescFlexName, List> list, + {String? empID, String? parentValue, bool hasParent = false}) async { + String url = "${ApiConsts.erpRest}GET_VALUE_SET_VALUES_SRCH"; + Map postParams = { + "P_SELECTED_RESP_ID": -999, + "P_MENU_TYPE": "E", + "P_PAGE_LIMIT": 1000, + "P_PAGE_NUM": 1, + "P_PARENT_VALUE": hasParent + ? parentValue + : empID != null + ? parentValue + : null, "P_SEGMENT_NAME": pSegmentName, "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, "P_DESC_FLEX_NAME": pDescFlexName, @@ -60,7 +116,6 @@ class MyAttendanceApiClient { return responseData.getValueSetValuesList ?? []; }, url, postParams); } - Future getDefaultValue(String pSegmentName, String pDescFlexContextCode, String pDescFlexName, List> list, {String? empID}) async { String url = "${ApiConsts.erpRest}GET_DEFAULT_VALUE"; Map postParams = { @@ -97,6 +152,25 @@ class MyAttendanceApiClient { }, url, postParams); } + Future submitCEITransaction(String pDescFlexContextCode, String pFunctionName, List> list, {String? empID, int? pContactRelationID}) async { + String url = "${ApiConsts.erpRest}SUBMIT_CEI_TRANSACTION"; + Map postParams = { + "P_SELECTED_RESP_ID": -999, + "P_MENU_TYPE": "E", + "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, + "P_CONTACT_RELATIONSHIP_ID": pContactRelationID, + "P_FUNCTION_NAME": pFunctionName, + "EITTransactionTBL": list, + "EITTransactionTBLModel": list, + }; + postParams.addAll(AppState().postParamsJson); + if (empID != null) postParams["P_SELECTED_EMPLOYEE_NUMBER"] = empID; + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.submitCEITransactionList!; //ESERVICESDV.fromJson(responseData.getDefaultValueList!.toJson()); + }, url, postParams); + } + Future submitEitTransaction(String pDescFlexContextCode, String pFunctionName, List> list, {String? empID}) async { String url = "${ApiConsts.erpRest}SUBMIT_EIT_TRANSACTION"; Map postParams = { diff --git a/lib/api/worklist/worklist_api_client.dart b/lib/api/worklist/worklist_api_client.dart index 611bcf4..10d9472 100644 --- a/lib/api/worklist/worklist_api_client.dart +++ b/lib/api/worklist/worklist_api_client.dart @@ -21,12 +21,14 @@ import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart' import 'package:mohem_flutter_app/models/get_stamp_ms_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/get_stamp_ns_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/get_user_item_type_list.dart'; +import 'package:mohem_flutter_app/models/itg_forms_models/itg_forms_attachments_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/itg_request_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart'; import 'package:mohem_flutter_app/models/termination/termination_notification_body.dart'; import 'package:mohem_flutter_app/models/update_user_item_type_list.dart'; import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; +import 'package:mohem_flutter_app/models/worklist/get_fad_notifications.dart'; import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_address_notification_body_list.dart'; @@ -35,6 +37,7 @@ import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_bo import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; import 'package:mohem_flutter_app/models/worklist_response_model.dart'; +import 'package:mohem_flutter_app/models/worklist/payment_details_list.dart'; class WorkListApiClient { static final WorkListApiClient _instance = WorkListApiClient._internal(); @@ -43,8 +46,15 @@ class WorkListApiClient { factory WorkListApiClient() => _instance; - Future?> getWorkList(int pPageNum, String pItemType, String pNotificationType, - {String pSearchUser = "", String pSearchItemType = "", String pSentDate = "", String pSearchSubject = ""}) async { + Future?> getWorkList( + int pPageNum, + String pItemType, + String pNotificationType, { + String pSearchUser = "", + String pSearchItemType = "", + String pSentDate = "", + String pSearchSubject = "", + }) async { String url = "${ApiConsts.erpRest}GET_WORKLIST"; Map postParams = { "P_NOTIFICATION_TYPE": pNotificationType, @@ -54,171 +64,215 @@ class WorkListApiClient { "P_SEARCH_FROM_USER": pSearchUser, "P_SEARCH_ITEM_TYPE_DSP_NAME": pSearchItemType, "P_SEARCH_SENT_DATE": pSentDate, - "P_SEARCH_SUBJECT": pSearchSubject + "P_SEARCH_SUBJECT": pSearchSubject, }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel? responseData = GenericResponseModel.fromJson(json); - return responseData.getWorkList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + return responseData.getWorkList; + }, + url, + postParams, + ); } Future getITGTaskCountRequestType() async { String url = "${ApiConsts.cocRest}ITGGetTaskCountRequestType"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future getSubordinatesLeaves(String fromDate, String toDate) async { String url = "${ApiConsts.erpRest}GET_SUBORDINATES_LEAVES"; Map postParams = {"P_DATE_FROM": "/Date(1639861200000+0300)/", "P_DATE_TO": "/Date(1640120400000+0300)/"}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future> getAttachments(int pNotificationID) async { String url = "${ApiConsts.erpRest}GET_ATTACHMENTS"; Map postParams = {"P_NOTIFICATION_ID": pNotificationID}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getAttachementList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAttachementList ?? []; + }, + url, + postParams, + ); } Future> getPRAttachments(String pOLineID) async { String url = "${ApiConsts.erpRest}GET_PR_ATTACHMENTS"; Map postParams = {"P_PO_LINE_ID": pOLineID}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getPRAttachmentList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPRAttachmentList ?? []; + }, + url, + postParams, + ); } Future> getRFCEmployeeeList(int pNotificationID) async { String url = "${ApiConsts.erpRest}GET_RFC_EMPLOYEE_LIST"; Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_PAGE_NUM": 1, "P_PAGE_LIMIT": 10}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getRFCEmployeeListList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getRFCEmployeeListList ?? []; + }, + url, + postParams, + ); } Future> getActionHistory(int pNotificationID) async { String url = "${ApiConsts.erpRest}GET_ACTION_HISTORY"; - Map postParams = { - "P_NOTIFICATION_ID": pNotificationID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getActionHistoryList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getActionHistoryList ?? []; + }, + url, + postParams, + ); } Future> getActionHistoryForPR(String pOLineID) async { String url = "${ApiConsts.erpRest}GET_PR_ACTION_HISTORY"; - Map postParams = { - "P_PO_LINE_ID": pOLineID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_PO_LINE_ID": pOLineID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getPRActionHistoryList?.reversed.toList() ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPRActionHistoryList?.reversed.toList() ?? []; + }, + url, + postParams, + ); } Future> getNotificationButtons(int pNotificationID) async { String url = "${ApiConsts.erpRest}GET_NOTIFICATION_BUTTONS"; Map postParams = {"P_NOTIFICATION_ID": pNotificationID}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getNotificationButtonsList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getNotificationButtonsList ?? []; + }, + url, + postParams, + ); } Future> notificationGetRespondAttributes(int pNotificationID) async { String url = "${ApiConsts.erpRest}NOTIFICATION_GET_RESPOND_ATTRIBUTES"; Map postParams = {"P_NOTIFICATION_ID": pNotificationID}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.notificationGetRespondAttributesList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.notificationGetRespondAttributesList ?? []; + }, + url, + postParams, + ); } Future getBasicDetNTFBody(int pNotificationID, int pTransactionID) async { String url = "${ApiConsts.erpRest}GET_BASIC_DET_NTF_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": pNotificationID, - "P_TRANSACTION_ID": pTransactionID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_TRANSACTION_ID": pTransactionID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } - Future getUserInformation(int pSelectedResopID, String selectedEmployeeNumber) async { - String url = "${ApiConsts.erpRest}Get_UserInformation"; - Map postParams = { - "P_SELECTED_RESP_ID": pSelectedResopID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + // Future getUserInformation(int pSelectedResopID, String selectedEmployeeNumber) async { + // String url = "${ApiConsts.erpRest}Get_UserInformation"; + // Map postParams = {"P_SELECTED_RESP_ID": pSelectedResopID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; + // postParams.addAll(AppState().postParamsJson); + // if (selectedEmployeeNumber != null) postParams["P_SELECTED_EMPLOYEE_NUMBER"] = selectedEmployeeNumber; + // return await ApiClient().postJsonForObject( + // (json) { + // GenericResponseModel responseData = GenericResponseModel.fromJson(json); + // return responseData.memberInformationList![0]; + // }, + // url, + // postParams, + // ); + // } + + Future getNotificationUserInformation(int pSelectedResopID, String selectedEmployeeNumber, int pNotificationID) async { + String url = "${ApiConsts.erpRest}Get_Notification_UserInformation"; + Map postParams = {"P_SELECTED_RESP_ID": pSelectedResopID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1, "P_NOTIFICATION_ID": pNotificationID}; postParams.addAll(AppState().postParamsJson); if (selectedEmployeeNumber != null) postParams["P_SELECTED_EMPLOYEE_NUMBER"] = selectedEmployeeNumber; - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.memberInformationList![0]; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.memberInformationList![0]; + }, + url, + postParams, + ); } Future> getStampMsNotificationBody(int pNotificationID, int pTransactionID) async { String url = "${ApiConsts.erpRest}GET_STAMP_MS_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": pNotificationID, - "P_TRANSACTION_ID": pTransactionID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_TRANSACTION_ID": pTransactionID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getStampMsNotificationBodyList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getStampMsNotificationBodyList ?? []; + }, + url, + postParams, + ); } Future> getStampNsNotificationBody(int pNotificationID, int pTransactionID) async { String url = "${ApiConsts.erpRest}GET_STAMP_NS_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": pNotificationID, - "P_TRANSACTION_ID": pTransactionID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_TRANSACTION_ID": pTransactionID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getStampNsNotificationBodyList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getStampNsNotificationBodyList ?? []; + }, + url, + postParams, + ); } // Future> getAbsenceNotificationBody(int pNotificationID, int pTransactionID) async { @@ -239,196 +293,251 @@ class WorkListApiClient { Future postNotificationActions(Map postParams) async { String url = "${ApiConsts.erpRest}NOTIFICATION_ACTIONS"; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future> getMoNotificationBody(int pNotificationID, int pTransactionID) async { String url = "${ApiConsts.erpRest}GET_MO_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": pNotificationID, - "P_TRANSACTION_ID": pTransactionID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_TRANSACTION_ID": pTransactionID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getMoNotificationBodyList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getMoNotificationBodyList ?? []; + }, + url, + postParams, + ); } Future getPoNotificationBody(int pNotificationID, int pTransactionID) async { String url = "${ApiConsts.erpRest}GET_PO_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": pNotificationID, - "P_TRANSACTION_ID": pTransactionID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_TRANSACTION_ID": pTransactionID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getPoNotificationBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPoNotificationBodyList; + }, + url, + postParams, + ); } Future getPRNotificationBody(int pNotificationID, int pTransactionID) async { String url = "${ApiConsts.erpRest}GET_PR_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": pNotificationID, - "P_TRANSACTION_ID": pTransactionID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_TRANSACTION_ID": pTransactionID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getPrNotificationBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPrNotificationBodyList; + }, + url, + postParams, + ); + } + + Future getPaymentNotificationBody(int pNotificationID, int pTransactionID) async { + String url = "${ApiConsts.erpRest}GET_PAY_REQ_NOTIFICATION_BODY"; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_TRANSACTION_ID": pTransactionID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPaymentNotificationBodyList; + }, + url, + postParams, + ); } Future> getMoItemHistory(int pItemID, int pOrgID) async { String url = "${ApiConsts.erpRest}GET_MO_ITEM_HISTORY"; - Map postParams = { - "P_ITEM_ID": pItemID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - "P_ORG_ID": pOrgID, - }; + Map postParams = {"P_ITEM_ID": pItemID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1, "P_ORG_ID": pOrgID}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getMoItemHistoryList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getMoItemHistoryList ?? []; + }, + url, + postParams, + ); } Future> getPoItemHistory(int pItemID) async { String url = "${ApiConsts.erpRest}GET_PO_ITEM_HISTORY"; - Map postParams = { - "P_ITEM_ID": pItemID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_ITEM_ID": pItemID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getPoItemHistoryList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPoItemHistoryList ?? []; + }, + url, + postParams, + ); } Future> getQuotationAnalysis(int pItemID, int pPoHeaderId) async { String url = "${ApiConsts.erpRest}GET_QUOTATION_ANALYSIS"; - Map postParams = { - "P_ITEM_ID": pItemID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - "P_PO_HEADER_ID": pPoHeaderId, - }; + Map postParams = {"P_ITEM_ID": pItemID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1, "P_PO_HEADER_ID": pPoHeaderId}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getQuotationAnalysisList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getQuotationAnalysisList ?? []; + }, + url, + postParams, + ); } Future getItemCreationNtfBody(int pNotificationID, int pTransactionID) async { String url = "${ApiConsts.erpRest}GET_ITEM_CREATION_NTF_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": pNotificationID, - "P_TRANSACTION_ID": pTransactionID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_TRANSACTION_ID": pTransactionID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getItemCreationNtfBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getItemCreationNtfBodyList; + }, + url, + postParams, + ); } Future getITGFormDetails(String requestType, taskId, itemId, String employeeNumber) async { String url = "${ApiConsts.cocRest}ITGGetFormDetials"; - Map postParams = { - "RequestType": requestType, - "TaskID": taskId, - "ItemIDStr": itemId, - "EmployeeNumber": employeeNumber, - }; - postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData.itgRequest; - }, url, postParams); - } - - Future rejectITGRequest(String requestType, taskId, itemId, String employeeNumber, String comments) async { + Map postParams = {"RequestType": requestType, "TaskID": taskId, "ItemIDStr": itemId, "EmployeeNumber": employeeNumber}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, + url, + postParams, + ); + } + + Future getITGTimeCardDetails(String requestType, String monthStr, String employeeNumber) async { + String url = "${ApiConsts.cocRest}ITG_TimeCard_Get"; + // String url = "https://webservices.hmg.com/Services/COCWS.svc/REST/ITG_TimeCard_Get"; + Map postParams = {"MonthStr": monthStr, "EmployeeNumber": employeeNumber}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.mohemmItgResponseItem; + }, + url, + postParams, + ); + } + + Future?> getITGFormAttachments(String requestType, taskId, itemId, String employeeNumber) async { + String url = "${ApiConsts.cocRest}ITGGetFormDetialsAttachment"; + Map postParams = {"RequestType": requestType, "TaskID": taskId, "ItemIDStr": itemId, "EmployeeNumber": employeeNumber}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgFormAttachmentsList; + }, + url, + postParams, + ); + } + + Future rejectITGRequest(String requestType, taskId, itemId, String employeeNumber, String comments) async { String url = "${ApiConsts.cocRest}ITGRejectRequest"; - Map postParams = { - "RequestType": requestType, - "TaskID": taskId, - "ItemIDStr": itemId, - "EmployeeNumber": employeeNumber, - "Comments": comments, - }; + Map postParams = {"RequestType": requestType, "TaskID": taskId, "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "Comments": comments}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData.itgRequest; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, + url, + postParams, + ); } - Future approveITGRequest(String requestType, taskId, itemId, String employeeNumber, String comments) async { + Future approveITGRequest(String requestType, taskId, itemId, String employeeNumber, String comments) async { String url = "${ApiConsts.cocRest}ITGApproveRequest"; - Map postParams = { - "RequestType": requestType, - "TaskID": taskId, - "ItemIDStr": itemId, - "EmployeeNumber": employeeNumber, - "Comments": comments, - }; + Map postParams = {"RequestType": requestType, "TaskID": taskId, "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "Comments": comments}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData.itgRequest; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, + url, + postParams, + ); } - Future delegateITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { + Future delegateITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGDelegateRequest"; - Map postParams = { - "RequestType": requestType, - "TaskID": taskId, - "ItemIDStr": itemId, - "EmployeeNumber": employeeNumber, - "NewUserEMPId": newUserEMPId, - "Comments": comments, - }; + Map postParams = {"RequestType": requestType, "TaskID": taskId, "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "NewUserEMPId": newUserEMPId, "Comments": comments}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData.itgRequest; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, + url, + postParams, + ); } // ANSWER = 'Services/COCWS.svc/REST/ITGAnswer'; - Future answerITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { + Future answerITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGAnswer"; + Map postParams = {"RequestType": requestType, "TaskID": taskId, "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "Comments": comments}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, + url, + postParams, + ); + } + + Future requestActionITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments, String email) async { + String url = "${ApiConsts.cocRest}Mohemm_ITG_GenerateQR_RequestAction"; Map postParams = { "RequestType": requestType, "TaskID": taskId, "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "Comments": comments, + "EmailAddress": email, + "RequestID": itemId, + "RequestActionId": 3, + "IsQRCodeGenerate": true, }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData.itgRequest; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, + url, + postParams, + ); } Future grantITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { @@ -440,200 +549,228 @@ class WorkListApiClient { "EmployeeNumber": employeeNumber, "Comments": "", "AdditionalFields": null, - "NewUserEMPId": newUserEMPId + "NewUserEMPId": newUserEMPId, }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData.itgRequest; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, + url, + postParams, + ); } - Future informationITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { + Future informationITGRequest(String requestType, taskId, itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGRequestInformation"; - Map postParams = { - "RequestType": requestType, - "TaskID": taskId, - "ItemIDStr": itemId, - "EmployeeNumber": employeeNumber, - "NewUserEMPId": newUserEMPId, - "Comments": comments, - }; + Map postParams = {"RequestType": requestType, "TaskID": taskId, "ItemIDStr": itemId, "EmployeeNumber": employeeNumber, "NewUserEMPId": newUserEMPId, "Comments": comments}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - ItgFormsModel responseData = ItgFormsModel.fromJson(json); - return responseData.itgRequest; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, + url, + postParams, + ); } //HR Detail Screen Requests Future?> GetEitNotificationBody(int? notificationId) async { String url = "${ApiConsts.erpRest}GET_EIT_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": notificationId, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getEITCollectionNotificationBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getEITCollectionNotificationBodyList; + }, + url, + postParams, + ); + } + + Future?> GetCeiNotificationBody(int? notificationId) async { + String url = "${ApiConsts.erpRest}GET_CEI_NOTIFICATION_BODY"; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getCEICollectionNotificationBodyList; + }, + url, + postParams, + ); } Future?> getPhonesNotificationBodyList(int? notificationId) async { String url = "${ApiConsts.erpRest}GET_PHONES_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": notificationId, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getPhonesNotificationBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPhonesNotificationBodyList; + }, + url, + postParams, + ); } Future?> getBasicDetNtfBodyList(int? notificationId) async { String url = "${ApiConsts.erpRest}GET_BASIC_DET_NTF_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": notificationId, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getBasicDetNtfBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getBasicDetNtfBodyList; + }, + url, + postParams, + ); } Future?> getAbsenceNotificationBody(int? notificationId) async { String url = "${ApiConsts.erpRest}GET_ABSENCE_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": notificationId, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getAbsenceCollectionNotificationBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAbsenceCollectionNotificationBodyList; + }, + url, + postParams, + ); } Future getContactNotificationBodyList(int? notificationId) async { String url = "${ApiConsts.erpRest}GET_CONTACT_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": notificationId, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getContactNotificationBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getContactNotificationBodyList; + }, + url, + postParams, + ); } Future?> getAddressNotificationBodyList(int? notificationId) async { String url = "${ApiConsts.erpRest}GET_ADDRESS_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": notificationId, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getAddressNotificationBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAddressNotificationBodyList; + }, + url, + postParams, + ); } Future?> getTerminationNotificationBodyList(int? notificationId) async { String url = "${ApiConsts.erpRest}GET_TERM_NOTIFICATION_BODY"; - Map postParams = { - "P_NOTIFICATION_ID": notificationId, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getTermNotificationBodyList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getTermNotificationBodyList; + }, + url, + postParams, + ); } - - Future?> getFavoriteReplacementWithoutImage() async { String url = "${ApiConsts.erpRest}Mohemm_GetFavoriteReplacementsWithoutImage"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.mohemmGetFavoriteReplacementsList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.mohemmGetFavoriteReplacementsList; + }, + url, + postParams, + ); } Future?> getFavoriteReplacementWithImage(String selectedFavLetter) async { String url = "${ApiConsts.erpRest}Mohemm_GetFavoriteReplacements"; Map postParams = {"ItgFilter": selectedFavLetter}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.mohemmGetFavoriteReplacementsList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.mohemmGetFavoriteReplacementsList; + }, + url, + postParams, + ); } Future?> getFavoriteReplacementWithImageNew(String selectedFavLetter) async { String url = "${ApiConsts.erpRest}Mohemm_GetFavoriteReplacements_Images"; Map postParams = {"ItgFilter": selectedFavLetter}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.mohemmGetFavoriteReplacementsList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.mohemmGetFavoriteReplacementsList; + }, + url, + postParams, + ); } Future changeFavoriteReplacements({required String email, required String employeName, required String image, required String userName, bool isFav = false}) async { String url = "${ApiConsts.erpRest}Mohemm_ChangeFavoriteReplacements"; - Map postParamsObj = { - "EMAIL_ADDRESS": email, - "EMPLOYEE_DISPLAY_NAME": employeName, - "EMPLOYEE_IMAGE": image, - "IsFavorite": isFav, - "USER_NAME": userName, - }; + Map postParamsObj = {"EMAIL_ADDRESS": email, "EMPLOYEE_DISPLAY_NAME": employeName, "EMPLOYEE_IMAGE": image, "IsFavorite": isFav, "USER_NAME": userName}; Map postParams = { "Mohemm_ChangeReplacementsInputList": [postParamsObj], }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future?> searchUserByInput({String userId = "", String userName = "", String email = ""}) async { String url = "${ApiConsts.erpRest}GET_REPLACEMENT_LIST"; - Map postParams = { - "P_SEARCH_USER_NAME": userId, - "P_SEARCH_EMPLOYEE_DISPLAY_NAME": userName, - "P_SEARCH_EMAIL_ADDRESS": email, - "P_PAGE_LIMIT": 50, - "P_PAGE_NUM": 1, - }; - postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.replacementList; - }, url, postParams); - } - - Future submitComment( - {String? comment, String? email, String? userId, int? notificationId, required String apiMode, int? approverIndex = null, List>? attributeData = const []}) async { + Map postParams = {"P_SEARCH_USER_NAME": userId, "P_SEARCH_EMPLOYEE_DISPLAY_NAME": userName, "P_SEARCH_EMAIL_ADDRESS": email, "P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.replacementList; + }, + url, + postParams, + ); + } + + Future submitComment({ + String? comment, + String? email, + String? userId, + int? notificationId, + required String apiMode, + int? approverIndex = null, + List>? attributeData = const [], + }) async { String url = "${ApiConsts.erpRest}NOTIFICATION_ACTIONS"; Map postParams = { "P_COMMENTS": comment, @@ -642,46 +779,87 @@ class WorkListApiClient { "P_FORWARD_TO_USER_NAME": userId, "P_NOTIFICATION_ID": notificationId, "P_APPROVER_INDEX": approverIndex, - "RespondAttributeList": attributeData + "RespondAttributeList": attributeData, }; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); } Future> getUserItemTypes() async { String url = "${ApiConsts.erpRest}GET_USER_ITEM_TYPES"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getUserItemTypesList ?? []; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getUserItemTypesList ?? []; + }, + url, + postParams, + ); } Future updateUserItemTypes(List> itemList) async { String url = "${ApiConsts.erpRest}UPDATE_USER_ITEM_TYPES"; Map postParams = {"UpdateItemTypeList": itemList}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.updateUserItemTypesList; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.updateUserItemTypesList; + }, + url, + postParams, + ); } Future getPRDetailsForPO(String poLineID) async { String url = "${ApiConsts.erpRest}GET_PR_INFORMATION"; - Map postParams = { - "P_PO_LINE_ID": poLineID, - "P_PAGE_LIMIT": 100, - "P_PAGE_NUM": 1, - }; - postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.getPRInformationList; - }, url, postParams); + Map postParams = {"P_PO_LINE_ID": poLineID, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPRInformationList; + }, + url, + postParams, + ); + } + + Future?> getPaymentDetailsNotification(int? notificationId) async { + String url = "${ApiConsts.erpRest}GET_PAY_REQ_NOTIFICATION_BODY"; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAbsenceCollectionNotificationBodyList; + }, + url, + postParams, + ); + } + + + Future getFADNotificationBody(int? notificationId) async { + String url = "${ApiConsts.erpRest}GetFADisposalNtfDetails"; + Map postParams = {"P_NOTIFICATION_ID": notificationId, "P_PAGE_LIMIT": 100, "P_PAGE_NUM": 1}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getFADisposalNtfDetails; + }, + url, + postParams, + ); } } diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 51469c2..5ce6861 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -90,7 +90,7 @@ class AppState { String get getHuaweiPushToken => _huaweiPushToken; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.7, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 9.7, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart index 915f35d..1b0dd06 100644 --- a/lib/classes/colors.dart +++ b/lib/classes/colors.dart @@ -66,4 +66,5 @@ class MyColors { static const Color darkGrey3BColor = Color(0xff3B3B3B); static const Color lightGreyIconColor = Color(0xff919191); static const Color selectedBorderColor = Color(0xff37A4BE); + static const Color mazayaRedColor = Color(0xffED1C2B); } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 437839b..88ebf73 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,10 +1,23 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; class ApiConsts { - //static String baseUrl = "http://10.200.204.20:2801/"; // Local server + // 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 = "https://hmgwebservices.com"; // Live server + // static String baseUrl = "http://10.201.204.101:2024"; + // 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 = "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 baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; @@ -14,6 +27,9 @@ 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"; // UAT + // static String ssoAuthRedirection = "https://sso.hmg.com/api/auth/connect"; // Prod + //Chat static String chatServerBaseUrl = "https://apiderichat.hmg.com/"; static String chatServerBaseApiUrl = chatServerBaseUrl + "api/"; @@ -51,6 +67,7 @@ class ApiConsts { static String marathonQualifiersUrl = marathonBaseUrl + "winner/getWinner/"; static String marathonSelectedWinner = marathonBaseUrl + "winner/getSelectedWinner/"; static String marathonGetMarathonersCount = marathonBaseUrl + "Participant/GetRemainingParticipants"; + static String marathonGetTutorial = marathonBaseUrl + "tutorial/GetTutorialNotification"; //DummyCards for the UI diff --git a/lib/classes/date_uitl.dart b/lib/classes/date_uitl.dart index 89e237d..8714b40 100644 --- a/lib/classes/date_uitl.dart +++ b/lib/classes/date_uitl.dart @@ -7,7 +7,7 @@ class DateUtil { /// static DateTime convertStringToDateMarathon(String date) { - // /Date(1585774800000+0300)/ + // return DateTime(2025, 2, 5); if (date != null) { const start = "/Date("; const end = "+0300)"; @@ -38,12 +38,12 @@ class DateUtil { return DateTime.now(); } - static DateTime convertSimpleStringDateToDate(String date) { + static DateTime convertSimpleStringDateToDate(String date, {bool isITG = false}) { // print(date.toUpperCase()); - return getDateTimeFromString(date.split(" ")[0], date.toUpperCase().split(" ")[1] + " " + date.toUpperCase().split(" ")[2]); + return getDateTimeFromString(date.split(" ")[0], date.toUpperCase().split(" ")[1] + " " + date.toUpperCase().split(" ")[2], isITG: isITG); } - static DateTime getDateTimeFromString(String date, String time) { + static DateTime getDateTimeFromString(String date, String time, {bool isITG = false}) { var hours = num.parse(time.split(":")[0]); var mins = time.split(":")[1]; var secs = time.split(":")[2].split(" ")[0]; @@ -60,7 +60,7 @@ class DateUtil { } } date = date + " $hours:$mins:$secs"; - DateTime returnDate = DateFormat("MM/dd/yyyy HH:mm:ss", "en_US").parse(date); + DateTime returnDate = isITG ? DateFormat("dd/MM/yyyy HH:mm:ss", "en_US").parse(date) : DateFormat("MM/dd/yyyy HH:mm:ss", "en_US").parse(date); return returnDate; } @@ -524,4 +524,14 @@ class DateUtil { // } // return ""; // } + static String replaceArabicNumber(String input) { + const english = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; + const arabic = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩']; + + for (int i = 0; i < english.length; i++) { + input = input.replaceAll(arabic[i], english[i]); + } + + return input; + } } diff --git a/lib/classes/file_process.dart b/lib/classes/file_process.dart index 6974702..0720c8d 100644 --- a/lib/classes/file_process.dart +++ b/lib/classes/file_process.dart @@ -2,8 +2,9 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:open_file/open_file.dart'; +import 'package:open_filex/open_filex.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:http/http.dart' as http; class FileProcess { static bool isFolderCreated = false; @@ -23,9 +24,9 @@ class FileProcess { } } - static void openFile(String fileName) { + static void openFile(String fileName, {bool isFullPath = false}) { String dir = directory!.path + "/$fileName.pdf"; - OpenFile.open(dir); + OpenFilex.open(isFullPath ? fileName : dir); } static Future downloadFile(String base64Content, String fileName) async { @@ -37,4 +38,24 @@ class FileProcess { await file.writeAsBytes(bytes); return file; } + + static Future downloadFileFromUrl(String url,String fileName) async { + await checkDocumentFolder(); + String filePath = '${directory!.path}/$fileName'; + + if (await File(filePath).exists()) { + await Future.delayed(const Duration(seconds: 1)); + return filePath; + } else { + var response = await http.get(Uri.parse(url)); + if (response.statusCode == 200) { + var bytes = response.bodyBytes; + File file = File(filePath); + await file.writeAsBytes(bytes); + return filePath; + } else { + throw Exception('Failed to download file'); + } + } + } } 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/notifications.dart b/lib/classes/notifications.dart index 8f432d7..058606c 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -34,8 +34,8 @@ class AppNotifications { if (Platform.isIOS) { await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(alert: true, badge: true, sound: true); } else if (Platform.isAndroid) { - AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); - bool? granted = await androidImplementation?.requestPermission(); + AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); + bool? granted = await androidImplementation?.requestNotificationsPermission(); if (granted == false) { if (kDebugMode) { print("-------------------- Permission Granted ------------------------"); diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 9c55375..2ae4fe3 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -16,6 +16,7 @@ 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/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:mohem_flutter_app/widgets/loading_dialog.dart'; import 'package:nfc_manager/nfc_manager.dart'; @@ -31,13 +32,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 +65,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 +115,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) { @@ -137,34 +135,19 @@ 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, - ), - ); + static Future showErrorDialog({required BuildContext context, required VoidCallback onOkTapped, required String message, VoidCallback? onCloseTap}) async { + return showDialog(context: context, builder: (BuildContext context) => ConfirmDialog(message: message, onTap: onOkTapped, onCloseTap: onCloseTap)); } 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 +155,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 +189,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 +197,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 +320,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 +346,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 @@ -401,6 +376,7 @@ class Utils { } return false; } + static bool isDate(String input, String format) { try { DateTime d = DateFormat(format).parseStrict(input); @@ -411,4 +387,16 @@ class Utils { return false; } } + + static Future performLogout(BuildContext? context, ChatProviderModel? chatData) async { + AppState().isAuthenticated = false; + AppState().isLogged = false; + AppState().setPostParamsInitConfig(); + if (chatData != null) { + chatData.disposeData(); + } + // SharedPreferences prefs = await SharedPreferences.getInstance(); + // await prefs.clear(); + Navigator.pushNamedAndRemoveUntil(context!, AppRoutes.login, (Route route) => false, arguments: null); + } } diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 07a927d..9bae8df 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:mohem_flutter_app/models/my_documents/employee_documents_list_model.dart'; import 'package:mohem_flutter_app/ui/app_update_screen.dart'; import 'package:mohem_flutter_app/ui/attendance/add_vacation_rule_screen.dart'; import 'package:mohem_flutter_app/ui/attendance/monthly_attendance_screen.dart'; @@ -11,6 +10,9 @@ import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart'; import 'package:mohem_flutter_app/ui/chat/group_members.dart'; import 'package:mohem_flutter_app/ui/chat/manage_group.dart'; +import 'package:mohem_flutter_app/ui/etqan_ovr/etqan_create_request.dart'; +import 'package:mohem_flutter_app/ui/etqan_ovr/etqan_ovr_home.dart'; +import 'package:mohem_flutter_app/ui/etqan_ovr/etqan_request_detailed.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; @@ -27,12 +29,12 @@ import 'package:mohem_flutter_app/ui/login/verify_login_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_intro_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_sponsor_video_screen.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_tutorial_viewer_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_waiting_screen.dart'; import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_input_screen.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/ui/my_attendance/my_attendance_screen.dart'; import 'package:mohem_flutter_app/ui/my_team/create_request.dart'; import 'package:mohem_flutter_app/ui/my_team/employee_details.dart'; @@ -41,6 +43,7 @@ import 'package:mohem_flutter_app/ui/my_team/profile_details.dart'; import 'package:mohem_flutter_app/ui/my_team/subordinate_leave.dart'; import 'package:mohem_flutter_app/ui/my_team/team_members.dart'; import 'package:mohem_flutter_app/ui/my_team/view_attendance.dart'; +import 'package:mohem_flutter_app/ui/parking_qr/parking_qr.dart'; import 'package:mohem_flutter_app/ui/payslip/monthly_pay_slip_screen.dart'; import 'package:mohem_flutter_app/ui/performance/performance_appraisal_screen.dart'; import 'package:mohem_flutter_app/ui/profile/add_update_family_member.dart'; @@ -54,16 +57,17 @@ import 'package:mohem_flutter_app/ui/profile/personal_info.dart'; import 'package:mohem_flutter_app/ui/profile/profile_screen.dart'; import 'package:mohem_flutter_app/ui/screens/announcements/announcement_details.dart'; import 'package:mohem_flutter_app/ui/screens/announcements/announcements.dart'; - +import 'package:mohem_flutter_app/ui/screens/child_education/child_education_assistance.dart'; +import 'package:mohem_flutter_app/ui/screens/courses/courses_screen.dart'; // import 'package:mohem_flutter_app/ui/my_attendance/work_from_home_screen.dart'; import 'package:mohem_flutter_app/ui/screens/eit/add_eit.dart'; +import 'package:mohem_flutter_app/ui/screens/event_activity/event_activity.dart'; import 'package:mohem_flutter_app/ui/screens/items_for_sale/add_new_item_for_sale.dart'; import 'package:mohem_flutter_app/ui/screens/items_for_sale/item_for_sale_detail.dart'; import 'package:mohem_flutter_app/ui/screens/items_for_sale/items_for_sale_home.dart'; import 'package:mohem_flutter_app/ui/screens/mowadhafhi/mowadhafhi_home.dart'; import 'package:mohem_flutter_app/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart'; import 'package:mohem_flutter_app/ui/screens/mowadhafhi/request_details.dart'; -import 'package:mohem_flutter_app/ui/screens/my_documents/my_document_detail_screen.dart'; import 'package:mohem_flutter_app/ui/screens/my_documents/my_documents_screen.dart'; import 'package:mohem_flutter_app/ui/screens/my_requests/my_requests.dart'; import 'package:mohem_flutter_app/ui/screens/my_requests/new_request.dart'; @@ -167,6 +171,9 @@ class AppRoutes { static const String offersAndDiscounts = "/offersAndDiscounts"; static const String offersAndDiscountsDetails = "/offersAndDiscountsDetails"; + // Courses + static const String courses = "/courses"; + //Pay slip static const String monthlyPaySlip = "/monthlyPaySlip"; @@ -197,15 +204,27 @@ class AppRoutes { static const String manageGroup = "/manageGroup"; static const String groupMembers = "/groupmembers"; static const String groupChatDetailed = "/groupChatDetailed"; + //Marathon static const String marathonIntroScreen = "/marathonIntroScreen"; static const String marathonScreen = "/marathonScreen"; static const String marathonWinnerScreen = "/marathonWinnerScreen"; static const String marathonSponsorVideoScreen = "/marathonSponsorVideoScreen"; static const String marathonWaitingScreen = "/marathonWaitingScreen"; + static const String marathonTutorialScreen = "/marathonTutorialScreen"; static const String unsafeDeviceScreen = "/unsafeDeviceScreen"; static const String appUpdateScreen = "/appUpdateScreen"; + static const String childEducation = "/childEducation"; + + static const String activityScreen = "/activityScreen"; + + static const String etqanOvr = "/etqanOvr"; + static const String etqanCreateRequest = "/etqanCreateRequest"; + static const String etqanGetIncidientRequest = "/etqanGetIncidientRequest"; + + //Parking QR + static const String parkingQr = "/parkingQrScreen"; static final Map routes = { login: (BuildContext context) => LoginScreen(), @@ -287,6 +306,9 @@ class AppRoutes { offersAndDiscounts: (BuildContext context) => OffersAndDiscountsHome(), offersAndDiscountsDetails: (BuildContext context) => OffersAndDiscountsDetails(), + // Courses + courses: (BuildContext context) => const CoursesScreen(), + //pay slip monthlyPaySlip: (BuildContext context) => MonthlyPaySlipScreen(), performanceEvaluation: (BuildContext context) => PerformanceAppraisal(), @@ -319,8 +341,21 @@ class AppRoutes { marathonScreen: (BuildContext context) => MarathonScreen(), marathonSponsorVideoScreen: (BuildContext context) => const SponsorVideoScreen(), marathonWaitingScreen: (BuildContext context) => const MarathonWaitingScreen(), + marathonTutorialScreen: (BuildContext context) => const MarathonTutorialViewerScreen(), unsafeDeviceScreen: (BuildContext context) => const UnsafeDeviceScreen(), appUpdateScreen: (BuildContext context) => const AppUpdateScreen(), + childEducation: (BuildContext context) => ChildEducationAssistance(), + activityScreen:(BuildContext context) => const EventActivityScreen(), + + //ETQAN OVR + etqanOvr: (BuildContext context) => EtqanOvrHome(), + etqanCreateRequest: (BuildContext context) => EtqanOvrCreateRequest(), + etqanGetIncidientRequest: (BuildContext context) => EtqanOvrRequestDetailed(), + activityScreen:(BuildContext context) => const EventActivityScreen(), + + //Parking QR + parkingQr: (BuildContext context) => const ParkingQrScreen(), + }; } diff --git a/lib/dialogs/otp_dialog.dart b/lib/dialogs/otp_dialog.dart index 9f7c82e..da2611e 100644 --- a/lib/dialogs/otp_dialog.dart +++ b/lib/dialogs/otp_dialog.dart @@ -67,6 +67,7 @@ class OtpDialog { // projectProvider = Provider.of(context); return Dialog( backgroundColor: Colors.white, + surfaceTintColor: Colors.transparent, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), insetPadding: const EdgeInsets.only(left: 21, right: 21), child: StatefulBuilder(builder: (context, setState) { @@ -202,11 +203,16 @@ class OtpDialog { ), errorBorder: OutlineInputBorder( borderRadius: const BorderRadius.all(Radius.circular(10.0)), - borderSide: BorderSide(color: Theme.of(context).errorColor), + borderSide: BorderSide(color: Colors.red), ), + // focusedErrorBorder: OutlineInputBorder( + // borderRadius: const BorderRadius.all(Radius.circular(10.0)), + // borderSide: BorderSide(color: Colors.red), + // // borderSide: BorderSide(color: Theme.of(context).colorScheme.error), + // ), focusedErrorBorder: OutlineInputBorder( borderRadius: const BorderRadius.all(Radius.circular(10.0)), - borderSide: BorderSide(color: Theme.of(context).errorColor), + borderSide: BorderSide(color: Theme.of(context).colorScheme.error), ), ); } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 3af55f0..93a6cf8 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -68,8 +68,9 @@ extension EmailValidator on String { style: TextStyle(fontSize: 10, fontStyle: fontStyle ?? FontStyle.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4), ); - Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isBold = false, int maxLine = 0}) => Text( + Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0}) => Text( this, + textAlign: isCenter ? TextAlign.center : null, maxLines: (maxLine > 0) ? maxLine : null, style: TextStyle( fontSize: 11, @@ -80,28 +81,30 @@ extension EmailValidator on String { ), ); - Widget toText12({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0}) => Text( + Widget toText12({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int? maxLine, TextOverflow? overflow}) => Text( this, textAlign: isCenter ? TextAlign.center : null, - maxLines: (maxLine > 0) ? maxLine : null, + maxLines: maxLine == 0 ? null : maxLine, style: TextStyle( fontSize: 12, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.72, decoration: isUnderLine ? TextDecoration.underline : null, + overflow: TextOverflow.visible ), ); - Widget toText12Auto({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0}) => AutoSizeText( + Widget toText12Auto({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int? maxLine,TextOverflow? overflow}) => AutoSizeText( this, textAlign: isCenter ? TextAlign.center : null, - maxLines: (maxLine > 0) ? maxLine : null, + maxLines: maxLine == 0 ? null : maxLine, minFontSize: 8, style: TextStyle( fontSize: 12, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, + overflow: overflow, letterSpacing: -0.72, decoration: isUnderLine ? TextDecoration.underline : null, ), diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index a433421..f186a22 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -1,1113 +1,1360 @@ // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart -// ignore_for_file: prefer_single_quotes +// ignore_for_file: prefer_single_quotes, avoid_renaming_method_parameters, constant_identifier_names import 'dart:ui'; import 'package:easy_localization/easy_localization.dart' show AssetLoader; -class CodegenLoader extends AssetLoader { +class CodegenLoader extends AssetLoader{ const CodegenLoader(); @override - Future> load(String fullPath, Locale locale) { + Future?> load(String path, Locale locale) { return Future.value(mapLocales[locale.toString()]); } - static const Map ar_SA = { - "mohemm": "Mohemm", - "english": "English", - "arabic": "عربي", - "login": "تسجيل الدخول", - "pleaseEnterLoginDetails": "الرجاء إدخال التفاصيل أدناه لتسجيل الدخول", - "username": "اسم المستخدم", - "password": "كلمة المرور", - "welcomeBack": "مرحبا بعودتك", - "wouldYouLikeToLoginWithCurrentUsername": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟", - "lastLoginDetails": "تفاصيل تسجيل الدخول الأخير:", - "verificationType": "نوع التحقق:", - "pleaseVerify": "ارجوك تحقق", - "pleaseVerifyForBio": "الرجاء التحقق من تسجيل الدخول باستخدام أحد هذه الخيارات", - "verifyThroughFace": "تحقق من خلال الوجه", - "verifyThroughFingerprint": "تحقق من خلال بصمة الإصبع", - "verifyThroughSMS": "تحقق من خلال الرسائل القصيرة", - "verifyThroughWhatsapp": "تحقق من خلال Whatsapp", - "useAnotherAccount": "استخدم حسابا آخر", - "pleaseEnterTheVerificationCodeSentTo": "الرجاء إدخال رمز التحقق المرسل إلى ", - "theVerificationCodeWillExpireIn": "ستنتهي صلاحية رمز التحقق في ", - "goodMorning": "صباح الخير", - "markAttendance": "علامة الحضور", - "timeLeftToday": "الوقت المتبقي اليوم", - "checkIn": "تحقق في", - "workList": "قائمة العمل", - "leaveBalance": "رصيد الاجازات", - "missingSwipes": "تسجيل بصمة حضور", - "ticketBalance": "رصيد التذكرة", - "other": "آخر", - "services": "خدمات", - "viewAllServices": "عرض جميع الخدمات", - "monthlyAttendance": "الحضور الشهري", - "vacationRule": "قاعدة الاجازات", - "vacationType": "نوع الاجازة", - "startDateT": "تاريخ البدء", - "endDateT": "تاريخ الانتهاء", - "workFromHome": "العمل من المنزل", - "ticketRequest": "طلب تذكرة", - "viewAllOffers": "مشاهدة جميع العروض", - "offers": "عروض & ", - "discounts": "الخصومات", - "newString": "جديد", - "setTheNewPassword": "قم بتعيين كلمة المرور الجديدة", - "typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه", - "typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه", - "confirmPassword": "تأكيد كلمة المرور", - "update": "تحديث", - "title": "عنوان", - "home": "الرئيسية", - "mySalary": "راتبي", - "createRequest": "إنشاء طلب", - "forgotPassword": "هل نسيت كلمة السر", - "employeeId": "هوية الموظف", - "loginCodeWillSentToMobileNumber": "الرجاء إدخال معرف الموظف الخاص بك ، وسيتم إرسال رمز تسجيل الدخول إلى رقم هاتفك المحمول", - "changePassword": "تغيير كلمة المرور", - "ok": "موافق", - "confirm": "تؤكد", - "passwordChangedSuccessfully": "تم تغيير الرقم السري بنجاح", - "itemsForSale": "سلع للبيع", - "attendanceDetails": "تفاصيل الحضور", - "order": "الطلبات", - "earlyOut": "الخروج مبكرا", - "shortage": "ساعات التقصير", - "excess": "فائض", - "lateIn": "القدوم المتاخر", - "approvedCheckOut": "اعتماد وقت الخروج", - "approvedCheckIn": "اعتماد وقت الدخول", - "actualCheckOut": "وقت الخروج", - "actualCheckIn": "وقت الدخول", - "present": "حضور", - "pres": "حضور", - "shiftTime": "وقت التناوب", - "absent": "غياب", - "attendance": "الحضور", - "scheduleDays": "ايام العمل", - "offDays": "ايام الراحه", - "nonAnalyzed": "لايوجد تحليل", - "shortageHour": "ساعات التقصير", - "stats": "الحاله", - "completed": "تم اكمال", - "msg": "Hello {} in the {} world ", - "msg_named": "{} are written in the {lang} language", - "clickMe": "Click me", - "doNotUseRecentPassword": "لا تستخدم كلمة مرور حديثة", - "atLeastOneLowercase": "حرف صغير واحد على الأقل", - "atLeastOneUppercase": "حرف كبير واحد على الأقل", - "atLeastOneNumeric": "رقم واحد على الأقل", - "minimum8Characters": "8 أحرف على الأقل", - "doNotAddRepeatingLetters": "لا تقم بإضافة أحرف متكررة", - "itShouldContainSpecialCharacter": "يجب أن يحتوي على طابع خاص", - "confirmPasswordMustMatch": "يجب أن يتطابق تأكيد كلمة المرور", - "sms": "رسالة قصيرة", - "fingerPrint": "بصمة", - "face": "التعرف على الوجه", - "whatsapp": "واتس اب", - "reject": "يرفض", - "approve": "يوافق", - "cancel": "إلغاء", - "requestedItems": "العناصر المطلوبة", - "request": "طلب", - "myRequest": "طلبي", - "actions": "أجراءات", - "delegate": "مندوب", - "request_info": "اطلب معلومات", - "attachments": "المرفقات", - "info": "معلومات", - "employeeNumber": "رقم الموظف", - "assignmentNumber": "رقم الواجب", - "employeeName": "اسم الموظف", - "scheduleDate": "تاريخ الجدول الزمني", - "shiftType": "نوع التحول", - "shift": "يحول", - "breakText": "استراحة", - "actualSwipeStart": "بدء التمرير الفعلي", - "actualSwipeEnd": "التمرير الفعلي للنهاية", - "approvedSwipeStart": "وافق انتقاد البدء", - "approvedSwipeStartReason": "تمت الموافقة على سبب بدء التمرير السريع", - "approvedSwipeEnd": "تمت الموافقة على تمرير النهاية", - "approvedSwipeEndReason": "الموافقة على سبب إنهاء التمرير", - "from": "من", - "to": "ل", - "sent": "أرسلت", - "closed": "مغلق", - "id": "هوية شخصية", - "responder": "المستجيب", - "jobTitle": "عنوان وظيفي", - "grade": "درجة", - "jobCategory": "تصنيف الوظيفة", - "category": "فئة", - "employeeEmailAddress": "عنوان البريد الإلكتروني للموظف", - "payrollBranch": "فرع الرواتب", - "yourChangeHasBeenSavedSuccessfully": "تم حفظ التغيير الخاص بك بنجاح", - "code": "شفرة", - "unit": "وحدة", - "quantity": "كمية", - "dateRequired": "التاريخ مطلوب", - "lineStatus": "حالة الخط", - "statusDate": "تاريخ الحالة", - "transactionType": "نوع المعاملة", - "operatingUnit": "وحدة التشغيل", - "organizationCode": "كود المنظمة", - "organization": "منظمة", - "fromSubInventory": "من الجرد الفرعي", - "fromLocator": "من محدد المواقع", - "toSubInventory": "إلى الجرد الفرعي", - "toLocator": "إلى محدد المواقع", - "shipToLocator": "شحن إلى محدد المواقع", - "itemHistory": "تاريخ العنصر", - "mfg": "مبدع", - "lineType": "نوع الخط", - "price": "السعر", - "lineAmount": "مبلغ الخط", - "lineDiscount": "خصم الخط٪", - "needByDate": "القادمة إلى الأمام", - "promisedDate": "التسجيل وعد", - "deliverToLocation": "تسليم إلى الموقع", - "requisitionNumber": "رقم الطلب", - "requester": "مقدم الطلب", - "quotationAnalysis": "تحليل الاقتباس", - "subject": "موضوعات", - "description": "وصف", - "supplier": "المورد", - "site": "موقع", - "buyer": "مشتر", - "preparer": "معد", - "creationDate": "تاريخ الإنشاء", - "shipToLocation": "الشحن الى الموقع", - "quotationNumber": "رقم الإقتباس", - "quotationDate": "تاريخ الاقتباس", - "paymentTerms": "شروط الدفع", - "currency": "عملة", - "grossAmount": "المبلغ الإجمالي", - "discountAmount": "مقدار الخصم", - "customDuty": "الرسوم الجمركية", - "shipHandle": "مقبض السفينة", - "otherCharges": "رسوم أخرى", - "totalPOAmountWithVAT": "إجمالي مبلغ الشراء مع ضريبة القيمة المضافة", - "totalPOAmountInWords": "إجمالي مبلغ أمر الشراء بالكلمات", - "requestNumber": "رقم الطلب", - "uom": "UOM", - "operatingCode": "كود التشغيل", - "poNumber": "PO عدد", - "revision": "مراجعة", - "quantityOrdered": "الكمية المطلوبة", - "quantityReceived": "الكمية المستلمة", - "bonusQuantity": "كمية المكافأة", - "purchasePrice": "سعر الشراء", - "discountPer": "خصم ٪", - "balanceQuantity": "كمية التوازن", - "netPrice": "السعر الصافي", - "closureStatus": "حالة الإغلاق", - "quotationNetPrice": "صافي سعر الاقتباس", - "quotationUOM": "اقتباس UOM", - "quotationQty": "اقتباس الكمية", - "itemCode": "رمز الصنف", - "vendorName": "اسم البائع", - "quotationMFGPartNumber": "رقم الجزء MFG الاقتباس", - "quotationDeliveryDate": "تاريخ تسليم عرض الأسعار", - "quotationBonusQuantity": "كمية مكافأة الاقتباس", - "quotationLineTotal": "مجموع خط الاقتباس", - "rfqUOM": "RFQ UOM", - "rfqQty": "RFQ الكمية", - "rfqNumber": "رقم RFQ", - "human": "بشري", - "resources": "موارد", - "details": "تفاصيل", - "noDataAvailable": "لا تتوافر بيانات", - "productName": "اسم المنتج", - "productDescription": "وصف المنتج", - "unitPrice": "سعر الوحده", - "manufacturerName": "اسم المصنع", - "manufacturerPartName": "اسم جزء الشركة المصنعة", - "supplierName": "اسم المورد", - "supplierContact": "الاتصال بالمورد", - "chargeToPatient": "المسؤول عن المريض", - "justification": "التبرير", - "itemDescription": "وصف السلعة", - "groupCode": "كود المجموعة", - "primaryUOM": "UOM الابتدائية", - "subgroupDescription": "وصف المجموعة الفرعية", - "subgroupCode": "رمز المجموعة الفرعية", - "groupDescription": "وصف المجموعة", - "templateName": "اسم القالب", - "itemCreationStatus": "حالة إنشاء العنصر", - "standardizationApprovalStatus": "حالة الموافقة على التقييس", - "standardizationApprovalRejectionReason": "سبب رفض الموافقة على التقييس", - "analyzedBy": "تحليل بواسطة", - "approvedDate": "تاريخ الموافقة", - "itemType": "نوع العنصر", - "relatedTo": "متعلق ب", - "requestDate": "تاريخ الطلب", - "analyzedDate": "تاريخ التحليل", - "urgent": "العاجلة", - "requestDetails": "طلب تفاصيل", - "approvalLevel": "مستوى الموافقة", - "requesterDetails": "تفاصيل مقدم الطلب", - "myAttendance": "حضوري", - "workOnBreak": "التعويض عن العمل اثناءالاستراحه", - "next": "التالي", - "apply": "يتقدم", - "mobile": "التليفون المحمول", - "completingYear": "نحن نقدر لك لاستكمال خدمة", - "year": "سنة", - "month": "شهر", - "day": "يوم", - "address": "العنوان", - "phoneNumber": "رقم الجوال", - "businessGroup": "مجموعة العمل", - "Payroll": "الراتب", - "civilIdentityNumber": "رقم الهويه", - "dateOfBirth": "تاريخ الميلاد", - "maritalStatus ": "الحالة الاجتماعية", - "fullName": "الأسم الكامل", - "remove": "حذف", - "submit": "ارسال", - "areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟", - "comments": "تعليقات", - "writeComment": "أكتب تعليقا", - "approversList": "قائمة الموافقين", - "yourRequestHasBeenSubmittedForApprovals": "تم تقديم طلبك للموافقات", - "monthlyPaySlip": "قسيمة الراتب الشهرية", - "particular": "خاص", - "earnings": "أرباح", - "deductions": "الخصومات", - "paymentMethodName": "اسم طريقة الدفع", - "bankName": "اسم البنك", - "branchCode": "رمز الفرع", - "accountNo": "رقم الحساب", - "summaryOfInformation": "ملخص المعلومات", - "totalPayAmount": "المبلغ الإجمالي للدفع", - "paymentInformation": "معلومات الدفع", - "performance": "تقييم الاداء", - "performanceEvaluation": "تقييم الأداء في", - "performanceEvaluationIn": "تقييم أدائك في", - "valuationIn": "تقييم الأداء في", - "amount": "مقدار", - "correctCurrentDatails": "تعديل او اكمال التفاصيل الحالية", - "selectType": " حدد نوع التغيير الذي تريد القيام به", - "enterNewInfo": " أدخل معلومات جديدة بسبب تغيير حقيقي في التفاصيل الحالية (على سبيل المثال بسبب تغيير في الحالة الاجتماعية", - "endDate": "تاريخ الانتهاء", - "removeThisMember": "هل انت متأكد تريد ازالة هذا العضو؟", - "wantUpdateThisMember ": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", - "addNewFamilyMember": "اضافة عضو جديد", - "addRow": "اضافة صف جديد", - "pleaseSelect": "الرجاء اختيار", - "delete": "حذف", - "edit": "تعديل", - "add": "اضافه", - "myProfile": "معلوماتي", - "mowadhafhi": "موظفي", - "searchAnnouncements": "بحث الاعلانات", - "announcements": "اعلانات", - "swipeRequest": "طلب تسجيل حضور", - "serviceType": "نوع الخدمه", - "departmentName": "اسم القسم", - "selectDepartment": "اختر القسم", - "relatedSection": "قسم ذو صله", - "selectSection": "اختيار القسم", - "relatedTopic": "عنوان ذو صله", - "selectTopic": "اختر العنوان", - "supportingDocument": "ارفاق مستند", - "mowadhafhiRequest": "طلب موظفي", - "ticketReference": "مرجع التذكره", - "section": "القسم", - "topic": "العنوان", - "actionBy": "الرد بواسطة", - "pending": "معلق", - "pendingTransactions": "المعاملات المعلقه", - "selectRequestType": "الرجاء اختيار نوع الطلب", - "dateFrom": "من تاريخ", - "dateTo": "الى تاريخ", - "requestName": "اسم الطلب", - "createdFor": "انشاء لأجل", - "requestCreatedSuccessfully": "تم انشاء الطلب بنجاح", - "search": "بحث", - "wantToReject": "هل انت متأكد تريد الرفض", - "requestType": "نوع الطلب", - "employeeDigitalID": "هويةالموظف الرقمية", - "businessCard": "بطاقة العمل", - "viewBusinessCard": "عرض بطاقة العمل", - "logout": "تسجيل خروج", - "checkOut": "وقت الخروج", - "regular": "منتظم", - "mark": "علامة", - "selectMethodOfAttendance": "اختر طريقة تسجيل الحضور", - "comeNearHMGWifi": "HMG wifi من فضلك اقترب من", - "deliverNotificationToMeRegardless": "تسليم الإخطارات إلي بغض النظر عن أي قواعد عامة", - "close": "أغلق", - "respond": "يرد", - "vacationRuleAdded": "تمت إضافة قاعدة الإجازة", - "selectTypeT": "اختر صنف", - "notification": "تنبيه", - "selectNotification": "حدد إعلام", - "ifAllSelectedYouWillSkip": "* إذا تم تحديد الكل ، فستنتقل إلى الخطوة 3", - "applyForVacationRule": "التقدم بطلب للحصول على قانون الإجازة", - "step1": "الخطوة 1", - "step2": "الخطوة 2", - "step3": "الخطوه 3", - "message": "رسالة", - "writeAMessage": "اكتب رسالة", - "notificationReassign": "إعادة تعيين الإخطار", - "selectEmployee": "حدد الموظف", - "searchEmployeeForReplacement": "ابحث عن موظف بديل", - "searchForEmployee": "ابحث عن موظف", - "pleaseSpecifyEndTime": "الرجاء تحديد وقت الانتهاء", - "pleaseSelectNotificationReassign": "يرجى تحديد إعادة تعيين الإخطار", - "pleaseSelectEmployeeForReplacement": "الرجاء تحديد موظف للاستبدال", - "pleaseSelectAction": "الرجاء تحديد الإجراء", - "pleaseSelectDate": "الرجاء تحديد التاريخ", - "todayAttendance": "حضور اليوم", - "viewAttendance": "عرض الحضور", - "teamMembers": "اعضاءالفريق", - "profileDetails": "الملف الشخصي", - "noResultsFound": "لايوجد نتائج", - "searchBy": "بحث بواسطة", - "myTeamMembers": "اعضاء فريقي", - "save": "حفظ", - "TurnNotificationsFor": "تفعيل الاشعارات", - "worklistSettings": "اعدادات الاشعارات", - "absenceType": "نوع الغياب", - "absenceCategory": "فئة الغياب", - "days": "أيام", - "hours": "ساعات", - "approvalStatus": "حالة القبول", - "absenceStatus": "حالة الغياب", - "subordinateLeave": "إجازة التابعيين", - "numberDays": "عدد الأيام", - "poweredBy": "مشغل بواسطة", - "cloudSolutions": "حلول السحابة", - "selectTemplate": "حدد قالب", - "myPostedAds": "إعلاناتي المنشورة", - "browseCategories": "تصفح الفئات", - "searchItems": "عناصر البحث", - "offerAndDiscounts": "العروض والخصومات", - "offerValid": "العرض صالح", - "offerExpired": "انتهى العرض", - "whatAreYouOffering": "ما الذي تعرضه؟", - "selectCategory": "اختر الفئة", - "inProgress": "في تَقَدم", - "locked": "مقفل", - "addDetails": "أضف التفاصيل", - "reviewAndSell": "مراجعة وبيع", - "itemTitle": "عنوان البند", - "itemCondition": "حالة السلعة", - "used": "تستخدم", - "region": "منطقة", - "selectRegion": "اختر المنطقة", - "itemPrice": "سعر السلعة", - "itemPhotos": "صور البند", - "itemInfo": "معلومات العنصر", - "uploadAttachment": "تحميل المرفق", - "selectFromGalleryOrOpenCamera": "اختر من المعرض أو فتح الكاميرا", - "openCamera": "فتح\nالكاميرا", - "uploadFromGallery": "تحميل من\nملفات الجهاز", - "name": "الأسم", - "email": "ايميل", - "noHistoryAvailable": "لايوجد سجل بيانات سابقة ", - "purchaseRequisition": "طلب شراء", - "moveOrder": "طلب تغيير", - "humanResource": "الموارد البشريه", - "purchaseOrder": "امر شراء", - "ITGForms": "ITG نماذج", - "itemCreation": "أنشاء عنصر", - "stamp": "ختم", - "addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله", - "feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم", - "rateUI": "كيف تريد أن تقيم", - "rateUI2": "ما مدى رضائك عن هذا التطبيق", - "submitSurvey": "ارسال الاستبيان", - "typeHere": "اكتب هنا", - "infoDetail": "تفاصيل المعلومات", - "amount_detail": "تفاصيل المبلغ", - "currentBalance": "الرصيد الحالي", - "currentLeaveBalance": "رصيد الاجازات الحالي", - "calculatedDays": "الايام المحسوبه", - "totalDays": "مجموع الأيام", - "usedBalance": "المستخدم", - "infants": "رضيع", - "child": "طفل", - "adult": "بالغ", - "updateMember": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", - "fieldIsEmpty": "'{data}' الحقل فارغ. الرجاء التحديد", - "pleaseEnterComments": "الرجاء إدخال التعليقات", - "skip": "يتخطى", - "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", - "currentPassword": "كلمة المرور الحاليه", - "concurrentReports": "التقارير المتزامنه", - "EnterNewAddressMoved": "أدخل عنوان جديد إذا كنت قد انتقلت", - "CorrectAddress": "تصحيح أو تعديل هذا العنوان", - "SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.", - "profile": { - "reset_password": {"label": "Reset Password", "username": "Username", "password": "password"}, - "profileCompletionPer": "استكمال الملف الشخصي", - "completeProfile": "الملف الشخصي الكامل", - "personalInformation": "معلومات شخصية", - "basicDetails": "تفاصيل أساسية", - "address": "العنوان", - "contactDetails": "بيانات التواصل", - "familyDetails": "تفاصيل عائلية", - "effectiveDate": "تاريخ النفاذ", - "country": "دولة" - }, - "clicked": { - "zero": "You clicked {} times!", - "one": "You clicked {} time!", - "two": "You clicked {} times!", - "few": "You clicked {} times!", - "many": "You clicked {} times!", - "other": "You clicked {} times!" + static const Map _ar_SA = { + "mohemm": "Mohemm", + "english": "English", + "arabic": "عربي", + "login": "تسجيل الدخول", + "pleaseEnterLoginDetails": "الرجاء إدخال التفاصيل أدناه لتسجيل الدخول", + "userId": "UserID", + "username": "اسم المستخدم", + "userName": "اسم المستخدم", + "userSearch": "User Search", + "password": "كلمة المرور", + "welcomeBack": "مرحبا بعودتك", + "wouldYouLikeToLoginWithCurrentUsername": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟", + "lastLoginDetails": "تفاصيل تسجيل الدخول الأخير:", + "verificationType": "نوع التحقق:", + "pleaseVerify": "ارجوك تحقق", + "pleaseVerifyForBio": "الرجاء التحقق من تسجيل الدخول باستخدام أحد هذه الخيارات", + "verifyThroughFace": "تحقق من خلال الوجه", + "verifyThroughFingerprint": "تحقق من خلال بصمة الإصبع", + "verifyThroughSMS": "تحقق من خلال الرسائل القصيرة", + "verifyThroughWhatsapp": "تحقق من خلال Whatsapp", + "useAnotherAccount": "استخدم حسابا آخر", + "pleaseEnterTheVerificationCodeSentTo": "الرجاء إدخال رمز التحقق المرسل إلى ", + "theVerificationCodeWillExpireIn": "ستنتهي صلاحية رمز التحقق في ", + "goodMorning": "صباح الخير", + "markAttendance": "علامة الحضور", + "timeLeftToday": "الوقت المتبقي اليوم", + "checkIn": "تحقق في", + "workList": "قائمة العمل", + "leaveBalance": "رصيد الاجازات", + "missingSwipes": "تسجيل بصمة حضور", + "ticketBalance": "رصيد التذكرة", + "other": "آخر", + "services": "خدمات", + "viewAllServices": "عرض جميع الخدمات", + "monthlyAttendance": "الحضور الشهري", + "vacationRule": "قاعدة الاجازات", + "vacationType": "نوع الاجازة", + "startDateT": "تاريخ البدء", + "endDateT": "تاريخ الانتهاء", + "workFromHome": "العمل من المنزل", + "ticketRequest": "طلب تذكرة", + "viewAllOffers": "مشاهدة جميع العروض", + "offers": "عروض & ", + "discounts": "الخصومات", + "newString": "جديد", + "setTheNewPassword": "قم بتعيين كلمة المرور الجديدة", + "typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه", + "typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه", + "confirmPassword": "تأكيد كلمة المرور", + "update": "تحديث", + "title": "عنوان", + "home": "الرئيسية", + "mySalary": "راتبي", + "createRequest": "إنشاء طلب", + "forgotPassword": "هل نسيت كلمة السر", + "employeeId": "هوية الموظف", + "loginCodeWillSentToMobileNumber": "الرجاء إدخال معرف الموظف الخاص بك ، وسيتم إرسال رمز تسجيل الدخول إلى رقم هاتفك المحمول", + "changePassword": "تغيير كلمة المرور", + "ok": "موافق", + "confirm": "تؤكد", + "passwordChangedSuccessfully": "تم تغيير الرقم السري بنجاح", + "itemsForSale": "سلع للبيع", + "attendanceDetails": "تفاصيل الحضور", + "order": "الطلبات", + "earlyOut": "الخروج مبكرا", + "shortage": "ساعات التقصير", + "excess": "فائض", + "lateIn": "القدوم المتاخر", + "approvedCheckOut": "اعتماد وقت الخروج", + "approvedCheckIn": "اعتماد وقت الدخول", + "actualCheckOut": "وقت الخروج", + "actualCheckIn": "وقت الدخول", + "present": "حضور", + "pres": "حضور", + "shiftTime": "وقت التناوب", + "absent": "غياب", + "attendance": "الحضور", + "scheduleDays": "ايام العمل", + "offDays": "ايام الراحه", + "nonAnalyzed": "لايوجد تحليل", + "shortageHour": "ساعات التقصير", + "stats": "الحاله", + "completed": "تم اكمال", + "msg": "Hello {} in the {} world ", + "msg_named": "{} are written in the {lang} language", + "clickMe": "Click me", + "doNotUseRecentPassword": "لا تستخدم كلمة مرور حديثة", + "atLeastOneLowercase": "حرف صغير واحد على الأقل", + "atLeastOneUppercase": "حرف كبير واحد على الأقل", + "atLeastOneNumeric": "رقم واحد على الأقل", + "minimum8Characters": "8 أحرف على الأقل", + "doNotAddRepeatingLetters": "لا تقم بإضافة أحرف متكررة", + "itShouldContainSpecialCharacter": "يجب لا يحتوي على أحرف خاصة", + "confirmPasswordMustMatch": "يجب أن يتطابق تأكيد كلمة المرور", + "sms": "رسالة قصيرة", + "fingerPrint": "بصمة", + "face": "التعرف على الوجه", + "whatsapp": "واتس اب", + "reject": "يرفض", + "approve": "يوافق", + "cancel": "إلغاء", + "generate": "يولد", + "requestedItems": "العناصر المطلوبة", + "request": "طلب", + "myRequest": "طلبي", + "actions": "أجراءات", + "delegate": "مندوب", + "request_info": "اطلب معلومات", + "attachments": "المرفقات", + "info": "معلومات", + "employeeNumber": "رقم الموظف", + "assignmentNumber": "رقم الواجب", + "employeeName": "اسم الموظف", + "scheduleDate": "تاريخ الجدول الزمني", + "shiftType": "نوع التحول", + "shift": "يحول", + "breakText": "استراحة", + "actualSwipeStart": "بدء التمرير الفعلي", + "actualSwipeEnd": "التمرير الفعلي للنهاية", + "approvedSwipeStart": "وافق انتقاد البدء", + "approvedSwipeStartReason": "تمت الموافقة على سبب بدء التمرير السريع", + "approvedSwipeEnd": "تمت الموافقة على تمرير النهاية", + "approvedSwipeEndReason": "الموافقة على سبب إنهاء التمرير", + "from": "من", + "to": "ل", + "sent": "أرسلت", + "closed": "مغلق", + "id": "هوية شخصية", + "responder": "المستجيب", + "jobTitle": "عنوان وظيفي", + "grade": "درجة", + "jobCategory": "تصنيف الوظيفة", + "category": "فئة", + "employeeEmailAddress": "عنوان البريد الإلكتروني للموظف", + "payrollBranch": "فرع الرواتب", + "yourChangeHasBeenSavedSuccessfully": "تم حفظ التغيير الخاص بك بنجاح", + "code": "شفرة", + "unit": "وحدة", + "quantity": "كمية", + "dateRequired": "التاريخ مطلوب", + "lineStatus": "حالة الخط", + "statusDate": "تاريخ الحالة", + "transactionType": "نوع المعاملة", + "operatingUnit": "وحدة التشغيل", + "organizationCode": "كود المنظمة", + "organization": "منظمة", + "fromSubInventory": "من الجرد الفرعي", + "fromLocator": "من محدد المواقع", + "toSubInventory": "إلى الجرد الفرعي", + "toLocator": "إلى محدد المواقع", + "shipToLocator": "شحن إلى محدد المواقع", + "itemHistory": "تاريخ العنصر", + "mfg": "مبدع", + "lineType": "نوع الخط", + "price": "السعر", + "lineAmount": "مبلغ الخط", + "lineDiscount": "خصم الخط٪", + "needByDate": "القادمة إلى الأمام", + "promisedDate": "التسجيل وعد", + "deliverToLocation": "تسليم إلى الموقع", + "requisitionNumber": "رقم الطلب", + "requester": "مقدم الطلب", + "quotationAnalysis": "تحليل الاقتباس", + "subject": "موضوعات", + "description": "وصف", + "pleaseEnterDescription": "الرجاء إدخال الوصف", + "supplier": "المورد", + "site": "موقع", + "buyer": "مشتر", + "preparer": "معد", + "creationDate": "تاريخ الإنشاء", + "shipToLocation": "الشحن الى الموقع", + "quotationNumber": "رقم الإقتباس", + "quotationDate": "تاريخ الاقتباس", + "paymentTerms": "شروط الدفع", + "currency": "عملة", + "grossAmount": "المبلغ الإجمالي", + "discountAmount": "مقدار الخصم", + "customDuty": "الرسوم الجمركية", + "shipHandle": "مقبض السفينة", + "otherCharges": "رسوم أخرى", + "totalPOAmountWithVAT": "إجمالي مبلغ الشراء مع ضريبة القيمة المضافة", + "totalPOAmountInWords": "إجمالي مبلغ أمر الشراء بالكلمات", + "requestNumber": "رقم الطلب", + "uom": "UOM", + "operatingCode": "كود التشغيل", + "poNumber": "PO عدد", + "revision": "مراجعة", + "quantityOrdered": "الكمية المطلوبة", + "quantityReceived": "الكمية المستلمة", + "bonusQuantity": "كمية المكافأة", + "purchasePrice": "سعر الشراء", + "discountPer": "خصم ٪", + "balanceQuantity": "كمية التوازن", + "netPrice": "السعر الصافي", + "closureStatus": "حالة الإغلاق", + "quotationNetPrice": "صافي سعر الاقتباس", + "quotationUOM": "اقتباس UOM", + "quotationQty": "اقتباس الكمية", + "itemCode": "رمز الصنف", + "vendorName": "اسم البائع", + "quotationMFGPartNumber": "رقم الجزء MFG الاقتباس", + "quotationDeliveryDate": "تاريخ تسليم عرض الأسعار", + "quotationBonusQuantity": "كمية مكافأة الاقتباس", + "quotationLineTotal": "مجموع خط الاقتباس", + "rfqUOM": "RFQ UOM", + "rfqQty": "RFQ الكمية", + "rfqNumber": "رقم RFQ", + "human": "بشري", + "resources": "موارد", + "details": "تفاصيل", + "noDataAvailable": "لا تتوافر بيانات", + "productName": "اسم المنتج", + "productDescription": "وصف المنتج", + "unitPrice": "سعر الوحده", + "manufacturerName": "اسم المصنع", + "manufacturerPartName": "اسم جزء الشركة المصنعة", + "supplierName": "اسم المورد", + "supplierContact": "الاتصال بالمورد", + "chargeToPatient": "المسؤول عن المريض", + "justification": "التبرير", + "itemDescription": "وصف السلعة", + "groupCode": "كود المجموعة", + "primaryUOM": "UOM الابتدائية", + "subgroupDescription": "وصف المجموعة الفرعية", + "subgroupCode": "رمز المجموعة الفرعية", + "groupDescription": "وصف المجموعة", + "templateName": "اسم القالب", + "itemCreationStatus": "حالة إنشاء العنصر", + "standardizationApprovalStatus": "حالة الموافقة على التقييس", + "standardizationApprovalRejectionReason": "سبب رفض الموافقة على التقييس", + "analyzedBy": "تحليل بواسطة", + "approvedDate": "تاريخ الموافقة", + "itemType": "نوع العنصر", + "relatedTo": "متعلق ب", + "requestDate": "تاريخ الطلب", + "analyzedDate": "تاريخ التحليل", + "urgent": "العاجلة", + "requestDetails": "طلب تفاصيل", + "approvalLevel": "مستوى الموافقة", + "requesterDetails": "تفاصيل مقدم الطلب", + "myAttendance": "حضوري", + "workOnBreak": "التعويض عن العمل اثناءالاستراحه", + "next": "التالي", + "apply": "يتقدم", + "mobile": "التليفون المحمول", + "completingYear": "نحن نقدر لك لاستكمال خدمة", + "year": "سنة", + "month": "شهر", + "day": "يوم", + "address": "العنوان", + "phoneNumber": "رقم الجوال", + "businessGroup": "مجموعة العمل", + "Payroll": "الراتب", + "civilIdentityNumber": "رقم الهويه", + "dateOfBirth": "تاريخ الميلاد", + "maritalStatus ": "الحالة الاجتماعية", + "fullName": "الأسم الكامل", + "remove": "حذف", + "submit": "ارسال", + "submitAsAnonymous": "إرسال كمجهول", + "areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟", + "comments": "تعليقات", + "writeComment": "أكتب تعليقا", + "approversList": "قائمة الموافقين", + "yourRequestHasBeenSubmittedForApprovals": "تم تقديم طلبك للموافقات", + "monthlyPaySlip": "قسيمة الراتب الشهرية", + "particular": "خاص", + "earnings": "أرباح", + "deductions": "الخصومات", + "paymentMethodName": "اسم طريقة الدفع", + "bankName": "اسم البنك", + "branchCode": "رمز الفرع", + "accountNo": "رقم الحساب", + "summaryOfInformation": "ملخص المعلومات", + "totalPayAmount": "المبلغ الإجمالي للدفع", + "paymentInformation": "معلومات الدفع", + "performance": "تقييم الاداء", + "performanceEvaluation": "تقييم الأداء في", + "performanceEvaluationIn": "تقييم أدائك في", + "valuationIn": "تقييم الأداء في", + "amount": "مقدار", + "correctCurrentDatails": "تعديل او اكمال التفاصيل الحالية", + "selectType": " حدد نوع التغيير الذي تريد القيام به", + "enterNewInfo": " أدخل معلومات جديدة بسبب تغيير حقيقي في التفاصيل الحالية (على سبيل المثال بسبب تغيير في الحالة الاجتماعية", + "endDate": "تاريخ الانتهاء", + "removeThisMember": "هل انت متأكد تريد ازالة هذا العضو؟", + "wantUpdateThisMember ": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", + "addNewFamilyMember": "اضافة عضو جديد", + "addRow": "اضافة صف جديد", + "pleaseSelect": "الرجاء اختيار", + "delete": "حذف", + "edit": "تعديل", + "add": "اضافه", + "myProfile": "معلوماتي", + "mowadhafhi": "موظفي", + "searchAnnouncements": "بحث الاعلانات", + "announcements": "اعلانات", + "swipeRequest": "طلب تسجيل حضور", + "serviceType": "نوع الخدمه", + "departmentName": "اسم القسم", + "selectDepartment": "اختر القسم", + "relatedSection": "قسم ذو صله", + "selectSection": "اختيار القسم", + "relatedTopic": "عنوان ذو صله", + "selectTopic": "اختر العنوان", + "supportingDocument": "ارفاق مستند", + "mowadhafhiRequest": "طلب موظفي", + "ticketReference": "مرجع التذكره", + "section": "القسم", + "topic": "العنوان", + "actionBy": "الرد بواسطة", + "pending": "معلق", + "pendingTransactions": "المعاملات المعلقه", + "selectRequestType": "الرجاء اختيار نوع الطلب", + "dateFrom": "من تاريخ", + "dateTo": "الى تاريخ", + "requestName": "اسم الطلب", + "createdFor": "انشاء لأجل", + "requestCreatedSuccessfully": "تم انشاء الطلب بنجاح", + "search": "بحث", + "wantToReject": "هل انت متأكد تريد الرفض", + "requestType": "نوع الطلب", + "employeeDigitalID": "هويةالموظف الرقمية", + "businessCard": "بطاقة العمل", + "viewBusinessCard": "عرض بطاقة العمل", + "logout": "تسجيل خروج", + "checkOut": "وقت الخروج", + "regular": "منتظم", + "mark": "علامة", + "selectMethodOfAttendance": "اختر طريقة تسجيل الحضور", + "comeNearHMGWifi": "HMG wifi من فضلك اقترب من", + "deliverNotificationToMeRegardless": "تسليم الإخطارات إلي بغض النظر عن أي قواعد عامة", + "close": "أغلق", + "respond": "يرد", + "vacationRuleAdded": "تمت إضافة قاعدة الإجازة", + "selectTypeT": "اختر صنف", + "notification": "تنبيه", + "selectNotification": "حدد إعلام", + "ifAllSelectedYouWillSkip": "* إذا تم تحديد الكل ، فستنتقل إلى الخطوة 3", + "applyForVacationRule": "التقدم بطلب للحصول على قانون الإجازة", + "step1": "الخطوة 1", + "step2": "الخطوة 2", + "step3": "الخطوه 3", + "message": "رسالة", + "writeAMessage": "اكتب رسالة", + "notificationReassign": "إعادة تعيين الإخطار", + "selectEmployee": "حدد الموظف", + "searchEmployeeForReplacement": "ابحث عن موظف بديل", + "searchForEmployee": "ابحث عن موظف", + "pleaseSpecifyEndTime": "الرجاء تحديد وقت الانتهاء", + "pleaseSelectNotificationReassign": "يرجى تحديد إعادة تعيين الإخطار", + "pleaseSelectEmployeeForReplacement": "الرجاء تحديد موظف للاستبدال", + "pleaseSelectAction": "الرجاء تحديد الإجراء", + "pleaseSelectDate": "الرجاء تحديد التاريخ", + "todayAttendance": "حضور اليوم", + "viewAttendance": "عرض الحضور", + "teamMembers": "اعضاءالفريق", + "profileDetails": "الملف الشخصي", + "noResultsFound": "لايوجد نتائج", + "searchBy": "بحث بواسطة", + "myTeamMembers": "اعضاء فريقي", + "save": "حفظ", + "TurnNotificationsFor": "تفعيل الاشعارات", + "worklistSettings": "اعدادات الاشعارات", + "absenceType": "نوع الغياب", + "absenceCategory": "فئة الغياب", + "days": "أيام", + "hours": "ساعات", + "approvalStatus": "حالة القبول", + "absenceStatus": "حالة الغياب", + "subordinateLeave": "إجازة التابعيين", + "numberDays": "عدد الأيام", + "poweredBy": "مشغل بواسطة", + "cloudSolutions": "حلول السحابة", + "selectTemplate": "حدد قالب", + "myPostedAds": "إعلاناتي المنشورة", + "browseCategories": "تصفح الفئات", + "searchItems": "عناصر البحث", + "offerAndDiscounts": "العروض والخصومات", + "offerValid": "العرض صالح", + "offerExpired": "انتهى العرض", + "whatAreYouOffering": "ما الذي تعرضه؟", + "selectCategory": "اختر الفئة", + "inProgress": "في تَقَدم", + "locked": "مقفل", + "addDetails": "أضف التفاصيل", + "reviewAndSell": "مراجعة وبيع", + "itemTitle": "عنوان البند", + "itemCondition": "حالة السلعة", + "used": "تستخدم", + "region": "منطقة", + "selectRegion": "اختر المنطقة", + "itemPrice": "سعر السلعة", + "itemPhotos": "صور البند", + "itemInfo": "معلومات العنصر", + "uploadAttachment": "تحميل المرفق", + "selectFromGalleryOrOpenCamera": "اختر من المعرض أو فتح الكاميرا", + "openCamera": "فتح\nالكاميرا", + "uploadFromGallery": "تحميل من\nملفات الجهاز", + "name": "الأسم", + "email": "ايميل", + "noHistoryAvailable": "لايوجد سجل بيانات سابقة ", + "purchaseRequisition": "طلب شراء", + "moveOrder": "طلب تغيير", + "humanResource": "الموارد البشريه", + "purchaseOrder": "امر شراء", + "ITGForms": "ITG نماذج", + "itemCreation": "أنشاء عنصر", + "stamp": "ختم", + "addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله", + "feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم", + "rateUI": "كيف تريد أن تقيم", + "rateUI2": "ما مدى رضائك عن هذا التطبيق", + "submitSurvey": "ارسال الاستبيان", + "typeHere": "اكتب هنا", + "infoDetail": "تفاصيل المعلومات", + "amount_detail": "تفاصيل المبلغ", + "currentBalance": "الرصيد الحالي", + "currentLeaveBalance": "رصيد الاجازات الحالي", + "calculatedDays": "الايام المحسوبه", + "totalDays": "مجموع الأيام", + "usedBalance": "المستخدم", + "infants": "رضيع", + "child": "طفل", + "adult": "بالغ", + "updateMember": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", + "fieldIsEmpty": "'{data}' الحقل فارغ. الرجاء التحديد", + "pleaseEnterComments": "الرجاء إدخال التعليقات", + "skip": "يتخطى", + "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", + "currentPassword": "كلمة المرور الحاليه", + "concurrentReports": "التقارير المتزامنه", + "EnterNewAddressMoved": "أدخل عنوان جديد إذا كنت قد انتقلت", + "CorrectAddress": "تصحيح أو تعديل هذا العنوان", + "SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.", + "profile": { + "reset_password": { + "label": "Reset Password", + "username": "Username", + "password": "password" }, - "gender": { - "male": "Hi man ;) ", - "female": "Hello girl :)", - "with_arg": {"male": "Hi man ;) {}", "female": "Hello girl :) {}"} + "profileCompletionPer": "استكمال الملف الشخصي", + "completeProfile": "الملف الشخصي الكامل", + "personalInformation": "معلومات شخصية", + "basicDetails": "تفاصيل أساسية", + "address": "العنوان", + "contactDetails": "بيانات التواصل", + "familyDetails": "تفاصيل عائلية", + "effectiveDate": "تاريخ النفاذ", + "country": "دولة" + }, + "clicked": { + "zero": "You clicked {} times!", + "one": "You clicked {} time!", + "two": "You clicked {} times!", + "few": "You clicked {} times!", + "many": "You clicked {} times!", + "other": "You clicked {} times!" + }, + "gender": { + "male": "Hi man ;) ", + "female": "Hello girl :)", + "with_arg": { + "male": "Hi man ;) {}", + "female": "Hello girl :) {}" + } + }, + "reset_locale": "إعادة ضبط اللغة", + "chat": "دردشة", + "mychats": "دردشاتي", + "advancedSearch": "بحث متقدم", + "openNot": "التبليغات المفتوحة", + "fyi": "تبليغات للعلم", + "toDo": "تبليغات الأعمال", + "all": "كل التبليغات", + "meNot": "تبليغات صادرة مني", + "view": "عرض", + "fromUserName": "من", + "sentDate": "تاريخ الإرسال", + "itemTypeDisplayName": "اسم العرض", + "none": "بدون", + "createNewChat": "إنشاء محادثة جديدة", + "brainMarathon": "ماراثون الدماغ", + "contestTopicAbout": "سيكون موضوع المسابقة حول:", + "gameDate": "تاريخ اللعبة:", + "gameTime": "وقت اللعب:", + "joinMarathon": "انضم إلى ماراثون", + "joinDemoMarathon": "انضم إلى الماراثون التجريبي", + "demo": "تجريبي", + "minutes": "الدقائق", + "seconds": "ثواني", + "note": "ملحوظة:", + "demoMarathonNoteP1": "يمكنك لعب ماراثون العرض لتتعلم كيف يعمل. يمكنك الانضمام إلى ماراثون", + "demoMarathonNoteP2": "خمس دقائق", + "demoMarathonNoteP3": "قبل الوقت الفعلي.", + "sponsoredBy": "برعاية:", + "question": "سؤال", + "marathoners": "الماراثون", + "marathoner": "ماراثونر", + "prize": "جائزة:", + "winnerSelection": "اختيار الفائز", + "qualifiers": "تصفيات", + "qualifier": "المؤهل", + "getReadyForContest": "استعد للمسابقة القادمة:", + "winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.", + "fingersCrossed": "تشابك الاصابع!!!", + "congrats": "مبروك !!!", + "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح.", + "otp": "OTP", + "verification": "تَحَقّق", + "resend": "إعادة إرسال", + "codeExpire": "انتهت صلاحية رمز التحقق", + "typeheretoreply": "اكتب هنا للرد", + "favorite": "مفضلتي", + "searchfromchat": "البحث من الدردشة", + "yourAnswerCorrect": "إجابتك صحيحة", + "youMissedTheQuestion": "نفد منك الوقت. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", + "wrongAnswer": "إجابتك غير صحيحة. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", + "oops": "أوه!!!", + "winner": "الفائز", + "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", + "ourSponsor": "راعينا:", + "startingIn": "يبدأ في", + "youAreOutOfContest": "أنت خارج المسابقة.", + "winners": "الفائزين!!!", + "expireAfter": "تنتهي بعد", + "oneWeek": "أسبوع 1", + "twoWeek": "2 أسبوع", + "noUpcoming": "لا يوجد قادم", + "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية", + "noWinner": "حزين! لم يفز أحد اليوم.", + "myTeam": "فريقي", + "youCanPlayDemo": "لكن يمكنك لعب العرض", + "group": "مجموعة", + "searchGroup": "مجموعة البحث", + "connectHmgWifi": "قم بتوصيل HMG WIFI", + "connectedHmgWifi": "اتصال HMG WIFI", + "itgForms": "نماذج (ITG)", + "resetAdPassword": "إعادة تعيين كلمة مرور AD", + "myDocuments": "مستنداتي", + "requiredDocuments": "المستندات المطلوبة", + "optionalDocuments": "المستندات الاختيارية", + "allDocuments": "كافة المستندات", + "expiredDocuments": "المستندات منتهية الصلاحية", + "missingDocuments": "مستندات مفقودة", + "uploadedDocuments": "المستندات التي تم تحميلها", + "addAtLeastOneAttachment": "الرجاء إضافة مرفق واحد على الأقل.", + "pleaseClickButtonToJoinMarathon": "الرجاء الضغط على الزر أدناه للانضمام إلى الماراثون", + "youCannotJoinTheMarathon": "لا يمكنك الانضمام إلى الماراثون لأنك تجاوزت الحد الزمني", + "open": "يفتح", + "paymentRequest": "طلب الدفع", + "paymentDetails": "تفاصيل الدفع", + "requestNo": "رقم الطلب", + "requesterEmpNum": "رقم الموظف الذي قدم الطلب", + "requesterEmpName": "اسم الموظف مقدم الطلب", + "prepareEmpName": "إعداد اسم الموظف", + "requesterPositionName": "اسم الوظيفة لمقدم الطلب", + "preparePositionName": "إعداد اسم الوظيفة", + "requesterPayrollName": "اسم مقدم الطلب", + "payingORGName": "اسم المنظمة الدافعة", + "requestAmount": "مبلغ الطلب", + "typeofPayment": "نوع الدفع", + "beneficiaryDetails": "تفاصيل المستفيد", + "beneficiaryName": "اسم المستفيد", + "idIqama": "الهوية السعودية / الإقامة", + "beneficiaryBankName": "اسم البنك المستفيد", + "sadadNumber": "رقم سداد", + "beneficiaryIBAN": "رقم IBAN للمستفيد", + "purchaseOrders": "طلبات الشراء", + "approvalDate": "تاريخ الموافقة", + "pOAmount": "مبلغ الطلب", + "versionStatus": "حالة الإصدار", + "supplierNo": "رقم المورد", + "general": "عام", + "requesterOperatingUnit": "وحدة تشغيل مقدم الطلب", + "prepareEmpNum": "إعداد رقم الموظف", + "supplierInfo": "معلومات المورد", + "supplierAcNo": "رقم حساب المورد", + "supplierAcName": "اسم حساب المورد", + "supplierIBAN": "رقم IBAN للمورد", + "supplierCRNo": "رقم السجل التجاري", + "suppliedAcNo": "رقم الحساب المقدم", + "patientRefundInvoice": "فاتورة استرداد الأموال للمريض", + "patientNumber": "رقم المريض", + "patientName": "اسم المريض", + "invoiceDate": "تاريخ الفاتورة", + "refundInvoice": "فاتورة الاسترجاع", + "hospitalClinic": "عيادة المستشفى", + "graphicalAnalysis": "التحليل الرسومي", + "itemHistoryAnalysis": "تحليل تاريخ العنصر", + "pOno": "امر شراء #", + "oprUnit": "وحدة التشغيل", + "qtyOrdered": "الكمية المطلوبة", + "qtyReceived": "الكمية المستلمة", + "bonusQty": "كمية المكافأة", + "balQty": "كمية التوازن", + "videoCall": "مكالمة فيديو", + "addUsers": "إضافة مستخدمين إلى المجموعة", + "admin": "مشرف", + "areYouSureWantTodelete": "هل أنت متأكد أنك تريد الحذف؟", + "Attendance": "الحضور", + "audioCall": "مكالمة صوتية", + "editGroups": "تعديل المجموعة", + "enterGroupName": "يرجى إدخال اسم المجموعة الصحيح", + "enterGroupNamePlease": "يرجى إدخال اسم المجموعة", + "groupMembers": "أعضاء المجموعة", + "groupName": "اسم المجموعة", + "groupNameshouldbe": "يجب أن يتكون اسم المجموعة من 10 أحرف على الأقل", + "manage": "إدارة", + "manageGroup": "إدارة المجموعة", + "members": "الأعضاء", + "searchByUserName": "البحث بواسطة اسم المستخدم", + "shareScreen": "مشاركة الشاشة", + "start": "يبدأ", + "about": "عن", + "explore": "يستكشف", + "mazaya": "مازيا", + "benefits": "فوائد", + "mazayaDesc": "اكتشف الخصومات والعروض الخاصة المتاحة للموظفين", + "viewallofferMazaya": "أعرض كل المزايا", + "buyerName": "اسم المشتري", + "buyerNumber": "رقم المشتري", + "highestBidder": "أعلى مزايد", + "remarks": "ملاحظات", + "faHeader": "تفاصيل رأس الصفحة FA", + "bookTypeCode": "رمز نوع الكتاب", + "categoryCode": "رمز الفئة", + "categoryGroup": "مجموعة الفئات", + "faLINES": "تفاصيل الأصول", + "assetNumber": "رقم الأصول", + "assetDescription": "وصف الأصول", + "barCodeNumber": "رقم الباركود", + "datePlaceInService": "تاريخ وضعه في الخدمة", + "serialNumber": "رقم سري", + "disposedDate": "تاريخ التخلص", + "netBookValue": "القيمة الدفترية الصافية", + "purchasedPrice": "سعر الشراء", + "usefulLife": "العمر الإنتاجي", + "yearsUsed": "سنوات الاستخدام", + "faRequest": "طلب التخلص من FA", + "showMore": "عرض المزيد", + "ticketDetails": "تفاصيل التذكرة", + "currentTicketBalance": "رصيد التذكرة الحالي", + "ticketHistory": "تاريخ التذكرة", + "proceedBooking": "المتابعة للحجز", + "courses": "الدورات التدريبية", + "course": "دورة", + "status": "الحالة", + "deadline": "الموعد النهائي", + "overdue": "متأخر", + "noCoursesAvailable": "لا توجد دورات متاحة", + "pullToRefresh": "اسحب للتحديث", + "courseUrlNotAvailable": "رابط الدورة غير متوفر", + "buyerDetails": "تفاصيل المشتري", + "etqanOVR": "الإبلاغ عن حادثة", + "etqanRequest": "طلبات الحوادث", + "selectProject": "حدد المشروع", + "project": "مشروع", + "keen": "حريص", + "reportIncident": "الإبلاغ عن الحادث", + "myIncidents": "حوادثي", + "incidentDetails": "تفاصيل الحادث", + "ticketNumber": "رقم التذكرة", + "ticketId": "معرف التذكرة", + "pleaseSelectProject": "الرجاء اختيار مشروع", + "viewAttachment": "عرض المرفق", + "parkingQr": "وقوف السيارات QR", + "startNow": "ابدأ الآن" +}; +static const Map _en_US = { + "mohemm": "Mohemm", + "english": "English", + "arabic": "عربي", + "login": "Login", + "pleaseEnterLoginDetails": "Please enter the detail below to login", + "username": "Username", + "password": "Password", + "welcomeBack": "Welcome back", + "wouldYouLikeToLoginWithCurrentUsername": "Would you like to login with current Username?", + "lastLoginDetails": "Last Login Details:", + "verificationType": "Verification Type:", + "pleaseVerify": "Please Verify", + "pleaseVerifyForBio": "Please verify login with one of the following options", + "verifyThroughFace": "Verify Through Face", + "verifyThroughFingerprint": "Verify Through Fingerprint", + "verifyThroughSMS": "Verify Through SMS", + "verifyThroughWhatsapp": "Verify Through Whatsapp", + "useAnotherAccount": "Use Another Account", + "pleaseEnterTheVerificationCodeSentTo": "Please enter the verification code sent to ", + "theVerificationCodeWillExpireIn": "The verification code will expire in ", + "goodMorning": "Good Morning", + "markAttendance": "Mark Attendance", + "timeLeftToday": "Time Left Today", + "checkIn": "Check In", + "workList": "Work List", + "leaveBalance": "Leave Balance", + "missingSwipes": "Missing Swipes", + "ticketBalance": "Ticket Balance", + "other": "Other", + "services": "Services", + "viewAllServices": "View All Services", + "monthlyAttendance": "Monthly Attendance", + "vacationRule": "Vacation Rule", + "vacationType": "Vacation Type", + "startDateT": "Start Date", + "endDateT": "End Date", + "workFromHome": "Work From Home", + "ticketRequest": "Ticket Request", + "viewAllOffers": "View All Offers", + "offers": "Offers & ", + "discounts": "Discounts", + "newString": "New", + "setTheNewPassword": "Set the new password", + "typeYourNewPasswordBelow": "Type your new password below", + "typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below", + "confirmPassword": "Confirm Password", + "update": "Update", + "title": "Title", + "home": "Home", + "mySalary": "My Salary", + "createRequest": "Create Request", + "forgotPassword": "Forgot Password", + "employeeId": "Employee ID", + "loginCodeWillSentToMobileNumber": "Please Enter your Employee ID, A login code will be sent to your mobile number", + "changePassword": "Change Password", + "ok": "OK", + "confirm": "Confirm", + "passwordChangedSuccessfully": "Password changed successfully", + "itemsForSale": "Items for Sale", + "attendanceDetails": "Attendance Details", + "order": "order", + "earlyOut": "Early Out", + "shortage": "Shortage", + "excess": "Excess", + "lateIn": "Late In", + "approvedCheckOut": "Approved Check Out", + "approvedCheckIn": "Approved Check In", + "actualCheckOut": "Actual Check Out", + "actualCheckIn": "Actual Check In", + "present": "PRESENT", + "pres": "present", + "shiftTime": "Shift Time", + "absent": "ABSENT", + "attendance": "Attendance", + "scheduleDays": "Schedule\nDays", + "offDays": "Off\nDays", + "nonAnalyzed": "Non\nAnalyzed", + "shortageHour": "Shortage\nHour", + "stats": "Stats", + "completed": "Completed", + "doNotUseRecentPassword": "Do not use recent password", + "atLeastOneLowercase": "At least one lowercase", + "atLeastOneUppercase": "At least one uppercase", + "atLeastOneNumeric": "At least one numeric", + "minimum8Characters": "Minimum 8 characters", + "doNotAddRepeatingLetters": "Do not add repeating letters", + "itShouldContainSpecialCharacter": "It should not contain special characters", + "confirmPasswordMustMatch": "Confirm password must match", + "sms": "SMS", + "fingerPrint": "Fingerprint", + "face": "Face", + "whatsapp": "Whatsapp", + "reject": "Reject", + "approve": "Approve", + "generate": "Generate", + "cancel": "Cancel", + "requestedItems": "Requested Items", + "request": "Request", + "myRequest": "My Request", + "actions": "Actions", + "delegate": "Delegate", + "request_info": "Request Info", + "attachments": "Attachments", + "info": "Info.", + "employeeNumber": "Employee Number", + "assignmentNumber": "Assignment Number", + "employeeName": "Employee Name", + "scheduleDate": "Schedule Date", + "shiftType": "Shift Type", + "shift": "Shift", + "breakText": "Break", + "actualSwipeStart": "Actual Swipe Start", + "actualSwipeEnd": "Actual Swipe End", + "approvedSwipeStart": "Approved Swipe Start", + "approvedSwipeStartReason": "Approved Swipe Start Reason", + "approvedSwipeEnd": "Approved Swipe End", + "approvedSwipeEndReason": "Approved Swipe End Reason", + "from": "From", + "to": "To", + "sent": "Sent", + "closed": "Closed", + "id": "ID", + "responder": "Responder", + "jobTitle": "Job Title", + "grade": "Grade", + "jobCategory": "Job Category", + "category": "Category", + "employeeEmailAddress": "Employee Email Address", + "payrollBranch": "Payroll Branch", + "yourChangeHasBeenSavedSuccessfully": "Your change has been saved successfully", + "code": "Code", + "unit": "Unit", + "quantity": "Quantity", + "dateRequired": "Date Required", + "lineStatus": "Line Status", + "statusDate": "Status Date", + "transactionType": "Transaction Type", + "operatingUnit": "Operating Unit", + "organizationCode": "Organization Code", + "organization": "Organization", + "fromSubInventory": "From Sub Inventory", + "fromLocator": "From Locator", + "toSubInventory": "To Sub Inventory", + "toLocator": "To Locator", + "shipToLocator": "Ship To Locator", + "itemHistory": "Item History", + "mfg": "MFG", + "lineType": "Line Type", + "price": "Price", + "lineAmount": "Line Amount", + "lineDiscount": "Line Discount %", + "needByDate": "Need By Date", + "promisedDate": "Promised Date", + "deliverToLocation": "Deliver To Location", + "requisitionNumber": "Requisition Number", + "requester": "Requester", + "subject": "Subject", + "quotationAnalysis": "Quotation Analysis", + "description": "Description", + "pleaseEnterDescription": "Please enter description", + "supplier": "Supplier", + "site": "Site", + "buyer": "Buyer", + "preparer": "Preparer", + "creationDate": "Creation Date", + "shipToLocation": "Ship To Location", + "quotationNumber": "Quotation Number", + "quotationDate": "Quotation Date", + "paymentTerms": "Payment Terms", + "currency": "Currency", + "grossAmount": "Gross Amount", + "discountAmount": "Discount Amount", + "customDuty": "Custom Duty", + "shipHandle": "Ship Handle", + "otherCharges": "Other Charges", + "totalPOAmountWithVAT": "Total PO Amount With VAT", + "totalPOAmountInWords": "Total PO Amount In Words", + "requestNumber": "Request Number", + "uom": "UOM", + "operatingCode": "Operating Code", + "poNumber": "PO Number", + "revision": "Revision", + "quantityOrdered": "Quantity Ordered", + "quantityReceived": "Quantity Received", + "bonusQuantity": "Bonus Quantity", + "purchasePrice": "Purchase Price", + "discountPer": "Discount %", + "balanceQuantity": "Balance Quantity", + "netPrice": "Net Price", + "closureStatus": "Closure Status", + "quotationNetPrice": "Quotation Net Price", + "quotationUOM": "Quotation UOM", + "quotationQty": "Quotation Qty", + "itemCode": "item Code", + "vendorName": "Vendor Name", + "quotationMFGPartNumber": "Quotation MFG Part Number", + "quotationDeliveryDate": "Quotation Delivery Date", + "quotationBonusQuantity": "Quotation Bonus Quantity", + "quotationLineTotal": "Quotation Line Total", + "rfqUOM": "RFQ UOM", + "rfqQty": "RFQ Qty", + "rfqNumber": "RFQ Number", + "msg": "Hello {} in the {} world ", + "msg_named": "{} are written in the {lang} language", + "clickMe": "Click me", + "human": "Human", + "resources": "Resources", + "details": "Details", + "noDataAvailable": "No Data Available", + "productName": "Product Name", + "productDescription": "Product Description", + "unitPrice": "Unit Price", + "manufacturerName": "Manufacturer Name", + "manufacturerPartName": "Manufacturer Part Name", + "supplierName": "Supplier Name", + "supplierContact": "Supplier Contact", + "chargeToPatient": "Charge To Patient", + "justification": "Justification", + "itemDescription": "Item Description", + "groupCode": "Group Code", + "primaryUOM": "Primary UOM", + "subgroupDescription": "Subgroup Description", + "subgroupCode": "Subgroup Code", + "groupDescription": "Group Description", + "templateName": "Template Name", + "itemCreationStatus": "Item Creation Status", + "standardizationApprovalStatus": "Standardization Approval Status", + "standardizationApprovalRejectionReason": "Standardization Approval Rejection Reason", + "analyzedBy": "Analyzed By", + "approvedDate": "Approved Date", + "itemType": "Item Type", + "relatedTo": "Related To", + "requestDate": "Request Date", + "analyzedDate": "Analyzed Date", + "urgent": "Urgent", + "requestDetails": "Request Details", + "approvalLevel": "Approval Level", + "requesterDetails": "Requester Details", + "myAttendance": "My Attendance", + "workOnBreak": "Work On Break", + "next": "Next", + "apply": "Apply", + "mobile": "Mobile", + "year": "Year", + "month": "Month", + "day": "Day", + "completingYear": "We appreciate you for completing the service of", + "address": "Address", + "phoneNumber": "Phone Number", + "businessGroup": "Business", + "Payroll": "Payroll", + "civilIdentityNumber": "Civil Identity Number", + "dateOfBirth": "Date of Birth", + "maritalStatus ": "Marital Status ", + "fullName": "Full Name", + "remove": "Remove", + "Attendance": "Attendance", + "submit": "Submit", + "submitAsAnonymous": "Submit as Anonymous", + "areYouSureYouWantToSubmit": "Are you sure you want to submit?", + "comments": "Comments", + "writeComment": "Write a comment", + "approversList": "Approvers List", + "yourRequestHasBeenSubmittedForApprovals": "Your request has been submitted for approvals", + "monthlyPaySlip": "Monthly Pay Slip", + "particular": "Particular", + "earnings": "Earnings", + "deductions": "Deductions", + "paymentMethodName": "Payment Method Name", + "bankName": "Bank Name", + "branchCode": "Branch Code", + "accountNo": "Account No", + "summaryOfInformation": "Summary of Information", + "totalPayAmount": "Total Pay Amount", + "paymentInformation": "Payment Information", + "amount": "Amount", + "correctCurrentDatails": "correct or complete the current details", + "selectType": "Select the type of change you want to make", + "enterNewInfo": "Enter new Information because of a real change to the current details (e.g because of a change in marital status)", + "endDate": "*End Date", + "removeThisMember": "Are You Sure You Want to Remove this Member?", + "wantUpdateThisMember": "Are You Sure You Want to Update this Member?", + "addNewFamilyMember": "Add New Family Member", + "addRow": "Add new row", + "pleaseSelect": "Please Select *", + "delete": "delete", + "add": "Add", + "edit": "Edit", + "myProfile": "My Profile", + "mowadhafhi": "Mowadhafi", + "searchAnnouncements": "Search Announcements", + "announcements": "Announcements", + "swipeRequest": "Swipe Request", + "serviceType": "Service Type", + "departmentName": "Department Name", + "selectDepartment": "Select Department", + "relatedSection": "Related Section", + "selectSection": "Select Section", + "relatedTopic": "Related Topic", + "selectTopic": "Select Topic", + "supportingDocument": "Supporting Document", + "mowadhafhiRequest": "Mowadhafi Request", + "ticketReference": "Ticket Reference", + "section": "Section", + "topic": "Topic", + "actionBy": "Action By", + "pending": "Pending", + "pendingTransactions": "Pending Transactions", + "selectRequestType": "Please select request type", + "dateFrom": "Date From", + "dateTo": "Date To", + "requestName": "Request Name", + "createdFor": "Created For", + "requestType": "Request Type", + "requestCreatedSuccessfully": "Request created successfully", + "search": "Search", + "wantToReject": "Are you sure want to reject?", + "employeeDigitalID": "Employee Digital ID", + "businessCard": "Business Card", + "checkOut": "Check Out", + "regular": "Regular", + "mark": "Mark", + "performance": "Performance Evaluation", + "performanceEvaluationIn": "Your performance Evaluation in", + "valuationIn": "Performance Evaluation in", + "viewBusinessCard": "View Business Card", + "performanceEvaluation": "Performance Evaluation", + "logout": "Logout", + "selectMethodOfAttendance": "Select the method to mark the attendance", + "comeNearHMGWifi": "Please come near to HMG wifi", + "deliverNotificationToMeRegardless": "Deliver notifications to me regardless of any general rules", + "close": "Close", + "respond": "Respond", + "vacationRuleAdded": "Vacation rule added", + "selectTypeT": "Select Type", + "notification": "Notification", + "selectNotification": "Select Notification", + "ifAllSelectedYouWillSkip": "*If All is selected, you will skip to step 3", + "applyForVacationRule": "Apply for Vacation Rule", + "step1": "Step 1", + "step2": "Step 2", + "step3": "Step 3", + "message": "Message", + "writeAMessage": "Write a message", + "notificationReassign": "Notification Reassign", + "selectEmployee": "Select Employee", + "searchEmployeeForReplacement": "Search employee for replacement", + "searchForEmployee": "Search for Employee", + "pleaseSpecifyEndTime": "Please specify End Time", + "pleaseSelectNotificationReassign": "Please select notification reassign", + "pleaseSelectEmployeeForReplacement": "Please select employee for replacement", + "pleaseSelectAction": "Please select action", + "pleaseSelectDate": "Please select date", + "todayAttendance": "Today's Attendance", + "viewAttendance": "View Attendance", + "teamMembers": "Team Members", + "profileDetails": "Profile Details", + "noResultsFound": "No Results Found", + "searchBy": "Search by", + "myTeamMembers": "My Team Members", + "save": "Save", + "TurnNotificationsFor": "Turn on notifications for", + "worklistSettings": "Worklist Settings", + "absenceType": "Absence Type", + "absenceCategory": "Absence Category", + "days": "Days", + "hours": "Hours", + "approvalStatus": "Approval Status", + "absenceStatus": "Absence Status", + "poweredBy": "Powered By", + "cloudSolutions": "Cloud Solutions", + "subordinateLeave": "Subordinate Leave", + "numberDays": "Number of days", + "selectTemplate": "Select Template", + "myPostedAds": "My posted ads", + "browseCategories": "Browse Categories", + "searchItems": "Search Items", + "offerAndDiscounts": "Offer & Discounts", + "offerValid": "Offer Valid", + "offerExpired": "Offer Expired", + "whatAreYouOffering": "What are you offering?", + "selectCategory": "Select Category", + "inProgress": "InProgress", + "locked": "Locked", + "addDetails": "Add Details", + "reviewAndSell": "Review & Sell", + "itemTitle": "Item Title", + "itemCondition": "Item Condition", + "used": "Used", + "region": "Region", + "selectRegion": "Select Region", + "itemPrice": "Item Price", + "itemPhotos": "Item Photos", + "itemInfo": "Item Info", + "uploadAttachment": "Upload Attachment", + "selectFromGalleryOrOpenCamera": "Select from gallery or open camera", + "openCamera": "Open\nCamera", + "uploadFromGallery": "Upload from\nGallery", + "name": "Name", + "email": "Email", + "noHistoryAvailable": "No History Available", + "purchaseRequisition": "Purchase Requisition", + "moveOrder": "Move Order", + "humanResource": "Human Resource", + "purchaseOrder": "Purchase Order", + "ITGForms": "ITG Forms", + "itemCreation": "Item Creation", + "stamp": "Stamp", + "addFavoriteList": "Do you want to add {name} in your favorite list", + "feedbackUserExperience": "This is to get the feedback about the user experience", + "rateUI": "How would you like to rate", + "rateUI2": "How do you satisfied with this application", + "submitSurvey": "Submit Survey", + "typeHere": "Type here", + "infoDetail": "Info Detail", + "amount_detail": "Amount Detail", + "currentBalance": "Current Balance", + "currentLeaveBalance": "Current Leave Balance", + "calculatedDays": "Calculated Days", + "totalDays": "Total Days", + "usedBalance": "Used", + "infants": "Infants", + "child": "Child", + "adult": "Adult", + "updateMember": "Are You Sure You Want to Update this Member?", + "fieldIsEmpty": "'{data}' Field is empty. Please select", + "pleaseEnterComments": "Please enter comments", + "skip": "Skip", + "typeCurrentPasswordBelow": "Type Your Current password below", + "currentPassword": "Current password", + "concurrentReports": "Concurrent Reports", + "EnterNewAddressMoved": "Enter a new address if you have moved", + "CorrectAddress": "Correct or amend this address", + "SelectChangeWantToMake": "Select the type of change you want to make", + "profile": { + "reset_password": { + "label": "Reset Password", + "username": "Username", + "password": "password" }, - "reset_locale": "إعادة ضبط اللغة", - "chat": "دردشة", - "mychats": "دردشاتي", - "advancedSearch": "بحث متقدم", - "openNot": "التبليغات المفتوحة", - "fyi": "تبليغات للعلم", - "toDo": "تبليغات الأعمال", - "all": "كل التبليغات", - "meNot": "تبليغات صادرة مني", - "view": "عرض", - "fromUserName": "من", - "sentDate": "تاريخ الإرسال", - "itemTypeDisplayName": "اسم العرض", - "none": "بدون", - "createNewChat": "إنشاء محادثة جديدة", - "brainMarathon": "ماراثون الدماغ", - "contestTopicAbout": "سيكون موضوع المسابقة حول:", - "gameDate": "تاريخ اللعبة:", - "gameTime": "وقت اللعب:", - "joinMarathon": "انضم إلى ماراثون", - "joinDemoMarathon": "انضم إلى الماراثون التجريبي", - "demo": "تجريبي", - "minutes": "الدقائق", - "seconds": "ثواني", - "note": "ملحوظة:", - "demoMarathonNoteP1": "يمكنك لعب ماراثون العرض لتتعلم كيف يعمل. يمكنك الانضمام إلى ماراثون", - "demoMarathonNoteP2": "خمس دقائق", - "demoMarathonNoteP3": "قبل الوقت الفعلي.", - "sponsoredBy": "برعاية:", - "question": "سؤال", - "marathoners": "الماراثون", - "marathoner": "ماراثونر", - "prize": "جائزة:", - "winnerSelection": "اختيار الفائز", - "qualifiers": "تصفيات", - "qualifier": "المؤهل", - "getReadyForContest": "استعد للمسابقة القادمة:", - "winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.", - "fingersCrossed": "تشابك الاصابع!!!", - "congrats": "مبروك !!!", - "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح.", - "otp": "OTP", - "verification": "تَحَقّق", - "resend": "إعادة إرسال", - "codeExpire": "انتهت صلاحية رمز التحقق", - "typeheretoreply": "اكتب هنا للرد", - "favorite": "مفضلتي", - "searchfromchat": "البحث من الدردشة", - "yourAnswerCorrect": "إجابتك صحيحة", - "youMissedTheQuestion": "نفد منك الوقت. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", - "wrongAnswer": "إجابتك غير صحيحة. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", - "oops": "أوه!!!", - "winner": "الفائز", - "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", - "ourSponsor": "راعينا:", - "startingIn": "يبدأ في", - "youAreOutOfContest": "أنت خارج المسابقة.", - "winners": "الفائزين!!!", - "expireAfter": "تنتهي بعد", - "oneWeek": "أسبوع 1", - "twoWeek": "2 أسبوع", - "noUpcoming": "لا يوجد قادم", - "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية", - "noWinner": "حزين! لم يفز أحد اليوم.", - "myTeam": "فريقي", - "youCanPlayDemo": "لكن يمكنك لعب العرض", - "group": "مجموعة", - "searchGroup": "مجموعة البحث", - "connectHmgWifi": "قم بتوصيل HMG WIFI", - "connectedHmgWifi": "اتصال HMG WIFI", - "itgForms": "نماذج (ITG)", - "resetAdPassword": "إعادة تعيين كلمة مرور AD", - "myDocuments": "مستنداتي", - "requiredDocuments": "المستندات المطلوبة", - "optionalDocuments": "المستندات الاختيارية", - "allDocuments": "كافة المستندات", - "expiredDocuments": "المستندات منتهية الصلاحية", - "missingDocuments": "مستندات مفقودة", - "uploadedDocuments": "المستندات التي تم تحميلها", - "youCannotJoinTheMarathon": "لا يمكنك الانضمام إلى الماراثون لأنك تجاوزت الحد الزمني", - "pleaseClickButtonToJoinMarathon": "الرجاء الضغط على الزر أدناه للانضمام إلى الماراثون", - }; - static const Map en_US = { - "mohemm": "Mohemm", - "english": "English", - "arabic": "عربي", - "login": "Login", - "pleaseEnterLoginDetails": "Please enter the detail below to login", - "username": "Username", - "password": "Password", - "welcomeBack": "Welcome back", - "wouldYouLikeToLoginWithCurrentUsername": "Would you like to login with current Username?", - "lastLoginDetails": "Last Login Details:", - "verificationType": "Verification Type:", - "pleaseVerify": "Please Verify", - "pleaseVerifyForBio": "Please verify login with one of the following options", - "verifyThroughFace": "Verify Through Face", - "verifyThroughFingerprint": "Verify Through Fingerprint", - "verifyThroughSMS": "Verify Through SMS", - "verifyThroughWhatsapp": "Verify Through Whatsapp", - "useAnotherAccount": "Use Another Account", - "pleaseEnterTheVerificationCodeSentTo": "Please enter the verification code sent to ", - "theVerificationCodeWillExpireIn": "The verification code will expire in ", - "goodMorning": "Good Morning", - "markAttendance": "Mark Attendance", - "timeLeftToday": "Time Left Today", - "checkIn": "Check In", - "workList": "Work List", - "leaveBalance": "Leave Balance", - "missingSwipes": "Missing Swipes", - "ticketBalance": "Ticket Balance", - "other": "Other", - "services": "Services", - "viewAllServices": "View All Services", - "monthlyAttendance": "Monthly Attendance", - "vacationRule": "Vacation Rule", - "vacationType": "Vacation Type", - "startDateT": "Start Date", - "endDateT": "End Date", - "workFromHome": "Work From Home", - "ticketRequest": "Ticket Request", - "viewAllOffers": "View All Offers", - "offers": "Offers & ", - "discounts": "Discounts", - "newString": "New", - "setTheNewPassword": "Set the new password", - "typeYourNewPasswordBelow": "Type your new password below", - "typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below", - "confirmPassword": "Confirm Password", - "update": "Update", - "title": "Title", - "home": "Home", - "mySalary": "My Salary", - "createRequest": "Create Request", - "forgotPassword": "Forgot Password", - "employeeId": "Employee ID", - "loginCodeWillSentToMobileNumber": "Please Enter your Employee ID, A login code will be sent to your mobile number", - "changePassword": "Change Password", - "ok": "OK", - "confirm": "Confirm", - "passwordChangedSuccessfully": "Password changed successfully", - "itemsForSale": "Items for Sale", - "attendanceDetails": "Attendance Details", - "order": "order", - "earlyOut": "Early Out", - "shortage": "Shortage", - "excess": "Excess", - "lateIn": "Late In", - "approvedCheckOut": "Approved Check Out", - "approvedCheckIn": "Approved Check In", - "actualCheckOut": "Actual Check Out", - "actualCheckIn": "Actual Check In", - "present": "PRESENT", - "pres": "present", - "shiftTime": "Shift Time", - "absent": "ABSENT", - "attendance": "Attendance", - "scheduleDays": "Schedule\nDays", - "offDays": "Off\nDays", - "nonAnalyzed": "Non\nAnalyzed", - "shortageHour": "Shortage\nHour", - "stats": "Stats", - "completed": "Completed", - "doNotUseRecentPassword": "Do not use recent password", - "atLeastOneLowercase": "At least one lowercase", - "atLeastOneUppercase": "At least one uppercase", - "atLeastOneNumeric": "At least one numeric", - "minimum8Characters": "Minimum 8 characters", - "doNotAddRepeatingLetters": "Do not add repeating letters", - "itShouldContainSpecialCharacter": "It should contain special character", - "confirmPasswordMustMatch": "Confirm password must match", - "sms": "SMS", - "fingerPrint": "Fingerprint", - "face": "Face", - "whatsapp": "Whatsapp", - "reject": "Reject", - "approve": "Approve", - "cancel": "Cancel", - "requestedItems": "Requested Items", - "request": "Request", - "myRequest": "My Request", - "actions": "Actions", - "delegate": "Delegate", - "request_info": "Request Info", - "attachments": "Attachments", - "info": "Info.", - "employeeNumber": "Employee Number", - "assignmentNumber": "Assignment Number", - "employeeName": "Employee Name", - "scheduleDate": "Schedule Date", - "shiftType": "Shift Type", - "shift": "Shift", - "breakText": "Break", - "actualSwipeStart": "Actual Swipe Start", - "actualSwipeEnd": "Actual Swipe End", - "approvedSwipeStart": "Approved Swipe Start", - "approvedSwipeStartReason": "Approved Swipe Start Reason", - "approvedSwipeEnd": "Approved Swipe End", - "approvedSwipeEndReason": "Approved Swipe End Reason", - "from": "From", - "to": "To", - "sent": "Sent", - "closed": "Closed", - "id": "ID", - "responder": "Responder", - "jobTitle": "Job Title", - "grade": "Grade", - "jobCategory": "Job Category", - "category": "Category", - "employeeEmailAddress": "Employee Email Address", - "payrollBranch": "Payroll Branch", - "yourChangeHasBeenSavedSuccessfully": "Your change has been saved successfully", - "code": "Code", - "unit": "Unit", - "quantity": "Quantity", - "dateRequired": "Date Required", - "lineStatus": "Line Status", - "statusDate": "Status Date", - "transactionType": "Transaction Type", - "operatingUnit": "Operating Unit", - "organizationCode": "Organization Code", - "organization": "Organization", - "fromSubInventory": "From Sub Inventory", - "fromLocator": "From Locator", - "toSubInventory": "To Sub Inventory", - "toLocator": "To Locator", - "shipToLocator": "Ship To Locator", - "itemHistory": "Item History", - "mfg": "MFG", - "lineType": "Line Type", - "price": "Price", - "lineAmount": "Line Amount", - "lineDiscount": "Line Discount %", - "needByDate": "Need By Date", - "promisedDate": "Promised Date", - "deliverToLocation": "Deliver To Location", - "requisitionNumber": "Requisition Number", - "requester": "Requester", - "subject": "Subject", - "quotationAnalysis": "Quotation Analysis", - "description": "Description", - "supplier": "Supplier", - "site": "Site", - "buyer": "Buyer", - "preparer": "Preparer", - "creationDate": "Creation Date", - "shipToLocation": "Ship To Location", - "quotationNumber": "Quotation Number", - "quotationDate": "Quotation Date", - "paymentTerms": "Payment Terms", - "currency": "Currency", - "grossAmount": "Gross Amount", - "discountAmount": "Discount Amount", - "customDuty": "Custom Duty", - "shipHandle": "Ship Handle", - "otherCharges": "Other Charges", - "totalPOAmountWithVAT": "Total PO Amount With VAT", - "totalPOAmountInWords": "Total PO Amount In Words", - "requestNumber": "Request Number", - "uom": "UOM", - "operatingCode": "Operating Code", - "poNumber": "PO Number", - "revision": "Revision", - "quantityOrdered": "Quantity Ordered", - "quantityReceived": "Quantity Received", - "bonusQuantity": "Bonus Quantity", - "purchasePrice": "Purchase Price", - "discountPer": "Discount %", - "balanceQuantity": "Balance Quantity", - "netPrice": "Net Price", - "closureStatus": "Closure Status", - "quotationNetPrice": "Quotation Net Price", - "quotationUOM": "Quotation UOM", - "quotationQty": "Quotation Qty", - "itemCode": "item Code", - "vendorName": "Vendor Name", - "quotationMFGPartNumber": "Quotation MFG Part Number", - "quotationDeliveryDate": "Quotation Delivery Date", - "quotationBonusQuantity": "Quotation Bonus Quantity", - "quotationLineTotal": "Quotation Line Total", - "rfqUOM": "RFQ UOM", - "rfqQty": "RFQ Qty", - "rfqNumber": "RFQ Number", - "msg": "Hello {} in the {} world ", - "msg_named": "{} are written in the {lang} language", - "clickMe": "Click me", - "human": "Human", - "resources": "Resources", - "details": "Details", - "noDataAvailable": "No Data Available", - "productName": "Product Name", - "productDescription": "Product Description", - "unitPrice": "Unit Price", - "manufacturerName": "Manufacturer Name", - "manufacturerPartName": "Manufacturer Part Name", - "supplierName": "Supplier Name", - "supplierContact": "Supplier Contact", - "chargeToPatient": "Charge To Patient", - "justification": "Justification", - "itemDescription": "Item Description", - "groupCode": "Group Code", - "primaryUOM": "Primary UOM", - "subgroupDescription": "Subgroup Description", - "subgroupCode": "Subgroup Code", - "groupDescription": "Group Description", - "templateName": "Template Name", - "itemCreationStatus": "Item Creation Status", - "standardizationApprovalStatus": "Standardization Approval Status", - "standardizationApprovalRejectionReason": "Standardization Approval Rejection Reason", - "analyzedBy": "Analyzed By", - "approvedDate": "Approved Date", - "itemType": "Item Type", - "relatedTo": "Related To", - "requestDate": "Request Date", - "analyzedDate": "Analyzed Date", - "urgent": "Urgent", - "requestDetails": "Request Details", - "approvalLevel": "Approval Level", - "requesterDetails": "Requester Details", - "myAttendance": "My Attendance", - "workOnBreak": "Work On Break", - "next": "Next", - "apply": "Apply", - "mobile": "Mobile", - "year": "Year", - "month": "Month", - "day": "Day", - "completingYear": "We appreciate you for completing the service of", + "profileCompletionPer": "Profile Completion", + "completeProfile": "Complete Profile", + "personalInformation": "Personal Information", + "basicDetails": "Basic Details", "address": "Address", - "phoneNumber": "Phone Number", - "businessGroup": "Business", - "Payroll": "Payroll", - "civilIdentityNumber": "Civil Identity Number", - "dateOfBirth": "Date of Birth", - "maritalStatus ": "Marital Status ", - "fullName": "Full Name", - "remove": "Remove", - "Attendance": "Attendance", - "submit": "Submit", - "areYouSureYouWantToSubmit": "Are you sure you want to submit?", - "comments": "Comments", - "writeComment": "Write a comment", - "approversList": "Approvers List", - "yourRequestHasBeenSubmittedForApprovals": "Your request has been submitted for approvals", - "monthlyPaySlip": "Monthly Pay Slip", - "particular": "Particular", - "earnings": "Earnings", - "deductions": "Deductions", - "paymentMethodName": "Payment Method Name", - "bankName": "Bank Name", - "branchCode": "Branch Code", - "accountNo": "Account No", - "summaryOfInformation": "Summary of Information", - "totalPayAmount": "Total Pay Amount", - "paymentInformation": "Payment Information", - "amount": "Amount", - "correctCurrentDatails": "correct or complete the current details", - "selectType": "Select the type of change you want to make", - "enterNewInfo": "Enter new Information because of a real change to the current details (e.g because of a change in marital status)", - "endDate": "*End Date", - "removeThisMember": "Are You Sure You Want to Remove this Member?", - "wantUpdateThisMember": "Are You Sure You Want to Update this Member?", - "addNewFamilyMember": "Add New Family Member", - "addRow": "Add new row", - "pleaseSelect": "Please Select *", - "delete": "delete", - "add": "Add", - "edit": "Edit", - "myProfile": "My Profile", - "mowadhafhi": "Mowadhafi", - "searchAnnouncements": "Search Announcements", - "announcements": "Announcements", - "swipeRequest": "Swipe Request", - "serviceType": "Service Type", - "departmentName": "Department Name", - "selectDepartment": "Select Department", - "relatedSection": "Related Section", - "selectSection": "Select Section", - "relatedTopic": "Related Topic", - "selectTopic": "Select Topic", - "supportingDocument": "Supporting Document", - "mowadhafhiRequest": "Mowadhafi Request", - "ticketReference": "Ticket Reference", - "section": "Section", - "topic": "Topic", - "actionBy": "Action By", - "pendingTransactions": "Pending Transactions", - "selectRequestType": "Please select request type", - "dateFrom": "Date From", - "dateTo": "Date To", - "requestName": "Request Name", - "createdFor": "Created For", - "requestType": "Request Type", - "requestCreatedSuccessfully": "Request created successfully", - "search": "Search", - "wantToReject": "Are you sure want to reject?", - "employeeDigitalID": "Employee Digital ID", - "businessCard": "Business Card", - "checkOut": "Check Out", - "regular": "Regular", - "mark": "Mark", - "performance": "Performance Evaluation", - "performanceEvaluationIn": "Your performance Evaluation in", - "valuationIn": "Performance Evaluation in", - "viewBusinessCard": "View Business Card", - "performanceEvaluation": "Performance Evaluation", - "logout": "Logout", - "selectMethodOfAttendance": "Select the method to mark the attendance", - "comeNearHMGWifi": "Please come near to HMG wifi", - "deliverNotificationToMeRegardless": "Deliver notifications to me regardless of any general rules", - "close": "Close", - "respond": "Respond", - "vacationRuleAdded": "Vacation rule added", - "selectTypeT": "Select Type", - "notification": "Notification", - "selectNotification": "Select Notification", - "ifAllSelectedYouWillSkip": "*If All is selected, you will skip to step 3", - "applyForVacationRule": "Apply for Vacation Rule", - "step1": "Step 1", - "step2": "Step 2", - "step3": "Step 3", - "message": "Message", - "writeAMessage": "Write a message", - "notificationReassign": "Notification Reassign", - "selectEmployee": "Select Employee", - "searchEmployeeForReplacement": "Search employee for replacement", - "searchForEmployee": "Search for Employee", - "pleaseSpecifyEndTime": "Please specify End Time", - "pleaseSelectNotificationReassign": "Please select notification reassign", - "pleaseSelectEmployeeForReplacement": "Please select employee for replacement", - "pleaseSelectAction": "Please select action", - "pleaseSelectDate": "Please select date", - "todayAttendance": "Today's Attendance", - "viewAttendance": "View Attendance", - "teamMembers": "Team Members", - "profileDetails": "Profile Details", - "noResultsFound": "No Results Found", - "searchBy": "Search by", - "myTeamMembers": "My Team Members", - "save": "Save", - "TurnNotificationsFor": "Turn on notifications for", - "worklistSettings": "Worklist Settings", - "absenceType": "Absence Type", - "absenceCategory": "Absence Category", - "days": "Days", - "hours": "Hours", - "approvalStatus": "Approval Status", - "absenceStatus": "Absence Status", - "poweredBy": "Powered By", - "cloudSolutions": "Cloud Solutions", - "subordinateLeave": "Subordinate Leave", - "numberDays": "Number of days", - "selectTemplate": "Select Template", - "myPostedAds": "My posted ads", - "browseCategories": "Browse Categories", - "searchItems": "Search Items", - "offerAndDiscounts": "Offer & Discounts", - "offerValid": "Offer Valid", - "offerExpired": "Offer Expired", - "whatAreYouOffering": "What are you offering?", - "selectCategory": "Select Category", - "inProgress": "InProgress", - "locked": "Locked", - "addDetails": "Add Details", - "reviewAndSell": "Review & Sell", - "itemTitle": "Item Title", - "itemCondition": "Item Condition", - "used": "Used", - "region": "Region", - "selectRegion": "Select Region", - "itemPrice": "Item Price", - "itemPhotos": "Item Photos", - "itemInfo": "Item Info", - "uploadAttachment": "Upload Attachment", - "selectFromGalleryOrOpenCamera": "Select from gallery or open camera", - "openCamera": "Open\nCamera", - "uploadFromGallery": "Upload from\nGallery", - "name": "Name", - "email": "Email", - "noHistoryAvailable": "No History Available", - "purchaseRequisition": "Purchase Requisition", - "moveOrder": "Move Order", - "humanResource": "Human Resource", - "purchaseOrder": "Purchase Order", - "ITGForms": "ITG Forms", - "itemCreation": "Item Creation", - "stamp": "Stamp", - "addFavoriteList": "Do you want to add {name} in your favorite list", - "feedbackUserExperience": "This is to get the feedback about the user experience", - "rateUI": "How would you like to rate", - "rateUI2": "How do you satisfied with this application", - "submitSurvey": "Submit Survey", - "typeHere": "Type here", - "infoDetail": "Info Detail", - "amount_detail": "Amount Detail", - "currentBalance": "Current Balance", - "currentLeaveBalance": "Current Leave Balance", - "calculatedDays": "Calculated Days", - "totalDays": "Total Days", - "usedBalance": "Used", - "infants": "Infants", - "child": "Child", - "adult": "Adult", - "updateMember": "Are You Sure You Want to Update this Member?", - "fieldIsEmpty": "'{data}' Field is empty. Please select", - "pleaseEnterComments": "Please enter comments", - "skip": "Skip", - "typeCurrentPasswordBelow": "Type Your Current password below", - "currentPassword": "Current password", - "concurrentReports": "Concurrent Reports", - "EnterNewAddressMoved": "Enter a new address if you have moved", - "CorrectAddress": "Correct or amend this address", - "SelectChangeWantToMake": "Select the type of change you want to make", - "profile": { - "reset_password": {"label": "Reset Password", "username": "Username", "password": "password"}, - "profileCompletionPer": "Profile Completion", - "completeProfile": "Complete Profile", - "personalInformation": "Personal Information", - "basicDetails": "Basic Details", - "address": "Address", - "contactDetails": "Contact Details", - "familyDetails": "Family Members", - "effectiveDate": "Effective Date", - "country": "Country" - }, - "clicked": { - "zero": "You clicked {} times!", - "one": "You clicked {} time!", - "two": "You clicked {} times!", - "few": "You clicked {} times!", - "many": "You clicked {} times!", - "other": "You clicked {} times!" - }, - "gender": { - "male": "Hi man ;) ", - "female": "Hello girl :)", - "with_arg": {"male": "Hi man ;) {}", "female": "Hello girl :) {}"} - }, - "reset_locale": "Reset Language", - "chat": "Chat", - "mychats": "My Chats", - "createNewChat": "Create New Chat", - "brainMarathon": "Brain Marathon", - "contestTopicAbout": "Contest Topic will be about:", - "gameDate": "Game Date:", - "gameTime": "Game Time:", - "joinMarathon": "Join Marathon", - "joinDemoMarathon": "Join Demo Marathon", - "demo": "Demo", - "minutes": "Minutes", - "seconds": "Seconds", - "note": "Note:", - "demoMarathonNoteP1": "You can play the demo Marathon to learn how it works. You can join the Marathon", - "demoMarathonNoteP2": "5 Minutes", - "demoMarathonNoteP3": "before the actual time.", - "sponsoredBy": "Sponsored By:", - "question": "Question", - "marathoners": "Marathoners", - "marathoner": "Marathoner", - "prize": "Prize:", - "advancedSearch": "Advanced Search", - "openNot": "Open Notifications", - "fyi": "FYI Notifications", - "toDo": "To Do Notifications", - "all": "All Notifications", - "meNot": "Notifications from Me", - "view": "View", - "fromUserName": "From User Name", - "sentDate": "Sent Date", - "itemTypeDisplayName": "Item Type Display Name", - "none": "None", - "winnerSelection": "Winner Selection", - "qualifiers": "Qualifiers", - "qualifier": "Qualifier", - "getReadyForContest": "Get Ready for the coming contest:", - "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", - "fingersCrossed": "Fingers Crossed!!!", - "congrats": "Congratulations!!!", - "otp": "OTP", - "verification": "Verification", - "resend": "Resend", - "codeExpire": "The verification code has been expired", - "allQuestionsCorrect": "You have answered all questions correct", - "typeheretoreply": "Type here to reply", - "favorite": "My Favorites", - "searchfromchat": "Search from chat", - "yourAnswerCorrect": "Your answer is correct", - "youMissedTheQuestion": "You ran out of time. You are out of the game. But you can continue as a viewer.", - "wrongAnswer": "Your answer is Incorrect. You are out of the game. But you can continue as a viewer.", - "oops": "Ooopsss!!!!", - "winner": "WINNER", - "youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.", - "ourSponsor": "Our Sponsor:", - "startingIn": "Starting in", - "youAreOutOfContest": "You are out of the contest.", - "winners": "WINNERS!!!", - "expireAfter": "Expires After", - "oneWeek": "1 Week", - "twoWeek": "2 Week", - "noUpcoming": "There is no upcoming", - "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", - "noWinner": "Sad! No one won today.", - "myTeam": "My Team", - "youCanPlayDemo": "But you can play demo", - "group": "Groups", - "searchGroup": "Search Group", - "connectHmgWifi": "Connect HMG WIFI", - "connectedHmgWifi": "Connected HMG WIFI", - "itgForms": "ITG Forms", - "resetAdPassword": "Reset AD Password", - "myDocuments": "My Documents", - "requiredDocuments": "Required Documents", - "optionalDocuments": "Optional Documents", - "allDocuments": "All\nDocuments", - "expiredDocuments": "Expired\nDocuments", - "missingDocuments": "Missing\nDocuments", - "uploadedDocuments": "Uploaded\nDocuments", - "manage": "Manage", - "members": "Members", - "areYouSureWantTodelete": "Are you sure want to delete?", - "groupMembers": "Group Members", - "manageGroup": "Manage Group", - "admin": "Admin", - "addUsers": "Add users to the group", - "editGroups": "Edit Group", - "groupNameshouldbe": "Group name should be minimum 10 character long", - "enterGroupName": "Please enter valid group Name", - "groupName": "Group Name", - "enterGroupNamePlease": "Please enter group name", - "audioCall": "Audio Call", - "videoCall": "Video Call", - "shareScreen": "Share Screen", - "searchByUserName": "Search By Username", - "userSearch": "User Search", - "userName": "User Name", - "userId": "UserID", - "pleaseClickButtonToJoinMarathon": "Press the button below to join the Marathon.", - "youCannotJoinTheMarathon": "You cannot join the Marathon because you have exceeded the time limit." - }; - static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; + "contactDetails": "Contact Details", + "familyDetails": "Family Members", + "effectiveDate": "Effective Date", + "country": "Country" + }, + "clicked": { + "zero": "You clicked {} times!", + "one": "You clicked {} time!", + "two": "You clicked {} times!", + "few": "You clicked {} times!", + "many": "You clicked {} times!", + "other": "You clicked {} times!" + }, + "gender": { + "male": "Hi man ;) ", + "female": "Hello girl :)", + "with_arg": { + "male": "Hi man ;) {}", + "female": "Hello girl :) {}" + } + }, + "reset_locale": "Reset Language", + "chat": "Chat", + "mychats": "My Chats", + "createNewChat": "Create New Chat", + "brainMarathon": "Brain Marathon", + "contestTopicAbout": "Contest Topic will be about:", + "gameDate": "Game Date:", + "gameTime": "Game Time:", + "joinMarathon": "Join Marathon", + "joinDemoMarathon": "Join Demo Marathon", + "demo": "Demo", + "minutes": "Minutes", + "seconds": "Seconds", + "note": "Note:", + "demoMarathonNoteP1": "You can play the demo Marathon to learn how it works. You can join the Marathon", + "demoMarathonNoteP2": "5 Minutes", + "demoMarathonNoteP3": "before the actual time.", + "sponsoredBy": "Sponsored By:", + "question": "Question", + "marathoners": "Marathoners", + "marathoner": "Marathoner", + "prize": "Prize:", + "advancedSearch": "Advanced Search", + "openNot": "Open Notifications", + "fyi": "FYI Notifications", + "toDo": "To Do Notifications", + "all": "All Notifications", + "meNot": "Notifications from Me", + "view": "View", + "fromUserName": "From User Name", + "sentDate": "Sent Date", + "itemTypeDisplayName": "Item Type Display Name", + "none": "None", + "winnerSelection": "Winner Selection", + "qualifiers": "Qualifiers", + "qualifier": "Qualifier", + "getReadyForContest": "Get Ready for the coming contest:", + "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", + "fingersCrossed": "Fingers Crossed!!!", + "congrats": "Congratulations!!!", + "otp": "OTP", + "verification": "Verification", + "resend": "Resend", + "codeExpire": "The verification code has been expired", + "allQuestionsCorrect": "You have answered all questions correct", + "typeheretoreply": "Type here to reply", + "favorite": "My Favorites", + "searchfromchat": "Search from chat", + "yourAnswerCorrect": "Your answer is correct", + "youMissedTheQuestion": "You ran out of time. You are out of the game. But you can continue as a viewer.", + "wrongAnswer": "Your answer is Incorrect. You are out of the game. But you can continue as a viewer.", + "oops": "Ooopsss!!!!", + "winner": "WINNER", + "youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.", + "ourSponsor": "Our Sponsor:", + "startingIn": "Starting in", + "youAreOutOfContest": "You are out of the contest.", + "winners": "WINNERS!!!", + "expireAfter": "Expires After", + "oneWeek": "1 Week", + "twoWeek": "2 Week", + "noUpcoming": "There is no upcoming", + "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", + "noWinner": "Sad! No one won today.", + "myTeam": "My Team", + "youCanPlayDemo": "But you can play demo", + "group": "Groups", + "searchGroup": "Search Group", + "connectHmgWifi": "Connect HMG WIFI", + "connectedHmgWifi": "Connected HMG WIFI", + "itgForms": "ITG Forms", + "resetAdPassword": "Reset AD Password", + "myDocuments": "My Documents", + "requiredDocuments": "Required Documents", + "optionalDocuments": "Optional Documents", + "allDocuments": "All\nDocuments", + "expiredDocuments": "Expired\nDocuments", + "missingDocuments": "Missing\nDocuments", + "uploadedDocuments": "Uploaded\nDocuments", + "manage": "Manage", + "members": "Members", + "areYouSureWantTodelete": "Are you sure want to delete?", + "groupMembers": "Group Members", + "manageGroup": "Manage Group", + "admin": "Admin", + "addUsers": "Add users to the group", + "editGroups": "Edit Group", + "groupNameshouldbe": "Group name should be minimum 10 character long", + "enterGroupName": "Please enter valid group Name", + "groupName": "Group Name", + "enterGroupNamePlease": "Please enter group name", + "audioCall": "Audio Call", + "videoCall": "Video Call", + "shareScreen": "Share Screen", + "searchByUserName": "Search By Username", + "userSearch": "User Search", + "userName": "User Name", + "userId": "UserID", + "open": "open", + "addAtLeastOneAttachment": "Please add at least one attachment.", + "pleaseClickButtonToJoinMarathon": "Press the button below to join the Marathon.", + "youCannotJoinTheMarathon": "You cannot join the Marathon because you have exceeded the time limit.", + "requesterOperatingUnit": "Requester Operating Unit", + "paymentRequest": "Pay Request", + "paymentDetails": "Payment Details", + "requestNo": "Request No", + "requesterEmpNum": "Requester Employee Num", + "requesterEmpName": "Requester Employee Name", + "prepareEmpName": "Prepare Employee Name", + "requesterPositionName": "Requester Position Name", + "preparePositionName": "Prepare Position Name", + "requesterPayrollName": "Requester Payroll Name", + "payingORGName": "Paying Organization Name", + "requestAmount": "Request Amount", + "typeofPayment": "Type of Payment", + "beneficiaryDetails": "Beneficiary Details", + "beneficiaryName": "Beneficiary Name", + "idIqama": "Saudi ID / Iqama", + "beneficiaryBankName": "Beneficiary Bank Name", + "sadadNumber": "Sadad Number", + "beneficiaryIBAN": "Beneficiary IBAN", + "purchaseOrders": "Purchase Orders", + "approvalDate": "Approval Date", + "pOAmount": "PO Amount", + "versionStatus": "Version Status", + "supplierNo": "Supplier No", + "general": "General", + "prepareEmpNum": "Prepare Employee Num", + "supplierInfo": "Supplier Information", + "supplierAcNo": "Supplier Account No", + "supplierAcName": "Supplier Account Name", + "supplierIBAN": "Supplier IBAN", + "supplierCRNo": "CR Number", + "suppliedAcNo": "Supplied Account No.", + "patientRefundInvoice": "Patient Refund Invoice", + "patientNumber": "Patient Number", + "patientName": "Patient Name", + "invoiceDate": "Invoice Date", + "refundInvoice": "Refund Invoice", + "hospitalClinic": "Hospital Clinic", + "graphicalAnalysis": "Graphical Analysis", + "itemHistoryAnalysis": "Item History Analysis", + "pOno": "P.O #", + "oprUnit": "Opr. Unit", + "qtyOrdered": "Qty. Ordered", + "qtyReceived": "Qty. Received", + "bonusQty": "Bonus Qty.", + "balQty": "Bal. Qty.", + "start": "Start", + "about": "About", + "explore": "Explore", + "mazaya": "MAZAYA", + "benefits": "Benefits", + "mazayaDesc": "Discover special Discounts and offers available to Employees", + "viewallofferMazaya": "View All Offers", + "buyerName": "Buyer Name", + "buyerNumber": "Buyer Number", + "highestBidder": "Highest Bidder", + "remarks": "Remarks", + "faHeader": "FA Header Details", + "bookTypeCode": "Book Type Code", + "categoryCode": "Category Code", + "categoryGroup": "Category Group", + "faLINES": "Asset Details", + "assetNumber": "Asset Number", + "assetDescription": "Asset Description", + "barCodeNumber": "BarCode Number", + "datePlaceInService": "Date place In Service", + "serialNumber": "Serial Number", + "disposedDate": "Disposed Date", + "netBookValue": "Net Book Value", + "purchasedPrice": "Purchased Price", + "usefulLife": "Useful Life", + "yearsUsed": "Years Used", + "faRequest": "FA Disposal Request", + "showMore": "Show More", + "ticketDetails": "Ticket Details", + "currentTicketBalance": "Current Ticket Balance", + "ticketHistory": "Ticket History", + "proceedBooking": "Proceed For Booking", + "courses": "Courses", + "course": "Course", + "status": "Status", + "deadline": "Deadline", + "overdue": "Overdue", + "noCoursesAvailable": "No Courses Available", + "pullToRefresh": "Pull to refresh", + "courseUrlNotAvailable": "Course URL not available", + "buyerDetails": "Buyer Details", + "etqanOVR": "Report An Incident", + "etqanRequest": "Incident Requests", + "selectProject": "Select Project", + "project": "Project", + "keen": "Keen", + "reportIncident": "Report Incident", + "myIncidents": "My Incidents", + "incidentDetails": "Incident Details", + "ticketNumber": "Ticket Number", + "ticketId": "Ticket ID", + "pleaseSelectProject": "Please select a project", + "viewAttachment": "View Attachment", + "parkingQr": "Parking QR", + "startNow": "Start Now" +}; +static const Map> mapLocales = {"ar_SA": _ar_SA, "en_US": _en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 7a3501f..972583a 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1,12 +1,17 @@ // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart +// ignore_for_file: constant_identifier_names + abstract class LocaleKeys { static const mohemm = 'mohemm'; static const english = 'english'; static const arabic = 'arabic'; static const login = 'login'; static const pleaseEnterLoginDetails = 'pleaseEnterLoginDetails'; + static const userId = 'userId'; static const username = 'username'; + static const userName = 'userName'; + static const userSearch = 'userSearch'; static const password = 'password'; static const welcomeBack = 'welcomeBack'; static const wouldYouLikeToLoginWithCurrentUsername = 'wouldYouLikeToLoginWithCurrentUsername'; @@ -98,6 +103,7 @@ abstract class LocaleKeys { static const reject = 'reject'; static const approve = 'approve'; static const cancel = 'cancel'; + static const generate = 'generate'; static const requestedItems = 'requestedItems'; static const request = 'request'; static const myRequest = 'myRequest'; @@ -161,6 +167,7 @@ abstract class LocaleKeys { static const quotationAnalysis = 'quotationAnalysis'; static const subject = 'subject'; static const description = 'description'; + static const pleaseEnterDescription = 'pleaseEnterDescription'; static const supplier = 'supplier'; static const site = 'site'; static const buyer = 'buyer'; @@ -255,6 +262,7 @@ abstract class LocaleKeys { static const fullName = 'fullName'; static const remove = 'remove'; static const submit = 'submit'; + static const submitAsAnonymous = 'submitAsAnonymous'; static const areYouSureYouWantToSubmit = 'areYouSureYouWantToSubmit'; static const comments = 'comments'; static const writeComment = 'writeComment'; @@ -526,27 +534,127 @@ abstract class LocaleKeys { static const expiredDocuments = 'expiredDocuments'; static const missingDocuments = 'missingDocuments'; static const uploadedDocuments = 'uploadedDocuments'; - - static const manage = 'manage'; - static const members = 'members'; + static const addAtLeastOneAttachment = 'addAtLeastOneAttachment'; + static const pleaseClickButtonToJoinMarathon = 'pleaseClickButtonToJoinMarathon'; + static const youCannotJoinTheMarathon = 'youCannotJoinTheMarathon'; + static const open = 'open'; + static const paymentRequest = 'paymentRequest'; + static const paymentDetails = 'paymentDetails'; + static const requestNo = 'requestNo'; + static const requesterEmpNum = 'requesterEmpNum'; + static const requesterEmpName = 'requesterEmpName'; + static const prepareEmpName = 'prepareEmpName'; + static const requesterPositionName = 'requesterPositionName'; + static const preparePositionName = 'preparePositionName'; + static const requesterPayrollName = 'requesterPayrollName'; + static const payingORGName = 'payingORGName'; + static const requestAmount = 'requestAmount'; + static const typeofPayment = 'typeofPayment'; + static const beneficiaryDetails = 'beneficiaryDetails'; + static const beneficiaryName = 'beneficiaryName'; + static const idIqama = 'idIqama'; + static const beneficiaryBankName = 'beneficiaryBankName'; + static const sadadNumber = 'sadadNumber'; + static const beneficiaryIBAN = 'beneficiaryIBAN'; + static const purchaseOrders = 'purchaseOrders'; + static const approvalDate = 'approvalDate'; + static const pOAmount = 'pOAmount'; + static const versionStatus = 'versionStatus'; + static const supplierNo = 'supplierNo'; + static const general = 'general'; + static const requesterOperatingUnit = 'requesterOperatingUnit'; + static const prepareEmpNum = 'prepareEmpNum'; + static const supplierInfo = 'supplierInfo'; + static const supplierAcNo = 'supplierAcNo'; + static const supplierAcName = 'supplierAcName'; + static const supplierIBAN = 'supplierIBAN'; + static const supplierCRNo = 'supplierCRNo'; + static const suppliedAcNo = 'suppliedAcNo'; + static const patientRefundInvoice = 'patientRefundInvoice'; + static const patientNumber = 'patientNumber'; + static const patientName = 'patientName'; + static const invoiceDate = 'invoiceDate'; + static const refundInvoice = 'refundInvoice'; + static const hospitalClinic = 'hospitalClinic'; + static const graphicalAnalysis = 'graphicalAnalysis'; + static const itemHistoryAnalysis = 'itemHistoryAnalysis'; + static const pOno = 'pOno'; + static const oprUnit = 'oprUnit'; + static const qtyOrdered = 'qtyOrdered'; + static const qtyReceived = 'qtyReceived'; + static const bonusQty = 'bonusQty'; + static const balQty = 'balQty'; + static const videoCall = 'videoCall'; + static const addUsers = 'addUsers'; + static const admin = 'admin'; static const areYouSureWantTodelete = 'areYouSureWantTodelete'; - static const groupMembers = "groupMembers"; - static const manageGroup = "manageGroup"; - static const admin = "admin"; - static const addUsers ="addUsers"; - static const editGroups ="editGroups"; - static const groupNameshouldbe ="groupNameshouldbe"; - static const enterGroupName ="enterGroupName"; - static const groupName ="groupName"; - static const enterGroupNamePlease ="enterGroupNamePlease"; + static const Attendance = 'Attendance'; static const audioCall = 'audioCall'; - static const videoCall ='videoCall'; - static const shareScreen ='shareScreen'; - static const searchByUserName ='searchByUserName'; - static const userSearch ='userSearch'; - static const userName ='userName'; - static const userId ='userId'; - static const addAtLeastOneAttachment ='addAtLeastOneAttachment'; - static const pleaseClickButtonToJoinMarathon ='pleaseClickButtonToJoinMarathon'; - static const youCannotJoinTheMarathon ='youCannotJoinTheMarathon'; + static const editGroups = 'editGroups'; + static const enterGroupName = 'enterGroupName'; + static const enterGroupNamePlease = 'enterGroupNamePlease'; + static const groupMembers = 'groupMembers'; + static const groupName = 'groupName'; + static const groupNameshouldbe = 'groupNameshouldbe'; + static const manage = 'manage'; + static const manageGroup = 'manageGroup'; + static const members = 'members'; + static const searchByUserName = 'searchByUserName'; + static const shareScreen = 'shareScreen'; + static const start = 'start'; + static const about = 'about'; + static const explore = 'explore'; + static const mazaya = 'mazaya'; + static const benefits = 'benefits'; + static const mazayaDesc = 'mazayaDesc'; + static const viewallofferMazaya = 'viewallofferMazaya'; + static const buyerName = 'buyerName'; + static const buyerNumber = 'buyerNumber'; + static const highestBidder = 'highestBidder'; + static const remarks = 'remarks'; + static const faHeader = 'faHeader'; + static const bookTypeCode = 'bookTypeCode'; + static const categoryCode = 'categoryCode'; + static const categoryGroup = 'categoryGroup'; + static const faLINES = 'faLINES'; + static const assetNumber = 'assetNumber'; + static const assetDescription = 'assetDescription'; + static const barCodeNumber = 'barCodeNumber'; + static const datePlaceInService = 'datePlaceInService'; + static const serialNumber = 'serialNumber'; + static const disposedDate = 'disposedDate'; + static const netBookValue = 'netBookValue'; + static const purchasedPrice = 'purchasedPrice'; + static const usefulLife = 'usefulLife'; + static const yearsUsed = 'yearsUsed'; + static const faRequest = 'faRequest'; + static const showMore = 'showMore'; + static const ticketDetails = 'ticketDetails'; + static const currentTicketBalance = 'currentTicketBalance'; + static const ticketHistory = 'ticketHistory'; + static const proceedBooking = 'proceedBooking'; + static const courses = 'courses'; + static const course = 'course'; + static const status = 'status'; + static const deadline = 'deadline'; + static const overdue = 'overdue'; + static const noCoursesAvailable = 'noCoursesAvailable'; + static const pullToRefresh = 'pullToRefresh'; + static const courseUrlNotAvailable = 'courseUrlNotAvailable'; + static const buyerDetails = 'buyerDetails'; + static const etqanOVR = 'etqanOVR'; + static const etqanRequest = 'etqanRequest'; + static const selectProject = 'selectProject'; + static const project = 'project'; + static const keen = 'keen'; + static const reportIncident = 'reportIncident'; + static const myIncidents = 'myIncidents'; + static const incidentDetails = 'incidentDetails'; + static const ticketNumber = 'ticketNumber'; + static const ticketId = 'ticketId'; + static const pleaseSelectProject = 'pleaseSelectProject'; + static const viewAttachment = 'viewAttachment'; + static const parkingQr = 'parkingQr'; + static const startNow = 'startNow'; + } diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart index b59eec2..213926c 100644 --- a/lib/generated_plugin_registrant.dart +++ b/lib/generated_plugin_registrant.dart @@ -13,7 +13,7 @@ import 'package:firebase_core_web/firebase_core_web.dart'; import 'package:firebase_messaging_web/firebase_messaging_web.dart'; import 'package:fluttertoast/fluttertoast_web.dart'; import 'package:geolocator_web/geolocator_web.dart'; -import 'package:google_maps_flutter_web/google_maps_flutter_web.dart'; +// import 'package:google_maps_flutter_web/google_maps_flutter_web.dart'; import 'package:image_picker_for_web/image_picker_for_web.dart'; import 'package:just_audio_web/just_audio_web.dart'; // import 'package:record_web/record_web.dart'; @@ -32,7 +32,7 @@ void registerPlugins(Registrar registrar) { FirebaseMessagingWeb.registerWith(registrar); FluttertoastWebPlugin.registerWith(registrar); GeolocatorPlugin.registerWith(registrar); - GoogleMapsPlugin.registerWith(registrar); + // GoogleMapsPlugin.registerWith(registrar); ImagePickerPlugin.registerWith(registrar); JustAudioPlugin.registerWith(registrar); //RecordPluginWeb.registerWith(registrar); diff --git a/lib/main.dart b/lib/main.dart index 3eabd68..022204d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/models/post_params_model.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/provider/eit_provider_model.dart'; +import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart'; import 'package:mohem_flutter_app/theme/app_theme.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:month_year_picker/month_year_picker.dart'; @@ -19,18 +20,11 @@ import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; import 'package:sizer/sizer.dart'; - // test uat account // username 199067 // pass h123456 -Logger logger = Logger( - // filter: null, // Use the default LogFilter (-> only log in debug mode) - printer: PrettyPrinter( - lineLength: 0, - ), // Use the PrettyPrinter to format and print log - // output: null, // U -); +Logger logger = Logger(printer: PrettyPrinter(lineLength: 0)); class MyHttpOverrides extends HttpOverrides { @override @@ -43,10 +37,7 @@ bool isTablet = false; Future main() async { WidgetsFlutterBinding.ensureInitialized(); - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitUp, - DeviceOrientation.portraitDown, - ]); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); await EasyLocalization.ensureInitialized(); AppState().setPostParamsInitConfig(); HttpOverrides.global = MyHttpOverrides(); @@ -54,26 +45,16 @@ Future main() async { runApp( EasyLocalization( - supportedLocales: const [ - Locale('en', 'US'), - Locale('ar', 'SA'), - ], + supportedLocales: const [Locale('en', 'US'), Locale('ar', 'SA')], path: 'assets/langs', assetLoader: const CodegenLoader(), child: MultiProvider( providers: [ - ChangeNotifierProvider( - create: (_) => DashboardProviderModel(), - ), - ChangeNotifierProvider( - create: (_) => EITProviderModel(), - ), - ChangeNotifierProvider( - create: (_) => ChatProviderModel(), - ), - ChangeNotifierProvider( - create: (_) => MarathonProvider(), - ), + ChangeNotifierProvider(create: (_) => DashboardProviderModel()), + ChangeNotifierProvider(create: (_) => EITProviderModel()), + ChangeNotifierProvider(create: (_) => ChatProviderModel()), + ChangeNotifierProvider(create: (_) => MarathonProvider()), + ChangeNotifierProvider(create: (_) => EtqanOvrProviderModel()), // ChangeNotifierProvider( // create: (_) => ChatCallProvider(), // ), @@ -96,36 +77,29 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return Sizer( - builder: ( - BuildContext context, - Orientation orientation, - DeviceType deviceType, - ) { + builder: (BuildContext context, Orientation orientation, DeviceType deviceType) { PostParamsModel? obj = AppState().postParamsObject; obj?.languageID = EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2; AppState().setPostParamsModel(obj!); List> delegates = context.localizationDelegates; // delegates.add(GlobalMaterialLocalizations.delegate); - delegates.add( - MonthYearPickerLocalizations.delegate, - ); - return MaterialApp( - navigatorKey: AppRoutes.navigatorKey, - builder: (BuildContext context, Widget? child) { - return MediaQuery( - data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), - child: child!, - ); - }, - theme: AppTheme.getTheme( - EasyLocalization.of(context)?.locale.languageCode == "ar", + delegates.add(MonthYearPickerLocalizations.delegate); + return SafeArea( + top: false, // Set to true if you want to avoid the notch area as well + bottom: Platform.isIOS ? false : true, + child: MaterialApp( + navigatorKey: AppRoutes.navigatorKey, + builder: (BuildContext context, Widget? child) { + return MediaQuery(data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: child!); + }, + theme: AppTheme.getTheme(EasyLocalization.of(context)?.locale.languageCode == "ar"), + debugShowCheckedModeBanner: false, + localizationsDelegates: delegates, + supportedLocales: context.supportedLocales, + locale: context.locale, + initialRoute: AppRoutes.initialRoute, + routes: AppRoutes.routes, ), - debugShowCheckedModeBanner: false, - localizationsDelegates: delegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - initialRoute: AppRoutes.initialRoute, - routes: AppRoutes.routes, ); }, ); diff --git a/lib/models/chat/get_user_login_token_model.dart b/lib/models/chat/get_user_login_token_model.dart index 8d55461..f0620c3 100644 --- a/lib/models/chat/get_user_login_token_model.dart +++ b/lib/models/chat/get_user_login_token_model.dart @@ -5,21 +5,21 @@ UserAutoLoginModel userAutoLoginModelFromJson(String str) => UserAutoLoginModel. String userAutoLoginModelToJson(UserAutoLoginModel data) => json.encode(data.toJson()); class UserAutoLoginModel { - UserAutoLoginModel({ - this.response, - this.errorResponses, - }); + UserAutoLoginModel({this.response, this.errorResponses, this.StatusCode}); Response? response; List? errorResponses; + int? StatusCode; factory UserAutoLoginModel.fromJson(Map json) => UserAutoLoginModel( response: json["response"] == null ? null : Response.fromJson(json["response"]), + StatusCode: json["StatusCode"], errorResponses: json["errorResponses"] == null ? null : List.from(json["errorResponses"].map((x) => ErrorResponse.fromJson(x))), ); Map toJson() => { "response": response == null ? null : response!.toJson(), + "StatusCode": StatusCode, "errorResponses": errorResponses == null ? null : List.from(errorResponses!.map((x) => x.toJson())), }; } diff --git a/lib/models/dashboard/courses_response_model.dart b/lib/models/dashboard/courses_response_model.dart new file mode 100644 index 0000000..730d4a4 --- /dev/null +++ b/lib/models/dashboard/courses_response_model.dart @@ -0,0 +1,94 @@ +class CoursesResponseModel { + bool? success; + int? status; + String? username; + List? coursesStatus; + int? totalCourses; + + CoursesResponseModel({ + this.success, + this.status, + this.username, + this.coursesStatus, + this.totalCourses, + }); + + CoursesResponseModel.fromJson(Map json) { + success = json['success']; + status = json['status']; + username = json['username']; + if (json['courses_status'] != null) { + coursesStatus = []; + json['courses_status'].forEach((v) { + coursesStatus!.add(CourseStatus.fromJson(v)); + }); + } + totalCourses = json['total_courses']; + } + + Map toJson() { + Map data = {}; + data['success'] = success; + data['status'] = status; + data['username'] = username; + if (coursesStatus != null) { + data['courses_status'] = coursesStatus!.map((v) => v.toJson()).toList(); + } + data['total_courses'] = totalCourses; + return data; + } +} + +class CourseStatus { + String? cId; + String? cFullname; + String? cNameAr; + String? cShortname; + String? cStatus; + String? cIsMohemmAffective; + String? cStartdate; + String? cEnddate; + String? cUrl; + String? token; + CourseStatus({ + this.cId, + this.cFullname, + this.cNameAr, + this.cShortname, + this.cStatus, + this.cIsMohemmAffective, + this.cStartdate, + this.cEnddate, + this.cUrl, + this.token + }); + + CourseStatus.fromJson(Map json) { + cId = json['c_id']; + cFullname = json['c_fullname']; + cNameAr = json['c_name_ar']; + cShortname = json['c_shortname']; + cStatus = json['c_status']; + cIsMohemmAffective = json['c_is_mohemm_affective']; + cStartdate = json['c_startdate']; + cEnddate = json['c_enddate']; + cUrl = json['c_url']; + token =json['c_token']; + } + + Map toJson() { + Map data = {}; + data['c_id'] = cId; + data['c_fullname'] = cFullname; + data['c_name_ar'] = cNameAr; + data['c_shortname'] = cShortname; + data['c_status'] = cStatus; + data['c_is_mohemm_affective'] = cIsMohemmAffective; + data['c_startdate'] = cStartdate; + data['c_enddate'] = cEnddate; + data['c_url'] = cUrl; + data['c_token'] = token; + return data; + } +} + diff --git a/lib/models/dashboard/event_activity.dart b/lib/models/dashboard/event_activity.dart new file mode 100644 index 0000000..4b523d7 --- /dev/null +++ b/lib/models/dashboard/event_activity.dart @@ -0,0 +1,84 @@ + class EventActivityList { + EventActivityList({ + required this.id, + required this.titleEn, + required this.titleAr, + required this.shortDescEn, + required this.shortDescAr, + required this.longDescEn, + required this.longDescAr, + required this.url, + required this.startOn, + required this.endOn, + required this.channel, + required this.isActive, + required this.createdBy, + required this.createdOn, + required this.modifiedBy, + required this.modifiedOn, + required this.shortImageURL, + required this.detailImageURL + }); + + final int? id; + final String? titleEn; + final String? titleAr; + final String? shortDescEn; + final String? shortDescAr; + final String? longDescEn; + final String? longDescAr; + final String? url; + final String? startOn; + final String? endOn; + final int? channel; + final bool? isActive; + final int? createdBy; + final String? createdOn; + final String? modifiedBy; + final String? modifiedOn; + final String? shortImageURL; + final String? detailImageURL; + factory EventActivityList.fromJson(Map json) { + return EventActivityList( + id: json["ID"], + titleEn: json["TitleEn"], + titleAr: json["TitleAr"], + shortDescEn: json["ShortDescEn"], + shortDescAr: json["ShortDescAr"], + longDescEn: json["LongDescEn"], + longDescAr: json["LongDescAr"], + url: json["URL"], + startOn: json["StartOn"], + endOn: json["EndOn"], + channel: json["Channel"], + isActive: json["IsActive"], + createdBy: json["CreatedBy"], + createdOn: json["CreatedOn"], + modifiedBy: json["ModifiedBy"], + modifiedOn: json["ModifiedOn"], + shortImageURL: json["ShortImageURL"], + detailImageURL: json["DetailImageURL"] + ); + } + + Map toJson() => { + "ID": id, + "TitleEn": titleEn, + "TitleAr": titleAr, + "ShortDescEn": shortDescEn, + "ShortDescAr": shortDescAr, + "LongDescEn": longDescEn, + "LongDescAr": longDescAr, + "URL": url, + "StartOn": startOn, + "EndOn": endOn, + "Channel": channel, + "IsActive": isActive, + "CreatedBy": createdBy, + "CreatedOn": createdOn, + "ModifiedBy": modifiedBy, + "ModifiedOn": modifiedOn, + "DetailImageURL": detailImageURL, + "ShortImageURL" : shortImageURL + }; +} diff --git a/lib/models/dashboard/get_accural_ticket_balance_model.dart b/lib/models/dashboard/get_accural_ticket_balance_model.dart new file mode 100644 index 0000000..cc6520d --- /dev/null +++ b/lib/models/dashboard/get_accural_ticket_balance_model.dart @@ -0,0 +1,25 @@ +import 'dart:convert'; + +class GetTicketAccuralBalanceModel { + int? accrualNetEntitlement; + String? accuralPlanCode; + + GetTicketAccuralBalanceModel({ + this.accrualNetEntitlement, + this.accuralPlanCode, + }); + + factory GetTicketAccuralBalanceModel.fromRawJson(String str) => GetTicketAccuralBalanceModel.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetTicketAccuralBalanceModel.fromJson(Map json) => GetTicketAccuralBalanceModel( + accrualNetEntitlement: json["ACCRUAL_NET_ENTITLEMENT"], + accuralPlanCode: json["ACCURAL_PLAN_CODE"], + ); + + Map toJson() => { + "ACCRUAL_NET_ENTITLEMENT": accrualNetEntitlement, + "ACCURAL_PLAN_CODE": accuralPlanCode, + }; +} diff --git a/lib/models/dashboard/itg_forms_model.dart b/lib/models/dashboard/itg_forms_model.dart index ae67ef8..7109d4e 100644 --- a/lib/models/dashboard/itg_forms_model.dart +++ b/lib/models/dashboard/itg_forms_model.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:mohem_flutter_app/models/itg_forms_models/itg_forms_attachments_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/itg_request_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/request_type_model.dart'; @@ -84,7 +85,8 @@ class ItgFormsModel { dynamic successMsgN; dynamic vidaUpdatedResponse; ITGRequest? itgRequest; - dynamic itgFormAttachmentsList; + // dynamic itgFormAttachmentsList; + List? itgFormAttachmentsList; String? message; dynamic mohemmItgDepartmentSectionsList; dynamic mohemmItgProjectDepartmentsList; @@ -128,7 +130,11 @@ class ItgFormsModel { successMsgN: json["SuccessMsgN"], vidaUpdatedResponse: json["VidaUpdatedResponse"], itgRequest: json['ITGRequest'] != null ? ITGRequest.fromJson(json['ITGRequest']) : null, - itgFormAttachmentsList: json["Itg_FormAttachmentsList"], + itgFormAttachmentsList: + json["Itg_FormAttachmentsList"] == null ? [] : json["Itg_FormAttachmentsList"]!.map((v) => ITGFormsAttachmentsModel.fromJson(v)).toList(), + + // json["RequestType"] == null ? [] : json['RequestType']!.map((v) => RequestType.fromJson(v)).toList(), + message: json["Message"] == null ? null : json["Message"], mohemmItgDepartmentSectionsList: json["Mohemm_ITG_DepartmentSectionsList"], mohemmItgProjectDepartmentsList: json["Mohemm_ITG_ProjectDepartmentsList"], diff --git a/lib/models/dyanmic_forms/get_set_values_request_model.dart b/lib/models/dyanmic_forms/get_set_values_request_model.dart index 07c840a..9f1c52c 100644 --- a/lib/models/dyanmic_forms/get_set_values_request_model.dart +++ b/lib/models/dyanmic_forms/get_set_values_request_model.dart @@ -4,13 +4,15 @@ class GetSetValuesRequestModel { String? dESCRIPTION; String? iDCOLUMNNAME; String? fLEXVALUESETNAME; - + String? pSRCHVALUECOLUMNNAME; GetSetValuesRequestModel( {this.sEGMENTNAME, this.vALUECOLUMNNAME, this.dESCRIPTION, this.iDCOLUMNNAME, - this.fLEXVALUESETNAME}); + this.fLEXVALUESETNAME, + this.pSRCHVALUECOLUMNNAME, + }); GetSetValuesRequestModel.fromJson(Map json) { sEGMENTNAME = json['SEGMENT_NAME']; @@ -18,6 +20,7 @@ class GetSetValuesRequestModel { dESCRIPTION = json['DESCRIPTION']; iDCOLUMNNAME = json['ID_COLUMN_NAME']; fLEXVALUESETNAME = json['FLEX_VALUE_SET_NAME']; + pSRCHVALUECOLUMNNAME = json['P_SRCH_VALUE_COLUMN_NAME']; } Map toJson() { @@ -27,6 +30,7 @@ class GetSetValuesRequestModel { data['DESCRIPTION'] = this.dESCRIPTION; data['ID_COLUMN_NAME'] = this.iDCOLUMNNAME; data['FLEX_VALUE_SET_NAME'] = this.fLEXVALUESETNAME; + data['P_SRCH_VALUE_COLUMN_NAME'] =this.pSRCHVALUECOLUMNNAME; return data; } } diff --git a/lib/models/etqan_ovr/etqan_get_employee_incident_report.dart b/lib/models/etqan_ovr/etqan_get_employee_incident_report.dart new file mode 100644 index 0000000..e4a57fd --- /dev/null +++ b/lib/models/etqan_ovr/etqan_get_employee_incident_report.dart @@ -0,0 +1,57 @@ +import 'dart:convert'; + +class EtqanGetEmployeeIncidentRequestModel { + List? etqanGetIncidentRequestResponse; + + EtqanGetEmployeeIncidentRequestModel({ + this.etqanGetIncidentRequestResponse, + }); + + factory EtqanGetEmployeeIncidentRequestModel.fromRawJson(String str) => EtqanGetEmployeeIncidentRequestModel.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory EtqanGetEmployeeIncidentRequestModel.fromJson(Map json) => EtqanGetEmployeeIncidentRequestModel( + etqanGetIncidentRequestResponse: json["ETQAN_GetIncidentRequest_Response"] == null ? [] : List.from(json["ETQAN_GetIncidentRequest_Response"]!.map((x) => EtqanGetIncidentRequestResponse.fromJson(x))), + ); + + Map toJson() => { + "ETQAN_GetIncidentRequest_Response": etqanGetIncidentRequestResponse == null ? [] : List.from(etqanGetIncidentRequestResponse!.map((x) => x.toJson())), + }; +} + +class EtqanGetIncidentRequestResponse { + String? key; + String? keyAr; + String? value; + String? valueAr; + List? subValues; + + EtqanGetIncidentRequestResponse({ + this.key, + this.keyAr, + this.value, + this.valueAr, + this.subValues, + }); + + factory EtqanGetIncidentRequestResponse.fromRawJson(String str) => EtqanGetIncidentRequestResponse.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory EtqanGetIncidentRequestResponse.fromJson(Map json) => EtqanGetIncidentRequestResponse( + key: json["key"], + keyAr: json["keyAr"], + value: json["value"], + valueAr: json["valueAr"], + subValues: json["subValues"] == null ? [] : List.from(json["subValues"]!.map((x) => x)), + ); + + Map toJson() => { + "key": key, + "keyAr": keyAr, + "value": value, + "valueAr": valueAr, + "subValues": subValues == null ? [] : List.from(subValues!.map((x) => x)), + }; +} diff --git a/lib/models/etqan_ovr/etqan_get_requests_model.dart b/lib/models/etqan_ovr/etqan_get_requests_model.dart new file mode 100644 index 0000000..ac4911b --- /dev/null +++ b/lib/models/etqan_ovr/etqan_get_requests_model.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +class EtqanGetEmployeeRequestsModel { + List? etqanGetEmployeeOvrRequestsResponse; + + EtqanGetEmployeeRequestsModel({ + this.etqanGetEmployeeOvrRequestsResponse, + }); + + factory EtqanGetEmployeeRequestsModel.fromRawJson(String str) => EtqanGetEmployeeRequestsModel.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory EtqanGetEmployeeRequestsModel.fromJson(Map json) => EtqanGetEmployeeRequestsModel( + etqanGetEmployeeOvrRequestsResponse: json["ETQAN_GetEmployeeOVRRequests_Response"] == null ? [] : List.from(json["ETQAN_GetEmployeeOVRRequests_Response"]!.map((x) => EtqanGetEmployeeOvrRequestsResponse.fromJson(x))), + ); + + Map toJson() => { + "ETQAN_GetEmployeeOVRRequests_Response": etqanGetEmployeeOvrRequestsResponse == null ? [] : List.from(etqanGetEmployeeOvrRequestsResponse!.map((x) => x.toJson())), + }; +} + +class EtqanGetEmployeeOvrRequestsResponse { + String? createdDate; + String? description; + String? id; + bool? isAnonymous; + String? status; + String? statusAr; + String? ticketNumber; + + EtqanGetEmployeeOvrRequestsResponse({ + this.createdDate, + this.description, + this.id, + this.isAnonymous, + this.status, + this.statusAr, + this.ticketNumber, + }); + + factory EtqanGetEmployeeOvrRequestsResponse.fromRawJson(String str) => EtqanGetEmployeeOvrRequestsResponse.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory EtqanGetEmployeeOvrRequestsResponse.fromJson(Map json) => EtqanGetEmployeeOvrRequestsResponse( + createdDate: json["createdDate"], + description: json["description"], + id: json["id"], + isAnonymous: json["isAnonymous"], + status: json["status"], + statusAr: json["statusAr"], + ticketNumber: json["ticketNumber"], + ); + + Map toJson() => { + "createdDate": createdDate, + "description": description, + "id": id, + "isAnonymous": isAnonymous, + "status": status, + "statusAr": statusAr, + "ticketNumber": ticketNumber, + }; +} diff --git a/lib/models/etqan_ovr/etqan_getprojects_model.dart b/lib/models/etqan_ovr/etqan_getprojects_model.dart new file mode 100644 index 0000000..5584faa --- /dev/null +++ b/lib/models/etqan_ovr/etqan_getprojects_model.dart @@ -0,0 +1,53 @@ +import 'dart:convert'; + +class EtqanGetProjectsModel { + List? etqanGetProjectsResponse; + + EtqanGetProjectsModel({ + this.etqanGetProjectsResponse, + }); + + factory EtqanGetProjectsModel.fromRawJson(String str) => EtqanGetProjectsModel.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory EtqanGetProjectsModel.fromJson(Map json) => EtqanGetProjectsModel( + etqanGetProjectsResponse: json["ETQAN_GetProjects_Response"] == null ? [] : List.from(json["ETQAN_GetProjects_Response"]!.map((x) => EtqanGetProjectsResponse.fromJson(x))), + ); + + Map toJson() => { + "ETQAN_GetProjects_Response": etqanGetProjectsResponse == null ? [] : List.from(etqanGetProjectsResponse!.map((x) => x.toJson())), + }; +} + +class EtqanGetProjectsResponse { + String? projectAr; + String? projectCode; + String? projectEn; + int? projectId; + + EtqanGetProjectsResponse({ + this.projectAr, + this.projectCode, + this.projectEn, + this.projectId, + }); + + factory EtqanGetProjectsResponse.fromRawJson(String str) => EtqanGetProjectsResponse.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory EtqanGetProjectsResponse.fromJson(Map json) => EtqanGetProjectsResponse( + projectAr: json["projectAr"], + projectCode: json["projectCode"], + projectEn: json["projectEn"], + projectId: json["projectId"], + ); + + Map toJson() => { + "projectAr": projectAr, + "projectCode": projectCode, + "projectEn": projectEn, + "projectId": projectId, + }; +} diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 893b5b9..df94c8b 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -1,7 +1,11 @@ +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'; +import 'package:mohem_flutter_app/models/dashboard/event_activity.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; +import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_open_missing_swipes_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_open_notifications_list.dart'; @@ -104,12 +108,14 @@ import 'package:mohem_flutter_app/models/vacation_rule/vr_item_types_list_model. import 'package:mohem_flutter_app/models/vacation_rule/wf_look_up_list_model.dart'; import 'package:mohem_flutter_app/models/validate_eit_transaction_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; +import 'package:mohem_flutter_app/models/worklist/get_fad_notifications.dart'; import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_address_notification_body_list.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/payment_details_list.dart'; import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/resubmit_eit_response_model.dart'; import 'package:mohem_flutter_app/models/worklist_response_model.dart'; @@ -173,6 +179,7 @@ class GenericResponseModel { List? getAbsenceDffStructureList; List? getAbsenceTransactionList; List? getAccrualBalancesList; + List? getAccrualBalancesTicketList; List? getActionHistoryList; List? getPRActionHistoryList; List? getAddressDffStructureList; @@ -183,10 +190,11 @@ class GenericResponseModel { List? getBasicDetColsStructureList; List? getBasicDetDffStructureList; List? getBasicDetNtfBodyList; - List? getCEICollectionNotificationBodyList; - List? getCEIDFFStructureList; - List? getCEITransactionList; + List? getCEICollectionNotificationBodyList; + List? getCEIDFFStructureList; + List? getCEITransactionList; List? getCcpTransactionsList; + List? getContactColsStructureList; List? getContactDetailsList; List? getContactDffStructureList; @@ -212,6 +220,7 @@ class GenericResponseModel { List? getItemTypesList; List? getLookupValuesList; List? getMenuEntriesList; + List? getEventActivityList; List? getMoItemHistoryList; List? getMoNotificationBodyList; List? getNotificationButtonsList; @@ -224,6 +233,7 @@ class GenericResponseModel { List? getOrganizationsSalariesList; List? getPaymentInformationList; List? getPayslipList; + // List? getPendingReqDetailsList; // List? getPendingReqFunctionsList; List? getPerformanceAppraisalList; @@ -232,6 +242,7 @@ class GenericResponseModel { List? getPoItemHistoryList; GetPoNotificationBodyList? getPoNotificationBodyList; GetPrNotificationBodyList? getPrNotificationBodyList; + GetPaymentNotificationBodyList? getPaymentNotificationBodyList; GetPRInformationList? getPRInformationList; List? getQuotationAnalysisList; List? getRFCEmployeeListList; @@ -352,7 +363,7 @@ class GenericResponseModel { StartTermApprovalProcessList? startTermApprovalProcessList; SubmitAddressTransaction? submitAddressTransactionList; SubmitBasicDetailsTransactionList? submitBasicDetTransactionList; - String? submitCEITransactionList; + SubmitEITTransactionList? submitCEITransactionList; SubmitCcpTransactionList? submitCcpTransactionList; SubmitContactTransactionList? submitContactTransactionList; SubmitEITTransactionList? submitEITTransactionList; @@ -378,6 +389,7 @@ class GenericResponseModel { String? validatePhonesTransactionList; List? vrItemTypesList; List? wFLookUpList; + GetFaDisposalNtfDetails? getFADisposalNtfDetails; String? eLearningGETEMPLOYEEPROFILEList; String? eLearningLOGINList; String? eLearningValidateLoginList; @@ -385,273 +397,280 @@ 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.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.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.getAccrualBalancesTicketList, + 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, + this.getFADisposalNtfDetails + }); GenericResponseModel.fromJson(Map json) { date = json['Date']; @@ -680,6 +699,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 = []; @@ -696,7 +716,7 @@ class GenericResponseModel { cancelHRTransactionLIst = json['CancelHRTransactionLIst'] != null ? new CancelHRTransactionLIst.fromJson(json['CancelHRTransactionLIst']) : null; if (json['GetTermNotificationBodyList'] != null) { - getTermNotificationBodyList = []; + getTermNotificationBodyList = []; json['GetTermNotificationBodyList'].forEach((v) { getTermNotificationBodyList!.add(TerminationNotificationBody.fromJson(v)); }); @@ -768,6 +788,8 @@ class GenericResponseModel { } getAccrualBalancesList = json["GetAccrualBalancesList"] == null ? null : List.from(json["GetAccrualBalancesList"].map((x) => GetAccrualBalancesList.fromJson(x))); + getAccrualBalancesTicketList = + json["GetAccrualBalancesTicketList"] == null ? null : List.from(json["GetAccrualBalancesTicketList"].map((x) => GetTicketAccuralBalanceModel.fromJson(x))); if (json['GetActionHistoryList'] != null) { getActionHistoryList = []; @@ -840,9 +862,25 @@ class GenericResponseModel { }); } - getCEICollectionNotificationBodyList = json['GetCEICollectionNotificationBodyList']; - getCEIDFFStructureList = json['GetCEIDFFStructureList']; - getCEITransactionList = json['GetCEITransactionList']; + getCEICollectionNotificationBodyList = + json["GetCEICollectionNotificationBodyList"] == null + ? null + : List.from(json["GetCEICollectionNotificationBodyList"].map((x) => GetEitCollectionNotificationBodyList.fromJson(x))); + + if (json['GetCEIDFFStructureList'] != null) { + getCEIDFFStructureList = []; + json['GetCEIDFFStructureList'].forEach((v) { + getCEIDFFStructureList!.add(GetEITDFFStructureList.fromJson(v)); + }); + } + + if (json['GetCEITransactionList'] != null) { + getCEITransactionList = []; + json['GetCEITransactionList'].forEach((v) { + getCEITransactionList!.add(GetCEITransactionList.fromJson(v)); + }); + } + getCcpTransactionsList = json['GetCcpTransactionsList']; getContactNotificationBodyList = json["GetContactNotificationBodyList"] == null ? null : GetContactNotificationBodyList.fromJson(json["GetContactNotificationBodyList"]); if (json['GetContactColsStructureList'] != null) { @@ -886,9 +924,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) { @@ -902,6 +941,9 @@ class GenericResponseModel { }); } + getFADisposalNtfDetails = json['GetFADisposalNtfDetails'] != null ? GetFaDisposalNtfDetails.fromJson(json['GetFADisposalNtfDetails']) : null; + + if (json['GetEarningsList'] != null) { getEarningsList = []; json['GetEarningsList'].forEach((v) { @@ -954,6 +996,7 @@ class GenericResponseModel { getItemTypesList = json['GetItemTypesList']; getLookupValuesList = json['GetLookupValuesList']; getMenuEntriesList = json["GetMenuEntriesList"] == null ? null : List.from(json["GetMenuEntriesList"].map((x) => GetMenuEntriesList.fromJson(x))); + getEventActivityList = json["EventActivityList"] == null ? null : List.from(json["EventActivityList"].map((x) => EventActivityList.fromJson(x))); if (json['GetMoItemHistoryList'] != null) { getMoItemHistoryList = []; json['GetMoItemHistoryList'].forEach((v) { @@ -1022,6 +1065,8 @@ class GenericResponseModel { } getPoNotificationBodyList = json['GetPoNotificationBodyList'] != null ? GetPoNotificationBodyList.fromJson(json['GetPoNotificationBodyList']) : null; getPrNotificationBodyList = json['GetPrNotificationBodyList'] != null ? GetPrNotificationBodyList.fromJson(json['GetPrNotificationBodyList']) : null; + getPaymentNotificationBodyList = json['Pay_ReqNotificationBody'] != null ? GetPaymentNotificationBodyList.fromJson(json['Pay_ReqNotificationBody']) : null; + getPRInformationList = json['PR_Information_List'] != null ? GetPRInformationList.fromJson(json['PR_Information_List']) : null; if (json['GetQuotationAnalysisList'] != null) { getQuotationAnalysisList = []; @@ -1099,8 +1144,6 @@ class GenericResponseModel { }); } - - if (json['GetTimeCardSummaryList'] != null) { getTimeCardSummaryList = []; json['GetTimeCardSummaryList'].forEach((v) { @@ -1360,7 +1403,7 @@ class GenericResponseModel { submitAddressTransactionList = json['SubmitAddressTransactionList'] != null ? SubmitAddressTransaction.fromJson(json['SubmitAddressTransactionList']) : null; submitBasicDetTransactionList = json['SubmitBasicDetTransactionList'] != null ? SubmitBasicDetailsTransactionList.fromJson(json['SubmitBasicDetTransactionList']) : null; - submitCEITransactionList = json['SubmitCEITransactionList']; + submitCEITransactionList = json['SubmitCEITransactionList'] != null ? SubmitEITTransactionList.fromJson(json['SubmitCEITransactionList']) : null; submitCcpTransactionList = json['SubmitCcpTransactionList'] != null ? new SubmitCcpTransactionList.fromJson(json['SubmitCcpTransactionList']) : null; submitContactTransactionList = json['SubmitContactTransactionList'] != null ? SubmitContactTransactionList.fromJson(json['SubmitContactTransactionList']) : null; submitEITTransactionList = json['SubmitEITTransactionList'] != null ? SubmitEITTransactionList.fromJson(json['SubmitEITTransactionList']) : null; @@ -1451,6 +1494,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(); @@ -1512,10 +1556,12 @@ class GenericResponseModel { data['GetAbsenceTransactionList'] = this.getAbsenceTransactionList!.map((v) => v.toJson()).toList(); } data['GetAccrualBalancesList'] = this.getAccrualBalancesList; + data['GetAccrualBalancesTicketList'] = this.getAccrualBalancesTicketList; if (this.getActionHistoryList != null) { data['GetActionHistoryList'] = this.getActionHistoryList!.map((v) => v.toJson()).toList(); } + data['GetFADisposalNtfDetails'] =this.getFADisposalNtfDetails; data['GetAddressDffStructureList'] = this.getAddressDffStructureList; data['GetAddressNotificationBodyList'] = this.getAddressNotificationBodyList; @@ -1535,10 +1581,15 @@ class GenericResponseModel { if (this.getBasicDetNtfBodyList != null) { data['GetBasicDetNtfBodyList'] = this.getBasicDetNtfBodyList!.map((v) => v.toJson()).toList(); } - data['GetCEICollectionNotificationBodyList'] = this.getCEICollectionNotificationBodyList; - data['GetCEIDFFStructureList'] = this.getCEIDFFStructureList; - data['GetCEITransactionList'] = this.getCEITransactionList; + + if (this.getCEIDFFStructureList != null) { + data['GetCEIDFFStructureList'] = this.getCEIDFFStructureList!.map((v) => v.toJson()).toList(); + } + + if (this.getCEITransactionList != null) { + data['GetCEITransactionList'] = this.getCEITransactionList!.map((v) => v.toJson()).toList(); + } data['GetCcpTransactionsList'] = this.getCcpTransactionsList; if (this.getContactDetailsList != null) { data['GetContactDetailsList'] = this.getContactDetailsList!.map((v) => v.toJson()).toList(); @@ -1605,6 +1656,7 @@ class GenericResponseModel { data['GetItemTypesList'] = this.getItemTypesList; data['GetLookupValuesList'] = this.getLookupValuesList; data['GetMenuEntriesList'] = this.getMenuEntriesList; + data['EventActivityList'] = this.getEventActivityList; if (this.getMoItemHistoryList != null) { data['GetMoItemHistoryList'] = this.getMoItemHistoryList!.map((v) => v.toJson()).toList(); } @@ -1621,7 +1673,7 @@ class GenericResponseModel { data['GetNotificationReassignModeList'] = getNotificationReassignModeList!.map((v) => v.toJson()).toList(); } - if(getTermNotificationBodyList !=null){ + if (getTermNotificationBodyList != null) { data['GetTermNotificationBodyList'] = getTermNotificationBodyList!.map((v) => v.toJson()).toList(); } data['GetObjectValuesList'] = this.getObjectValuesList; @@ -1650,6 +1702,9 @@ class GenericResponseModel { if (this.getPrNotificationBodyList != null) { data['GetPrNotificationBodyList'] = this.getPrNotificationBodyList!.toJson(); } + if (this.getPaymentNotificationBodyList != null) { + data['Pay_ReqNotificationBody'] = this.getPaymentNotificationBodyList!.toJson(); + } if (this.getPRInformationList != null) { data['PR_Information_List'] = this.getPRInformationList!.toJson(); @@ -1827,6 +1882,10 @@ class GenericResponseModel { } data['SubmitCEITransactionList'] = this.submitCEITransactionList; + + if (this.submitCEITransactionList != null) { + data['SubmitCEITransactionList'] = this.submitCEITransactionList!.toJson(); + } if (this.submitCcpTransactionList != null) { data['SubmitCcpTransactionList'] = this.submitCcpTransactionList!.toJson(); } @@ -1893,3 +1952,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); +} diff --git a/lib/models/get_eit_dff_structure_list_model.dart b/lib/models/get_eit_dff_structure_list_model.dart index 3aed98c..59736d3 100644 --- a/lib/models/get_eit_dff_structure_list_model.dart +++ b/lib/models/get_eit_dff_structure_list_model.dart @@ -39,7 +39,7 @@ class GetEITDFFStructureList { String? vALIDATIONTYPE; String? vALIDATIONTYPEDSP; String? fieldAnswer; - + String? vSSRCHFLAG; GetEITDFFStructureList( {this.aLPHANUMERICALLOWEDFLAG, this.aPPLICATIONCOLUMNNAME, @@ -80,7 +80,9 @@ class GetEITDFFStructureList { this.uSEDFLAG, this.vALIDATIONTYPE, this.vALIDATIONTYPEDSP, - this.fieldAnswer}); + this.fieldAnswer, + this.vSSRCHFLAG + }); GetEITDFFStructureList.fromJson(Map json) { aLPHANUMERICALLOWEDFLAG = json['ALPHANUMERIC_ALLOWED_FLAG']; @@ -148,6 +150,7 @@ class GetEITDFFStructureList { uSEDFLAG = json['USED_FLAG']; vALIDATIONTYPE = json['VALIDATION_TYPE']; vALIDATIONTYPEDSP = json['VALIDATION_TYPE_DSP']; + vSSRCHFLAG = json['VS_SRCH_FLAG']; } Map toJson() { @@ -203,6 +206,7 @@ class GetEITDFFStructureList { data['USED_FLAG'] = this.uSEDFLAG; data['VALIDATION_TYPE'] = this.vALIDATIONTYPE; data['VALIDATION_TYPE_DSP'] = this.vALIDATIONTYPEDSP; + data['VS_SRCH_FLAG'] =this.vSSRCHFLAG; return data; } @@ -214,14 +218,15 @@ class ESERVICESDV { dynamic pRETURNMSG; String? pRETURNSTATUS; dynamic pVALUECOLUMNNAME; - - ESERVICESDV({this.pIDCOLUMNNAME, this.pRETURNMSG, this.pRETURNSTATUS, this.pVALUECOLUMNNAME}); + dynamic pSRCHVALUECOLUMNNAME; + ESERVICESDV({this.pIDCOLUMNNAME, this.pRETURNMSG, this.pRETURNSTATUS, this.pVALUECOLUMNNAME, this.pSRCHVALUECOLUMNNAME}); ESERVICESDV.fromJson(Map json) { pIDCOLUMNNAME = json['P_ID_COLUMN_NAME']; pRETURNMSG = json['P_RETURN_MSG']; pRETURNSTATUS = json['P_RETURN_STATUS']; pVALUECOLUMNNAME = json['P_VALUE_COLUMN_NAME']; + pSRCHVALUECOLUMNNAME = json['P_SRCH_VALUE_COLUMN_NAME']; } Map toJson() { @@ -230,6 +235,7 @@ class ESERVICESDV { data['P_RETURN_MSG'] = pRETURNMSG; data['P_RETURN_STATUS'] = pRETURNSTATUS; data['P_VALUE_COLUMN_NAME'] = pVALUECOLUMNNAME; + data['P_SRCH_VALUE_COLUMN_NAME'] =pSRCHVALUECOLUMNNAME; return data; } } diff --git a/lib/models/get_eit_transaction_list_model.dart b/lib/models/get_eit_transaction_list_model.dart index d8c39c9..c459bbd 100644 --- a/lib/models/get_eit_transaction_list_model.dart +++ b/lib/models/get_eit_transaction_list_model.dart @@ -15,8 +15,30 @@ class GetEITTransactionList { Map toJson() { Map data = new Map(); if (this.collectionTransaction != null) { - data['Collection_Transaction'] = - this.collectionTransaction!.map((v) => v.toJson()).toList(); + data['Collection_Transaction'] = this.collectionTransaction!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class GetCEITransactionList { + List? collectionTransaction; + + GetCEITransactionList({this.collectionTransaction}); + + GetCEITransactionList.fromJson(Map json) { + if (json['Collection_Transaction'] != null) { + collectionTransaction = []; + json['Collection_Transaction'].forEach((v) { + collectionTransaction!.add(new CollectionTransaction.fromJson(v)); + }); + } + } + + Map toJson() { + Map data = new Map(); + if (this.collectionTransaction != null) { + data['Collection_Transaction'] = this.collectionTransaction!.map((v) => v.toJson()).toList(); } return data; } @@ -43,22 +65,22 @@ class CollectionTransaction { CollectionTransaction( {this.aPPLICATIONCOLUMNNAME, - this.dATATYPE, - this.dATEVALUE, - this.dESCFLEXCONTEXTCODE, - this.dESCFLEXNAME, - this.dISPLAYFLAG, - this.fROMROWNUM, - this.nOOFROWS, - this.nUMBERVALUE, - this.rOWNUM, - this.sEGMENTNAME, - this.sEGMENTPROMPT, - this.sEGMENTSEQNUM, - this.sEGMENTVALUEDSP, - this.tOROWNUM, - this.tRANSACTIONNUMBER, - this.vARCHAR2VALUE}); + this.dATATYPE, + this.dATEVALUE, + this.dESCFLEXCONTEXTCODE, + this.dESCFLEXNAME, + this.dISPLAYFLAG, + this.fROMROWNUM, + this.nOOFROWS, + this.nUMBERVALUE, + this.rOWNUM, + this.sEGMENTNAME, + this.sEGMENTPROMPT, + this.sEGMENTSEQNUM, + this.sEGMENTVALUEDSP, + this.tOROWNUM, + this.tRANSACTIONNUMBER, + this.vARCHAR2VALUE}); CollectionTransaction.fromJson(Map json) { aPPLICATIONCOLUMNNAME = json['APPLICATION_COLUMN_NAME']; @@ -101,4 +123,4 @@ class CollectionTransaction { data['VARCHAR2_VALUE'] = this.vARCHAR2VALUE; return data; } -} \ No newline at end of file +} diff --git a/lib/models/get_employee_parking_details_model.dart b/lib/models/get_employee_parking_details_model.dart new file mode 100644 index 0000000..4a385c8 --- /dev/null +++ b/lib/models/get_employee_parking_details_model.dart @@ -0,0 +1,61 @@ +import 'dart:convert'; + +class GetEmployeeParking { + GetEmployeeParkingClass? getEmployeeParking; + + GetEmployeeParking({ + this.getEmployeeParking, + }); + + factory GetEmployeeParking.fromRawJson(String str) => GetEmployeeParking.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetEmployeeParking.fromJson(Map json) => GetEmployeeParking( + getEmployeeParking: json["GET_Employee_Parking"] == null ? null : GetEmployeeParkingClass.fromJson(json["GET_Employee_Parking"]), + ); + + Map toJson() => { + "GET_Employee_Parking": getEmployeeParking?.toJson(), + }; +} + +class GetEmployeeParkingClass { + DateTime? createdAt; + String? employeeCode; + String? isNewQrCode; + String? qrCode; + String? qrCodeImageBase64; + bool? success; + + GetEmployeeParkingClass({ + this.createdAt, + this.employeeCode, + this.isNewQrCode, + this.qrCode, + this.qrCodeImageBase64, + this.success, + }); + + factory GetEmployeeParkingClass.fromRawJson(String str) => GetEmployeeParkingClass.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetEmployeeParkingClass.fromJson(Map json) => GetEmployeeParkingClass( + createdAt: json["createdAt"] == null ? null : DateTime.parse(json["createdAt"]), + employeeCode: json["employeeCode"], + isNewQrCode: json["isNewQRCode"], + qrCode: json["qrCode"], + qrCodeImageBase64: json["qrCodeImageBase64"], + success: json["success"], + ); + + Map toJson() => { + "createdAt": createdAt?.toIso8601String(), + "employeeCode": employeeCode, + "isNewQRCode": isNewQrCode, + "qrCode": qrCode, + "qrCodeImageBase64": qrCodeImageBase64, + "success": success, + }; +} diff --git a/lib/models/greetings/greeting_card_model.dart b/lib/models/greetings/greeting_card_model.dart new file mode 100644 index 0000000..486aa8f --- /dev/null +++ b/lib/models/greetings/greeting_card_model.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +class GetGreetingCardsModelResponse { + List? getGreetingCardsModelResponse; + + GetGreetingCardsModelResponse({ + this.getGreetingCardsModelResponse, + }); + + factory GetGreetingCardsModelResponse.fromRawJson(String str) => GetGreetingCardsModelResponse.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetGreetingCardsModelResponse.fromJson(Map json) => GetGreetingCardsModelResponse( + getGreetingCardsModelResponse: json["Get_GreetingCardsModel_Response"] == null ? [] : List.from(json["Get_GreetingCardsModel_Response"]!.map((x) => GetGreetingCardsModelResponseElement.fromJson(x))), + ); + + Map toJson() => { + "Get_GreetingCardsModel_Response": getGreetingCardsModelResponse == null ? [] : List.from(getGreetingCardsModelResponse!.map((x) => x.toJson())), + }; +} + +class GetGreetingCardsModelResponseElement { + String? backgroundImageUrlAr; + String? backgroundImageUrlEn; + String? buttonBgColor; + String? buttonText; + String? buttonTextN; + int? cardType; + int? categoryId; + String? categoryNameAr; + String? categoryNameEn; + int? channel; + String? createdOn; + String? descriptionAr; + String? descriptionEn; + String? endDate; + bool? hasButton; + int? id; + bool? isActive; + int? moduleId; + String? moduleName; + String? moduleNameN; + String? startDate; + String? textColor; + String? titleAr; + String? titleEn; + String? urlAr; + String? urlEn; + + GetGreetingCardsModelResponseElement({ + this.backgroundImageUrlAr, + this.backgroundImageUrlEn, + this.buttonBgColor, + this.buttonText, + this.buttonTextN, + this.cardType, + this.categoryId, + this.categoryNameAr, + this.categoryNameEn, + this.channel, + this.createdOn, + this.descriptionAr, + this.descriptionEn, + this.endDate, + this.hasButton, + this.id, + this.isActive, + this.moduleId, + this.moduleName, + this.moduleNameN, + this.startDate, + this.textColor, + this.titleAr, + this.titleEn, + this.urlAr, + this.urlEn, + }); + + factory GetGreetingCardsModelResponseElement.fromRawJson(String str) => GetGreetingCardsModelResponseElement.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetGreetingCardsModelResponseElement.fromJson(Map json) => GetGreetingCardsModelResponseElement( + backgroundImageUrlAr: json["BackgroundImageUrlAr"], + backgroundImageUrlEn: json["BackgroundImageUrlEn"], + buttonBgColor: json["ButtonBgColor"], + buttonText: json["ButtonText"], + buttonTextN: json["ButtonTextN"], + cardType: json["CardType"], + categoryId: json["CategoryID"], + categoryNameAr: json["CategoryNameAr"], + categoryNameEn: json["CategoryNameEn"], + channel: json["Channel"], + createdOn: json["CreatedOn"], + descriptionAr: json["DescriptionAr"], + descriptionEn: json["DescriptionEn"], + endDate: json["EndDate"], + hasButton: json["HasButton"], + id: json["ID"], + isActive: json["IsActive"], + moduleId: json["ModuleID"], + moduleName: json["ModuleName"], + moduleNameN: json["ModuleNameN"], + startDate: json["StartDate"], + textColor: json["TextColor"], + titleAr: json["TitleAr"], + titleEn: json["TitleEn"], + urlAr: json["UrlAr"], + urlEn: json["UrlEn"], + ); + + Map toJson() => { + "BackgroundImageUrlAr": backgroundImageUrlAr, + "BackgroundImageUrlEn": backgroundImageUrlEn, + "ButtonBgColor": buttonBgColor, + "ButtonText": buttonText, + "ButtonTextN": buttonTextN, + "CardType": cardType, + "CategoryID": categoryId, + "CategoryNameAr": categoryNameAr, + "CategoryNameEn": categoryNameEn, + "Channel": channel, + "CreatedOn": createdOn, + "DescriptionAr": descriptionAr, + "DescriptionEn": descriptionEn, + "EndDate": endDate, + "HasButton": hasButton, + "ID": id, + "IsActive": isActive, + "ModuleID": moduleId, + "ModuleName": moduleName, + "ModuleNameN": moduleNameN, + "StartDate": startDate, + "TextColor": textColor, + "TitleAr": titleAr, + "TitleEn": titleEn, + "UrlAr": urlAr, + "UrlEn": urlEn, + }; +} + diff --git a/lib/models/itg/advertisement.dart b/lib/models/itg/advertisement.dart index ebcf704..2379d37 100644 --- a/lib/models/itg/advertisement.dart +++ b/lib/models/itg/advertisement.dart @@ -1,6 +1,7 @@ class Advertisement { int? advertisementId; String? advertisementTitle; + String? advertisementTitleAr; int? durationInSeconds; bool? showDelete; dynamic acknowledgment; @@ -16,6 +17,7 @@ class Advertisement { Advertisement({ this.advertisementId, this.advertisementTitle, + this.advertisementTitleAr, this.durationInSeconds, this.showDelete, this.acknowledgment, @@ -34,6 +36,7 @@ class Advertisement { Advertisement.fromJson(Map json) { advertisementId = json['advertisementId']; advertisementTitle = json['advertisementTitle']; + advertisementTitleAr = json['advertisementTitleAr']; durationInSeconds = json['durationInSeconds']; showDelete = json['showDelete']; acknowledgment = json['acknowledgment']; @@ -63,6 +66,7 @@ class Advertisement { Map data = Map(); data['advertisementId'] = this.advertisementId; data['advertisementTitle'] = this.advertisementTitle; + data['advertisementTitleAr'] = this.advertisementTitleAr; data['durationInSeconds'] = this.durationInSeconds; data['showDelete'] = this.showDelete; data['acknowledgment'] = this.acknowledgment; @@ -94,8 +98,9 @@ class ViewAttachFileColl { dynamic referenceItemId; dynamic content; dynamic filePath; + dynamic languageId; - ViewAttachFileColl({this.attachmentId, this.fileName, this.contentType, this.attachFileStream, this.base64String, this.isActive, this.referenceItemId, this.content, this.filePath}); + ViewAttachFileColl({this.attachmentId, this.fileName, this.contentType, this.attachFileStream, this.base64String, this.isActive, this.referenceItemId, this.content, this.filePath, this.languageId}); ViewAttachFileColl.fromJson(Map json) { attachmentId = json['attachmentId']; @@ -107,6 +112,7 @@ class ViewAttachFileColl { referenceItemId = json['referenceItemId']; content = json['content']; filePath = json['filePath']; + languageId = json['languageId']; } Map toJson() { @@ -120,6 +126,7 @@ class ViewAttachFileColl { data['referenceItemId'] = this.referenceItemId; data['content'] = this.content; data['filePath'] = this.filePath; + data['languageId'] = this.languageId; return data; } } @@ -129,10 +136,21 @@ class ActionButtonsColl { late String btnTextEn; late String btnTextAr; late String actionValue; - late dynamic iconOrImage; + dynamic iconOrImage; + String? actionType; late int orderNo; + String? url; - ActionButtonsColl({required this.actionButtonId, required this.btnTextEn, required this.btnTextAr, required this.actionValue, required this.iconOrImage, required this.orderNo}); + ActionButtonsColl({ + required this.actionButtonId, + required this.btnTextEn, + required this.btnTextAr, + required this.actionValue, + this.iconOrImage, + this.actionType, + required this.orderNo, + this.url, + }); ActionButtonsColl.fromJson(Map json) { actionButtonId = json['actionButtonId']; @@ -140,7 +158,9 @@ class ActionButtonsColl { btnTextAr = json['btnTextAr']; actionValue = json['actionValue']; iconOrImage = json['iconOrImage']; + actionType = json['actionType']; orderNo = json['orderNo']; + url = json['url']; } Map toJson() { @@ -150,7 +170,9 @@ class ActionButtonsColl { data['btnTextAr'] = this.btnTextAr; data['actionValue'] = this.actionValue; data['iconOrImage'] = this.iconOrImage; + data['actionType'] = this.actionType; data['orderNo'] = this.orderNo; + data['url'] = this.url; return data; } } diff --git a/lib/models/itg/itg_response_model.dart b/lib/models/itg/itg_response_model.dart index dff7869..6a85cb1 100644 --- a/lib/models/itg/itg_response_model.dart +++ b/lib/models/itg/itg_response_model.dart @@ -45,22 +45,57 @@ class ItgResponseResult { this.data, this.errormsg, }); +// +// final dynamic totalItemsCount; +// final ItgResponseData? data; +// final dynamic errormsg; +// +// factory ItgResponseResult.fromJson(Map json) => ItgResponseResult( +// totalItemsCount: json["totalItemsCount"], +// data: json["data"] == null ? null : ItgResponseData.fromJson(json["data"]), +// errormsg: json["errormsg"], +// ); +// +// Map toJson() => { +// "totalItemsCount": totalItemsCount, +// "data": data == null ? null : data!.toJson(), +// "errormsg": errormsg, +// }; +// } + +// todo these lines, for ERM new change on UAT +dynamic totalItemsCount; +List? data; +dynamic errormsg; + +ItgResponseResult.fromJson(Map json) { + totalItemsCount = json['totalItemsCount']; + if (json['data'] != null) { + data = []; + if(json['data'] is List) { + json['data'].forEach((v) { + data!.add(ItgResponseData.fromJson(v)); + }); + } else { + data!.add(ItgResponseData.fromJson(json['data'])); + } + + } + errormsg = json['errormsg']; +} - final dynamic totalItemsCount; - final ItgResponseData? data; - final dynamic errormsg; - - factory ItgResponseResult.fromJson(Map json) => ItgResponseResult( - totalItemsCount: json["totalItemsCount"], - data: json["data"] == null ? null : ItgResponseData.fromJson(json["data"]), - errormsg: json["errormsg"], - ); - - Map toJson() => { - "totalItemsCount": totalItemsCount, - "data": data == null ? null : data!.toJson(), - "errormsg": errormsg, - }; +// +// factory ItgResponseResult.fromJson(Map json) => ItgResponseResult( +// totalItemsCount: json["totalItemsCount"], +// data: json["data"] == null ? null : ItgResponseData.fromJson(json["data"]), +// errormsg: json["errormsg"], +// ); + +Map toJson() => { + "totalItemsCount": totalItemsCount, + "data": data == null ? null : data!.map((v) => v.toJson()).toList(), + "errormsg": errormsg, + }; } class ItgResponseData { diff --git a/lib/models/itg/itg_summary_data.dart b/lib/models/itg/itg_summary_data.dart new file mode 100644 index 0000000..7371857 --- /dev/null +++ b/lib/models/itg/itg_summary_data.dart @@ -0,0 +1,101 @@ +import 'dart:convert'; + +class ItgTimeCardSummaryData { + String? returNStatus; + String? returNMsg; + List? summeries; + List>? details; + + ItgTimeCardSummaryData({this.returNStatus, this.returNMsg, this.summeries, this.details}); + + factory ItgTimeCardSummaryData.fromRawJson(String str) => ItgTimeCardSummaryData.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory ItgTimeCardSummaryData.fromJson(Map json) => ItgTimeCardSummaryData( + returNStatus: json["returN_STATUS"], + returNMsg: json["returN_MSG"], + summeries: json["summeries"] == null ? [] : List.from(json["summeries"]!.map((x) => Summery.fromJson(x))), + details: json["details"] == null ? [] : List>.from(json["details"]!.map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), + ); + + Map toJson() => { + "returN_STATUS": returNStatus, + "returN_MSG": returNMsg, + "summeries": summeries == null ? [] : List.from(summeries!.map((x) => x.toJson())), + "details": details == null ? [] : List.from(details!.map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), + }; +} + +class Summery { + int? missinGSwipesDays; + String? scheduleDHrs; + String? actuaLHrs; + String? excesSHrs; + String? timebacKHrs; + String? shortagEHrs; + String? latEInHrs; + String? earlYOutHrs; + double? uncovereDShortageHrs; + int? sicKLeaves; + int? publiCHolidays; + int? unauthorizeDLeaves; + int? unpaiDLeaves; + int? paiDLeaves; + + Summery({ + + this.missinGSwipesDays, + this.scheduleDHrs, + this.actuaLHrs, + this.excesSHrs, + this.timebacKHrs, + this.shortagEHrs, + this.latEInHrs, + this.earlYOutHrs, + this.uncovereDShortageHrs, + this.sicKLeaves, + this.publiCHolidays, + this.unauthorizeDLeaves, + this.unpaiDLeaves, + this.paiDLeaves, + }); + + factory Summery.fromRawJson(String str) => Summery.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Summery.fromJson(Map json) => Summery( + missinGSwipesDays: json["missinG_SWIPES_DAYS"], + scheduleDHrs: json["scheduleD_HRS"], + actuaLHrs: json["actuaL_HRS"], + excesSHrs: json["excesS_HRS"], + timebacKHrs: json["timebacK_HRS"], + shortagEHrs: json["shortagE_HRS"], + latEInHrs: json["latE_IN_HRS"], + earlYOutHrs: json["earlY_OUT_HRS"], + uncovereDShortageHrs: json["uncovereD_SHORTAGE_HRS"]?.toDouble(), + sicKLeaves: json["sicK_LEAVES"], + publiCHolidays: json["publiC_HOLIDAYS"], + unauthorizeDLeaves: json["unauthorizeD_LEAVES"], + unpaiDLeaves: json["unpaiD_LEAVES"], + paiDLeaves: json["paiD_LEAVES"], + ); + + Map toJson() => { + "missinG_SWIPES_DAYS": missinGSwipesDays, + "scheduleD_HRS": scheduleDHrs, + "actuaL_HRS": actuaLHrs, + "excesS_HRS": excesSHrs, + "timebacK_HRS": timebacKHrs, + "shortagE_HRS": shortagEHrs, + "latE_IN_HRS": latEInHrs, + "earlY_OUT_HRS": earlYOutHrs, + "uncovereD_SHORTAGE_HRS": uncovereDShortageHrs, + "sicK_LEAVES": sicKLeaves, + "publiC_HOLIDAYS": publiCHolidays, + "unauthorizeD_LEAVES": unauthorizeDLeaves, + "unpaiD_LEAVES": unpaiDLeaves, + "paiD_LEAVES": paiDLeaves, + }; +} diff --git a/lib/models/itg/survey_model.dart b/lib/models/itg/survey_model.dart index f9ac415..501ce65 100644 --- a/lib/models/itg/survey_model.dart +++ b/lib/models/itg/survey_model.dart @@ -9,13 +9,18 @@ class SurveyModel { dynamic pageNo; dynamic languageId; - SurveyModel({this.surveyId, this.referenceNo, this.title, this.description, this.questions, this.isActive, this.pageSize, this.pageNo, this.languageId}); + String? descriptionAr; + String? titleAr; + + SurveyModel({this.surveyId, this.referenceNo, this.title,this.titleAr, this.description, this.descriptionAr, this.questions, this.isActive, this.pageSize, this.pageNo, this.languageId}); SurveyModel.fromJson(Map json) { surveyId = json['surveyId']; referenceNo = json['referenceNo']; title = json['title']; + titleAr = json['titleAr']; description = json['description']; + descriptionAr = json['descriptionAr']; if (json['questions'] != null) { questions = []; json['questions'].forEach((v) { @@ -33,7 +38,9 @@ class SurveyModel { data['surveyId'] = this.surveyId; data['referenceNo'] = this.referenceNo; data['title'] = this.title; + data['titleAr'] = this.titleAr; data['description'] = this.description; + data['descriptionAr'] = this.descriptionAr; if (this.questions != null) { data['questions'] = this.questions!.map((v) => v.toJson()).toList(); } @@ -48,6 +55,7 @@ class SurveyModel { class Questions { int? questionId; String? title; + String? titleAr; bool? isRequired; String? type; int? sequenceNo; @@ -59,11 +67,12 @@ class Questions { dynamic pageNo; dynamic languageId; - Questions({this.questionId, this.title, this.isRequired, this.type, this.sequenceNo, this.surveyId, this.options, this.rspPercentage, this.isActive, this.pageSize, this.pageNo, this.languageId}); + Questions({this.questionId, this.title, this.titleAr, this.isRequired, this.type, this.sequenceNo, this.surveyId, this.options, this.rspPercentage, this.isActive, this.pageSize, this.pageNo, this.languageId}); Questions.fromJson(Map json) { questionId = json['questionId']; title = json['title']; + titleAr = json['titleAr']; isRequired = json['isRequired']; type = json['type']; sequenceNo = json['sequenceNo']; @@ -85,6 +94,7 @@ class Questions { Map data = new Map(); data['questionId'] = this.questionId; data['title'] = this.title; + data['titleAr'] = this.titleAr; data['isRequired'] = this.isRequired; data['type'] = this.type; data['sequenceNo'] = this.sequenceNo; @@ -104,6 +114,7 @@ class Questions { class Options { int? optionId; String? title; + String? titleAr; bool? isCommentsRequired; int? sequenceNo; int? questionId; @@ -114,11 +125,12 @@ class Options { dynamic pageNo; dynamic languageId; - Options({this.optionId, this.title, this.isCommentsRequired, this.sequenceNo, this.questionId, this.rspPercentage, this.count, this.isActive, this.pageSize, this.pageNo, this.languageId}); + Options({this.optionId, this.title,this.titleAr, this.isCommentsRequired, this.sequenceNo, this.questionId, this.rspPercentage, this.count, this.isActive, this.pageSize, this.pageNo, this.languageId}); Options.fromJson(Map json) { optionId = json['optionId']; title = json['title']; + titleAr = json['titleAr']; isCommentsRequired = json['isCommentsRequired']; sequenceNo = json['sequenceNo']; questionId = json['questionId']; @@ -134,6 +146,7 @@ class Options { Map data = new Map(); data['optionId'] = this.optionId; data['title'] = this.title; + data['titleAr'] = this.titleAr; data['isCommentsRequired'] = this.isCommentsRequired; data['sequenceNo'] = this.sequenceNo; data['questionId'] = this.questionId; diff --git a/lib/models/itg_forms_models/itg_forms_attachments_model.dart b/lib/models/itg_forms_models/itg_forms_attachments_model.dart new file mode 100644 index 0000000..2f5d8b5 --- /dev/null +++ b/lib/models/itg_forms_models/itg_forms_attachments_model.dart @@ -0,0 +1,25 @@ +class ITGFormsAttachmentsModel { + String? fileBase64; + dynamic fileData; + String? fileName; + String? fileType; + + ITGFormsAttachmentsModel( + {this.fileBase64, this.fileData, this.fileName, this.fileType}); + + ITGFormsAttachmentsModel.fromJson(Map json) { + fileBase64 = json['fileBase64']; + fileData = json['fileData']; + fileName = json['fileName']; + fileType = json['fileType']; + } + + Map toJson() { + Map data = new Map(); + data['fileBase64'] = this.fileBase64; + data['fileData'] = this.fileData; + data['fileName'] = this.fileName; + data['fileType'] = this.fileType; + return data; + } +} diff --git a/lib/models/leave_balance/calculate_absence_duration_model.dart b/lib/models/leave_balance/calculate_absence_duration_model.dart index cf32a0e..df6a5d2 100644 --- a/lib/models/leave_balance/calculate_absence_duration_model.dart +++ b/lib/models/leave_balance/calculate_absence_duration_model.dart @@ -1,5 +1,5 @@ class CalculateAbsenceDuration { - double? pABSENCEDAYS; + num? pABSENCEDAYS; double? pABSENCEHOURS; String? pRETURNMSG; String? pRETURNSTATUS; diff --git a/lib/models/marathon/tutorial_notification_model.dart b/lib/models/marathon/tutorial_notification_model.dart new file mode 100644 index 0000000..ca1dd52 --- /dev/null +++ b/lib/models/marathon/tutorial_notification_model.dart @@ -0,0 +1,104 @@ +// class TutorialNotificationModel { +// List? data; +// bool? isSuccessful; +// String? message; +// int? statusCode; +// +// TutorialNotificationModel({this.data, this.isSuccessful, this.message, this.statusCode}); +// +// TutorialNotificationModel.fromJson(Map json) { +// if (json['data'] != null) { +// data = []; +// json['data'].forEach((v) { +// data!.add(new Data.fromJson(v)); +// }); +// } +// isSuccessful = json['isSuccessful']; +// message = json['message']; +// statusCode = json['statusCode']; +// } +// +// Map toJson() { +// final Map data = new Map(); +// if (this.data != null) { +// data['data'] = this.data!.map((v) => v.toJson()).toList(); +// } +// data['isSuccessful'] = this.isSuccessful; +// data['message'] = this.message; +// data['statusCode'] = this.statusCode; +// +// return data; +// } +// } + +class TutorialNotificationModel { + String? tutorialNotificationId; + String? tutorialName; + String? tutorialDescription; + String? startDate; + String? endDate; + String? fileName; + String? contentType; + String? filePath; + int? orderNo; + bool? isActive; + int? isStatus; + String? created; + String? createdBy; + String? modified; + String? modifiedBy; + + TutorialNotificationModel({this.tutorialNotificationId, + this.tutorialName, + this.tutorialDescription, + this.startDate, + this.endDate, + this.fileName, + this.contentType, + this.filePath, + this.orderNo, + this.isActive, + this.isStatus, + this.created, + this.createdBy, + this.modified, + this.modifiedBy}); + + TutorialNotificationModel.fromJson(Map json) { + tutorialNotificationId = json['tutorialNotificationId']; + tutorialName = json['tutorialName']; + tutorialDescription = json['tutorialDescription']; + startDate = json['startDate']; + endDate = json['endDate']; + fileName = json['fileName']; + contentType = json['contentType']; + filePath = json['filePath']; + orderNo = json['orderNo']; + isActive = json['isActive']; + isStatus = json['isStatus']; + created = json['created']; + createdBy = json['createdBy']; + modified = json['modified']; + modifiedBy = json['modifiedBy']; + } + + Map toJson() { + Map data = new Map(); + data['tutorialNotificationId'] = this.tutorialNotificationId; + data['tutorialName'] = this.tutorialName; + data['tutorialDescription'] = this.tutorialDescription; + data['startDate'] = this.startDate; + data['endDate'] = this.endDate; + data['fileName'] = this.fileName; + data['contentType'] = this.contentType; + data['filePath'] = this.filePath; + data['orderNo'] = this.orderNo; + data['isActive'] = this.isActive; + data['isStatus'] = this.isStatus; + data['created'] = this.created; + data['createdBy'] = this.createdBy; + data['modified'] = this.modified; + data['modifiedBy'] = this.modifiedBy; + return data; + } +} diff --git a/lib/models/mowadhafhi/get_ticket_transactions.dart b/lib/models/mowadhafhi/get_ticket_transactions.dart index be793ca..3cb0ce1 100644 --- a/lib/models/mowadhafhi/get_ticket_transactions.dart +++ b/lib/models/mowadhafhi/get_ticket_transactions.dart @@ -1,24 +1,24 @@ class GetTicketTransactions { String? actionBy; String? actionDate; + List? attachments; String? comments; String? statusDisplayText; String? statusName; String? ticketId; int? ticketTransactionId; - GetTicketTransactions( - {this.actionBy, - this.actionDate, - this.comments, - this.statusDisplayText, - this.statusName, - this.ticketId, - this.ticketTransactionId}); + GetTicketTransactions({this.actionBy, this.actionDate, this.attachments, this.comments, this.statusDisplayText, this.statusName, this.ticketId, this.ticketTransactionId}); GetTicketTransactions.fromJson(Map json) { actionBy = json['actionBy']; actionDate = json['actionDate']; + if (json['attachments'] != null) { + attachments = []; + json['attachments'].forEach((v) { + attachments!.add(new Attachments.fromJson(v)); + }); + } comments = json['comments']; statusDisplayText = json['statusDisplayText']; statusName = json['statusName']; @@ -27,9 +27,12 @@ class GetTicketTransactions { } Map toJson() { - Map data = new Map(); + Map data = Map(); data['actionBy'] = this.actionBy; data['actionDate'] = this.actionDate; + if (this.attachments != null) { + data['attachments'] = this.attachments!.map((v) => v.toJson()).toList(); + } data['comments'] = this.comments; data['statusDisplayText'] = this.statusDisplayText; data['statusName'] = this.statusName; @@ -38,3 +41,22 @@ class GetTicketTransactions { return data; } } + +class Attachments { + int? attachmentId; + String? fileName; + + Attachments({this.attachmentId, this.fileName}); + + Attachments.fromJson(Map json) { + attachmentId = json['attachmentId']; + fileName = json['fileName']; + } + + Map toJson() { + Map data = Map(); + data['attachmentId'] = this.attachmentId; + data['fileName'] = this.fileName; + return data; + } +} diff --git a/lib/models/mowadhafhi/get_transaction_attachment_model.dart b/lib/models/mowadhafhi/get_transaction_attachment_model.dart new file mode 100644 index 0000000..1234946 --- /dev/null +++ b/lib/models/mowadhafhi/get_transaction_attachment_model.dart @@ -0,0 +1,52 @@ +class GetTransactionAttachmentModel { + int? attachmentId; + String? fileName; + String? contentType; + dynamic attachFileStream; + String? base64String; + dynamic isActive; + dynamic referenceItemId; + dynamic content; + dynamic filePath; + int? languageId; + + GetTransactionAttachmentModel( + {this.attachmentId, + this.fileName, + this.contentType, + this.attachFileStream, + this.base64String, + this.isActive, + this.referenceItemId, + this.content, + this.filePath, + this.languageId}); + + GetTransactionAttachmentModel.fromJson(Map json) { + attachmentId = json['attachmentId']; + fileName = json['fileName']; + contentType = json['contentType']; + attachFileStream = json['attachFileStream']; + base64String = json['base64String']; + isActive = json['isActive']; + referenceItemId = json['referenceItemId']; + content = json['content']; + filePath = json['filePath']; + languageId = json['languageId']; + } + + Map toJson() { + Map data = Map(); + data['attachmentId'] = this.attachmentId; + data['fileName'] = this.fileName; + data['contentType'] = this.contentType; + data['attachFileStream'] = this.attachFileStream; + data['base64String'] = this.base64String; + data['isActive'] = this.isActive; + data['referenceItemId'] = this.referenceItemId; + data['content'] = this.content; + data['filePath'] = this.filePath; + data['languageId'] = this.languageId; + return data; + } +} 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/models/worklist/get_fad_notifications.dart b/lib/models/worklist/get_fad_notifications.dart new file mode 100644 index 0000000..3a7ed2d --- /dev/null +++ b/lib/models/worklist/get_fad_notifications.dart @@ -0,0 +1,233 @@ +import 'dart:convert'; + +class GetFaDisposalNtfDetails { + List? pFaBuyers; + List? pFaHeader; + List? pFaLines; + String? pInformation; + dynamic pQuestion; + + GetFaDisposalNtfDetails({ + this.pFaBuyers, + this.pFaHeader, + this.pFaLines, + this.pInformation, + this.pQuestion, + }); + + factory GetFaDisposalNtfDetails.fromRawJson(String str) => GetFaDisposalNtfDetails.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetFaDisposalNtfDetails.fromJson(Map json) => GetFaDisposalNtfDetails( + pFaBuyers: json["P_FA_BUYERS"] == null ? [] : List.from(json["P_FA_BUYERS"]!.map((x) => PFaBuyer.fromJson(x))), + pFaHeader: json["P_FA_HEADER"] == null ? [] : List.from(json["P_FA_HEADER"]!.map((x) => PFaHeader.fromJson(x))), + pFaLines: json["P_FA_LINES"] == null ? [] : List.from(json["P_FA_LINES"]!.map((x) => PFaLine.fromJson(x))), + pInformation: json["P_INFORMATION"], + pQuestion: json["P_QUESTION"], + ); + + Map toJson() => { + "P_FA_BUYERS": pFaBuyers == null ? [] : List.from(pFaBuyers!.map((x) => x.toJson())), + "P_FA_HEADER": pFaHeader == null ? [] : List.from(pFaHeader!.map((x) => x.toJson())), + "P_FA_LINES": pFaLines == null ? [] : List.from(pFaLines!.map((x) => x.toJson())), + "P_INFORMATION": pInformation, + "P_QUESTION": pQuestion, + }; +} + +class PFaBuyer { + int? amount; + String? buyerName; + String? buyerNumber; + int? fromRowNum; + String? highestBidder; + int? noOfRows; + String? receiptNumber; + String? remarks; + int? requestNo; + int? rowNum; + int? toRowNum; + + PFaBuyer({ + this.amount, + this.buyerName, + this.buyerNumber, + this.fromRowNum, + this.highestBidder, + this.noOfRows, + this.receiptNumber, + this.remarks, + this.requestNo, + this.rowNum, + this.toRowNum, + }); + + factory PFaBuyer.fromRawJson(String str) => PFaBuyer.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory PFaBuyer.fromJson(Map json) => PFaBuyer( + amount: json["AMOUNT"], + buyerName: json["BUYER_NAME"], + buyerNumber: json["BUYER_NUMBER"], + fromRowNum: json["FROM_ROW_NUM"], + highestBidder: json["HIGHEST_BIDDER"], + noOfRows: json["NO_OF_ROWS"], + receiptNumber: json["RECEIPT_NUMBER"], + remarks: json["REMARKS"], + requestNo: json["REQUEST_NO"], + rowNum: json["ROW_NUM"], + toRowNum: json["TO_ROW_NUM"], + ); + + Map toJson() => { + "AMOUNT": amount, + "BUYER_NAME": buyerName, + "BUYER_NUMBER": buyerNumber, + "FROM_ROW_NUM": fromRowNum, + "HIGHEST_BIDDER": highestBidder, + "NO_OF_ROWS": noOfRows, + "RECEIPT_NUMBER": receiptNumber, + "REMARKS": remarks, + "REQUEST_NO": requestNo, + "ROW_NUM": rowNum, + "TO_ROW_NUM": toRowNum, + }; +} + +class PFaHeader { + String? bookTypeCode; + String? categoryCode; + String? categoryGroup; + String? comments; + int? requestNo; + String? status; + + PFaHeader({ + this.bookTypeCode, + this.categoryCode, + this.categoryGroup, + this.comments, + this.requestNo, + this.status, + }); + + factory PFaHeader.fromRawJson(String str) => PFaHeader.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory PFaHeader.fromJson(Map json) => PFaHeader( + bookTypeCode: json["BOOK_TYPE_CODE"], + categoryCode: json["CATEGORY_CODE"], + categoryGroup: json["CATEGORY_GROUP"], + comments: json["COMMENTS"], + requestNo: json["REQUEST_NO"], + status: json["STATUS"], + ); + + Map toJson() => { + "BOOK_TYPE_CODE": bookTypeCode, + "CATEGORY_CODE": categoryCode, + "CATEGORY_GROUP": categoryGroup, + "COMMENTS": comments, + "REQUEST_NO": requestNo, + "STATUS": status, + }; +} + +class PFaLine { + String? action; + String? assetDescription; + int? assetNumber; + String? barcodeNumber; + String? bme; + String? datePlacedInService; + String? department; + String? disposedDate; + int? fromRowNum; + double? netBookValue; + int? noOfRows; + String? poNumber; + double? purchasePrice; + int? quantity; + int? requestNo; + int? rowNum; + String? serialNumber; + int? toRowNum; + int? usefulLife; + String? yearsUsed; + + PFaLine({ + this.action, + this.assetDescription, + this.assetNumber, + this.barcodeNumber, + this.bme, + this.datePlacedInService, + this.department, + this.disposedDate, + this.fromRowNum, + this.netBookValue, + this.noOfRows, + this.poNumber, + this.purchasePrice, + this.quantity, + this.requestNo, + this.rowNum, + this.serialNumber, + this.toRowNum, + this.usefulLife, + this.yearsUsed, + }); + + factory PFaLine.fromRawJson(String str) => PFaLine.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory PFaLine.fromJson(Map json) => PFaLine( + action: json["ACTION"], + assetDescription: json["ASSET_DESCRIPTION"], + assetNumber: json["ASSET_NUMBER"], + barcodeNumber: json["BARCODE_NUMBER"], + bme: json["BME"], + datePlacedInService: json["DATE_PLACED_IN_SERVICE"], + department: json["DEPARTMENT"], + disposedDate: json["DISPOSED_DATE"], + fromRowNum: json["FROM_ROW_NUM"], + netBookValue: json["NET_BOOK_VALUE"]?.toDouble(), + noOfRows: json["NO_OF_ROWS"], + poNumber: json["PO_NUMBER"], + purchasePrice: json["PURCHASE_PRICE"]?.toDouble(), + quantity: json["QUANTITY"], + requestNo: json["REQUEST_NO"], + rowNum: json["ROW_NUM"], + serialNumber: json["SERIAL_NUMBER"], + toRowNum: json["TO_ROW_NUM"], + usefulLife: json["USEFUL_LIFE"], + yearsUsed: json["YEARS_USED"], + ); + + Map toJson() => { + "ACTION": action, + "ASSET_DESCRIPTION": assetDescription, + "ASSET_NUMBER": assetNumber, + "BARCODE_NUMBER": barcodeNumber, + "BME": bme, + "DATE_PLACED_IN_SERVICE": datePlacedInService, + "DEPARTMENT": department, + "DISPOSED_DATE": disposedDate, + "FROM_ROW_NUM": fromRowNum, + "NET_BOOK_VALUE": netBookValue, + "NO_OF_ROWS": noOfRows, + "PO_NUMBER": poNumber, + "PURCHASE_PRICE": purchasePrice, + "QUANTITY": quantity, + "REQUEST_NO": requestNo, + "ROW_NUM": rowNum, + "SERIAL_NUMBER": serialNumber, + "TO_ROW_NUM": toRowNum, + "USEFUL_LIFE": usefulLife, + "YEARS_USED": yearsUsed, + }; +} diff --git a/lib/models/worklist/payment_details_list.dart b/lib/models/worklist/payment_details_list.dart new file mode 100644 index 0000000..be7bada --- /dev/null +++ b/lib/models/worklist/payment_details_list.dart @@ -0,0 +1,285 @@ +import 'dart:convert'; + +class GetPaymentNotificationBodyList { + List? beneficieryList; + dynamic pInformation; + dynamic pQuestion; + List? paymentDetailsList; + List? purchaseOrdersList; + List? refundInvoiceList; + List? supplierInformationList; + + GetPaymentNotificationBodyList({ + this.beneficieryList, + this.pInformation, + this.pQuestion, + this.paymentDetailsList, + this.purchaseOrdersList, + this.refundInvoiceList, + this.supplierInformationList, + }); + + factory GetPaymentNotificationBodyList.fromRawJson(String str) => GetPaymentNotificationBodyList.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetPaymentNotificationBodyList.fromJson(Map json) => GetPaymentNotificationBodyList( + beneficieryList: json["Beneficiery_List"] == null ? [] : List.from(json["Beneficiery_List"]!.map((x) => BeneficieryList.fromJson(x))), + pInformation: json["P_INFORMATION"], + pQuestion: json["P_QUESTION"], + paymentDetailsList: json["PaymentDetails_List"] == null ? [] : List.from(json["PaymentDetails_List"]!.map((x) => PaymentDetailsList.fromJson(x))), + purchaseOrdersList: json["PurchaseOrders_List"] == null ? [] : List.from(json["PurchaseOrders_List"]!.map((x) => PurchaseOrdersList.fromJson(x))), + refundInvoiceList: json["RefundInvoice_List"] == null ? [] : List.from(json["RefundInvoice_List"]!.map((x) => RefundInvoiceList.fromJson(x))), + supplierInformationList: json["SupplierInformation_List"] == null ? [] : List.from(json["SupplierInformation_List"]!.map((x) => SupplierInformationList.fromJson(x))), + ); + + Map toJson() => { + "Beneficiery_List": beneficieryList == null ? [] : List.from(beneficieryList!.map((x) => x.toJson())), + "P_INFORMATION": pInformation, + "P_QUESTION": pQuestion, + "PaymentDetails_List": paymentDetailsList == null ? [] : List.from(paymentDetailsList!.map((x) => x.toJson())), + "PurchaseOrders_List": purchaseOrdersList == null ? [] : List.from(purchaseOrdersList!.map((x) => x.toJson())), + "RefundInvoice_List": refundInvoiceList == null ? [] : List.from(refundInvoiceList!.map((x) => x.toJson())), + "SupplierInformation_List": supplierInformationList == null ? [] : List.from(supplierInformationList!.map((x) => x.toJson())), + }; +} + +class BeneficieryList { + String? beneficiaryBankName; + String? beneficiaryIban; + String? beneficiaryName; + String? iqamaNumber; + String? saddadNumber; + + BeneficieryList({ + this.beneficiaryBankName, + this.beneficiaryIban, + this.beneficiaryName, + this.iqamaNumber, + this.saddadNumber, + }); + + factory BeneficieryList.fromRawJson(String str) => BeneficieryList.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory BeneficieryList.fromJson(Map json) => BeneficieryList( + beneficiaryBankName: json["BENEFICIARY_BANK_NAME"], + beneficiaryIban: json["BENEFICIARY_IBAN"], + beneficiaryName: json["BENEFICIARY_NAME"], + iqamaNumber: json["IQAMA_NUMBER"], + saddadNumber: json["SADDAD_NUMBER"], + ); + + Map toJson() => { + "BENEFICIARY_BANK_NAME": beneficiaryBankName, + "BENEFICIARY_IBAN": beneficiaryIban, + "BENEFICIARY_NAME": beneficiaryName, + "IQAMA_NUMBER": iqamaNumber, + "SADDAD_NUMBER": saddadNumber, + }; +} + +class PaymentDetailsList { + String? currency; + String? payingOrganizationName; + String? paymentDetails; + String? paymentMethodName; + String? prepareEmployeeName; + String? prepareEmployeeNumber; + String? preparePositionName; + String? requesterEmployeeName; + String? requesterEmployeeNumber; + String? requesterOperatingUnits; + String? requesterPayrollName; + String? requesterPositionName; + String? requestAmount; + String? requestDate; + String? requestNumber; + String? typeOfPayment; + + PaymentDetailsList({ + this.currency, + this.payingOrganizationName, + this.paymentDetails, + this.paymentMethodName, + this.prepareEmployeeName, + this.prepareEmployeeNumber, + this.preparePositionName, + this.requesterEmployeeName, + this.requesterEmployeeNumber, + this.requesterOperatingUnits, + this.requesterPayrollName, + this.requesterPositionName, + this.requestAmount, + this.requestDate, + this.requestNumber, + this.typeOfPayment, + }); + + factory PaymentDetailsList.fromRawJson(String str) => PaymentDetailsList.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory PaymentDetailsList.fromJson(Map json) => PaymentDetailsList( + currency: json["CURRENCY"], + payingOrganizationName: json["PAYING_ORGANIZATION_NAME"], + paymentDetails: json["PAYMENT_DETAILS"], + paymentMethodName: json["PAYMENT_METHOD_NAME"], + prepareEmployeeName: json["PREPARE_EMPLOYEE_NAME"], + prepareEmployeeNumber: json["PREPARE_EMPLOYEE_NUMBER"], + preparePositionName: json["PREPARE_POSITION_NAME"], + requesterEmployeeName: json["REQUESTER_EMPLOYEE_NAME"], + requesterEmployeeNumber: json["REQUESTER_EMPLOYEE_NUMBER"], + requesterOperatingUnits: json["REQUESTER_OPERATING_UNITS"], + requesterPayrollName: json["REQUESTER_PAYROLL_NAME"], + requesterPositionName: json["REQUESTER_POSITION_NAME"], + requestAmount: json["REQUEST_AMOUNT"], + requestDate: json["REQUEST_DATE"], + requestNumber: json["REQUEST_NUMBER"], + typeOfPayment: json["TYPE_OF_PAYMENT"], + ); + + Map toJson() => { + "CURRENCY": currency, + "PAYING_ORGANIZATION_NAME": payingOrganizationName, + "PAYMENT_DETAILS": paymentDetails, + "PAYMENT_METHOD_NAME": paymentMethodName, + "PREPARE_EMPLOYEE_NAME": prepareEmployeeName, + "PREPARE_EMPLOYEE_NUMBER": prepareEmployeeNumber, + "PREPARE_POSITION_NAME": preparePositionName, + "REQUESTER_EMPLOYEE_NAME": requesterEmployeeName, + "REQUESTER_EMPLOYEE_NUMBER": requesterEmployeeNumber, + "REQUESTER_OPERATING_UNITS": requesterOperatingUnits, + "REQUESTER_PAYROLL_NAME": requesterPayrollName, + "REQUESTER_POSITION_NAME": requesterPositionName, + "REQUEST_AMOUNT": requestAmount, + "REQUEST_DATE": requestDate, + "REQUEST_NUMBER": requestNumber, + "TYPE_OF_PAYMENT": typeOfPayment, + }; +} + +class PurchaseOrdersList { + dynamic poAmount; + dynamic poApprovalDate; + String? poNumber; + String? prNumber; + String? supplierName; + String? supplierNumber; + String? versionStatus; + + PurchaseOrdersList({ + this.poAmount, + this.poApprovalDate, + this.poNumber, + this.prNumber, + this.supplierName, + this.supplierNumber, + this.versionStatus, + }); + + factory PurchaseOrdersList.fromRawJson(String str) => PurchaseOrdersList.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory PurchaseOrdersList.fromJson(Map json) => PurchaseOrdersList( + poAmount: json["PO_AMOUNT"], + poApprovalDate: json["PO_APPROVAL_DATE"], + poNumber: json["PO_NUMBER"], + prNumber: json["PR_NUMBER"], + supplierName: json["SUPPLIER_NAME"], + supplierNumber: json["SUPPLIER_NUMBER"], + versionStatus: json["VERSION_STATUS"], + ); + + Map toJson() => { + "PO_AMOUNT": poAmount, + "PO_APPROVAL_DATE": poApprovalDate, + "PO_NUMBER": poNumber, + "PR_NUMBER": prNumber, + "SUPPLIER_NAME": supplierName, + "SUPPLIER_NUMBER": supplierNumber, + "VERSION_STATUS": versionStatus, + }; +} + +class RefundInvoiceList { + dynamic amount; + String? hospitalClinic; + dynamic invoicedDate; + String? invoiceNumber; + String? patientName; + String? patientNumber; + + RefundInvoiceList({ + this.amount, + this.hospitalClinic, + this.invoicedDate, + this.invoiceNumber, + this.patientName, + this.patientNumber, + }); + + factory RefundInvoiceList.fromRawJson(String str) => RefundInvoiceList.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory RefundInvoiceList.fromJson(Map json) => RefundInvoiceList( + amount: json["AMOUNT"], + hospitalClinic: json["HOSPITAL_CLINIC"], + invoicedDate: json["INVOICED_DATE"], + invoiceNumber: json["INVOICE_NUMBER"], + patientName: json["PATIENT_NAME"], + patientNumber: json["PATIENT_NUMBER"], + ); + + Map toJson() => { + "AMOUNT": amount, + "HOSPITAL_CLINIC": hospitalClinic, + "INVOICED_DATE": invoicedDate, + "INVOICE_NUMBER": invoiceNumber, + "PATIENT_NAME": patientName, + "PATIENT_NUMBER": patientNumber, + }; +} + +class SupplierInformationList { + String? crNumber; + String? supplierBankAccountName; + String? supplierBankAccountNumber; + String? supplierBankIban; + String? supplierName; + String? supplierNumber; + + SupplierInformationList({ + this.crNumber, + this.supplierBankAccountName, + this.supplierBankAccountNumber, + this.supplierBankIban, + this.supplierName, + this.supplierNumber, + }); + + factory SupplierInformationList.fromRawJson(String str) => SupplierInformationList.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory SupplierInformationList.fromJson(Map json) => SupplierInformationList( + crNumber: json["CR_NUMBER"], + supplierBankAccountName: json["SUPPLIER_BANK_ACCOUNT_NAME"], + supplierBankAccountNumber: json["SUPPLIER_BANK_ACCOUNT_NUMBER"], + supplierBankIban: json["SUPPLIER_BANK_IBAN"], + supplierName: json["SUPPLIER_NAME"], + supplierNumber: json["SUPPLIER_NUMBER"], + ); + + Map toJson() => { + "CR_NUMBER": crNumber, + "SUPPLIER_BANK_ACCOUNT_NAME": supplierBankAccountName, + "SUPPLIER_BANK_ACCOUNT_NUMBER": supplierBankAccountNumber, + "SUPPLIER_BANK_IBAN": supplierBankIban, + "SUPPLIER_NAME": supplierName, + "SUPPLIER_NUMBER": supplierNumber, + }; +} diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 00545b2..4c19817 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -19,25 +19,20 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart'; -import 'package:mohem_flutter_app/models/chat/create_group_request.dart' - as createGroup; -import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart' - as groupchathistory; +import 'package:mohem_flutter_app/models/chat/create_group_request.dart' as createGroup; +import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart' as groupchathistory; import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; -import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart' - as groups; +import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart' as groups; import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart'; -import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' - as userLoginToken; -import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' - as fav; +import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as userLoginToken; +import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; import 'package:mohem_flutter_app/models/chat/target_users.dart'; import 'package:mohem_flutter_app/models/my_team/get_employee_subordinates_list.dart'; import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/widgets/image_picker.dart'; -import 'package:open_file/open_file.dart'; +import 'package:open_filex/open_filex.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:signalr_netcore/hub_connection.dart'; @@ -64,10 +59,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List favUsersList = []; int paginationVal = 0; int? cTypingUserId = 0; - bool isTextMsg = false, - isReplyMsg = false, - isAttachmentMsg = false, - isVoiceMsg = false; + bool isTextMsg = false, isReplyMsg = false, isAttachmentMsg = false, isVoiceMsg = false; // Audio Recoding Work Timer? _timer; @@ -100,8 +92,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? uGroups = [], searchGroups = []; Future getUserAutoLoginToken() async { - userLoginToken.UserAutoLoginModel userLoginResponse = - await ChatApiClient().getUserLoginToken(); + userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); + + if (userLoginResponse.StatusCode == 500) { + disbaleChatForThisUser = true; + notifyListeners(); + } + if (userLoginResponse.response != null) { AppState().setchatUserDetails = userLoginResponse; } else { @@ -130,15 +127,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future getHubConnection() async { HubConnection hub; - HttpConnectionOptions httpOp = - HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); + HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); hub = HubConnectionBuilder() - .withUrl( - ApiConsts.chatHubConnectionUrl + - "?UserId=${AppState().chatDetails!.response!.id}&source=Desktop&access_token=${AppState().chatDetails!.response!.token}", - options: httpOp) - .withAutomaticReconnect( - retryDelays: [2000, 5000, 10000, 20000]).build(); + .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Desktop&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) + .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).build(); return hub; } @@ -150,12 +142,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatHubConnection.on("OnUserTypingAsync", onUserTyping); chatHubConnection.on("OnUserCountAsync", userCountAsync); // chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); - chatHubConnection.on( - "OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); - chatHubConnection.on( - "OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); - chatHubConnection.on( - "OnGetGroupUserStatusAsync", getGroupUserStatus); + chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); + chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); + chatHubConnection.on("OnGetGroupUserStatusAsync", getGroupUserStatus); // // {"type":1,"target":"","arguments":[[{"id":217869,"userName":"Sultan.Khan","email":"Sultan.Khan@cloudsolutions.com.sa","phone":null,"title":"Sultan.Khan","userStatus":1,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":false,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null},{"id":15153,"userName":"Tamer.Fanasheh","email":"Tamer.F@cloudsolutions.com.sa","phone":null,"title":"Tamer Fanasheh","userStatus":2,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":true,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null}]]} @@ -171,8 +160,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // userGroups = await ChatApiClient().getGroupsByUserId(); if (favUList.response != null && recentChat.response != null) { favUsersList = favUList.response!; - favUsersList.sort((ChatUser a, ChatUser b) => - a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); + favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); for (dynamic user in recentChat.response!) { for (dynamic favUser in favUList.response!) { if (user.id == favUser.id) { @@ -183,12 +171,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } pChatHistory = recentChat.response ?? []; uGroups = userGroups.groupresponse ?? []; - pChatHistory!.sort((ChatUser a, ChatUser b) => - a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); + pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); searchedChats = pChatHistory; isLoading = false; - await invokeUserChatHistoryNotDeliveredAsync( - userId: int.parse(AppState().chatDetails!.response!.id.toString())); + await invokeUserChatHistoryNotDeliveredAsync(userId: int.parse(AppState().chatDetails!.response!.id.toString())); sort(); notifyListeners(); if (searchedChats!.isNotEmpty || favUsersList.isNotEmpty) { @@ -197,38 +183,27 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future invokeUserChatHistoryNotDeliveredAsync({required int userId}) async { - await chatHubConnection - .invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); + await chatHubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); return ""; } - void getSingleUserChatHistory( - {required int senderUID, - required int receiverUID, - required bool loadMore, - bool isNewChat = false}) async { + void getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async { isLoading = true; if (isNewChat) userChatHistory = []; if (!loadMore) paginationVal = 0; isChatScreenActive = true; receiverID = receiverUID; - Response response = await ChatApiClient().getSingleUserChatHistory( - senderUID: senderUID, - receiverUID: receiverUID, - loadMore: loadMore, - paginationVal: paginationVal); + Response response = await ChatApiClient().getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal); if (response.statusCode == 204) { if (isNewChat) { userChatHistory = []; } else if (loadMore) {} } else { if (loadMore) { - List temp = - getSingleUserChatModel(response.body).reversed.toList(); + List temp = getSingleUserChatModel(response.body).reversed.toList(); userChatHistory.addAll(temp); } else { - userChatHistory = - getSingleUserChatModel(response.body).reversed.toList(); + userChatHistory = getSingleUserChatModel(response.body).reversed.toList(); } } isLoading = false; @@ -255,9 +230,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { dynamic data = [ { "userChatHistoryId": element.userChatHistoryId, - "TargetUserId": element.currentUserId == receiverID - ? element.currentUserId - : element.targetUserId, + "TargetUserId": element.currentUserId == receiverID ? element.currentUserId : element.targetUserId, "isDelivered": true, "isSeen": true, } @@ -279,8 +252,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateUserChatHistoryStatusAsync(List data) { try { - chatHubConnection - .invoke("UpdateUserChatHistoryStatusAsync", args: [data]); + chatHubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); } catch (e) { throw e; } @@ -288,26 +260,21 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateUserChatHistoryOnMsg(List data) { try { - chatHubConnection - .invoke("UpdateUserChatHistoryStatusAsync", args: [data]); + chatHubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); } catch (e) { throw e; } } - List getSingleUserChatModel(String str) => - List.from( - json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); + List getSingleUserChatModel(String str) => List.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); List getGroupChatHistoryAsync(String str) => - List.from( - json.decode(str).map((x) => groupchathistory.GetGroupChatHistoryAsync.fromJson(x))); - + List.from(json.decode(str).map((x) => groupchathistory.GetGroupChatHistoryAsync.fromJson(x))); - Future uploadAttachments(String userId, File file) async { + Future uploadAttachments(String userId, File file, String fileSource) async { dynamic result; try { - Object? response = await ChatApiClient().uploadMedia(userId, file); + Object? response = await ChatApiClient().uploadMedia(userId, file, fileSource); if (response != null) { result = response; } else { @@ -332,9 +299,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - void getGroupUserStatus(List? args){ - //note: need to implement this function... - print(args); + void getGroupUserStatus(List? args) { + //note: need to implement this function... + print(args); } void onChatSeen(List? args) { @@ -363,8 +330,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateChatHistoryWindow(List? args) { dynamic items = args!.toList(); if (kDebugMode) { - logger.i( - "---------------------------------Update Chat History Windows Async -------------------------------------"); + logger.i("---------------------------------Update Chat History Windows Async -------------------------------------"); } logger.d(items); // for (var user in searchedChats!) { @@ -433,26 +399,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserName = temp.first.targetUserName; data.first.currentUserEmail = temp.first.targetUserEmail; - if (data.first.fileTypeId == 12 || - data.first.fileTypeId == 4 || - data.first.fileTypeId == 3) { - data.first.image = await ChatApiClient().downloadURL( - fileName: data.first.contant!, - fileTypeDescription: - data.first.fileTypeResponse!.fileTypeDescription ?? - "image/jpg"); + if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) { + data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg", fileSource: 1); } if (data.first.userChatReplyResponse != null) { if (data.first.fileTypeResponse != null) { - if (data.first.userChatReplyResponse!.fileTypeId == 12 || - data.first.userChatReplyResponse!.fileTypeId == 4 || - data.first.userChatReplyResponse!.fileTypeId == 3) { + if (data.first.userChatReplyResponse!.fileTypeId == 12 || data.first.userChatReplyResponse!.fileTypeId == 4 || data.first.userChatReplyResponse!.fileTypeId == 3) { data.first.userChatReplyResponse!.image = await ChatApiClient() - .downloadURL( - fileName: data.first.userChatReplyResponse!.contant!, - fileTypeDescription: - data.first.fileTypeResponse!.fileTypeDescription ?? - "image/jpg"); + .downloadURL(fileName: data.first.userChatReplyResponse!.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg", fileSource: 1); data.first.userChatReplyResponse!.isImageLoaded = true; } } @@ -460,14 +414,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } if (searchedChats != null) { - dynamic contain = searchedChats! - .where((ChatUser element) => element.id == data.first.currentUserId); + dynamic contain = searchedChats!.where((ChatUser element) => element.id == data.first.currentUserId); if (contain.isEmpty) { List emails = []; - emails.add(await EmailImageEncryption() - .encrypt(val: data.first.currentUserEmail!)); - List chatImages = - await ChatApiClient().getUsersImages(encryptedEmails: emails); + emails.add(await EmailImageEncryption().encrypt(val: data.first.currentUserEmail!)); + List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); searchedChats!.add( ChatUser( id: data.first.currentUserId, @@ -479,9 +430,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isImageLoaded: true, userStatus: 1, isTyping: false, - userLocalDownlaodedImage: await downloadImageLocal( - chatImages.first.profilePicture, - data.first.currentUserId.toString()), + userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, data.first.currentUserId.toString()), ), ); } @@ -506,9 +455,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "userChatHistoryId": data.first.userChatHistoryId, "TargetUserId": temp.first.targetUserId, "isDelivered": true, - "isSeen": isChatScreenActive && data.first.currentUserId == receiverID - ? true - : false + "isSeen": isChatScreenActive && data.first.currentUserId == receiverID ? true : false } ]; updateUserChatHistoryOnMsg(list); @@ -519,38 +466,24 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future onGroupMsgReceived(List? parameters) async { List data = [], temp = []; - for (dynamic msg in parameters!) { - // groupChatHistory.add(groupchathistory.GetGroupChatHistoryAsync.fromJson(msg)); + // groupChatHistory.add(groupchathistory.GetGroupChatHistoryAsync.fromJson(msg)); data.add(groupchathistory.GetGroupChatHistoryAsync.fromJson(msg)); - temp =data; + temp = data; // data.first.currentUserId = temp.first.currentUserId; // data.first.currentUserName = temp.first.currentUserName; // // data.first.currentUserId = temp.first.currentUserId; // data.first.currentUserName = temp.first.currentUserName; - - if (data.first.fileTypeId == 12 || - data.first.fileTypeId == 4 || - data.first.fileTypeId == 3) { - data.first.image = await ChatApiClient().downloadURL( - fileName: data.first.contant!, - fileTypeDescription: - data.first.fileTypeResponse!.fileTypeDescription ?? - "image/jpg"); + if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) { + data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg", fileSource: 2); } if (data.first.groupChatReplyResponse != null) { if (data.first.fileTypeResponse != null) { - if (data.first.groupChatReplyResponse!.fileTypeId == 12 || - data.first.groupChatReplyResponse!.fileTypeId == 4 || - data.first.groupChatReplyResponse!.fileTypeId == 3) { + if (data.first.groupChatReplyResponse!.fileTypeId == 12 || data.first.groupChatReplyResponse!.fileTypeId == 4 || data.first.groupChatReplyResponse!.fileTypeId == 3) { data.first.groupChatReplyResponse!.image = await ChatApiClient() - .downloadURL( - fileName: data.first.groupChatReplyResponse!.contant!, - fileTypeDescription: - data.first.fileTypeResponse!.fileTypeDescription ?? - "image/jpg"); + .downloadURL(fileName: data.first.groupChatReplyResponse!.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg", fileSource: 2); data.first.groupChatReplyResponse!.isImageLoaded = true; } } @@ -583,10 +516,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // ), // ); // } - // } + // } groupChatHistory.insert(0, data.first); setMsgTune(); - // if (isChatScreenActive && data.first.currentUserId == receiverID) { + // if (isChatScreenActive && data.first.currentUserId == receiverID) { // } else { // if (searchedChats != null) { @@ -596,8 +529,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // user.unreadMessageCount = tempCount + 1; // } // } - sort(); - //} + sort(); + //} //} // // List list = [ @@ -610,13 +543,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // : false // } // ]; - // updateUserChatHistoryOnMsg(list); - // invokeChatCounter(userId: AppState().chatDetails!.response!.id!); + // updateUserChatHistoryOnMsg(list); + // invokeChatCounter(userId: AppState().chatDetails!.response!.id!); notifyListeners(); } - - void OnSubmitChatAsync(List? parameters) { print(isChatScreenActive); print(receiverID); @@ -634,8 +565,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserEmail = temp.first.targetUserEmail; } if (isChatScreenActive && data.first.currentUserId == receiverID) { - int index = userChatHistory.indexWhere( - (SingleUserChatModel element) => element.userChatHistoryId == 0); + int index = userChatHistory.indexWhere((SingleUserChatModel element) => element.userChatHistoryId == 0); logger.d(index); userChatHistory[index] = data.first; } @@ -645,8 +575,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void sort() { searchedChats!.sort( - (ChatUser a, ChatUser b) => - b.unreadMessageCount!.compareTo(a.unreadMessageCount!), + (ChatUser a, ChatUser b) => b.unreadMessageCount!.compareTo(a.unreadMessageCount!), ); } @@ -698,6 +627,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return 13; case ".mp3": return 14; + case ".mp4": + return 16; + case ".mov": + return 16; + case ".avi": + return 16; + case ".flv": + return 16; + default: return 0; } @@ -735,6 +673,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return "audio/aac"; case ".mp3": return "audio/mp3"; + case ".mp4": + return "video/mp4"; + case ".avi": + return "video/avi"; + case ".flv": + return "video/flv"; + case ".mov": + return "video/mov"; + default: return ""; } @@ -777,22 +724,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { targetUserName: targetUserName, isReplied: false, fileTypeId: fileTypeId, - userChatReplyResponse: isReply - ? UserChatReplyResponse.fromJson(repliedMsg.first.toJson()) - : null, + userChatReplyResponse: isReply ? UserChatReplyResponse.fromJson(repliedMsg.first.toJson()) : null, fileTypeResponse: isAttachment ? FileTypeResponse( fileTypeId: fileTypeId, - fileTypeName: isVoiceMsg - ? getFileExtension(voiceFile!.path).toString() - : getFileExtension(selectedFile.path).toString(), + fileTypeName: isVoiceMsg ? getFileExtension(voiceFile!.path).toString() : getFileExtension(selectedFile.path).toString(), fileKind: "file", fileName: isVoiceMsg ? msg : selectedFile.path.split("/").last, - fileTypeDescription: isVoiceMsg - ? getFileTypeDescription( - getFileExtension(voiceFile!.path).toString()) - : getFileTypeDescription( - getFileExtension(selectedFile.path).toString()), + fileTypeDescription: isVoiceMsg ? getFileTypeDescription(getFileExtension(voiceFile!.path).toString()) : getFileTypeDescription(getFileExtension(selectedFile.path).toString()), ) : null, image: image, @@ -814,8 +753,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { String chatData = '{"contant":"$msg","contantNo":"$contentNo","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"$chatCID"}'; - await chatHubConnection - .invoke("AddChatUserAsync", args: [json.decode(chatData)]); + await chatHubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); } //groupChatMessage @@ -834,8 +772,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { int? userStatus, File? voiceFile, required bool isVoiceAttached, - required List userList - }) async { + required List userList}) async { Uuid uuid = const Uuid(); String contentNo = uuid.v4(); String msg; @@ -845,36 +782,36 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { msg = message.text; logger.w(msg); } - groupchathistory.GetGroupChatHistoryAsync data = - groupchathistory.GetGroupChatHistoryAsync( - //userChatHistoryId: 0, - chatEventId: chatEventId, - chatSource: 1, - contant: msg, - contantNo: contentNo, - conversationId: chatCID, - createdDate: DateTime.now().toString(), - currentUserId: AppState().chatDetails!.response!.id, - currentUserName: AppState().chatDetails!.response!.userName, - groupId: targetGroupId, - groupName: targetUserName, - isReplied: false, - fileTypeId: fileTypeId, - fileTypeResponse: isAttachment - ? groupchathistory.FileTypeResponse( - fileTypeId: fileTypeId, - fileTypeName: isVoiceMsg ? getFileExtension(voiceFile!.path).toString() : getFileExtension(selectedFile.path).toString(), - fileKind: "file", - fileName: isVoiceMsg ? msg : selectedFile.path.split("/").last, - fileTypeDescription: isVoiceMsg ? getFileTypeDescription(getFileExtension(voiceFile!.path).toString()) : getFileTypeDescription(getFileExtension(selectedFile.path).toString())) : null, - image: image, - isImageLoaded: isImageLoaded, - voice: isVoiceMsg ? voiceFile! : null, - voiceController: isVoiceMsg ? AudioPlayer() : null); + groupchathistory.GetGroupChatHistoryAsync data = groupchathistory.GetGroupChatHistoryAsync( + //userChatHistoryId: 0, + chatEventId: chatEventId, + chatSource: 1, + contant: msg, + contantNo: contentNo, + conversationId: chatCID, + createdDate: DateTime.now().toString(), + currentUserId: AppState().chatDetails!.response!.id, + currentUserName: AppState().chatDetails!.response!.userName, + groupId: targetGroupId, + groupName: targetUserName, + isReplied: false, + fileTypeId: fileTypeId, + fileTypeResponse: isAttachment + ? groupchathistory.FileTypeResponse( + fileTypeId: fileTypeId, + fileTypeName: isVoiceMsg ? getFileExtension(voiceFile!.path).toString() : getFileExtension(selectedFile.path).toString(), + fileKind: "file", + fileName: isVoiceMsg ? msg : selectedFile.path.split("/").last, + fileTypeDescription: isVoiceMsg ? getFileTypeDescription(getFileExtension(voiceFile!.path).toString()) : getFileTypeDescription(getFileExtension(selectedFile.path).toString())) + : null, + image: image, + isImageLoaded: isImageLoaded, + voice: isVoiceMsg ? voiceFile! : null, + voiceController: isVoiceMsg ? AudioPlayer() : null); if (kDebugMode) { logger.i("model data: " + jsonEncode(data)); } - groupChatHistory.insert(0, data); + groupChatHistory.insert(0, data); isTextMsg = false; isReplyMsg = false; isAttachmentMsg = false; @@ -883,27 +820,26 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { message.clear(); notifyListeners(); - List targetUsers =[]; + List targetUsers = []; for (GroupUserList element in userList) { - targetUsers.add(TargetUsers(isDelivered: false,isSeen: false, targetUserId: element.id, userAction: element.userAction, userStatus: element.userStatus)); - + targetUsers.add(TargetUsers(isDelivered: false, isSeen: false, targetUserId: element.id, userAction: element.userAction, userStatus: element.userStatus)); } String chatData = '{"contant":"$msg","contantNo":"$contentNo","chatEventId":$chatEventId,"fileTypeId":$fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"groupId":$targetGroupId,"groupChatHistoryLineRequestList":${json.encode(targetUsers)},"chatReplyId": $chatReplyId,"conversationId":"${uuid.v4()}"}'; - await chatHubConnection.invoke("AddGroupChatHistoryAsync", - args: [json.decode(chatData)]); + await chatHubConnection.invoke("AddGroupChatHistoryAsync", args: [json.decode(chatData)]); } - void sendGroupChatMessage(BuildContext context, - {required int targetUserId, - required int userStatus, - required String userEmail, - required String targetUserName, - required List userList, - }) async { + void sendGroupChatMessage( + BuildContext context, { + required int targetUserId, + required int userStatus, + required String userEmail, + required String targetUserName, + required List userList, + }) async { if (isTextMsg && !isAttachmentMsg && !isVoiceMsg && !isReplyMsg) { logger.d("// Normal Text Message"); if (message.text.isEmpty) { @@ -922,8 +858,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isVoiceAttached: false, userEmail: userEmail, userStatus: userStatus, - userList:userList - ); + userList: userList); } else if (isTextMsg && !isAttachmentMsg && !isVoiceMsg && isReplyMsg) { logger.d("// Text Message as Reply"); if (message.text.isEmpty) { @@ -943,15 +878,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { voiceFile: null, userEmail: userEmail, userStatus: userStatus, - userList:userList - ); + userList: userList); } // Attachment else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) { logger.d("// Normal Image Message"); Utils.showLoading(context); - dynamic value = await uploadAttachments( - AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile, "2"); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendGroupChatToServer( @@ -967,19 +900,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isVoiceAttached: false, userEmail: userEmail, userStatus: userStatus, - userList:userList - ); + userList: userList); } else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) { logger.d("// Image as Reply Msg"); Utils.showLoading(context); - dynamic value = await uploadAttachments( - AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile, "2"); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendGroupChatToServer( chatEventId: 2, fileTypeId: getFileType(ext.toString()), - targetGroupId: targetUserId, targetUserName: targetUserName, isAttachment: true, @@ -990,8 +920,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isVoiceAttached: false, userEmail: userEmail, userStatus: userStatus, - userList:userList - ); + userList: userList); } //Voice @@ -1011,9 +940,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isPlaying = false; isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments( - AppState().chatDetails!.response!.id.toString(), voiceFile); - String? ext = getFileExtension(voiceFile.path); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile, "2"); + String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendGroupChatToServer( chatEventId: 2, @@ -1029,8 +957,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isVoiceAttached: true, userEmail: userEmail, userStatus: userStatus, - userList:userList - ); + userList: userList); notifyListeners(); } else if (!isTextMsg && !isAttachmentMsg && isVoiceMsg && isReplyMsg) { logger.d("// Voice as Reply Msg"); @@ -1049,9 +976,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments( - AppState().chatDetails!.response!.id.toString(), voiceFile); - String? ext = getFileExtension(voiceFile.path); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile, "2"); + String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendGroupChatToServer( chatEventId: 2, @@ -1066,18 +992,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isVoiceAttached: true, userEmail: userEmail, userStatus: userStatus, - userList:userList - ); + userList: userList); notifyListeners(); } if (searchedChats != null) { - dynamic contain = searchedChats! - .where((ChatUser element) => element.id == targetUserId); + dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); if (contain.isEmpty) { List emails = []; emails.add(await EmailImageEncryption().encrypt(val: userEmail)); - List chatImages = - await ChatApiClient().getUsersImages(encryptedEmails: emails); + List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); searchedChats!.add( ChatUser( id: targetUserId, @@ -1098,13 +1021,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - void sendChatMessage(BuildContext context, - {required int targetUserId, - required int userStatus, - required String userEmail, - required String targetUserName, - - }) async { + void sendChatMessage( + BuildContext context, { + required int targetUserId, + required int userStatus, + required String userEmail, + required String targetUserName, + }) async { if (kDebugMode) { print("====================== Values ============================"); print("Is Text " + isTextMsg.toString()); @@ -1155,8 +1078,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) { logger.d("// Normal Image Message"); Utils.showLoading(context); - dynamic value = await uploadAttachments( - AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile, "1"); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendChatToServer( @@ -1175,8 +1097,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) { logger.d("// Image as Reply Msg"); Utils.showLoading(context); - dynamic value = await uploadAttachments( - AppState().chatDetails!.response!.id.toString(), selectedFile); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile, "1"); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendChatToServer( @@ -1211,8 +1132,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isPlaying = false; isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments( - AppState().chatDetails!.response!.id.toString(), voiceFile); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile, "1"); String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendChatToServer( @@ -1246,8 +1166,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isRecoding = false; Utils.showLoading(context); - dynamic value = await uploadAttachments( - AppState().chatDetails!.response!.id.toString(), voiceFile); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile, "1"); String? ext = getFileExtension(voiceFile.path); Utils.hideLoading(context); sendChatToServer( @@ -1266,13 +1185,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } if (searchedChats != null) { - dynamic contain = searchedChats! - .where((ChatUser element) => element.id == targetUserId); + dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); if (contain.isEmpty) { List emails = []; emails.add(await EmailImageEncryption().encrypt(val: userEmail)); - List chatImages = - await ChatApiClient().getUsersImages(encryptedEmails: emails); + List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); searchedChats!.add( ChatUser( id: targetUserId, @@ -1285,8 +1202,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isTyping: false, isFav: false, userStatus: userStatus, - userLocalDownlaodedImage: await downloadImageLocal( - chatImages.first.profilePicture, targetUserId.toString()), + userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()), ), ); notifyListeners(); @@ -1316,8 +1232,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void selectImageToUpload(BuildContext context) { - ImageOptions.showImageOptionsNew(context, true, - (String image, File file) async { + ImageOptions.showImageOptionsNew(context, true, (String image, File file) async { if (checkFileSize(file.path)) { selectedFile = file; isAttachmentMsg = true; @@ -1351,10 +1266,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } bool checkFileSize(String path) { - int fileSizeLimit = 1024; + int fileSizeLimit = 5120; File f = File(path); - double fileSizeInKB = f.lengthSync() / 1024; - double fileSizeInMB = fileSizeInKB / 1024; + double fileSizeInKB = f.lengthSync() / 5000; + double fileSizeInMB = fileSizeInKB / 5000; if (fileSizeInKB > fileSizeLimit) { return false; } else { @@ -1406,6 +1321,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { repliedMsg.add(data); notifyListeners(); } + void groupChatReply(groupchathistory.GetGroupChatHistoryAsync data) { groupChatReplyData = []; data.isReplied = true; @@ -1413,6 +1329,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { groupChatReplyData.add(data); notifyListeners(); } + void closeMe() { repliedMsg = []; isReplyMsg = false; @@ -1425,18 +1342,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return f.format(data); } - Future favoriteUser( - {required int userID, - required int targetUserID, - required bool fromSearch}) async { - fav.FavoriteChatUser favoriteChatUser = await ChatApiClient() - .favUser(userID: userID, targetUserID: targetUserID); + Future favoriteUser({required int userID, required int targetUserID, required bool fromSearch}) async { + fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().favUser(userID: userID, targetUserID: targetUserID); if (favoriteChatUser.response != null) { for (ChatUser user in searchedChats!) { if (user.id == favoriteChatUser.response!.targetUserId!) { user.isFav = favoriteChatUser.response!.isFav; - dynamic contain = favUsersList!.where((ChatUser element) => - element.id == favoriteChatUser.response!.targetUserId!); + dynamic contain = favUsersList!.where((ChatUser element) => element.id == favoriteChatUser.response!.targetUserId!); if (contain.isEmpty) { favUsersList.add(user); } @@ -1446,8 +1358,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUser user in chatUsersList!) { if (user.id == favoriteChatUser.response!.targetUserId!) { user.isFav = favoriteChatUser.response!.isFav; - dynamic contain = favUsersList!.where((ChatUser element) => - element.id == favoriteChatUser.response!.targetUserId!); + dynamic contain = favUsersList!.where((ChatUser element) => element.id == favoriteChatUser.response!.targetUserId!); if (contain.isEmpty) { favUsersList.add(user); } @@ -1466,10 +1377,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - Future unFavoriteUser( - {required int userID, required int targetUserID}) async { - fav.FavoriteChatUser favoriteChatUser = await ChatApiClient() - .unFavUser(userID: userID, targetUserID: targetUserID); + Future unFavoriteUser({required int userID, required int targetUserID}) async { + fav.FavoriteChatUser favoriteChatUser = await ChatApiClient().unFavUser(userID: userID, targetUserID: targetUserID); if (favoriteChatUser.response != null) { for (ChatUser user in searchedChats!) { @@ -1574,14 +1483,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { emails.add(await EmailImageEncryption().encrypt(val: element.email!)); } - List chatImages = - await ChatApiClient().getUsersImages(encryptedEmails: emails); + List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); for (ChatUser user in searchedChats!) { for (ChatUserImageModel uImage in chatImages) { if (user.email == uImage.email) { user.image = uImage.profilePicture ?? ""; - user.userLocalDownlaodedImage = await downloadImageLocal( - uImage.profilePicture, user.id.toString()); + user.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, user.id.toString()); user.isImageLoading = false; user.isImageLoaded = true; } @@ -1591,8 +1498,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUserImageModel uImage in chatImages) { if (favUser.email == uImage.email) { favUser.image = uImage.profilePicture ?? ""; - favUser.userLocalDownlaodedImage = await downloadImageLocal( - uImage.profilePicture, favUser.id.toString()); + favUser.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, favUser.id.toString()); favUser.isImageLoading = false; favUser.isImageLoaded = true; } @@ -1609,8 +1515,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } else { await deleteFile(userID); Uint8List decodedBytes = base64Decode(encodedBytes); - Directory appDocumentsDirectory = - await getApplicationDocumentsDirectory(); + Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); String dirPath = '${appDocumentsDirectory.path}/chat_images'; if (!await Directory(dirPath).exists()) { await Directory(dirPath).create(); @@ -1633,8 +1538,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future downChatMedia(Uint8List bytes, String ext) async { String dir = (await getApplicationDocumentsDirectory()).path; - File file = File( - "$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); + File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); await file.writeAsBytes(bytes); return file.path; } @@ -1657,24 +1561,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - Future getChatMedia(BuildContext context, - {required String fileName, - required String fileTypeName, - required int fileTypeID}) async { + Future getChatMedia(BuildContext context, {required String fileName, required String fileTypeName, required int fileTypeID, required int fileSource}) async { Utils.showLoading(context); - if (fileTypeID == 1 || - fileTypeID == 5 || - fileTypeID == 7 || - fileTypeID == 6 || - fileTypeID == 8 || - fileTypeID == 2) { - Uint8List encodedString = await ChatApiClient().downloadURL( - fileName: fileName, - fileTypeDescription: getFileTypeDescription(fileTypeName)); + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2 || fileTypeID == 16) { + Uint8List encodedString = await ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: getFileTypeDescription(fileTypeName), fileSource: fileSource); try { String path = await downChatMedia(encodedString, fileTypeName ?? ""); Utils.hideLoading(context); - OpenFile.open(path); + OpenFilex.open(path); } catch (e) { Utils.showToast("Cannot open file."); } @@ -1692,19 +1586,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return ""; } - void userTypingInvoke( - {required int currentUser, required int reciptUser}) async { - await chatHubConnection - .invoke("UserTypingAsync", args: [reciptUser, currentUser]); + void userTypingInvoke({required int currentUser, required int reciptUser}) async { + await chatHubConnection.invoke("UserTypingAsync", args: [reciptUser, currentUser]); } - void groupTypingInvoke( - {required GroupResponse groupDetails, required int groupId}) async { + + void groupTypingInvoke({required GroupResponse groupDetails, required int groupId}) async { var data = json.decode(json.encode(groupDetails.groupUserList)); - await chatHubConnection - .invoke("GroupTypingAsync", args: ["${groupDetails.adminUser!.userName}",data, groupId ]); + await chatHubConnection.invoke("GroupTypingAsync", args: ["${groupDetails.adminUser!.userName}", data, groupId]); } - //////// Audio Recoding Work //////////////////// Future initAudio({required int receiverId}) async { @@ -1718,8 +1608,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await Directory(dirPath).create(); await File('$dirPath/.nomedia').create(); } - path = - "$dirPath/${AppState().chatDetails!.response!.id}-$receiverID-${DateTime.now().microsecondsSinceEpoch}.aac"; + path = "$dirPath/${AppState().chatDetails!.response!.id}-$receiverID-${DateTime.now().microsecondsSinceEpoch}.aac"; recorderController = RecorderController() ..androidEncoder = AndroidEncoder.aac ..androidOutputFormat = AndroidOutputFormat.mpeg4 @@ -1770,7 +1659,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void sRecoding() async { isVoiceMsg = true; recorderController.reset(); - await recorderController.record(path); + await recorderController.record(path: path); _recodeDuration = 0; _startTimer(); isRecoding = !isRecoding; @@ -1802,7 +1691,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { File file = File(path!); file.readAsBytesSync(); path = file.path; - await playerController.preparePlayer(file.path, 1.0); + await playerController.preparePlayer(path:file.path, volume: 1.0); _timer?.cancel(); notifyListeners(); } @@ -1849,19 +1738,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return numberStr; } - Future downChatVoice( - Uint8List bytes, String ext, SingleUserChatModel data) async { + Future downChatVoice(Uint8List bytes, String ext, SingleUserChatModel data) async { File file; try { - String dirPath = - '${(await getApplicationDocumentsDirectory()).path}/chat_audios'; + String dirPath = '${(await getApplicationDocumentsDirectory()).path}/chat_audios'; if (!await Directory(dirPath).exists()) { await Directory(dirPath).create(); await File('$dirPath/.nomedia').create(); } - file = File( - "$dirPath/${data.currentUserId}-${data.targetUserId}-${DateTime.now().microsecondsSinceEpoch}" + - ext); + file = File("$dirPath/${data.currentUserId}-${data.targetUserId}-${DateTime.now().microsecondsSinceEpoch}" + ext); await file.writeAsBytes(bytes); } catch (e) { if (kDebugMode) { @@ -1873,14 +1758,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void scrollToMsg(SingleUserChatModel data) { - if (data.userChatReplyResponse != null && - data.userChatReplyResponse!.userChatHistoryId != null) { - int index = userChatHistory.indexWhere((SingleUserChatModel element) => - element.userChatHistoryId == - data.userChatReplyResponse!.userChatHistoryId); + if (data.userChatReplyResponse != null && data.userChatReplyResponse!.userChatHistoryId != null) { + int index = userChatHistory.indexWhere((SingleUserChatModel element) => element.userChatHistoryId == data.userChatReplyResponse!.userChatHistoryId); if (index >= 1) { - double contentSize = scrollController.position.viewportDimension + - scrollController.position.maxScrollExtent; + double contentSize = scrollController.position.viewportDimension + scrollController.position.maxScrollExtent; double target = contentSize * index / userChatHistory.length; scrollController.position.animateTo( target, @@ -1912,18 +1793,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isImageLoading: false, image: element.eMPLOYEEIMAGE ?? "", isImageLoaded: element.eMPLOYEEIMAGE == null ? false : true, - userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null - ? null - : await downloadImageLocal( - element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!), + userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null ? null : await downloadImageLocal(element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!), ), ); } } } } else { - getEmployeeSubordinatesList = - await MyTeamApiClient().getEmployeeSubordinates("", "", ""); + getEmployeeSubordinatesList = await MyTeamApiClient().getEmployeeSubordinates("", "", ""); AppState().setemployeeSubordinatesList = getEmployeeSubordinatesList; for (GetEmployeeSubordinatesList element in getEmployeeSubordinatesList) { if (element.eMPLOYEEEMAILADDRESS != null) { @@ -1941,10 +1818,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isImageLoading: false, image: element.eMPLOYEEIMAGE ?? "", isImageLoaded: element.eMPLOYEEIMAGE == null ? false : true, - userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null - ? null - : await downloadImageLocal( - element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!), + userLocalDownlaodedImage: element.eMPLOYEEIMAGE == null ? null : await downloadImageLocal(element.eMPLOYEEIMAGE ?? "", element.eMPLOYEENUMBER!), ), ); } @@ -2013,14 +1887,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { SingleUserChatModel nUser = SingleUserChatModel(); Utils.saveStringFromPrefs("isAppOpendByChat", "false"); if (await Utils.getStringFromPrefs("notificationData") != "null") { - nUser = SingleUserChatModel.fromJson( - jsonDecode(await Utils.getStringFromPrefs("notificationData"))); + nUser = SingleUserChatModel.fromJson(jsonDecode(await Utils.getStringFromPrefs("notificationData"))); Utils.saveStringFromPrefs("notificationData", "null"); Future.delayed(const Duration(seconds: 2)); for (ChatUser user in searchedChats!) { if (user.id == nUser.targetUserId) { - Navigator.pushNamed(context, AppRoutes.chatDetailed, - arguments: ChatDetailedScreenParams(user, false)); + Navigator.pushNamed(context, AppRoutes.chatDetailed, arguments: ChatDetailedScreenParams(user, false)); return; } } @@ -2057,9 +1929,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future getGroupChatHistory(groups.GroupResponse groupDetails) async { isLoading = true; - groupChatHistory = await ChatApiClient().getGroupChatHistory( - groupDetails.groupId, - groupDetails.groupUserList as List); + groupChatHistory = await ChatApiClient().getGroupChatHistory(groupDetails.groupId, groupDetails.groupUserList as List); isLoading = false; @@ -2076,12 +1946,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future addGroupAndUsers(createGroup.CreateGroupRequest request) async { isLoading = true; var groups = await ChatApiClient().addGroupAndUsers(request); - userGroups.groupresponse! - .add(GroupResponse.fromJson(json.decode(groups)['response'])); + userGroups.groupresponse!.add(GroupResponse.fromJson(json.decode(groups)['response'])); isLoading = false; notifyListeners(); } + Future updateGroupAndUsers(createGroup.CreateGroupRequest request) async { isLoading = true; await ChatApiClient().updateGroupAndUsers(request); diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 0e18544..2b7a2bb 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -9,7 +9,9 @@ import 'package:mohem_flutter_app/config/routes.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/drawer_menu_item_model.dart'; +import 'package:mohem_flutter_app/models/dashboard/event_activity.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; +import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_open_notifications_list.dart'; import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart'; @@ -17,10 +19,13 @@ import 'package:mohem_flutter_app/models/dashboard/list_menu.dart'; import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart'; import 'package:mohem_flutter_app/models/dashboard/menus.dart'; import 'package:mohem_flutter_app/models/dashboard/mohemm_itg_pending_task_responseitem.dart'; +import 'package:mohem_flutter_app/models/dashboard/courses_response_model.dart'; +import 'package:mohem_flutter_app/models/eit/get_eit_transaction_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; +import 'package:mohem_flutter_app/models/greetings/greeting_card_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/ui/landing/dashboard_screen.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 @@ -43,20 +48,36 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { //Leave and Ticket Balance bool isLeaveTicketBalanceLoading = true; List? accrualList; + List? accrualTicketBalanceList; GetAccrualBalancesList? leaveBalanceAccrual; double get leaveBalance => leaveBalanceAccrual?.accrualNetEntitlement ?? 0; double ticketBalance = 0; + double walletBalance = 0; //Menu Entries bool isServicesMenusLoading = true; + bool isEventLoadingLoading = true; List? homeMenus; List? getMenuEntriesList; + EventActivityList? eventActivity; + TicketBookingResult? ticketBookingResponse; + List>? ticketHistoryTransactionList = []; + //Offers And Discounts bool isOffersLoading = true; List getOffersList = []; + //Courses + bool isCoursesLoading = true; + CoursesResponseModel? coursesResponse; + List coursesList = []; + + bool isGreetingCardsLoading = true; + bool isDisplayEidGreetings = false; + List? greetingCardsList; + //Attendance Tracking API's & Methods Future fetchAttendanceTracking(context) async { try { @@ -95,20 +116,28 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isLeaveTicketBalanceLoading = true; accrualList = null; + accrualTicketBalanceList = null; leaveBalanceAccrual = null; ticketBalance = 0; isServicesMenusLoading = true; + isEventLoadingLoading = true; homeMenus = null; getMenuEntriesList = null; isOffersLoading = true; getOffersList = []; + isGreetingCardsLoading = true; + isDisplayEidGreetings = false; drawerMenuItemList = [ DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile), DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation), DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi), + // DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.etqanOVR.tr(), AppRoutes.etqanOvr), + DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.keen.tr(), AppRoutes.etqanOvr), + // DrawerMenuItem("assets/images/drawer/car_parking_icon.svg", LocaleKeys.parkingQr.tr(), AppRoutes.parkingQr), DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions), + // DrawerMenuItem("assets/images/drawer/courses.svg", "courses".tr(), AppRoutes.courses), // DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen), DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword), ]; @@ -162,12 +191,13 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Utils.hideLoading(context); showDialog( context: context, - builder: (cxt) => ConfirmDialog( - message: err, - onTap: () { - Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route route) => false); - }, - ), + builder: + (cxt) => ConfirmDialog( + message: err, + onTap: () { + Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route route) => false); + }, + ), ); }); } @@ -195,6 +225,20 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isLeaveTicketBalanceLoading = false; leaveBalanceAccrual = accrualList![0]; ticketBalance = (accrualList![1].accrualNetEntitlement ?? 0.0) + (accrualList![2].accrualNetEntitlement ?? 0.0) + (accrualList![3].accrualNetEntitlement ?? 0.0); + walletBalance = (accrualList![4].accrualNetEntitlement ?? 0.0); + notifyListeners(); + } catch (ex) { + isLeaveTicketBalanceLoading = false; + logger.wtf(ex); + notifyListeners(); + Utils.handleException(ex, context, null); + } + } + + Future fetchTicketAccuralBalance(context, DateTime date) async { + try { + accrualTicketBalanceList = await DashboardApiClient().getTicketAccuralBalance(DateFormat("MM/dd/yyyy", "en_US").format(date)); + isLeaveTicketBalanceLoading = false; notifyListeners(); } catch (ex) { isLeaveTicketBalanceLoading = false; @@ -234,6 +278,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; @@ -253,8 +298,111 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } catch (ex) { // Utils.hideLoading(context); + getOffersList = []; + isOffersLoading = false; notifyListeners(); - Utils.handleException(ex, context, null); + // Utils.handleException(ex, context, null); + } + } + + void fetchEventActivity() async { + try { + GenericResponseModel? genericResponseModel = await DashboardApiClient().getEventActivity(); + List eventList = (genericResponseModel!.getEventActivityList ?? []); + if (eventList.isNotEmpty) { + eventActivity = eventList.first; + } + + isEventLoadingLoading = false; + notifyListeners(); + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + // Utils.handleException(ex, null, null); + } + } + + void fetchGreetingCards() async { + isGreetingCardsLoading = true; + notifyListeners(); + try { + GetGreetingCardsModelResponse? response = await DashboardApiClient().getGreetingCards(); + greetingCardsList = response?.getGreetingCardsModelResponse ?? []; + if (greetingCardsList != null && greetingCardsList!.isNotEmpty) { + isDisplayEidGreetings = greetingCardsList!.any((card) => card.isActive == true); + } else { + isDisplayEidGreetings = false; + } + isGreetingCardsLoading = false; + notifyListeners(); + } catch (ex) { + logger.wtf(ex); + isDisplayEidGreetings = false; + greetingCardsList = []; + isGreetingCardsLoading = false; + notifyListeners(); + } + } + + Future fetchTicketBooking() async { + try { + GenericResponseModel? genericResponseModel = await DashboardApiClient().getTicketBookingRedirection(); + if (genericResponseModel?.portalDirectionData?.pRedirection!.toLowerCase() == "alma") { + ticketBookingResponse = TicketBookingResult(true, genericResponseModel?.portalDirectionData?.clientID); + return; + } + ticketBookingResponse = TicketBookingResult(false, null); + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + Utils.handleException(ex, null, null); + ticketBookingResponse = TicketBookingResult(false, null); // Ensure a return value in case of an exception + } + } + + void fetchTicketBalance() async { + try { + GenericResponseModel? ticketResponse = await DashboardApiClient().getTicketBalance(); + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + Utils.handleException(ex, null, null); + // ticketBookingResponse = 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!); + 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; + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + Utils.handleException(ex, null, null); + return null; } } @@ -291,6 +439,30 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return res; } + //Courses API's & Methods + Future fetchCourses(BuildContext context) async { + try { + isCoursesLoading = true; + notifyListeners(); + + coursesResponse = await DashboardApiClient().fetchAllCoursesStatus(); + + if (coursesResponse != null && coursesResponse!.success == true) { + coursesList = coursesResponse!.coursesStatus ?? []; + } else { + coursesList = []; + } + + isCoursesLoading = false; + notifyListeners(); + } catch (ex) { + isCoursesLoading = false; + coursesList = []; + notifyListeners(); + Utils.handleException(ex, context, null); + } + } + void notify() { notifyListeners(); } diff --git a/lib/provider/eit_provider_model.dart b/lib/provider/eit_provider_model.dart index 1543184..75a210f 100644 --- a/lib/provider/eit_provider_model.dart +++ b/lib/provider/eit_provider_model.dart @@ -18,6 +18,7 @@ import 'package:mohem_flutter_app/widgets/Updater.dart'; class EITProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? eitTransactionList; late bool isEitLoaded = false; + void getEITList(String functionName) async { try { eitTransactionList = await EITApiClient().getEITTransactions(functionName); diff --git a/lib/provider/etqan_ovr_provider.dart b/lib/provider/etqan_ovr_provider.dart new file mode 100644 index 0000000..b4f2eb1 --- /dev/null +++ b/lib/provider/etqan_ovr_provider.dart @@ -0,0 +1,262 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/etqan_ovr_api_client.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_employee_incident_report.dart'; +import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_requests_model.dart'; +import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin { + // Home screen state + List? getEtqanProjectsList; + List? getEtqanEmployeeRequestsList; + List? getEtqanEmployeeIncidnetRequest; + bool isLoading = false; + String? _ticketId; + String? _currentStatus; + String? _currentStatusAr; + bool? _currentIsAnonymous; + + // Speech to text state + final SpeechToText _speechToText = SpeechToText(); + bool _speechEnabled = false; + bool _isListening = false; + String _currentLocaleId = ''; + TextEditingController? _currentController; + String _baseText = ''; // Text that was there when we started listening + String _currentSessionText = ''; // Text captured in current listening session + + // Getters for speech state + bool get speechEnabled => _speechEnabled; + + bool get isListening => _isListening; + + // Getter for ticketId + String get getTicketId => _ticketId ?? ''; + String get getCurrentStatus => _currentStatus ?? ''; + String get getCurrentStatusAr => _currentStatusAr ?? ''; + bool get getCurrentIsAnonymous => _currentIsAnonymous ?? false; + + // Setter for ticketId with status and isAnonymous + void setTicketId(String ticketId, {String? status, String? statusAr, bool? isAnonymous}) { + _ticketId = ticketId; + _currentStatus = status; + _currentStatusAr = statusAr; + _currentIsAnonymous = isAnonymous; + notifyListeners(); + } + + // Create request screen state + EtqanGetProjectsResponse? selectedProject; + String? selectedEmployeeNumber; + File? attachment; + String? attachmentBase64; + String description = ''; + bool isAnonymous = false; + + /// Initialize speech recognition - call this once when screen loads + Future initSpeech() async { + _speechEnabled = await _speechToText.initialize( + onStatus: (String status) { + print('Speech status: $status, isListening: $_isListening'); + // If user wants to keep listening but speech stopped, restart it + if ((status == 'done' || status == 'notListening') && _isListening && _currentController != null) { + // Save the finalized text before restarting + if (_currentSessionText.isNotEmpty) { + _baseText = _currentController!.text.trim(); + _currentSessionText = ''; + } + + // Automatically restart listening after a brief pause + Future.delayed(const Duration(milliseconds: 300), () { + if (_isListening && _currentController != null) { + _startListeningInternal(_currentLocaleId, _currentController!); + } + }); + } + }, + ); + notifyListeners(); + } + + /// Internal method to start listening + Future _startListeningInternal(String localeId, TextEditingController controller) async { + if (!_speechEnabled) return; + + await _speechToText.listen( + onResult: (SpeechRecognitionResult result) { + _currentSessionText = result.recognizedWords; + + // Combine base text with current session text + String combinedText = _baseText.isEmpty + ? _currentSessionText + : _baseText + (_baseText.endsWith(' ') ? '' : ' ') + _currentSessionText; + + description = combinedText; + controller.text = combinedText; + controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length)); + notifyListeners(); + }, + localeId: localeId, + listenFor: const Duration(seconds: 60), + pauseFor: const Duration(seconds: 10), + listenOptions: SpeechListenOptions( + partialResults: true, + listenMode: ListenMode.confirmation, + cancelOnError: false, + ), + ); + } + + /// Start listening for speech input + Future startListening(String localeId, TextEditingController controller) async { + _isListening = true; + _currentLocaleId = localeId; + _currentController = controller; + _baseText = controller.text.trim(); // Save existing text + _currentSessionText = ''; + notifyListeners(); + await _startListeningInternal(localeId, controller); + } + + /// Stop listening for speech input + Future stopListening() async { + _isListening = false; + _currentLocaleId = ''; + _currentController = null; + _baseText = ''; + _currentSessionText = ''; + await _speechToText.stop(); + notifyListeners(); + } + + /// Toggle listening state + Future toggleListening(String localeId, TextEditingController controller) async { + if (_isListening) { + await stopListening(); + } else { + await startListening(localeId, controller); + } + } + + // Fetch Etqan Projects + Future fetchEtqanProjects(BuildContext context) async { + isLoading = true; + notifyListeners(); + Utils.showLoading(context); + getEtqanProjectsList?.clear(); + getEtqanProjectsList = await EtqanApiClient().getEtqanProjects(); + Utils.hideLoading(context); + isLoading = false; + notifyListeners(); + } + + // Fetch Etqan Employee Requests + Future fetchEtqanEmployeeRequests(BuildContext context) async { + isLoading = true; + notifyListeners(); + Utils.showLoading(context); + getEtqanEmployeeRequestsList?.clear(); + getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests(); + Utils.hideLoading(context); + isLoading = false; + notifyListeners(); + } + + // Fetch Etqan Employee Incident Report + Future fetchEtqanEmployeeIncidentRequests(BuildContext context, String ticketNo) async { + isLoading = true; + notifyListeners(); + Utils.showLoading(context); + getEtqanEmployeeIncidnetRequest?.clear(); + getEtqanEmployeeIncidnetRequest = await EtqanApiClient().getEtqanIncidentRequests(ticketNo); + Utils.hideLoading(context); + isLoading = false; + notifyListeners(); + } + + // Set selected project + void setSelectedProject(EtqanGetProjectsResponse? project) { + selectedProject = project; + notifyListeners(); + } + + // Set selected employee number + void setSelectedEmployeeNumber(String? employeeNumber) { + selectedEmployeeNumber = employeeNumber; + notifyListeners(); + } + + // Set attachment with base64 + void setAttachment(File file, String base64) { + attachment = file; + attachmentBase64 = base64; + notifyListeners(); + } + + // Remove attachment + void removeAttachment() { + attachment = null; + attachmentBase64 = null; + notifyListeners(); + } + + // Set description + void setDescription(String value) { + description = value; + notifyListeners(); + } + + // Validate description + bool isDescriptionValid() { + return description.trim().isNotEmpty; + } + + // Set isAnonymous + void setIsAnonymous(bool value) { + isAnonymous = value; + notifyListeners(); + } + + // Clear create request form + void clearCreateRequestForm() { + selectedProject = null; + selectedEmployeeNumber = null; + attachment = null; + attachmentBase64 = null; + description = ''; + isAnonymous = false; + notifyListeners(); + } + + // Submit request + Future?> submitRequest(BuildContext context) async { + try { + Utils.showLoading(context); + Map? response = await EtqanApiClient().createRequest(description, selectedProject?.projectId, attachmentBase64, isAnonymous); + Utils.hideLoading(context); + if (response != null) { + getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests(); + notifyListeners(); + return response; + } + return null; + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + return null; + } + } + + @override + void dispose() { + if (_isListening) { + _speechToText.stop(); + } + super.dispose(); + } +} diff --git a/lib/theme/app_theme.dart b/lib/theme/app_theme.dart index 586c3aa..f228600 100644 --- a/lib/theme/app_theme.dart +++ b/lib/theme/app_theme.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/theme/colors.dart'; @@ -15,36 +16,36 @@ class AppTheme { }, ), hintColor: Colors.grey[400], - colorScheme: ColorScheme.fromSwatch(accentColor: MyColors.backgroundColor), + colorScheme: ColorScheme.fromSwatch(accentColor: MyColors.backgroundColor).copyWith(surfaceTint : Colors.transparent), disabledColor: Colors.grey[300], - errorColor: const Color.fromRGBO(235, 80, 60, 1.0), + // errorColor: const Color.fromRGBO(235, 80, 60, 1.0), + applyElevationOverlayColor: false, scaffoldBackgroundColor: MyColors.backgroundColor, textSelectionTheme: const TextSelectionThemeData(cursorColor: Colors.grey, selectionColor: Color.fromRGBO(80, 100, 253, 0.5), selectionHandleColor: Colors.grey), canvasColor: Colors.white, - backgroundColor: const Color.fromRGBO(255, 255, 255, 1), + // backgroundColor: const Color.fromRGBO(255, 255, 255, 1), highlightColor: Colors.grey[100]!.withOpacity(0.4), splashColor: Colors.transparent, primaryColor: primaryColor, primaryColorDark: primaryColor, - buttonColor: Colors.black, - toggleableActiveColor: secondaryColor, + // toggleableActiveColor: secondaryColor, indicatorColor: secondaryColor, bottomSheetTheme: const BottomSheetThemeData( backgroundColor: Color(0xFFE0E0E0), ), primaryTextTheme: const TextTheme( - bodyText2: TextStyle(color: Colors.white), + // bodyText2: TextStyle(color: Colors.white), ), iconTheme: const IconThemeData(color: MyColors.darkIconColor), textTheme: const TextTheme( - bodyText1: TextStyle(color: Colors.black, letterSpacing: 0.6), - headline1: TextStyle(color: Colors.white, letterSpacing: 0.6), - headline2: TextStyle(color: Colors.white, letterSpacing: 0.6), + // bodyText1: TextStyle(color: Colors.black, letterSpacing: 0.6), + // headline1: TextStyle(color: Colors.white, letterSpacing: 0.6), + // headline2: TextStyle(color: Colors.white, letterSpacing: 0.6), ), floatingActionButtonTheme: const FloatingActionButtonThemeData(highlightElevation: 2, disabledElevation: 0, elevation: 2), appBarTheme: AppBarTheme( color: const Color(0xff515A5D), - brightness: Brightness.light, + systemOverlayStyle: const SystemUiOverlayStyle(statusBarBrightness: Brightness.light), elevation: 0.0, actionsIconTheme: IconThemeData( color: Colors.grey[800], diff --git a/lib/ui/attendance/monthly_attendance_screen.dart b/lib/ui/attendance/monthly_attendance_screen.dart index 1753c29..cce9d3b 100644 --- a/lib/ui/attendance/monthly_attendance_screen.dart +++ b/lib/ui/attendance/monthly_attendance_screen.dart @@ -16,7 +16,7 @@ import 'package:mohem_flutter_app/models/get_schedule_shifts_details_list_model. import 'package:mohem_flutter_app/models/get_time_card_summary_list_model.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/circular_step_progress_bar.dart'; -import 'package:month_picker_dialog_2/month_picker_dialog_2.dart'; +import 'package:month_picker_dialog/month_picker_dialog.dart'; import 'package:pie_chart/pie_chart.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; @@ -117,8 +117,6 @@ class _MonthlyAttendanceScreenState extends State { initialDate: formattedDate, firstDate: DateTime(searchYear - 2), lastDate: DateTime.now(), - confirmText: Text(LocaleKeys.confirm.tr()), - cancelText: Text(LocaleKeys.cancel.tr()), ).then((selectedDate) { if (selectedDate != null) { searchMonth = getMonth(selectedDate.month); @@ -303,11 +301,19 @@ class _MonthlyAttendanceScreenState extends State { monthCellBuilder: (build, details) { if (details.date.month == formattedDate.month && details.date.year == formattedDate.year) { int val = details.date.day; + int index = val-1; //check day is off - if (getDayHoursTypeDetailsList.isNotEmpty) { - bool isDayIsOff = getDayHoursTypeDetailsList[val - 1].aTTENDEDFLAG == 'N' && getDayHoursTypeDetailsList[val - 1].dAYTYPE == 'OFF'; - bool isDayIsPresent = getDayHoursTypeDetailsList[val - 1].aTTENDEDFLAG == 'Y'; - bool isDayIsAbsent = getDayHoursTypeDetailsList[val - 1].aTTENDEDFLAG == 'N' && getDayHoursTypeDetailsList[val - 1].aBSENTFLAG == 'Y'; + // if (getDayHoursTypeDetailsList.isNotEmpty) { + // bool isDayIsOff = getDayHoursTypeDetailsList[val - 1].aTTENDEDFLAG == 'N' && getDayHoursTypeDetailsList[val - 1].dAYTYPE == 'OFF'; + // bool isDayIsPresent = getDayHoursTypeDetailsList[val - 1].aTTENDEDFLAG == 'Y'; + // bool isDayIsAbsent = getDayHoursTypeDetailsList[val - 1].aTTENDEDFLAG == 'N' && getDayHoursTypeDetailsList[val - 1].aBSENTFLAG == 'Y'; + List getDayHours = + getDayHoursTypeDetailsList.where((GetDayHoursTypeDetailsList element) => DateFormat("MM/dd/yyyy", "en_US").parse(element.sCHEDULEDATE!).day == details.date.day).toList(); + + if (getDayHours.isNotEmpty) { + bool isDayIsOff = getDayHoursTypeDetailsList[index].aTTENDEDFLAG == 'N' && getDayHoursTypeDetailsList[index].dAYTYPE == 'OFF'; + bool isDayIsPresent = getDayHoursTypeDetailsList[index].aTTENDEDFLAG == 'Y'; + bool isDayIsAbsent = getDayHoursTypeDetailsList[index].aTTENDEDFLAG == 'N' && getDayHoursTypeDetailsList[index].aBSENTFLAG == 'Y'; if (isDayIsOff) { return Container( diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index d6483dc..28103f8 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -18,9 +17,9 @@ import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.da import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/chat_full_image_preview.dart'; import 'package:mohem_flutter_app/ui/chat/common.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; import 'package:rxdart/rxdart.dart'; +import 'package:video_player/video_player.dart'; class ChatBubble extends StatelessWidget { ChatBubble({Key? key, required this.dateTime, required this.cItem}) : super(key: key); @@ -82,7 +81,8 @@ class ChatBubble extends StatelessWidget { } } else { Utils.showLoading(context); - Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? "")); + Uint8List encodedString = + await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? ""), fileSource: 1); // try { File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); if (sFile.path.isEmpty) { @@ -195,20 +195,26 @@ class ChatBubble extends StatelessWidget { }), ), ).paddingOnly(bottom: 4), - if (fileTypeID == 13 && cItem.voiceController != null) - currentWaveBubble(context, cItem) + if (fileTypeID == 13 && cItem.voiceController != null) currentWaveBubble(context, cItem), + if (fileTypeID == 16) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + showVideoThumb(context, cItem), + Row( + children: [ + Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12().expanded), + ], + ), + ], + ) else Row( children: [ - if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 - // || fileTypeID == 2 - ) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) SvgPicture.asset(provider.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10), Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12().expanded), - if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 - //|| fileTypeID == 2 - ) - const Icon(Icons.remove_red_eye, size: 16) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) const Icon(Icons.remove_red_eye, size: 16) ], ), Align( @@ -276,7 +282,12 @@ class ChatBubble extends StatelessWidget { child: showImage( isReplyPreview: true, fileName: cItem.userChatReplyResponse!.contant!, - fileTypeDescription: cItem.userChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg"), + fileTypeDescription: cItem.fileTypeResponse != null && cItem.fileTypeResponse!.fileTypeDescription != null + ? cItem.fileTypeResponse!.fileTypeDescription + : cItem.fileTypeResponse!.fileTypeName + // fileTypeDescription: cItem.userChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg" + + ), ), ).paddingOnly(left: 10, right: 10, bottom: 16, top: 16) ], @@ -300,20 +311,26 @@ class ChatBubble extends StatelessWidget { }), ), ).paddingOnly(bottom: 4), - if (fileTypeID == 13 && cItem.voiceController != null) - recipetWaveBubble(context, cItem) + if (fileTypeID == 13 && cItem.voiceController != null) recipetWaveBubble(context, cItem), + if (fileTypeID == 16) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + showVideoThumb(context, cItem), + Row( + children: [ + Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12(color: Colors.white).expanded), + ], + ), + ], + ) else Row( children: [ - if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 - // || fileTypeID == 2 - ) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) SvgPicture.asset(provider.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10), Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12(color: Colors.white).expanded), - if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 - //|| fileTypeID == 2 - ) - const Icon(Icons.remove_red_eye, color: Colors.white, size: 16) + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8) const Icon(Icons.remove_red_eye, color: Colors.white, size: 16) ], ), Align( @@ -324,11 +341,7 @@ class ChatBubble extends StatelessWidget { ), ], ), - ).paddingOnly(right: MediaQuery.of(context).size.width * 0.3); - } - - Widget voiceMsg(BuildContext context) { - return Container(); + ).paddingOnly(right: MediaQuery.of(context).size.width * 0.33); } Widget showImage({required bool isReplyPreview, required String fileName, required String fileTypeDescription}) { @@ -342,7 +355,7 @@ class ChatBubble extends StatelessWidget { ); } else { return FutureBuilder( - future: ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: fileTypeDescription), + future: ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: fileTypeDescription, fileSource: 1), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState != ConnectionState.waiting) { if (snapshot.data == null) { @@ -470,4 +483,50 @@ class ChatBubble extends StatelessWidget { }, ); } + + Widget showVideoThumb(BuildContext context, SingleUserChatModel data) { + return LoadVideo(data: data); + } +} + +class LoadVideo extends StatefulWidget { + final SingleUserChatModel data; + + const LoadVideo({Key? key, required this.data}) : super(key: key); + + @override + State createState() => _LoadVideoState(); +} + +class _LoadVideoState extends State { + late VideoPlayerController videoController; + + @override + void initState() { + videoController = VideoPlayerController.networkUrl(Uri.parse('https://apiderichat.hmg.com/attachments/${widget.data.fileTypeResponse?.fileName}'))..initialize().then((_) {}); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return ClipRRect( + borderRadius: BorderRadius.circular(5.0), + child: AspectRatio( + aspectRatio: videoController.value.aspectRatio, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + VideoPlayer(videoController), + Align( + alignment: Alignment.center, + child: Icon( + Icons.play_arrow, + color: Colors.white.withOpacity(.7), + size: 56, + ), + ) + ], + ), + )); + } } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index a81219b..8cafdec 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -152,14 +152,13 @@ class _ChatDetailScreenState extends State { logger.w(m.userChatHistory[i].toJson()); if (m.userChatHistory[i].fileTypeResponse != null && m.userChatHistory[i].fileTypeId != null) { if (m.userChatHistory[i].fileTypeId! == 1 || - m.userChatHistory[i].fileTypeId! == 5 || - m.userChatHistory[i].fileTypeId! == 7 || - m.userChatHistory[i].fileTypeId! == 6 || - m.userChatHistory[i].fileTypeId! == 8 - // || m.userChatHistory[i].fileTypeId! == 2 - ) { + m.userChatHistory[i].fileTypeId! == 5 || + m.userChatHistory[i].fileTypeId! == 7 || + m.userChatHistory[i].fileTypeId! == 6 || + m.userChatHistory[i].fileTypeId! == 8 || + m.userChatHistory[i].fileTypeId! == 16) { m.getChatMedia(context, - fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!); + fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!, fileSource: 1); } } }); diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 426c9a2..c522475 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -32,8 +32,11 @@ class _ChatHomeState extends State { @override void initState() { super.initState(); - data = Provider.of(context, listen: false); - data.registerEvents(); + + if (chatHubConnection.state == HubConnectionState.Connected) { + data = Provider.of(context, listen: false); + data.registerEvents(); + } } @override @@ -47,7 +50,6 @@ class _ChatHomeState extends State { data.getUserAutoLoginToken().whenComplete(() async { await data.buildHubConnection(); data.getUserRecentChats(); - }); return; } @@ -57,7 +59,7 @@ class _ChatHomeState extends State { // String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); // String notificationData = await Utils.getStringFromPrefs("notificationData"); // if (isAppOpendByChat != "null" || isAppOpendByChat == "true" && notificationData != "null") { - // data.openChatByNoti(context); + // data.openChatByNoti(context); // } }); } diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 04d7c2e..846f19d 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -214,6 +214,13 @@ class _ChatHomeScreenState extends State { }, ), floatingActionButton: FloatingActionButton( +// <<<<<<< HEAD +// elevation: 0, +// backgroundColor : Colors.transparent, +// ======= + backgroundColor: Colors.transparent, + elevation: 0, + child: Container( width: 60, height: 60, diff --git a/lib/ui/chat/common.dart b/lib/ui/chat/common.dart index e0cb4d0..daaeca9 100644 --- a/lib/ui/chat/common.dart +++ b/lib/ui/chat/common.dart @@ -170,7 +170,7 @@ class WaveBubble extends StatelessWidget { padding: EdgeInsets.zero, margin: EdgeInsets.zero, enableSeekGesture: true, - density: 1, + // density: 1, playerWaveStyle: const PlayerWaveStyle( fixedWaveColor: Colors.white, liveWaveColor: MyColors.greenColor, @@ -178,7 +178,7 @@ class WaveBubble extends StatelessWidget { showBottom: true, waveCap: StrokeCap.round, seekLineThickness: 2, - visualizerHeight: 4, + // visualizerHeight: 4, backgroundColor: Colors.transparent, ), ), diff --git a/lib/ui/chat/group_chat_bubble.dart b/lib/ui/chat/group_chat_bubble.dart index 69a50df..9907ed9 100644 --- a/lib/ui/chat/group_chat_bubble.dart +++ b/lib/ui/chat/group_chat_bubble.dart @@ -22,6 +22,7 @@ import 'package:mohem_flutter_app/ui/chat/common.dart'; import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; import 'package:rxdart/rxdart.dart'; +import 'package:video_player/video_player.dart'; class GroupChatBubble extends StatelessWidget { GroupChatBubble({Key? key, required this.dateTime, required this.cItem}) @@ -66,19 +67,19 @@ class GroupChatBubble extends StatelessWidget { ? cItem.fileTypeResponse!.fileTypeDescription : ""; isDelivered = cItem.currentUserId == AppState().chatDetails!.response!.id && - cItem.isDelivered == true + cItem.isDelivered == true ? true : false; userName = AppState().chatDetails!.response!.userName == - cItem.currentUserName.toString() + cItem.currentUserName.toString() ? "You" : cItem.currentUserName.toString(); } void playVoice( - BuildContext context, { - required SingleUserChatModel data, - }) async { + BuildContext context, { + required SingleUserChatModel data, + }) async { if (data.voice != null && data.voice!.existsSync()) { if (Platform.isIOS) { Duration? duration = await data.voiceController! @@ -100,7 +101,7 @@ class GroupChatBubble extends StatelessWidget { Uint8List encodedString = await ChatApiClient().downloadURL( fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription( - data.fileTypeResponse!.fileTypeName ?? "")); + data.fileTypeResponse!.fileTypeName ?? ""), fileSource: 2); // try { File sFile = await provider.downChatVoice( encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); @@ -122,7 +123,7 @@ class GroupChatBubble extends StatelessWidget { data.voiceController!.play(); } else { Duration? duration = - await data.voiceController!.setFilePath(sFile.path); + await data.voiceController!.setFilePath(sFile.path); await data.voiceController!.setLoopMode(LoopMode.off); await data.voiceController!.seek(duration); Utils.hideLoading(context); @@ -148,7 +149,7 @@ class GroupChatBubble extends StatelessWidget { cItem.voiceController!.positionStream, cItem.voiceController!.bufferedPositionStream, cItem.voiceController!.durationStream, - (Duration position, Duration bufferedPosition, Duration? duration) => + (Duration position, Duration bufferedPosition, Duration? duration) => PositionData( position, bufferedPosition, duration ?? Duration.zero)); @@ -189,24 +190,24 @@ class GroupChatBubble extends StatelessWidget { children: [ (userName) .toText12( - color: MyColors.gradiantStartColor, isBold: false) + color: MyColors.gradiantStartColor, isBold: false) .paddingOnly(right: 5, top: 5, bottom: 0, left: 5), Directionality( textDirection: provider.getTextDirection( cItem.groupChatReplyResponse != null ? cItem.groupChatReplyResponse!.contant - .toString() + .toString() : ""), child: (cItem.groupChatReplyResponse != null - ? cItem.groupChatReplyResponse!.contant - .toString() - : "") + ? cItem.groupChatReplyResponse!.contant + .toString() + : "") .toText10( - color: isCurrentUser - ? MyColors.grey71Color - : MyColors.white.withOpacity(0.5), - isBold: false, - maxlines: 4) + color: isCurrentUser + ? MyColors.grey71Color + : MyColors.white.withOpacity(0.5), + isBold: false, + maxlines: 4) .paddingOnly(right: 5, top: 5, bottom: 8, left: 5), ), ], @@ -223,11 +224,11 @@ class GroupChatBubble extends StatelessWidget { child: showImage( isReplyPreview: false, fileName: - cItem.groupChatReplyResponse!.contant!, + cItem.groupChatReplyResponse!.contant!, fileTypeDescription: cItem - .groupChatReplyResponse! - .fileTypeResponse! - .fileTypeDescription ?? + .groupChatReplyResponse! + .fileTypeResponse! + .fileTypeDescription ?? "image/jpg")), ).paddingOnly(left: 10, right: 10, bottom: 16, top: 16), ], @@ -243,10 +244,13 @@ class GroupChatBubble extends StatelessWidget { height: 140, width: 227, child: showImage( - isReplyPreview: false, - fileName: cItem.contant!, - fileTypeDescription: - cItem.fileTypeResponse!.fileTypeDescription) + isReplyPreview: false, + fileName: cItem.contant!, + fileTypeDescription: cItem.fileTypeResponse != null && + cItem.fileTypeResponse!.fileTypeDescription != + null + ? cItem.fileTypeResponse!.fileTypeDescription + : cItem.fileTypeResponse!.fileTypeName) .onPress(() { showDialog( context: context, @@ -258,7 +262,9 @@ class GroupChatBubble extends StatelessWidget { ), ).paddingOnly(bottom: 4), if (fileTypeID == 13 && cItem.voiceController != null) - currentWaveBubble(context, cItem) + currentWaveBubble(context, cItem), + if (fileTypeID == 16) + showVideoThumb(context, cItem) else Row( children: [ @@ -270,10 +276,10 @@ class GroupChatBubble extends StatelessWidget { // || fileTypeID == 2 ) SvgPicture.asset(provider.getType(fileTypeName ?? ""), - height: 30, - width: 22, - alignment: Alignment.center, - fit: BoxFit.cover) + height: 30, + width: 22, + alignment: Alignment.center, + fit: BoxFit.cover) .paddingOnly(left: 0, right: 10), Directionality( textDirection: provider.getTextDirection(cItem.contant ?? ""), @@ -349,27 +355,27 @@ class GroupChatBubble extends StatelessWidget { children: [ (userName) .toText12( - color: MyColors.gradiantStartColor, - isBold: false) + color: MyColors.gradiantStartColor, + isBold: false) .paddingOnly(right: 5, top: 5, bottom: 0, left: 5), Directionality( textDirection: provider.getTextDirection( cItem.groupChatReplyResponse != null ? cItem.groupChatReplyResponse!.contant - .toString() + .toString() : ""), child: (cItem.groupChatReplyResponse != null - ? cItem.groupChatReplyResponse!.contant - .toString() - : "") + ? cItem.groupChatReplyResponse!.contant + .toString() + : "") .toText10( - color: isCurrentUser - ? MyColors.grey71Color - : MyColors.white.withOpacity(0.5), - isBold: false, - maxlines: 4) + color: isCurrentUser + ? MyColors.grey71Color + : MyColors.white.withOpacity(0.5), + isBold: false, + maxlines: 4) .paddingOnly( - right: 5, top: 5, bottom: 8, left: 5), + right: 5, top: 5, bottom: 8, left: 5), ), ], ).expanded, @@ -385,11 +391,11 @@ class GroupChatBubble extends StatelessWidget { child: showImage( isReplyPreview: true, fileName: - cItem.groupChatReplyResponse!.contant!, + cItem.groupChatReplyResponse!.contant!, fileTypeDescription: cItem - .groupChatReplyResponse! - .fileTypeResponse! - .fileTypeDescription ?? + .groupChatReplyResponse! + .fileTypeResponse! + .fileTypeDescription ?? "image/jpg"), ), ).paddingOnly(left: 10, right: 10, bottom: 16, top: 16) @@ -406,11 +412,11 @@ class GroupChatBubble extends StatelessWidget { height: 140, width: 227, child: showImage( - isReplyPreview: false, - fileName: cItem.contant ?? "", - fileTypeDescription: - cItem.fileTypeResponse!.fileTypeDescription ?? - "image/jpg") + isReplyPreview: false, + fileName: cItem.contant ?? "", + fileTypeDescription: + cItem.fileTypeResponse!.fileTypeDescription ?? + "image/jpg") .onPress(() { showDialog( context: context, @@ -422,14 +428,18 @@ class GroupChatBubble extends StatelessWidget { ), ).paddingOnly(bottom: 4), if (fileTypeID == 13 && cItem.voiceController != null) - recipetWaveBubble(context, cItem) + recipetWaveBubble(context, cItem), + if (fileTypeID == 16) + showVideoThumb(context, cItem) else Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - cItem.currentUserName!.toText10( + cItem.currentUserName! + .toText10( color: Colors.black, - ).paddingOnly(bottom: 5), + ) + .paddingOnly(bottom: 5), Row( children: [ if (fileTypeID == 1 || @@ -440,14 +450,14 @@ class GroupChatBubble extends StatelessWidget { // || fileTypeID == 2 ) SvgPicture.asset(provider.getType(fileTypeName ?? ""), - height: 30, - width: 22, - alignment: Alignment.center, - fit: BoxFit.cover) + height: 30, + width: 22, + alignment: Alignment.center, + fit: BoxFit.cover) .paddingOnly(left: 0, right: 10), Directionality( textDirection: - provider.getTextDirection(cItem.contant ?? ""), + provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "") .toText12(color: Colors.white) .expanded), @@ -464,9 +474,11 @@ class GroupChatBubble extends StatelessWidget { ), Align( alignment: Alignment.topRight, - child: dateTime.toText10( + child: dateTime + .toText10( color: Colors.white.withOpacity(.71), - ).paddingOnly(top:5), + ) + .paddingOnly(top: 5), ), ], ), @@ -479,8 +491,8 @@ class GroupChatBubble extends StatelessWidget { Widget showImage( {required bool isReplyPreview, - required String fileName, - required String fileTypeDescription}) { + required String fileName, + required String fileTypeDescription}) { if (cItem.isImageLoaded != null && cItem.image != null) { return Image.memory( cItem.image!, @@ -492,7 +504,7 @@ class GroupChatBubble extends StatelessWidget { } else { return FutureBuilder( future: ChatApiClient().downloadURL( - fileName: fileName, fileTypeDescription: fileTypeDescription), + fileName: fileName, fileTypeDescription: fileTypeDescription, fileSource:2), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState != ConnectionState.waiting) { if (snapshot.data == null) { @@ -528,7 +540,7 @@ class GroupChatBubble extends StatelessWidget { left: BorderSide( width: 6, color: - isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), + isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), ), color: isCurrentUser ? MyColors.black.withOpacity(0.10) @@ -547,7 +559,7 @@ class GroupChatBubble extends StatelessWidget { duration: positionData?.duration ?? Duration.zero, position: positionData?.position ?? Duration.zero, bufferedPosition: - positionData?.bufferedPosition ?? Duration.zero, + positionData?.bufferedPosition ?? Duration.zero, onChangeEnd: data.voiceController!.seek, ).expanded; }, @@ -557,6 +569,11 @@ class GroupChatBubble extends StatelessWidget { ).circle(5); } + Widget showVideoThumb(BuildContext context, GetGroupChatHistoryAsync data) { + + return LoadVideo(data: data); + } + Widget recipetWaveBubble( BuildContext context, GetGroupChatHistoryAsync data) { return Container( @@ -566,7 +583,7 @@ class GroupChatBubble extends StatelessWidget { left: BorderSide( width: 6, color: - isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), + isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), ), color: isCurrentUser ? MyColors.black.withOpacity(0.10) @@ -586,7 +603,7 @@ class GroupChatBubble extends StatelessWidget { duration: positionData?.duration ?? Duration.zero, position: positionData?.position ?? Duration.zero, bufferedPosition: - positionData?.bufferedPosition ?? Duration.zero, + positionData?.bufferedPosition ?? Duration.zero, onChangeEnd: data.voiceController!.seek, ).expanded; }, @@ -641,3 +658,51 @@ class GroupChatBubble extends StatelessWidget { ); } } + +class LoadVideo extends StatefulWidget { + final GetGroupChatHistoryAsync data; + const LoadVideo({Key? key, required this.data}) : super(key: key); + + @override + State createState() => _LoadVideoState(); +} + +class _LoadVideoState extends State { + late VideoPlayerController videoController; + + @override + void initState() { + videoController = VideoPlayerController.networkUrl(Uri.parse( + 'https://apiderichat.hmg.com/groupattachments/${widget.data.fileTypeResponse?.fileName}')) + ..initialize().then((_) { + + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: AspectRatio( + aspectRatio: videoController.value.aspectRatio, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + VideoPlayer(videoController), + Align( + alignment: Alignment.center, + child: Icon( + Icons.play_arrow, + color: Colors.white.withOpacity(.7), + size: 56, + ), + ) + ], + ), + )); + } +} \ No newline at end of file diff --git a/lib/ui/chat/group_chat_detaied_screen.dart b/lib/ui/chat/group_chat_detaied_screen.dart index 84ae3bd..83fb09e 100644 --- a/lib/ui/chat/group_chat_detaied_screen.dart +++ b/lib/ui/chat/group_chat_detaied_screen.dart @@ -58,11 +58,11 @@ class _GroupChatDetailScreenState extends State { data.paginationVal = data.paginationVal + 10; if (params != null) { data.getGroupChatHistory(params!.groupChatDetails! - // senderUID: AppState().chatDetails!.response!.id!.toInt(), - // receiverUID: params!.groupChatDetails!.groupId!, - // loadMore: true, - // isNewChat: false, - ); + // senderUID: AppState().chatDetails!.response!.id!.toInt(), + // receiverUID: params!.groupChatDetails!.groupId!, + // loadMore: true, + // isNewChat: false, + ); } } await Future.delayed( @@ -83,13 +83,12 @@ class _GroupChatDetailScreenState extends State { data = Provider.of(context, listen: false); // callPro = Provider.of(context, listen: false); if (params != null) { - data.getGroupChatHistory( - params!.groupChatDetails! - // senderUID: AppState().chatDetails!.response!.id!.toInt(), - // receiverUID: params!.groupChatHistory!.groupId!, - // loadMore: false, - // isNewChat: params!.isNewChat!, - ); + data.getGroupChatHistory(params!.groupChatDetails! + // senderUID: AppState().chatDetails!.response!.id!.toInt(), + // receiverUID: params!.groupChatHistory!.groupId!, + // loadMore: false, + // isNewChat: params!.isNewChat!, + ); data.initAudio(receiverId: params!.groupChatDetails!.groupId!); } @@ -99,8 +98,8 @@ class _GroupChatDetailScreenState extends State { context, title: params!.groupChatDetails!.groupName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, - // showTyping: true, - // chatUser: params!.groupChatHistory!.groupChatHistoryTargetUserList as ChatUser, + // showTyping: true, + // chatUser: params!.groupChatHistory!.groupChatHistoryTargetUserList as ChatUser, actions: [ // SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() { // makeCall(callType: "AUDIO"); @@ -117,224 +116,219 @@ class _GroupChatDetailScreenState extends State { builder: (BuildContext context, ChatProviderModel m, Widget? child) { return (m.isLoading ? ChatHomeShimmer( - isDetailedScreen: true, - ) + isDetailedScreen: true, + ) : Column( - children: [ - SmartRefresher( - enablePullDown: false, - enablePullUp: true, - onLoading: () { - getMoreChat(); - }, - header: const MaterialClassicHeader( - color: MyColors.gradiantEndColor, - ), - controller: _rc, - reverse: true, - child: ListView.separated( - controller: m.scrollController, - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - reverse: true, - itemCount: m.groupChatHistory.length, - padding: const EdgeInsets.all(21), - separatorBuilder: (BuildContext cxt, int index) => 8.height, - itemBuilder: (BuildContext context, int i) { - return SwipeTo( - iconColor: MyColors.lightGreenColor, - child: GroupChatBubble( - dateTime: m.groupChatHistory[i].createdDate!, - cItem: m.groupChatHistory[i], - ), - onRightSwipe: (val) { - m.groupChatReply( - m.groupChatHistory[i], - ); + children: [ + SmartRefresher( + enablePullDown: false, + enablePullUp: true, + onLoading: () { + getMoreChat(); }, - ).onPress(() async { - logger.w(m.userChatHistory[i].toJson()); - if (m.userChatHistory[i].fileTypeResponse != null && m.userChatHistory[i].fileTypeId != null) { - if (m.userChatHistory[i].fileTypeId! == 1 || - m.userChatHistory[i].fileTypeId! == 5 || - m.userChatHistory[i].fileTypeId! == 7 || - m.userChatHistory[i].fileTypeId! == 6 || - m.userChatHistory[i].fileTypeId! == 8 - // || m.userChatHistory[i].fileTypeId! == 2 - ) { - m.getChatMedia(context, - fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!); - } - } - }); - }, - ), - ).expanded, - if (m.isReplyMsg) - SizedBox( - height: 82, - child: Row( - children: [ - Container(height: 82, color: MyColors.textMixColor, width: 6), - Container( - color: MyColors.darkTextColor.withOpacity(0.10), - padding: const EdgeInsets.only(top: 11, left: 14, bottom: 14, right: 21), + header: const MaterialClassicHeader( + color: MyColors.gradiantEndColor, + ), + controller: _rc, + reverse: true, + child: ListView.separated( + controller: m.scrollController, + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + reverse: true, + itemCount: m.groupChatHistory.length, + padding: const EdgeInsets.all(21), + separatorBuilder: (BuildContext cxt, int index) => 8.height, + itemBuilder: (BuildContext context, int i) { + return SwipeTo( + iconColor: MyColors.lightGreenColor, + child: GroupChatBubble( + dateTime: m.groupChatHistory[i].createdDate!, + cItem: m.groupChatHistory[i], + ), + onRightSwipe: (val) { + m.groupChatReply( + m.groupChatHistory[i], + ); + }, + ).onPress(() async { + logger.w(m.userChatHistory[i].toJson()); + if (m.userChatHistory[i].fileTypeResponse != null && m.userChatHistory[i].fileTypeId != null) { + if (m.userChatHistory[i].fileTypeId! == 1 || + m.userChatHistory[i].fileTypeId! == 5 || + m.userChatHistory[i].fileTypeId! == 7 || + m.userChatHistory[i].fileTypeId! == 6 || + m.userChatHistory[i].fileTypeId! == 8 || + m.userChatHistory[i].fileTypeId! == 16) { + m.getChatMedia(context, + fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!, fileSource: 2); + } + } + }); + }, + ), + ).expanded, + if (m.isReplyMsg) + SizedBox( + height: 82, child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - (AppState().chatDetails!.response!.userName == m.groupChatReplyData.first.currentUserName.toString() - ? "You" - : m.groupChatReplyData.first.currentUserName.toString().replaceAll(".", " ")) - .toText14(color: MyColors.lightGreenColor), - (m.groupChatReplyData.isNotEmpty ? m.groupChatReplyData.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2) - ], + children: [ + Container(height: 82, color: MyColors.textMixColor, width: 6), + Container( + color: MyColors.darkTextColor.withOpacity(0.10), + padding: const EdgeInsets.only(top: 11, left: 14, bottom: 14, right: 21), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (AppState().chatDetails!.response!.userName == m.groupChatReplyData.first.currentUserName.toString() + ? "You" + : m.groupChatReplyData.first.currentUserName.toString().replaceAll(".", " ")) + .toText14(color: MyColors.lightGreenColor), + (m.groupChatReplyData.isNotEmpty ? m.groupChatReplyData.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2) + ], + ).expanded, + 12.width, + if (m.isReplyMsg && m.groupChatReplyData.isNotEmpty) showReplyImage(m.groupChatReplyData, m), + 12.width, + const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), + ], + ), ).expanded, - 12.width, - if (m.isReplyMsg && m.groupChatReplyData.isNotEmpty) showReplyImage(m.groupChatReplyData, m), - 12.width, - const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), ], ), - ).expanded, - ], - ), - ), - if (m.isAttachmentMsg && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") - SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), - const Divider(height: 1, color: MyColors.lightGreyEFColor), - if (m.isRecoding) - Column( - children: [ - Row( - children: [ - Text(m.buildTimer()).paddingAll(10), - if (m.isRecoding && m.isPlaying) - WaveBubble( - playerController: m.playerController, - isPlaying: m.playerController.playerState == PlayerState.playing, - onTap: () {}, - ).expanded - else - AudioWaveforms( - waveStyle: const WaveStyle( - waveColor: MyColors.lightGreenColor, - middleLineColor: Colors.transparent, - extendWaveform: true, - showBottom: true, - showTop: true, - waveThickness: 2, - showMiddleLine: false, - middleLineThickness: 0, - ), - padding: const EdgeInsets.all(5), - shouldCalculateScrolledPosition: false, - margin: EdgeInsets.zero, - size: const Size(double.infinity, 30.0), - recorderController: m.recorderController, - backgroundColor: Colors.white, - ).expanded, - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Icon( - Icons.delete_outlined, - size: 26, - color: MyColors.lightGreenColor, - ).paddingAll(10).onPress(() { - m.deleteRecoding(); - }), - SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) - .onPress( - () => m.sendGroupChatMessage(context, - targetUserId: params!.groupChatDetails!.groupId!, - userStatus: 0, - userEmail: "", - targetUserName: params!.groupChatDetails!.groupName!, - userList: params!.groupChatDetails!.groupUserList! - ), - ) - .paddingOnly(right: 21), - ], - ), - ], - ).objectContainerView(disablePadding: true, radius: 0), - if (!m.isRecoding) - Row( - children: [ - CustomAutoDirection( - onDirectionChange: (bool isRTL) => m.onDirectionChange(isRTL), - text: m.msgText, - child: TextField( - // textDirection: m.textDirection, - controller: m.message, - decoration: InputDecoration( - hintTextDirection: m.textDirection, - hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), - hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - filled: true, - fillColor: MyColors.white, - contentPadding: const EdgeInsets.only( - left: 21, - top: 20, - bottom: 20, - ), - prefixIconConstraints: const BoxConstraints(), - prefixIcon: m.sFileType.isNotEmpty - ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15) - : null, - ), - onChanged: (String val) { - m.inputBoxDirection(val); - m.groupTypingInvoke(groupDetails: params!.groupChatDetails!, groupId: params!.groupChatDetails!.groupId!); - }, - ).expanded, - ), - if (m.sFileType.isNotEmpty) - Row( + ), + if (m.isAttachmentMsg && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") + SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), + const Divider(height: 1, color: MyColors.lightGreyEFColor), + if (m.isRecoding) + Column( children: [ - const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), - ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), + Row( + children: [ + Text(m.buildTimer()).paddingAll(10), + if (m.isRecoding && m.isPlaying) + WaveBubble( + playerController: m.playerController, + isPlaying: m.playerController.playerState == PlayerState.playing, + onTap: () {}, + ).expanded + else + AudioWaveforms( + waveStyle: const WaveStyle( + waveColor: MyColors.lightGreenColor, + middleLineColor: Colors.transparent, + extendWaveform: true, + showBottom: true, + showTop: true, + waveThickness: 2, + showMiddleLine: false, + middleLineThickness: 0, + ), + padding: const EdgeInsets.all(5), + shouldCalculateScrolledPosition: false, + margin: EdgeInsets.zero, + size: const Size(double.infinity, 30.0), + recorderController: m.recorderController, + backgroundColor: Colors.white, + ).expanded, + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Icon( + Icons.delete_outlined, + size: 26, + color: MyColors.lightGreenColor, + ).paddingAll(10).onPress(() { + m.deleteRecoding(); + }), + SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) + .onPress( + () => m.sendGroupChatMessage(context, + targetUserId: params!.groupChatDetails!.groupId!, + userStatus: 0, + userEmail: "", + targetUserName: params!.groupChatDetails!.groupName!, + userList: params!.groupChatDetails!.groupUserList!), + ) + .paddingOnly(right: 21), + ], + ), ], - ).onPress(() => m.removeAttachment()).paddingOnly(right: 15), - if (m.sFileType.isEmpty) - RotationTransition( - turns: const AlwaysStoppedAnimation(45 / 360), - child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( - () => { - m.selectImageToUpload(context) + ).objectContainerView(disablePadding: true, radius: 0), + if (!m.isRecoding) + Row( + children: [ + CustomAutoDirection( + onDirectionChange: (bool isRTL) => m.onDirectionChange(isRTL), + text: m.msgText, + child: TextField( + // textDirection: m.textDirection, + controller: m.message, + decoration: InputDecoration( + hintTextDirection: m.textDirection, + hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), + hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + filled: true, + fillColor: MyColors.white, + contentPadding: const EdgeInsets.only( + left: 21, + top: 20, + bottom: 20, + ), + prefixIconConstraints: const BoxConstraints(), + prefixIcon: m.sFileType.isNotEmpty + ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15) + : null, + ), + onChanged: (String val) { + m.inputBoxDirection(val); + m.groupTypingInvoke(groupDetails: params!.groupChatDetails!, groupId: params!.groupChatDetails!.groupId!); }, - ), - ).paddingOnly(right: 15), - const Icon( - Icons.mic, - color: MyColors.lightGreenColor, - ).paddingOnly(right: 15).onPress(() { - m.startRecoding(context); - }), - SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) - .onPress( - () =>m.sendGroupChatMessage(context, - targetUserId: params!.groupChatDetails!.groupId!, - userStatus: 0, - userEmail: "", - targetUserName: params!.groupChatDetails!.groupName!, - userList: params!.groupChatDetails!.groupUserList! + ).expanded, ), - ) - .paddingOnly(right: 21), + if (m.sFileType.isNotEmpty) + Row( + children: [ + const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), + ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), + ], + ).onPress(() => m.removeAttachment()).paddingOnly(right: 15), + if (m.sFileType.isEmpty) + RotationTransition( + turns: const AlwaysStoppedAnimation(45 / 360), + child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( + () => {m.selectImageToUpload(context)}, + ), + ).paddingOnly(right: 15), + const Icon( + Icons.mic, + color: MyColors.lightGreenColor, + ).paddingOnly(right: 15).onPress(() { + m.startRecoding(context); + }), + SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26) + .onPress( + () => m.sendGroupChatMessage(context, + targetUserId: params!.groupChatDetails!.groupId!, + userStatus: 0, + userEmail: "", + targetUserName: params!.groupChatDetails!.groupName!, + userList: params!.groupChatDetails!.groupUserList!), + ) + .paddingOnly(right: 21), + ], + ).objectContainerView(disablePadding: true, radius: 0), ], - ).objectContainerView(disablePadding: true, radius: 0), - ], - )); + )); }, ), ), @@ -352,11 +346,11 @@ class _GroupChatDetailScreenState extends State { } else { return data.first.fileTypeResponse != null && data.first.fileTypeResponse!.fileTypeName != null ? Container( - width: 43, - height: 43, - constraints: const BoxConstraints(), - decoration: BoxDecoration(border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), color: Colors.white), - child: SvgPicture.asset(m.getType(data.first.fileTypeResponse!.fileTypeName ?? ""), alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 5, right: 5, top: 5, bottom: 5)) + width: 43, + height: 43, + constraints: const BoxConstraints(), + decoration: BoxDecoration(border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), color: Colors.white), + child: SvgPicture.asset(m.getType(data.first.fileTypeResponse!.fileTypeName ?? ""), alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 5, right: 5, top: 5, bottom: 5)) : const SizedBox(); } } @@ -373,22 +367,22 @@ class _GroupChatDetailScreenState extends State { // "calltype": callType == "VIDEO" ? "Video" : "Audio", // }; logger.w(json); - // CallDataModel callData = CallDataModel.fromJson(json); - // await Navigator.push( - // context, - // MaterialPageRoute( - // builder: (BuildContext context) => OutGoingCall( - // isVideoCall: callType == "VIDEO" ? true : false, - // outGoingCallData: callData, - // ), - // ), - // ).then((value) { - // print("then"); - // callPro.stopListeners(); - // }); + // CallDataModel callData = CallDataModel.fromJson(json); + // await Navigator.push( + // context, + // MaterialPageRoute( + // builder: (BuildContext context) => OutGoingCall( + // isVideoCall: callType == "VIDEO" ? true : false, + // outGoingCallData: callData, + // ), + // ), + // ).then((value) { + // print("then"); + // callPro.stopListeners(); + // }); } + GroupUserList getCurrentUser(int id, GroupResponse groupChatDetails) { - return groupChatDetails.groupUserList!.firstWhere((GroupUserList item) => item.id ==id); + return groupChatDetails.groupUserList!.firstWhere((GroupUserList item) => item.id == id); } - } diff --git a/lib/ui/dialogs/id/business_card_dialog.dart b/lib/ui/dialogs/id/business_card_dialog.dart index ed9f260..a405ccf 100644 --- a/lib/ui/dialogs/id/business_card_dialog.dart +++ b/lib/ui/dialogs/id/business_card_dialog.dart @@ -21,7 +21,6 @@ class BusinessCardDialog extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, - children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/ui/etqan_ovr/etqan_create_request.dart b/lib/ui/etqan_ovr/etqan_create_request.dart new file mode 100644 index 0000000..ba3c504 --- /dev/null +++ b/lib/ui/etqan_ovr/etqan_create_request.dart @@ -0,0 +1,360 @@ +import 'dart:io'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.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/widget_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart'; +import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/image_picker.dart'; +import 'package:provider/provider.dart'; + +class EtqanOvrCreateRequest extends StatefulWidget { + const EtqanOvrCreateRequest({Key? key}) : super(key: key); + + @override + _EtqanOvrCreateRequestState createState() => _EtqanOvrCreateRequestState(); +} + +class _EtqanOvrCreateRequestState extends State { + final TextEditingController _descriptionController = TextEditingController(); + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + var provider = context.read(); + provider.initSpeech(); + provider.fetchEtqanProjects(context); + provider.clearCreateRequestForm(); + }); + } + + @override + void dispose() { + // Stop listening if active + context.read().stopListening(); + _descriptionController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget(context, title: LocaleKeys.reportIncident.tr(), showHomeButton: false), + body: Consumer( + builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) { + return Column( + children: [ + (ListView( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.all(21), + children: [ + _buildDropdownField( + label: LocaleKeys.project.tr(), + hint: LocaleKeys.selectProject.tr(), + value: _getProjectDisplayName(provider.selectedProject), + onTap: () => _showProjectSelectionSheet(context, provider), + isMandatory: true, + ), + 16.height, + // _buildDropdownField( + // label: 'Employee Number', + // hint: 'Write a message', + // value: provider.selectedEmployeeNumber, + // onTap: () { + // // TODO: Show employee selection dialog + // }, + // ), + // 16.height, + _buildAttachmentSection(provider), + 16.height, + _buildDescriptionField(provider), + 8.height, + _buildAnonymousCheckbox(provider), + 24.height, + ], + )).expanded, + DefaultButton(LocaleKeys.submit.tr(), () async { + provider.setDescription(_descriptionController.text); + if (provider.selectedProject == null) { + Utils.showErrorDialog( + context: context, + message: LocaleKeys.pleaseSelectProject.tr(), + onOkTapped: () { + Navigator.of(context).pop(); + }, + ); + return; + } + if (!provider.isDescriptionValid()) { + Utils.showErrorDialog( + context: context, + message: LocaleKeys.pleaseEnterDescription.tr(), + onOkTapped: () { + Navigator.of(context).pop(); + }, + ); + return; + } + Map? ticketInfo = await provider.submitRequest(context); + if (ticketInfo != null) { + String ticketNumber = ticketInfo['ticketNumber'] ?? ''; + String ticketId = ticketInfo['id'] ?? ''; + // String successMessage = '${LocaleKeys.requestCreatedSuccessfully.tr()}\n\n${LocaleKeys.ticketNumber.tr()}: $ticketNumber\n${LocaleKeys.ticketId.tr()}: $ticketId'; + String successMessage = '${LocaleKeys.requestCreatedSuccessfully.tr()}\n\n${LocaleKeys.ticketNumber.tr()}: $ticketNumber'; + Utils.showErrorDialog( + context: context, + message: successMessage, + onOkTapped: () { + Navigator.pop(context); + Navigator.pop(context); + // Navigator.popAndPushNamed(context, AppRoutes.etqanOvr); + }, + onCloseTap: () { + Navigator.pop(context); + Navigator.pop(context); + // Navigator.popAndPushNamed(context, AppRoutes.etqanOvr); + }, + ); + } + }).insideContainer, + ], + ); + }, + ), + ); + } + + String? _getProjectDisplayName(EtqanGetProjectsResponse? project) { + if (project == null) return null; + return AppState().isArabic(context) ? project.projectAr : project.projectEn; + } + + void _showProjectSelectionSheet(BuildContext context, EtqanOvrProviderModel provider) { + if (provider.getEtqanProjectsList == null || provider.getEtqanProjectsList!.isEmpty) { + return; + } + showMyBottomSheet( + context, + callBackFunc: () {}, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Text(LocaleKeys.selectProject.tr(), style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xff2B353E))), + ), + const Divider(), + ListView.separated( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + itemCount: provider.getEtqanProjectsList!.length, + separatorBuilder: (BuildContext context, int index) => const Divider(height: 1), + itemBuilder: (BuildContext context, int index) { + EtqanGetProjectsResponse project = provider.getEtqanProjectsList![index]; + bool isSelected = provider.selectedProject?.projectId == project.projectId; + return ListTile( + title: Text( + AppState().isArabic(context) ? (project.projectAr ?? '') : (project.projectEn ?? ''), + style: TextStyle(fontSize: 14, fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, color: isSelected ? MyColors.gradiantEndColor : const Color(0xff2B353E)), + ), + trailing: isSelected ? const Icon(Icons.check, color: MyColors.gradiantEndColor) : null, + onTap: () { + provider.setSelectedProject(project); + Navigator.pop(context); + }, + ); + }, + ), + 16.height, + ], + ), + ); + } + + Widget _buildDropdownField({required String label, required String hint, String? value, required VoidCallback onTap, bool isMandatory = false}) { + return InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(15), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text(label, style: const TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.44)), + if (isMandatory) const Text(' *', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Colors.red, letterSpacing: -0.44)), + ], + ), + const SizedBox(height: 4), + Text(value ?? hint, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: value != null ? const Color(0xff2B353E) : const Color(0xff575757), letterSpacing: -0.56)), + ], + ), + ), + const Icon(Icons.keyboard_arrow_down, color: Color(0xff575757)), + ], + ), + ), + ); + } + + Widget _buildAttachmentSection(EtqanOvrProviderModel provider) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(LocaleKeys.supportingDocument.tr(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E))), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(LocaleKeys.attachments.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xff2B353E))), + if (provider.attachment == null) + InkWell( + onTap: () { + ImageOptions.showImageOptionsNew(context, true, (String base64, File file) { + provider.setAttachment(file, base64); + Navigator.of(context).pop(); + }); + }, + borderRadius: BorderRadius.circular(8), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), + decoration: BoxDecoration(color: MyColors.gradiantEndColor, borderRadius: BorderRadius.circular(8)), + child: Text(LocaleKeys.add.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Colors.white)), + ), + ), + ], + ), + if (provider.attachment != null) ...[ + const SizedBox(height: 12), + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + children: [ + const Icon(Icons.attach_file, size: 18, color: Color(0xff575757)), + const SizedBox(width: 8), + Expanded(child: Text(provider.attachment!.path.split('/').last, style: const TextStyle(fontSize: 12, color: Color(0xff575757)), overflow: TextOverflow.ellipsis)), + InkWell( + onTap: () { + provider.removeAttachment(); + }, + child: const Icon(Icons.close, size: 18, color: Colors.red), + ), + ], + ), + ), + ], + ], + ), + ); + } + + Widget _buildDescriptionField(EtqanOvrProviderModel provider) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text(LocaleKeys.description.tr(), style: const TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.44)), + const Text(' *', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Colors.red, letterSpacing: -0.44)), + ], + ), + GestureDetector( + onTap: + provider.speechEnabled + ? () { + String localeId = AppState().isArabic(context) ? 'ar_SA' : 'en_US'; + provider.toggleListening(localeId, _descriptionController); + } + : null, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration(color: provider.isListening ? MyColors.gradiantEndColor.withOpacity(0.1) : Colors.transparent, borderRadius: BorderRadius.circular(20)), + child: Icon( + provider.isListening ? Icons.mic : Icons.mic_none, + color: provider.isListening ? MyColors.gradiantEndColor : (provider.speechEnabled ? MyColors.grey57Color : Colors.grey.shade300), + size: 24, + ), + ), + ), + ], + ), + if (provider.isListening) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + children: [ + Container(width: 8, height: 8, decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.circular(4))), + const SizedBox(width: 8), + const Text('Listening...', style: TextStyle(fontSize: 12, color: MyColors.gradiantEndColor, fontWeight: FontWeight.w500)), + ], + ), + ), + TextField( + controller: _descriptionController, + maxLines: 4, + onChanged: (String value) => provider.setDescription(value), + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Color(0xff2B353E), letterSpacing: -0.44), + decoration: InputDecoration( + isDense: true, + hintText: LocaleKeys.writeAMessage.tr(), + hintStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Color(0xff575757), letterSpacing: -0.56), + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + ), + ], + ), + ); + } + + Widget _buildAnonymousCheckbox(EtqanOvrProviderModel provider) { + return InkWell( + onTap: () { + provider.setIsAnonymous(!provider.isAnonymous); + }, + child: Row( + children: [ + Checkbox( + value: provider.isAnonymous, + onChanged: (bool? value) { + if (value != null) { + provider.setIsAnonymous(value); + } + }, + activeColor: MyColors.gradiantEndColor, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)), + ), + + Expanded(child: Text(LocaleKeys.submitAsAnonymous.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xff2B353E), letterSpacing: -0.44))), + ], + ), + ); + } +} diff --git a/lib/ui/etqan_ovr/etqan_ovr_home.dart b/lib/ui/etqan_ovr/etqan_ovr_home.dart new file mode 100644 index 0000000..b55b4c0 --- /dev/null +++ b/lib/ui/etqan_ovr/etqan_ovr_home.dart @@ -0,0 +1,165 @@ +import 'package:easy_localization/easy_localization.dart' as lclize; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.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/models/etqan_ovr/etqan_get_requests_model.dart'; +import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:provider/provider.dart'; +import 'package:intl/src/intl/text_direction.dart' as intl; +import 'package:sizer/sizer.dart'; + +class EtqanOvrHome extends StatefulWidget { + const EtqanOvrHome({Key? key}) : super(key: key); + + @override + _EtqanOvrHomeState createState() => _EtqanOvrHomeState(); +} + +class _EtqanOvrHomeState extends State { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + context.read().fetchEtqanEmployeeRequests(context); + }); + } + + Color _getStatusColor(String status) { + String statusLower = status.toLowerCase(); + if (statusLower.contains('open') || statusLower.contains('مفتوح')) { + return const Color(0xff2196F3); // Blue for open + } else if (statusLower.contains('progress') || statusLower.contains('قيد التنفيذ')) { + return const Color(0xffFF9800); // Orange for in progress + } else if (statusLower.contains('closed') || statusLower.contains('مغلق')) { + return const Color(0xff4CAF50); // Green for closed + } + return MyColors.grey70Color; // Default gray + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget(context, title: LocaleKeys.myIncidents.tr()), + body: Consumer( + builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) { + return Column( + children: [ + (provider.getEtqanEmployeeRequestsList == null || provider.getEtqanEmployeeRequestsList!.isEmpty + ? Utils.getNoDataWidget(context) + : ListView.separated( + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.all(20), + itemBuilder: (BuildContext context, int index) { + EtqanGetEmployeeOvrRequestsResponse data = provider.getEtqanEmployeeRequestsList![index]; + return InkWell( + onTap: () { + context.read().setTicketId(data.ticketNumber ?? '', status: data.status, statusAr: data.statusAr, isAnonymous: data.isAnonymous); + Navigator.pushNamed(context, AppRoutes.etqanGetIncidientRequest); + }, + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15), border: Border.all(color: const Color(0xffefefef), width: 1)), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Wrap( + spacing: 8, + runSpacing: 8, + children: [ + if (data.status != null && data.status!.isNotEmpty) + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: _getStatusColor(data.status ?? "").withOpacity(0.1), + borderRadius: BorderRadius.circular(6), + border: Border.all(color: _getStatusColor(data.status ?? "").withOpacity(0.3), width: 1), + ), + child: (AppState().isArabic(context) ? (data.statusAr ?? "") : (data.status ?? "")).toText11( + color: _getStatusColor(data.status ?? ""), + isBold: true, + ), + ), + if (data.isAnonymous == true) + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: MyColors.grey70Color.withOpacity(0.15), + borderRadius: BorderRadius.circular(6), + border: Border.all(color: MyColors.grey70Color.withOpacity(0.3), width: 1), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.visibility_off, size: 12, color: MyColors.grey70Color), + const SizedBox(width: 4), + (AppState().isArabic(context) ? "مجهول" : "Anonymous").toText11(color: MyColors.grey70Color, isBold: true), + ], + ), + ), + ], + ), + ), + const SizedBox(width: 8), + ], + ), + 8.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (data.ticketNumber ?? "").toText14(isBold: true, color: MyColors.darkTextColor), + Directionality(textDirection: TextDirection.ltr, child: (data.createdDate!.split(" ").first ?? "").toText12(color: MyColors.grey70Color)), + ], + ), + 8.height, + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [(data.description ?? "").toText12(color: MyColors.grey57Color).expanded]), + 3.height, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + RotatedBox( + quarterTurns: AppState().isArabic(context) ? 2 : 0, + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.grey70Color, width: 16, height: 16), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + }, + separatorBuilder: (BuildContext context, int index) => 12.height, + itemCount: provider.getEtqanEmployeeRequestsList!.length, + )) + .expanded, + DefaultButton(LocaleKeys.reportIncident.tr(), () async { + await Navigator.pushNamed(context, AppRoutes.etqanCreateRequest); + // getOpenTickets(); + }).insideContainer, + ], + ); + }, + ), + ); + } +} diff --git a/lib/ui/etqan_ovr/etqan_request_detailed.dart b/lib/ui/etqan_ovr/etqan_request_detailed.dart new file mode 100644 index 0000000..41d11c6 --- /dev/null +++ b/lib/ui/etqan_ovr/etqan_request_detailed.dart @@ -0,0 +1,235 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.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/models/etqan_ovr/etqan_get_employee_incident_report.dart'; +import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:provider/provider.dart'; +import 'package:open_filex/open_filex.dart'; +import 'package:path_provider/path_provider.dart'; + +class EtqanOvrRequestDetailed extends StatefulWidget { + const EtqanOvrRequestDetailed({Key? key}) : super(key: key); + + @override + _EtqanOvrRequestDetailedState createState() => _EtqanOvrRequestDetailedState(); +} + +class _EtqanOvrRequestDetailedState extends State { + List get fieldOrder => ['Status', 'Project', 'Created', 'Is Anonymous', 'Occurrence Time', 'OVR Reference No', 'Involved Employee Number', 'Description']; + + List get hiddenFields => ['OVR Id']; + + Color _getStatusColor(String status) { + String statusLower = status.toLowerCase(); + if (statusLower.contains('open') || statusLower.contains('مفتوح')) { + return const Color(0xff2196F3); // Blue for open + } else if (statusLower.contains('progress') || statusLower.contains('قيد التنفيذ')) { + return const Color(0xffFF9800); // Orange for in progress + } else if (statusLower.contains('closed') || statusLower.contains('مغلق')) { + return const Color(0xff4CAF50); // Green for closed + } + return MyColors.grey70Color; // Default gray + } + + Future _viewAttachment(BuildContext context, String base64Data) async { + try { + Uint8List bytes = base64.decode(base64Data); + String dir = (await getApplicationDocumentsDirectory()).path; + String ext = 'pdf'; + if (base64Data.startsWith('/9j/')) { + ext = 'jpg'; + } else if (base64Data.startsWith('iVBORw0KGgo')) { + ext = 'png'; + } + File file = File("$dir/${DateTime.now().millisecondsSinceEpoch}.$ext"); + await file.writeAsBytes(bytes); + OpenFilex.open(file.path); + } catch (e) { + Utils.showToast("Cannot open attachment."); + } + } + + List _getOrderedList(List list, EtqanOvrProviderModel provider) { + List orderedList = []; + + List filteredList = list.where((EtqanGetIncidentRequestResponse item) => !hiddenFields.any((f) => f.toLowerCase() == item.key?.toLowerCase())).toList(); + + for (String fieldName in fieldOrder) { + // Check if this is Status or Is Anonymous - inject from provider + if (fieldName.toLowerCase() == 'status' && provider.getCurrentStatus.isNotEmpty) { + orderedList.add(EtqanGetIncidentRequestResponse( + key: 'Status', + keyAr: 'الحالة', + value: provider.getCurrentStatus, + valueAr: provider.getCurrentStatusAr.isNotEmpty ? provider.getCurrentStatusAr : provider.getCurrentStatus, + )); + } else if (fieldName.toLowerCase() == 'is anonymous') { + orderedList.add(EtqanGetIncidentRequestResponse( + key: 'Is Anonymous', + keyAr: 'مجهول', + value: provider.getCurrentIsAnonymous.toString(), + valueAr: provider.getCurrentIsAnonymous.toString(), + )); + } else { + // Regular field from API + var item = filteredList.firstWhere((e) => e.key?.toLowerCase() == fieldName.toLowerCase(), orElse: () => EtqanGetIncidentRequestResponse()); + if (item.key != null) { + orderedList.add(item); + } + } + } + + for (var item in filteredList) { + if (!fieldOrder.any((f) => f.toLowerCase() == item.key?.toLowerCase())) { + orderedList.add(item); + } + } + + return orderedList; + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + EtqanOvrProviderModel provider = context.read(); + provider.fetchEtqanEmployeeIncidentRequests(context, provider.getTicketId); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget(context, title: LocaleKeys.incidentDetails.tr()), + body: Consumer( + builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) { + if (provider.getEtqanEmployeeIncidnetRequest == null || provider.getEtqanEmployeeIncidnetRequest!.isEmpty) { + return Utils.getNoDataWidget(context); + } + + List orderedList = _getOrderedList(provider.getEtqanEmployeeIncidnetRequest!, provider); + + return SingleChildScrollView( + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.all(16), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all(color: const Color(0xffefefef), width: 1), + boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.05), blurRadius: 10, offset: const Offset(0, 2))], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + orderedList.asMap().entries.map((MapEntry entry) { + int index = entry.key; + EtqanGetIncidentRequestResponse data = entry.value; + bool isLast = index == orderedList.length - 1; + bool isAttachment = data.key?.toLowerCase() == 'attachment'; + bool isStatus = data.key?.toLowerCase() == 'status'; + bool isAnonymous = data.key?.toLowerCase() == 'is anonymous'; + + String displayKey = context.locale.languageCode == "ar" ? (data.keyAr ?? data.key ?? "") : (data.key ?? ""); + String displayValue = context.locale.languageCode == "ar" ? (data.valueAr ?? data.value ?? "") : (data.value ?? ""); + + bool hasSubValues = data.subValues != null && data.subValues!.isNotEmpty; + + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(flex: 2, child: displayKey.toText12(isBold: true, color: MyColors.grey57Color)), + 8.width, + Expanded( + flex: 3, + child: isStatus + ? displayValue.toText14( + color: _getStatusColor(displayValue), + isBold: true, + ) + : isAnonymous + ? (displayValue.toLowerCase() == 'true' || displayValue.toLowerCase() == 'yes' || displayValue == '1' + ? (context.locale.languageCode == "ar" ? "نعم" : "Yes") + : (context.locale.languageCode == "ar" ? "لا" : "No") + ).toText14(color: MyColors.darkTextColor) + : isAttachment && hasSubValues + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: data.subValues!.asMap().entries.map((entry) { + int subIndex = entry.key; + String base64Data = entry.value; + return Padding( + padding: EdgeInsets.only(bottom: subIndex < data.subValues!.length - 1 ? 8.0 : 0), + child: GestureDetector( + onTap: () => _viewAttachment(context, base64Data), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: context.locale.languageCode == "ar" ? MainAxisAlignment.end : MainAxisAlignment.start, + children: [ + Text( + data.subValues!.length > 1 ? '${LocaleKeys.viewAttachment.tr()} ${subIndex + 1}' : LocaleKeys.viewAttachment.tr(), + style: const TextStyle( + fontSize: 14, + color: MyColors.green9CColor, + decoration: TextDecoration.underline, + decorationColor: MyColors.green9CColor, + ), + ), + ], + ), + ), + ); + }).toList(), + ) + : hasSubValues + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (displayValue.isNotEmpty) displayValue.toText14(color: MyColors.darkTextColor), + if (displayValue.isNotEmpty) 8.height, + ...data.subValues! + .map( + (subValue) => Padding( + padding: const EdgeInsets.only(bottom: 4), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [const Text("• ", style: TextStyle(fontSize: 14)), Expanded(child: subValue.toText14(color: MyColors.darkTextColor))], + ), + ), + ) + .toList(), + ], + ) + : (displayValue.isNotEmpty ? displayValue : "-").toText14(color: MyColors.darkTextColor), + ), + ], + ), + ), + if (!isLast) const Padding(padding: EdgeInsets.only(left: 14, right: 14), child: Divider(height: 1, thickness: 1, color: Color(0xffefefef))), + ], + ); + }).toList(), + ), + ), + ); + }, + ).paddingOnly(bottom: 20), + ); + } +} diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 4116594..a89c7f6 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -1,9 +1,7 @@ import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; - import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -16,10 +14,13 @@ 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/models/itg/itg_main_response.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/privilege_list_model.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/landing/event_activity_banner.dart'; import 'package:mohem_flutter_app/ui/landing/widget/app_drawer.dart'; import 'package:mohem_flutter_app/ui/landing/widget/menus_widget.dart'; import 'package:mohem_flutter_app/ui/landing/widget/services_widget.dart'; @@ -32,6 +33,7 @@ import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:signalr_netcore/signalr_client.dart'; +import 'package:url_launcher/url_launcher.dart'; late HubConnection chatHubConnection; @@ -54,14 +56,16 @@ class _DashboardScreenState extends State with WidgetsBindingOb int currentIndex = 0; + bool isDisplayMazaya = false; + @override void initState() { WidgetsBinding.instance.addObserver(this); super.initState(); + cProvider = Provider.of(context, listen: false); scheduleMicrotask(() { data = Provider.of(context, listen: false); marathonProvider = Provider.of(context, listen: false); - cProvider = Provider.of(context, listen: false); if (checkIfPrivilegedForChat()) { _bHubCon(); } @@ -115,6 +119,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb } Future checkHubCon() async { + // chatHubConnection = await context.read().getHubConnection(); if (chatHubConnection.state == HubConnectionState.Connected) { await chatHubConnection.stop(); await chatHubConnection.start(); @@ -146,139 +151,182 @@ class _DashboardScreenState extends State with WidgetsBindingOb data.fetchAttendanceTracking(context); data.fetchWorkListCounter(context); data.fetchMissingSwipe(context); + data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchMenuEntries(); + data.fetchEventActivity(); + data.fetchGreetingCards(); data.getCategoryOffersListAPI(context); marathonProvider.getMarathonDetailsFromApi(); + marathonProvider.getMarathonTutorial(); if (isFromInit) { checkERMChannel(); } if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon(); _refreshController.refreshCompleted(); + + // await data.fetchTicketBooking(); + + // if (data.ticketBookingResponse != null && !data.ticketBookingResponse!.success) { + // data.fetchTicketBalance(); + // } + + //continue here } - void checkERMChannel() { - data.getITGNotification().then((val) { - if (val!.result!.data != null) { - print("-------------------- Survey ----------------------------"); - if (val.result!.data!.notificationType == "Survey") { - DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (value) { - if (value!.mohemmItgResponseItem!.statusCode == 200) { - if (value.mohemmItgResponseItem!.result!.data != null) { - // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); - Navigator.pushNamed(context, AppRoutes.survey, arguments: value.mohemmItgResponseItem!.result!.data); - // Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { - // "masterId": val.result!.data!.notificationMasterId, - // "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, - // }); - } - } - }, - ); + int ermIndex = 0; + + void handleErmChannel(List list) async { + try { + if (ermIndex == list.length) { + return; + } + // Utils.showLoading(context); + ItgMainRes? response = await DashboardApiClient().getAdvertisementDetail(list[ermIndex].notificationMasterId ?? ""); + // Utils.hideLoading(context); + if (response!.mohemmItgResponseItem!.result!.data != null) { + if (list[ermIndex].notificationType == "Survey") { + await Navigator.pushNamed(context, AppRoutes.survey, arguments: response.mohemmItgResponseItem!.result!.data!.first); } else { - print("------------------------------------------- Ads --------------------"); - DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( - (value) { - if (value!.mohemmItgResponseItem!.statusCode == 200) { - if (value.mohemmItgResponseItem!.result!.data != null) { - Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { - "masterId": val.result!.data!.notificationMasterId, - "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, - }); - } - } - }, + await Navigator.pushNamed( + context, + AppRoutes.advertisement, + arguments: {"masterId": list[ermIndex].notificationMasterId, "advertisement": response.mohemmItgResponseItem!.result!.data!.first.advertisement}, ); } } + ermIndex++; + handleErmChannel(list); + } catch (ex) { + print(ex); + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + return; + } + } + + void checkERMChannel() { + data.getITGNotification().then((val) async { + if (val!.result!.data != null) { + ermIndex = 0; + val.result?.data?.removeWhere((element) => element.notificationType == "Announcement"); + handleErmChannel(val.result?.data ?? []); + { + // if (ERMvalue.notificationType == "Survey") { + // await DashboardApiClient().getAdvertisementDetail(val.result!.data!.first.notificationMasterId ?? "").then( + // (value) async { + // if (value!.mohemmItgResponseItem!.statusCode == 200) { + // if (value.mohemmItgResponseItem!.result!.data != null) { + // // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); + // await Navigator.pushNamed(context, AppRoutes.survey, arguments: value.mohemmItgResponseItem!.result!.data!.first); + // // Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { + // // "masterId": val.result!.data!.notificationMasterId, + // // "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, + // // }); + // } + // } + // }, + // ); + // } else { + // print("------------------------------------------- Ads --------------------"); + // await DashboardApiClient().getAdvertisementDetail(ERMvalue.notificationMasterId ?? "").then( + // (value) async { + // if (value!.mohemmItgResponseItem!.statusCode == 200) { + // if (value.mohemmItgResponseItem!.result!.data != null) { + // await Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { + // "masterId": val.result!.data!.first.notificationMasterId, + // "advertisement": value.mohemmItgResponseItem!.result!.data!.first.advertisement, + // }); + // } + // } + // }, + // ); + // } + } + } }); } @override Widget build(BuildContext context) { - return Scaffold( - key: _scaffoldState, - body: Column( - children: [ - Row( - children: [ - Builder(builder: (BuildContext context) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Image.memory( - Utils.dataFromBase64String( - AppState().memberInformationList!.eMPLOYEEIMAGE ?? "", - ), - errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { - return SvgPicture.asset( - "assets/images/user.svg", - height: 34, + return SafeArea( + bottom: Platform.isAndroid ? true : false, + top: false, + child: Scaffold( + key: _scaffoldState, + body: Column( + children: [ + Row( + children: [ + Builder( + builder: (BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Image.memory( + Utils.dataFromBase64String(AppState().memberInformationList!.eMPLOYEEIMAGE ?? ""), + errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { + return SvgPicture.asset("assets/images/user.svg", height: 34, width: 34); + }, width: 34, - ); - }, - width: 34, - height: 34, - fit: BoxFit.cover, - ).circle(50), - // CircularAvatar( - // width: 34, - // height: 34, - // url: "https://cdn4.iconfinder.com/data/icons/professions-2-2/151/89-512.png", - // ), - 8.width, - SvgPicture.asset("assets/images/side_nav.svg"), - ], - ).onPress(() { - _scaffoldState.currentState!.openDrawer(); - }); - }), - Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28).expanded, - SvgPicture.asset( - "assets/images/announcements.svg", - matchTextDirection: true, - ).onPress(() async { - await Navigator.pushNamed(context, AppRoutes.announcements); - }) - ], - ).paddingOnly(left: 21, right: 21, top: 48, bottom: 7), - Expanded( - child: SmartRefresher( - enablePullDown: true, - enablePullUp: false, - header: const MaterialClassicHeader( - color: MyColors.gradiantEndColor, - ), - controller: _refreshController, - onRefresh: () { - _onRefresh(false); - }, - child: SingleChildScrollView( - child: Column( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color), - (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true), - 16.height, - Row( - children: [ - Expanded( - child: AspectRatio( - aspectRatio: 159 / 159, - child: Consumer( - builder: (BuildContext context, DashboardProviderModel model, Widget? child) { - return (model.isAttendanceTrackingLoading - ? GetAttendanceTrackingShimmer() - : Container( + height: 34, + fit: BoxFit.cover, + ).circle(50), + // CircularAvatar( + // width: 34, + // height: 34, + // url: "https://cdn4.iconfinder.com/data/icons/professions-2-2/151/89-512.png", + // ), + 8.width, + SvgPicture.asset("assets/images/side_nav.svg"), + ], + ).onPress(() { + _scaffoldState.currentState!.openDrawer(); + }); + }, + ), + Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28).expanded, + SvgPicture.asset("assets/images/announcements.svg", matchTextDirection: true).onPress(() async { + await Navigator.pushNamed(context, AppRoutes.announcements); + }), + ], + ).paddingOnly(left: 21, right: 21, top: 48, bottom: 7), + Expanded( + child: SmartRefresher( + enablePullDown: true, + enablePullUp: false, + header: const MaterialClassicHeader(color: MyColors.gradiantEndColor), + controller: _refreshController, + onRefresh: () { + _onRefresh(false); + }, + child: SingleChildScrollView( + child: Column( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color), + (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true), + 16.height, + Row( + children: [ + Expanded( + child: AspectRatio( + aspectRatio: 159 / 159, + child: Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + return (model.isAttendanceTrackingLoading + ? GetAttendanceTrackingShimmer() + : Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - gradient: const LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ]), + gradient: const LinearGradient( + transform: GradientRotation(.46), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [MyColors.gradiantEndColor, MyColors.gradiantStartColor], + ), ), child: Stack( alignment: Alignment.center, @@ -333,9 +381,10 @@ class _DashboardScreenState extends State with WidgetsBindingOb crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.checkIn.tr().toText12(color: Colors.white), - (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn) - .toString() - .toText14(color: Colors.white, isBold: true), + (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn).toString().toText14( + color: Colors.white, + isBold: true, + ), 4.height, ], ).paddingOnly(left: 12, right: 12), @@ -346,19 +395,15 @@ class _DashboardScreenState extends State with WidgetsBindingOb height: 45, padding: const EdgeInsets.only(left: 10, right: 10), decoration: BoxDecoration( - color: Color(0xff259EA4), + color: const Color(0xff259EA4), borderRadius: BorderRadius.only( - bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15), - bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), + bottomRight: AppState().isArabic(context) ? const Radius.circular(0) : const Radius.circular(15), + bottomLeft: AppState().isArabic(context) ? const Radius.circular(15) : const Radius.circular(0), ), ), child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/biometrics.svg" : "assets/images/biometrics.svg"), ).onPress(() { - showMyBottomSheet( - context, - callBackFunc: () {}, - child: MarkAttendanceWidget(model, isFromDashboard: true), - ); + showMyBottomSheet(context, callBackFunc: () {}, child: MarkAttendanceWidget(model, isFromDashboard: true)); }), ], ), @@ -366,63 +411,223 @@ class _DashboardScreenState extends State with WidgetsBindingOb ), ], ), - ).onPress( - () { - Navigator.pushNamed(context, AppRoutes.todayAttendance); - }, - )) - .animatedSwither(); - }, + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.todayAttendance); + })) + .animatedSwither(); + }, + ), ), ), - ), - 9.width, - Expanded( - child: MenusWidget(), + 9.width, + Expanded(child: MenusWidget()), + ], + ), + ], + ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), + Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + if (model.isGreetingCardsLoading) { + return const GreetingCardShimmer(); + } else if (model.isDisplayEidGreetings && model.greetingCardsList != null && model.greetingCardsList!.isNotEmpty) { + return SizedBox( + height: 140, + child: ListView.separated( + shrinkWrap: true, + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 0), + itemCount: model.greetingCardsList!.length, + separatorBuilder: (context, index) => const SizedBox(width: 24), + itemBuilder: (context, index) { + var card = model.greetingCardsList![index]; + return SvgPicture.network( + AppState().isArabic(context) + ? (card.backgroundImageUrlAr ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg") + : (card.backgroundImageUrlEn ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg"), + fit: BoxFit.contain, + placeholderBuilder: (context) => ClipRRect(borderRadius: BorderRadius.circular(18), child: Container(height: 80, color: Colors.white).toShimmer()), + ).onPress(() { + launchUrl(Uri.parse(AppState().isArabic(context) ? card.urlAr! : card.urlEn!)); + }); + }, + ), + ).paddingOnly(bottom: 0); + } else { + return const SizedBox(); + } + }, + ).paddingOnly(bottom: 24), + // eventActivityWidget(context), + if (isDisplayMazaya) ...[ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Directionality( + textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + gradient: const LinearGradient(colors: [Color(0xFF91C481), Color(0xFF7CCED7)], begin: Alignment.centerLeft, end: Alignment.centerRight), + ), + child: Padding( + padding: const EdgeInsets.all(3.0), // This creates the border width + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(17), // Slightly less than outer radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + flex: 2, + child: RichText( + text: + AppState().isArabic(context) + ? TextSpan( + children: [ + TextSpan( + text: 'اطلع على مميزات', + style: TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: const Color(0xFF5D5E5E), + ), + ), + TextSpan( + text: ' مزايا', + style: TextStyle( + fontSize: 16, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + letterSpacing: -0.2, + height: 24 / 16, + color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + ), + ), + ], + ) + : TextSpan( + children: [ + TextSpan( + text: LocaleKeys.explore.tr() + ' ', + style: const TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + TextSpan( + text: LocaleKeys.mazaya.tr(), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Poppins', + letterSpacing: -0.2, + height: 24 / 16, + color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + ), + ), + TextSpan( + text: ' ' + LocaleKeys.benefits.tr(), + style: const TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + ], + ), + ), + ), + const Expanded(flex: 1, child: SizedBox()), + ], + ), + const SizedBox(height: 8), + LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), + ], + ), + ), + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), + const SizedBox(height: 28), + LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + }), + ], + ), + ), + ], + ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), + ), + ), + ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), ), ], ), ], - ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - LocaleKeys.offers.tr().toText12(), - Row( - children: [ - LocaleKeys.discounts.tr().toText24(isBold: true), - 6.width, - Container( + + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + LocaleKeys.offers.tr().toText12(), + Row( + children: [ + LocaleKeys.discounts.tr().toText24(isBold: true), + 6.width, + Container( padding: const EdgeInsets.only(left: 8, right: 8), - decoration: BoxDecoration( - color: MyColors.yellowColor, - borderRadius: BorderRadius.circular(10), - ), - child: LocaleKeys.newString.tr().toText10(isBold: true)), - ], - ), - ], + decoration: BoxDecoration(color: MyColors.yellowColor, borderRadius: BorderRadius.circular(10)), + child: LocaleKeys.newString.tr().toText10(isBold: true), + ), + ], + ), + ], + ), ), - ), - LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { - Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); - }) - ], - ).paddingOnly(left: 21, right: 21), - Consumer( - builder: (BuildContext context, DashboardProviderModel model, Widget? child) { - return SizedBox( - height: 103 + 33, - child: ListView.separated( + LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + }), + ], + ).paddingOnly(left: 21, right: 21), + Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + return SizedBox( + height: 103 + 33, + child: ListView.separated( shrinkWrap: true, physics: const BouncingScrollPhysics(), padding: const EdgeInsets.only(left: 21, right: 21, top: 13), @@ -431,155 +636,181 @@ class _DashboardScreenState extends State with WidgetsBindingOb return model.isOffersLoading ? const OffersShimmerWidget() : InkWell( - onTap: () { - navigateToDetails(data.getOffersList[index]); - }, - child: SizedBox( - width: 73, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 73, - height: 73, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all( - Radius.circular(100), - ), - border: Border.all(color: MyColors.lightGreyE3Color, width: 1), - ), - child: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(50), - ), - child: Hero( - tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, - transitionOnUserGestures: true, - child: Image.network( - data.getOffersList[index].logo ?? "", - fit: BoxFit.contain, - ), - ), - ), + onTap: () { + navigateToDetails(data.getOffersList[index]); + }, + child: SizedBox( + width: 73, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 73, + height: 73, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all(Radius.circular(100)), + border: Border.all(color: MyColors.lightGreyE3Color, width: 1), ), - 4.height, - Expanded( - child: AppState().isArabic(context) - ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) - : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(50)), + child: Hero( + tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, + transitionOnUserGestures: true, + child: Image.network(data.getOffersList[index].logo ?? "", fit: BoxFit.contain), + ), ), - ], - ), + ), + 4.height, + Expanded( + child: + AppState().isArabic(context) + ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) + : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), + ), + ], ), - ); + ), + ); }, separatorBuilder: (BuildContext cxt, int index) => 8.width, - itemCount: 9), - ); - }, - ), - ], - ), - Container( - width: double.infinity, - padding: const EdgeInsets.only(top: 31), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.only(topRight: Radius.circular(50), topLeft: Radius.circular(50)), - border: Border.all(color: MyColors.lightGreyEDColor, width: 1), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ServicesWidget(), - context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 8), + itemCount: 9, + ), + ); + }, + ), ], ), + + Container( + width: double.infinity, + padding: const EdgeInsets.only(top: 31), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.only(topRight: Radius.circular(50), topLeft: Radius.circular(50)), + border: Border.all(color: MyColors.lightGreyEDColor, width: 1), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ServicesWidget(), + context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 8, top: 8), + // context.watch().isTutorialLoading + // ? const MarathonBannerShimmer().paddingAll(20) + // : Container( + // padding: EdgeInsets.only(bottom: 12, top: 12), + // margin: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 8), + // width: double.infinity, + // alignment: Alignment.center, + // decoration: BoxDecoration( + // color: MyColors.backgroundBlackColor, + // borderRadius: BorderRadius.circular(20), + // border: Border.all(color: MyColors.lightGreyEDColor, width: 1), + // ), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisSize: MainAxisSize.min, + // children: [ + // Text( + // "Tutorial:", + // style: TextStyle( + // fontSize: 11, + // fontStyle: FontStyle.italic, + // fontWeight: FontWeight.w600, + // color: MyColors.white.withOpacity(0.83), + // letterSpacing: -0.4, + // ), + // ), + // Text( + // context.read().tutorial?.tutorialName ?? "", + // overflow: TextOverflow.ellipsis, + // style: TextStyle( + // fontStyle: FontStyle.italic, + // fontSize: 19, + // fontWeight: FontWeight.bold, + // color: MyColors.white, + // height: 32 / 22, + // ), + // ), + // ], + // ), + // ).onPress(() { + // checkERMChannel(); + // // Navigator.pushNamed(context, AppRoutes.marathonTutorialScreen); + // }), + ], + ), + ), + ], + ), + ), + ), + ), + ], + ), + drawer: AppDrawer(onLanguageChange: _onRefresh), + bottomNavigationBar: SizedBox( + height: Platform.isAndroid ? 70 : 100, + child: BottomNavigationBar( + items: [ + BottomNavigationBarItem( + icon: SvgPicture.asset("assets/icons/home.svg", color: currentIndex == 0 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), + label: LocaleKeys.home.tr(), + ), + BottomNavigationBarItem( + icon: SvgPicture.asset("assets/icons/create_req.svg", color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), + label: LocaleKeys.mowadhafhiRequest.tr(), + ), + BottomNavigationBarItem( + icon: Stack( + alignment: Alignment.centerLeft, + children: [ + SvgPicture.asset("assets/icons/work_list.svg", color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), + Consumer( + builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { + if (data.workListCounter == 0) { + return const SizedBox(); + } + return Positioned( + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.workListCounter.toString().toText10(color: Colors.white), + ), + ); + }, ), ], ), + label: LocaleKeys.workList.tr(), ), - ), - ) - ], - ), - drawer: SafeArea( - child: AppDrawer(onLanguageChange: _onRefresh), - ), - bottomNavigationBar: SizedBox( - height: Platform.isAndroid ? 70 : 100, - child: BottomNavigationBar( - items: [ - BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/home.svg", - color: currentIndex == 0 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - label: LocaleKeys.home.tr(), - ), - BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/create_req.svg", - color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - label: LocaleKeys.mowadhafhiRequest.tr(), - ), - BottomNavigationBarItem( - icon: Stack( - alignment: Alignment.centerLeft, - children: [ - SvgPicture.asset( - "assets/icons/work_list.svg", - color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - Consumer( - builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { - if (data.workListCounter == 0) { - return const SizedBox(); - } - return Positioned( - right: 0, - top: 0, - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - alignment: Alignment.center, - decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), - child: data.workListCounter.toString().toText10(color: Colors.white), - ), - ); - }, - ), - ], + BottomNavigationBarItem( + icon: SvgPicture.asset("assets/icons/item_for_sale.svg", color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), + label: LocaleKeys.itemsForSale.tr(), ), - label: LocaleKeys.workList.tr(), - ), - BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/item_for_sale.svg", - color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - label: LocaleKeys.itemsForSale.tr(), - ), - BottomNavigationBarItem( - icon: Stack( - alignment: Alignment.centerLeft, - children: [ - SvgPicture.asset( - "assets/icons/chat/chat.svg", - color: !checkIfPrivilegedForChat() - ? MyColors.lightGreyE3Color - : currentIndex == 4 - ? MyColors.grey3AColor - : cProvider.disbaleChatForThisUser - ? MyColors.lightGreyE3Color - : MyColors.grey98Color, - ).paddingAll(4), - Consumer( - builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { - return !checkIfPrivilegedForChat() - ? const SizedBox() - : Positioned( + BottomNavigationBarItem( + icon: Stack( + alignment: Alignment.centerLeft, + children: [ + SvgPicture.asset( + "assets/icons/chat/chat.svg", + color: + !checkIfPrivilegedForChat() + ? MyColors.lightGreyE3Color + : currentIndex == 4 + ? MyColors.grey3AColor + : cProvider.disbaleChatForThisUser + ? MyColors.lightGreyE3Color + : MyColors.grey98Color, + ).paddingAll(4), + Consumer( + builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { + return !checkIfPrivilegedForChat() + ? const SizedBox() + : Positioned( right: 0, top: 0, child: Container( @@ -589,39 +820,48 @@ class _DashboardScreenState extends State with WidgetsBindingOb child: data.chatUConvCounter.toString().toText10(color: Colors.white), ), ); - }, - ), - ], + }, + ), + ], + ), + label: LocaleKeys.chat.tr(), ), - label: LocaleKeys.chat.tr(), - ), - ], - currentIndex: currentIndex, - selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600), - unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600), - type: BottomNavigationBarType.fixed, - selectedItemColor: MyColors.grey3AColor, - backgroundColor: MyColors.backgroundColor, - selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28), - unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28), - onTap: (int index) { - if (index == 1) { - Navigator.pushNamed(context, AppRoutes.mowadhafhi); - } else if (index == 2) { - Navigator.pushNamed(context, AppRoutes.workList); - } else if (index == 3) { - Navigator.pushNamed(context, AppRoutes.itemsForSale); - } else if (index == 4) { - if (!cProvider.disbaleChatForThisUser && checkIfPrivilegedForChat()) { - Navigator.pushNamed(context, AppRoutes.chat); + ], + currentIndex: currentIndex, + selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600), + unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600), + type: BottomNavigationBarType.fixed, + selectedItemColor: MyColors.grey3AColor, + backgroundColor: MyColors.backgroundColor, + selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28), + unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28), + onTap: (int index) { + if (index == 1) { + Navigator.pushNamed(context, AppRoutes.mowadhafhi); + } else if (index == 2) { + Navigator.pushNamed(context, AppRoutes.workList); + } else if (index == 3) { + Navigator.pushNamed(context, AppRoutes.itemsForSale); + } else if (index == 4) { + if (!cProvider.disbaleChatForThisUser && checkIfPrivilegedForChat()) { + Navigator.pushNamed(context, AppRoutes.chat); + } } - } - }, + }, + ), ), ), ); } + Widget eventActivityWidget(BuildContext context) { + return (context.watch().isEventLoadingLoading) + ? const MarathonBannerShimmer().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) + : (context.watch().eventActivity != null && context.watch().eventActivity!.isActive == true) + ? const EventActivityBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) + : const SizedBox(); + } + void navigateToDetails(OffersListModel offersListModelObj) { List getOffersDetailList = []; getOffersDetailList.clear(); diff --git a/lib/ui/landing/event_activity_banner.dart b/lib/ui/landing/event_activity_banner.dart new file mode 100644 index 0000000..511b0fe --- /dev/null +++ b/lib/ui/landing/event_activity_banner.dart @@ -0,0 +1,367 @@ +import 'dart:math' as math; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.dart'; +import 'package:mohem_flutter_app/classes/decorations_helper.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/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer_main_screen.dart'; +import 'package:mohem_flutter_app/widgets/glowy_borders/glowy_borders.dart'; +import 'package:provider/provider.dart'; + +int dummyTime = DateTime.now().millisecondsSinceEpoch + 8690; + +class EventActivityBanner extends StatelessWidget { + const EventActivityBanner({Key? key}) : super(key: key); + + Widget getNoUpcomingMarathonWidget(BuildContext context) { + ; + return Container( + decoration: MyDecorations.shadowDecoration, + height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11, + clipBehavior: Clip.antiAlias, + child: Stack( + children: [ + Transform( + alignment: Alignment.center, + transform: Matrix4.rotationY( + AppState().isArabic(context) ? math.pi : 0, + ), + child: SvgPicture.asset( + "assets/images/marathon_banner_bg.svg", + fit: BoxFit.fill, + width: double.infinity, + ), + ), + AppState().isArabic(context) + ? Positioned( + right: -15, + top: -10, + child: Transform.rotate( + angle: 10, + child: Container( + width: isTablet ? 70 : 65, + height: isTablet ? 40 : 32, + color: MyColors.darkDigitColor, + ), + ), + ) + : Positioned( + left: -20, + top: -10, + child: Transform.rotate( + angle: 15, + child: Container( + width: isTablet ? 70 : 65, + height: isTablet ? 40 : 32, + color: MyColors.darkDigitColor, + ), + ), + ), + SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( + children: [ + const Expanded( + flex: 3, + child: SizedBox( + width: double.infinity, + height: double.infinity, + ), + ), + Expanded( + flex: AppState().isArabic(context) ? 4 : 5, + child: SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + AppState().isArabic(context) ? 0.height : 5.height, + Text( + LocaleKeys.noUpcoming.tr(), + style: TextStyle( + fontSize: isTablet ? 20 : 11, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w600, + color: MyColors.white.withOpacity(0.83), + letterSpacing: -0.4, + ), + ), + Text( + LocaleKeys.brainMarathon.tr(), + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: isTablet ? 30 : 19, + fontWeight: FontWeight.bold, + color: MyColors.white.withOpacity(0.83), + height: 32 / 22, + ), + ), + Text( + LocaleKeys.youCanPlayDemo.tr(), + style: TextStyle( + fontSize: isTablet ? 20 : 11, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w600, + color: MyColors.white.withOpacity(0.83), + letterSpacing: -0.4, + ), + ), + ], + ).paddingOnly( + left: AppState().isArabic(context) ? 12 : 3, + right: AppState().isArabic(context) ? 3 : 12, + ) + ], + ), + ), + ), + ], + ), + ), + AppState().isArabic(context) + ? Align( + alignment: Alignment.topRight, + child: SizedBox( + height: isTablet ? 30 : 20, + width: isTablet ? 45 : 35, + child: Transform.rotate( + angle: math.pi / 4.5, + child: Text( + LocaleKeys.brainMarathon.tr(), + textAlign: TextAlign.center, + maxLines: 2, + style: TextStyle( + color: MyColors.white, + fontWeight: FontWeight.bold, + fontSize: isTablet ? 8 : 6, + height: 1.2, + ), + ), + ), + ), + ).paddingOnly(top: 5) + : Align( + alignment: Alignment.topLeft, + child: SizedBox( + height: isTablet ? 30 : 20, + width: isTablet ? 45 : 35, + child: Transform.rotate( + angle: -math.pi / 4.5, + child: Text( + LocaleKeys.brainMarathon.tr(), + textAlign: TextAlign.center, + maxLines: 2, + style: TextStyle( + color: MyColors.kWhiteColor, + fontWeight: FontWeight.bold, + fontSize: isTablet ? 8 : 6, + height: 1.2, + ), + ), + ), + ), + ).paddingOnly(top: 5), + ], + ), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); + }); + } + + @override + Widget build(BuildContext context) { + DashboardProviderModel dashboardProvider = context.read(); + + return SizedBox( + // decoration: BoxDecoration( + // color: MyColors.kWhiteColor, + // borderRadius: BorderRadius.circular(8), + // boxShadow: [ + // BoxShadow( + // color: const Color(0xff000000).withOpacity(.05), + // blurRadius: 26, + // offset: const Offset(0, -3), + // ), + // ], + // ), + height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11, + child: AnimatedGradientBorder( + borderSize: 3, + stretchAlongAxis: true, + animationTime: 2, + stretchAxis: Axis.vertical, + gradientColors: const [ + Color(0xff0E5A64), + Color(0xff0E5A64), + Color(0xff0E5A64), + Color(0xff91C481), + ], + borderRadius: BorderRadius.circular(10), + child: Container( + decoration: BoxDecoration( + color: const Color(0xff0E5A64), + borderRadius: BorderRadius.circular(8), + ), + // height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11, + + child: Stack( + children: [ + // Transform( + // alignment: Alignment.center, + // // transform: Matrix4.rotationY( + // // AppState().isArabic(context) ? math.pi : 0, + // // ), + // child: + // + + AppState().isArabic(context) + ? Positioned( + left: -15, + top: -10, + child: Transform.rotate( + angle: 10, + child: SizedBox( + child: SvgPicture.asset( + "assets/images/light_bulb.svg"), + ), + ), + ) + : Positioned( + right: 0, + top: 10, + child: Opacity( + opacity: .5, + child: SvgPicture.asset( + "assets/images/light_bulb.svg", + ), + )), + + SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( + children: [ + + Expanded( + flex: 3, + child: Image.network( + dashboardProvider.eventActivity?.shortImageURL ?? + "", + fit: BoxFit.cover, + key: UniqueKey() + ).paddingAll(5)), + Expanded( + flex: AppState().isArabic(context) ? 4 : 5, + child: SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + AppState().isArabic(context) ? 0.height : 5.height, + + Flexible( + child: Text( + displayLocalizedContent( + isPhoneLangArabic: AppState().isArabic(context), + selectedLanguage: 3, + englishContent: dashboardProvider.eventActivity?.titleEn ?? "", + arabicContent: dashboardProvider.eventActivity?.titleAr ?? "", + ), + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: isTablet ? 25 : 16, + fontWeight: FontWeight.bold, + color: MyColors.white, + height: 32 / 24, + ), + ), + ), Text( + displayLocalizedContent( + isPhoneLangArabic: AppState().isArabic(context), + selectedLanguage: 3, + englishContent: dashboardProvider.eventActivity?.shortDescEn ?? "", + arabicContent: dashboardProvider.eventActivity?.shortDescAr ?? "", + ), + style: TextStyle( + fontSize: isTablet ? 20 : 11, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w600, + color: MyColors.white, + letterSpacing: -0.5, + ), + ), + + isTablet ? 15.height : 10.height, + CountdownTimerForMainScreen( + timeToMarathon: DateUtil.convertStringToDateMarathon(dashboardProvider.eventActivity!.startOn!).millisecondsSinceEpoch, + provider: context.read(), + isEvent: true, + ), + ], + ).paddingOnly( + left: AppState().isArabic(context) ? 12 : 3, + right: AppState().isArabic(context) ? 3 : 12, + ) + ], + ), + ), + ), + ], + ), + ), + + !AppState().isArabic(context) + ? Positioned( + right: 0, + bottom: 0, + child: RotatedBox( + quarterTurns: 4, + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), + ).paddingAll(isTablet ? 20 : 15), + ) + : Positioned( + bottom: 0, + left: 0, + child: RotatedBox( + quarterTurns: 2, + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), + ).paddingAll(isTablet ? 20 : 15), + ), + ], + ).onPress(() async { + // int remainingTimeInMinutes = DateUtil.convertStringToDateMarathon(dashboardProvider.eventActivity!.startOn!).difference(DateTime.now()).inMinutes; + // if (remainingTimeInMinutes < 0) { + Navigator.pushNamed(context, AppRoutes.activityScreen); + + //} + // provider.updateLanguageAsPerMarathon(context, provider.isUpComingMarathon ? provider.marathonDetailModel : provider.demoMarathonDetailModel); + })), + ), + ); + } +} diff --git a/lib/ui/landing/itg/its_add_screen_video_image.dart b/lib/ui/landing/itg/its_add_screen_video_image.dart index 8ce89d0..23bfc66 100644 --- a/lib/ui/landing/itg/its_add_screen_video_image.dart +++ b/lib/ui/landing/itg/its_add_screen_video_image.dart @@ -1,8 +1,3 @@ -import 'dart:convert'; -import 'dart:io' as Io; -import 'dart:io'; -import 'dart:typed_data'; - import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/index.dart'; import 'package:lottie/lottie.dart'; @@ -11,13 +6,20 @@ import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/lottie_consts.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/main.dart'; +import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart'; import 'package:mohem_flutter_app/models/itg/advertisement.dart' as ads; +import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/my_attendance/services_menu_list_screen.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; -import 'package:path_provider/path_provider.dart'; +import 'package:mohem_flutter_app/widgets/my_video_progress_indicator.dart'; +import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; import 'package:video_player/video_player.dart'; class ITGAdsScreen extends StatefulWidget { @@ -29,13 +31,17 @@ class ITGAdsScreen extends StatefulWidget { class _ITGAdsScreenState extends State { late Future _futureController; - late VideoPlayerController _controller; + VideoPlayerController? _controller; bool skip = false; bool isVideo = false; bool isImage = false; bool isAudio = false; String ext = ''; - late File imageFile; + + bool isTextURL = false; + + // late File imageFile; + late String imageUrl; ads.Advertisement? advertisementData; dynamic data; String? masterID; @@ -47,26 +53,35 @@ class _ITGAdsScreenState extends State { late CountdownTimerController timerController; - void checkFileType() async { - String? rFile = advertisementData!.viewAttachFileColl!.first.base64String; - String? rFileExt = advertisementData!.viewAttachFileColl!.first.fileName; - ext = "." + rFileExt!.split(".").last.toLowerCase(); - if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif") { - await processImage(rFile!); - isImage = true; + void checkFileType() { + if (advertisementData!.viewAttachFileColl!.first.contentType!.toLowerCase() == "text") { + isTextURL = true; } else { - if (ext == ".aac") { - isAudio = true; + String? rFile = advertisementData!.viewAttachFileColl!.first.base64String; + try { + rFile = advertisementData!.viewAttachFileColl!.where((element) => element.languageId == AppState().getLanguageID(context)).toList().first.base64String; + } catch (ex) {} + + String? rFileExt = advertisementData!.viewAttachFileColl!.first.fileName; + ext = "." + rFileExt!.split(".").last.toLowerCase(); + if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif") { + // await processImage(); + imageUrl = rFile!; + isImage = true; + } else { + if (ext == ".aac") { + isAudio = true; + } + isVideo = true; + _futureController = createVideoPlayer(rFile!); } - isVideo = true; - _futureController = createVideoPlayer(rFile!); } - advertisementData?.actionButtonsColl!.forEach((element) { - advertisementData?.actionButtonsColl!.removeWhere((element1) => element1.actionButtonId == advertisementData?.skipButtonId); - }); + // advertisementData?.actionButtonsColl!.forEach((element) { + advertisementData?.actionButtonsColl!.removeWhere((element1) => element1.actionButtonId == advertisementData?.skipButtonId); + //}); - setState(() {}); + // setState(() {}); } void changeTimer(bool isTimerEnd) { @@ -80,16 +95,17 @@ class _ITGAdsScreenState extends State { timerController.dispose(); } - Future processImage(String encodedBytes) async { - try { - Uint8List decodedBytes = base64Decode(encodedBytes.split("base64,").last); - Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 - imageFile = Io.File("${appDocumentsDirectory.path}/addImage$ext"); - imageFile.writeAsBytesSync(decodedBytes); - } catch (e) { - logger.d(e); - } - } + // + // Future processImage(String encodedBytes) async { + // try { + // Uint8List decodedBytes = base64Decode(encodedBytes.split("base64,").last); + // Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 + // imageFile = Io.File("${appDocumentsDirectory.path}/addImage$ext"); + // imageFile.writeAsBytesSync(decodedBytes); + // } catch (e) { + // logger.d(e); + // } + // } Future createVideoPlayer(String encodedBytes) async { try { @@ -114,7 +130,7 @@ class _ITGAdsScreenState extends State { @override void dispose() { - if (_controller != null) _controller.dispose(); + _controller?.dispose(); super.dispose(); } @@ -129,7 +145,17 @@ class _ITGAdsScreenState extends State { timerController = CountdownTimerController(endTime: DateTime.now().millisecondsSinceEpoch + 1000 * videoDuration, onEnd: onTimerEnd); } return Scaffold( - backgroundColor: Colors.black, + backgroundColor: isTextURL ? Colors.white : Colors.black, + appBar: isTextURL + ? AppBar( + centerTitle: true, + automaticallyImplyLeading: false, + backgroundColor: Colors.white, + title: (AppState().isArabic(context) ? advertisementData!.advertisementTitleAr! : advertisementData!.advertisementTitle!).toText24(color: MyColors.darkTextColor, isBold: true), + + //advertisementData!.viewAttachFileColl!.first.base64String!.toText24(color: MyColors.darkTextColor, isBold: true), + ) + : null, body: Stack( children: [ if (isVideo) @@ -145,8 +171,34 @@ class _ITGAdsScreenState extends State { child: isAudio ? Lottie.asset(MyLottieConsts.audioPlaybackLottie) : AspectRatio( - aspectRatio: _controller.value.aspectRatio, - child: VideoPlayer(_controller), + aspectRatio: _controller!.value.aspectRatio, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + VideoPlayer(_controller!), + if (advertisementData?.isOptional ?? false) + Positioned( + top: 4, + right: 8, + child: Container( + padding: const EdgeInsets.only(left: 8, right: 8, top: 4, bottom: 4), + decoration: BoxDecoration(color: Colors.white.withOpacity(0.5), borderRadius: BorderRadius.circular(30)), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(AppState().isArabic(context) ? "يتخطى" : "Skip"), + Icon(Icons.skip_next), + ], + ), + ).onPress(() { + Navigator.pop(context); + DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Skip").then((value) { + logger.d(value); + }); + }), + ), + ], + ), ), ), 30.height, @@ -157,72 +209,103 @@ class _ITGAdsScreenState extends State { textStyle: const TextStyle(color: Colors.white, fontSize: 16, letterSpacing: -0.48, fontWeight: FontWeight.bold), ), 50.height, - if (advertisementData?.isOptional ?? false) - DefaultButton(AppState().isArabic(context) ? "يتخطى" : "Skip", () async { - Navigator.pop(context); - DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Skip").then((value) { - logger.d(value); - }); - }).paddingOnly(left: 60.0, right: 60.0, top: 8, bottom: 8), + // if (advertisementData?.isOptional ?? false) + // DefaultButton(AppState().isArabic(context) ? "يتخطى" : "Skip", () async { + // Navigator.pop(context); + // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Skip").then((value) { + // logger.d(value); + // }); + // }).paddingOnly(left: 60.0, right: 60.0, top: 8, bottom: 8), ValueListenableBuilder( valueListenable: hasTimerEnded, builder: (context, val, child) { - if (hasTimerEndedBool) { - return GridView.builder( - padding: EdgeInsets.zero, - itemCount: advertisementData?.actionButtonsColl!.length, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - String? btnText = AppState().isArabic(context) ? advertisementData?.actionButtonsColl![index].btnTextAr : advertisementData?.actionButtonsColl![index].btnTextEn; - return DefaultButton(btnText!, () async { - Navigator.pop(context); - DashboardApiClient() - .setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, advertisementData?.actionButtonsColl![index].actionValue) - .then((value) { - logger.d(value); - }); - }).paddingOnly(left: 60.0, right: 60.0, top: 8, bottom: 8); - }, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 1, - childAspectRatio: (7.0), - ), - ); - // Row( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor)) - // .onPress(() { - // try { - // Navigator.pop(context); - // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Like").then((value) { - // logger.d(value); - // }); - // } catch (ex) { - // logger.wtf(ex); - // Utils.handleException(ex, context, null); - // } - // }), - // 20.width, - // Container( - // padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_down, color: MyColors.gradiantEndColor)) - // .onPress(() { - // try { - // Navigator.pop(context); - // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Dislike").then((value) { - // logger.d(value); - // }); - // } catch (ex) { - // logger.wtf(ex); - // Utils.handleException(ex, context, null); - // } - // }), - // ], - // ); - } else { - return Container(); - } + // if (hasTimerEndedBool) { + return ListView.builder( + padding: EdgeInsets.zero, + itemCount: advertisementData?.actionButtonsColl!.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + String? btnText = AppState().isArabic(context) ? advertisementData?.actionButtonsColl![index].btnTextAr : advertisementData?.actionButtonsColl![index].btnTextEn; + + // bool isAcknowledge = advertisementData?.actionButtonsColl![index].actionButtonId == 11; + bool isAcknowledge = advertisementData?.actionButtonsColl![index].actionButtonId == 17; + if (isAcknowledge) { + return Stack( + alignment: Alignment.center, + children: [ + MyVideoProgressIndicator( + _controller!, + allowScrubbing: false, + //padding: EdgeInsets.only(left: 60, right: 60), + ), + DefaultButton( + btnText!, + hasTimerEndedBool + ? () async { + Navigator.pop(context); + DashboardApiClient() + .setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, advertisementData?.actionButtonsColl![index].actionValue) + .then((value) { + logger.d(value); + }); + } + : null, + disabledColor: Colors.transparent, + textColor: !hasTimerEndedBool ? Colors.white.withOpacity(.5) : Colors.white, + ).paddingOnly(left: 60.0, right: 60.0, top: 8, bottom: 8), + ], + ); + } + return DefaultButton( + btnText!, + () async { + Navigator.pop(context); + DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, advertisementData?.actionButtonsColl![index].actionValue).then((value) { + logger.d(value); + }); + }, + ).paddingOnly(left: 60.0, right: 60.0, top: 8, bottom: 8); + }, + // gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + // crossAxisCount: 1, + // childAspectRatio: (7.0), + // ), + ); + // Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor)) + // .onPress(() { + // try { + // Navigator.pop(context); + // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Like").then((value) { + // logger.d(value); + // }); + // } catch (ex) { + // logger.wtf(ex); + // Utils.handleException(ex, context, null); + // } + // }), + // 20.width, + // Container( + // padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_down, color: MyColors.gradiantEndColor)) + // .onPress(() { + // try { + // Navigator.pop(context); + // DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Dislike").then((value) { + // logger.d(value); + // }); + // } catch (ex) { + // logger.wtf(ex); + // Utils.handleException(ex, context, null); + // } + // }), + // ], + // ); + // } else { + // return Container(); + // } }, ), 20.height, @@ -262,26 +345,91 @@ class _ITGAdsScreenState extends State { }, ), if (isImage) - Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.file(imageFile), - 50.height, - Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor)).onPress( - () { - try { - Navigator.pop(context); - DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Like").then((value) { - logger.d(value); - }); - } catch (ex) { - logger.wtf(ex); - Utils.handleException(ex, context, null); - } - }, - ), - ], + SingleChildScrollView( + padding: const EdgeInsets.only(top: 60, left: 12, right: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.network(imageUrl), + 50.height, + Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor)).onPress( + () { + try { + Navigator.pop(context); + DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!, "Like").then((value) { + logger.d(value); + }); + } catch (ex) { + logger.wtf(ex); + Utils.handleException(ex, context, null); + } + }, + ), + ], + ), + ), + if (isTextURL) + SingleChildScrollView( + padding: const EdgeInsets.all(21), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + (AppState().isArabic(context) ? advertisementData!.viewAttachFileColl![0].base64String! : advertisementData!.viewAttachFileColl![1].base64String!) + .toText16(color: MyColors.darkTextColor), + 24.height, + ListView.separated( + itemCount: advertisementData!.actionButtonsColl?.length ?? 0, + separatorBuilder: (cxt, index) => 16.height, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + itemBuilder: (cxt, index) => DefaultButton( + AppState().isArabic(context) ? advertisementData!.actionButtonsColl![index].btnTextAr : advertisementData!.actionButtonsColl![index].btnTextEn, + () async { + if (advertisementData!.actionButtonsColl![index].actionValue.toLowerCase() == "skip") { + Navigator.pop(context); + } else { + if (advertisementData!.actionButtonsColl![index].actionType!.toLowerCase() == 'redirect' && advertisementData!.actionButtonsColl![index].actionValue!.toLowerCase() == + 'external') { + Uri uri = Uri.parse(advertisementData!.actionButtonsColl![index].url!); + await launchUrl(uri, mode: LaunchMode.externalApplication).catchError((err) { + // print(err); + Utils.showToast('Could not launch'); + }); + Navigator.pop(context); + } else if (advertisementData!.actionButtonsColl![index].actionType!.toLowerCase() == 'redirect' && advertisementData!.actionButtonsColl![index].actionValue!.toLowerCase() == + 'internal') { + + await Navigator.pushNamed(context, advertisementData!.actionButtonsColl![index].url!); + + } else if(advertisementData!.actionButtonsColl![index].actionType!.toLowerCase() == 'eit' && advertisementData!.actionButtonsColl![index].actionValue!.toLowerCase() == + 'internal'){ + var pro = Provider.of(context, listen: false); + List _menuList = + pro.getMenuEntriesList?.where((element) => element.parentMenuName == advertisementData!.actionButtonsColl![index].url && (element.menuEntryType == "FUNCTION" || element.menuEntryType == "MENU")).toList() ?? []; + Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(advertisementData!.advertisementTitle!, _menuList)); + + } + else{ + Uri uri = Uri.parse(advertisementData!.actionButtonsColl![index].iconOrImage); + // if (await canLaunchUrl(uri)) { + await launchUrl(uri, mode: LaunchMode.externalApplication).catchError((err) { + // print(err); + Utils.showToast('Could not launch'); + }); + Navigator.pop(context); + // } else { + // Utils.showToast('Could not launch'); + // } + } + } + }, + ), + ), + ], + ), ), ], ), diff --git a/lib/ui/landing/itg/survey_screen.dart b/lib/ui/landing/itg/survey_screen.dart index 59f3c14..3bbb27f 100644 --- a/lib/ui/landing/itg/survey_screen.dart +++ b/lib/ui/landing/itg/survey_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -14,6 +15,8 @@ import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/itg/survey_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:flutter/widgets.dart' as fw; + class SurveyScreen extends StatefulWidget { const SurveyScreen({Key? key}) : super(key: key); @@ -46,29 +49,32 @@ class _SurveyScreenState extends State { body: Column( children: [ Expanded( - child: ListView( - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - 32.height, - itgResponseData?.survey?.title?.toText24() ?? const Text(""), - 8.height, - itgResponseData?.survey?.description?.toText16() ?? const Text(""), - ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: itgResponseData?.survey?.questions?.length, - itemBuilder: (cxt, index) { - return answeredQuestions.isNotEmpty ? getSurveyWidget(itgResponseData?.survey?.questions![index], index) : Container(); - }, - ), - ], - ).paddingOnly(left: 21, right: 21), - ), - ], + child: Directionality( + textDirection: AppState().isArabic(context) ? fw.TextDirection.rtl : fw.TextDirection.ltr, + child: ListView( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + 32.height, + (AppState().isArabic(context) ? itgResponseData?.survey?.titleAr : itgResponseData?.survey?.title)?.toText24() ?? const Text(""), + 8.height, + (AppState().isArabic(context) ? itgResponseData?.survey?.descriptionAr : itgResponseData?.survey?.description)?.toText16() ?? const Text(""), + ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: itgResponseData?.survey?.questions?.length, + itemBuilder: (cxt, index) { + return answeredQuestions.isNotEmpty ? getSurveyWidget(itgResponseData?.survey?.questions![index], index) : Container(); + }, + ), + ], + ).paddingOnly(left: 21, right: 21), + ), + ], + ), )), DefaultButton( LocaleKeys.submitSurvey.tr(), @@ -105,7 +111,7 @@ class _SurveyScreenState extends State { answeredQuestions.clear(); itgResponseData?.survey?.questions?.forEach((element) { if (element.type != "Stars") { - if(element.type == "Faces") { + if (element.type == "Faces") { _selectedIndex = element.options![0].optionId!; } answeredQuestions.add(element.options![0].optionId.toString()); @@ -122,15 +128,16 @@ class _SurveyScreenState extends State { return Column( children: [ 24.height, - question?.title?.toText18() ?? const Text(""), + (AppState().isArabic(context) ? question?.titleAr : question?.title)?.toText18() ?? const Text(""), 16.height, GridView.builder( padding: EdgeInsets.zero, - itemCount: question?.options?.length, + itemCount: question?.options?.length ?? 0, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { - return radioOption(question?.options?[index].title ?? "", question?.options?[index].optionId.toString() ?? "", answeredQuestions[parentIndex], parentIndex); + return radioOption((AppState().isArabic(context) ? (question!.options![index].titleAr) : question!.options![index].title) ?? "", question?.options?[index].optionId.toString() ?? "", + answeredQuestions[parentIndex], parentIndex); }, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, @@ -145,7 +152,7 @@ class _SurveyScreenState extends State { mainAxisSize: MainAxisSize.min, children: [ 24.height, - question?.title?.toText18() ?? Text(""), + (AppState().isArabic(context) ? question?.titleAr : question?.title)?.toText18() ?? Text(""), 16.height, RatingBar.builder( initialRating: 3, @@ -171,7 +178,7 @@ class _SurveyScreenState extends State { mainAxisSize: MainAxisSize.min, children: [ 24.height, - question?.title?.toText18() ?? Text("asdasdasdasd"), + (AppState().isArabic(context) ? question?.titleAr : question?.title)?.toText18() ?? Text(""), 16.height, GridView( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7), @@ -179,11 +186,13 @@ class _SurveyScreenState extends State { padding: const EdgeInsets.only(top: 0), shrinkWrap: true, children: [ - optionUI("poor.svg", question?.options?[0].optionId, parentIndex), - optionUI("bad.svg", question?.options?[1].optionId, parentIndex), - optionUI("normal.svg", question?.options?[2].optionId, parentIndex), - optionUI("good.svg", question?.options?[3].optionId, parentIndex), - optionUI("xcellent.svg", question?.options?[4].optionId, parentIndex), + for (int i = 0; i < (question?.options?.length ?? 0); i++) optionUI("${question?.options![i].title!.toLowerCase()}.svg", question?.options?[i].optionId, parentIndex), + + // optionUI("poor.svg", question?.options?[0].optionId, parentIndex), + // optionUI("fair.svg", question?.options?[1].optionId, parentIndex), + // optionUI("ok.svg", question?.options?[2].optionId, parentIndex), + // optionUI("good.svg", question?.options?[3].optionId, parentIndex), + // optionUI("excellent.svg", question?.options?[4].optionId, parentIndex), ], ), ], diff --git a/lib/ui/landing/widget/app_drawer.dart b/lib/ui/landing/widget/app_drawer.dart index 4721470..e18518b 100644 --- a/lib/ui/landing/widget/app_drawer.dart +++ b/lib/ui/landing/widget/app_drawer.dart @@ -120,7 +120,7 @@ class _AppDrawerState extends State { menuItem("assets/images/drawer/employee_id.svg", LocaleKeys.employeeDigitalID.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: EmployeeDigitialIdDialog())), if (AppState().businessCardPrivilege) menuItem("assets/images/drawer/view_business_card.svg", LocaleKeys.viewBusinessCard.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: BusinessCardDialog(), isBusniessCard: true)), - menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: performLogout), + menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: (){Utils.performLogout(context, chatData);}), // menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: () {Navigator.pushNamed(context, AppRoutes.survey,); ], ).expanded, @@ -171,13 +171,13 @@ class _AppDrawerState extends State { setState(() {}); } - void performLogout() async { - AppState().isAuthenticated = false; - AppState().isLogged = false; - AppState().setPostParamsInitConfig(); - chatData.disposeData(); - // SharedPreferences prefs = await SharedPreferences.getInstance(); - // await prefs.clear(); - Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: null); - } + // void performLogout() async { + // // AppState().isAuthenticated = false; + // // AppState().isLogged = false; + // // AppState().setPostParamsInitConfig(); + // // chatData.disposeData(); + // // // SharedPreferences prefs = await SharedPreferences.getInstance(); + // // // await prefs.clear(); + // // Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: null); + // } } diff --git a/lib/ui/landing/widget/menus_widget.dart b/lib/ui/landing/widget/menus_widget.dart index 64855ee..e764dca 100644 --- a/lib/ui/landing/widget/menus_widget.dart +++ b/lib/ui/landing/widget/menus_widget.dart @@ -1,13 +1,17 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:mohem_flutter_app/api/eit_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.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/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/screens/ticket/ticket_detailed_screen.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; @@ -27,114 +31,120 @@ class MenusWidget extends StatelessWidget { children: [ data.isWorkListLoading ? MenuShimmer().onPress(() { - data.fetchWorkListCounter(context, showLoading: true); - }) + data.fetchWorkListCounter(context, showLoading: true); + }) : Container( - decoration: BoxDecoration( - color: Color(namesColor[0]), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.workList.tr().toText12(color: Colors.white), - Row( - children: [ - Expanded( - child: data.workListCounter.toString().toText16(color: Colors.white, isBold: true, maxlines: 1), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), - ).onPress(() { - Navigator.pushNamed(context, AppRoutes.workList); - }), + decoration: BoxDecoration(color: Color(namesColor[0]), borderRadius: BorderRadius.circular(10)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.workList.tr().toText12(color: Colors.white), + Row( + children: [ + Expanded(child: data.workListCounter.toString().toText16(color: Colors.white, isBold: true, maxlines: 1)), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.workList); + }), data.isMissingSwipeLoading ? MenuShimmer().onPress(() { - data.fetchWorkListCounter(context); - }) + data.fetchWorkListCounter(context); + }) : Container( - decoration: BoxDecoration( - color: Color(namesColor[1]), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.missingSwipes.tr().toText12(color: Colors.white), - Row( - children: [ - Expanded( - child: data.missingSwipeCounter.toString().toText16(color: Colors.white, isBold: true, maxlines: 1), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), - ).onPress(() { - Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.missingSwipes.tr(), "HMG_OTL_MISSING_SWIPE_EIT_SS")); - }), + decoration: BoxDecoration(color: Color(namesColor[1]), borderRadius: BorderRadius.circular(10)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.missingSwipes.tr().toText12(color: Colors.white), + Row( + children: [ + Expanded(child: data.missingSwipeCounter.toString().toText16(color: Colors.white, isBold: true, maxlines: 1)), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.missingSwipes.tr(), "HMG_OTL_MISSING_SWIPE_EIT_SS")); + }), data.isLeaveTicketBalanceLoading ? MenuShimmer().onPress(() { - data.fetchWorkListCounter(context); - }) + data.fetchWorkListCounter(context); + }) : Container( - decoration: BoxDecoration( - color: Color(namesColor[2]), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.leaveBalance.tr().toText12(color: Colors.white), - Row( - children: [ - Expanded( - child: data.leaveBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), - ).onPress(() { - Navigator.pushNamed(context, AppRoutes.leaveBalance); - }), + decoration: BoxDecoration(color: Color(namesColor[2]), borderRadius: BorderRadius.circular(10)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.leaveBalance.tr().toText12(color: Colors.white), + Row( + children: [ + Expanded(child: data.leaveBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1)), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.leaveBalance); + }), data.isLeaveTicketBalanceLoading ? MenuShimmer().onPress(() { - data.fetchWorkListCounter(context); - }) + data.fetchWorkListCounter(context); + }) : Container( - decoration: BoxDecoration( - color: Color(namesColor[3]), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.ticketBalance.tr().toText12(color: Colors.white), - Row( - children: [ - Expanded( - child: data.ticketBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), - ).onPress( - () { - Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); - }, - ) + decoration: BoxDecoration(color: Color(namesColor[3]), borderRadius: BorderRadius.circular(10)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + data.ticketBookingResponse != null && data.ticketBookingResponse!.success + ? "Wallet Balance".toText12(color: Colors.white) + : LocaleKeys.ticketBalance.tr().toText12(color: Colors.white), + Row( + children: [ + Expanded( + child: + data.ticketBookingResponse != null && data.ticketBookingResponse!.success + ? data.walletBalance.toStringAsFixed(0).toText16(color: Colors.white, isBold: true, maxlines: 1) + : data.ticketBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1), + ), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), + ).onPress(() async { + Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); + + // var pro = Provider.of(context, listen: false); + // + // // if (menuEntry.menuName == "HMG_TICKET_REQUESTS") { + // Utils.showLoading(context); + // //Ticket Work + // if (pro.ticketBookingResponse != null && pro.ticketBookingResponse!.success) { + // SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: pro.ticketBookingResponse!.clientId); + // if (ssoToken != null) { + // dynamic url = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); + // await pro.fetchTicketAccuralBalance(context, DateTime.now()); + // pro.ticketHistoryTransactionList = await EITApiClient().getEITTransactions("HMG_TICKET_ITENARY_HR_EIT_SS", isCompleteList: true); + // + // Utils.hideLoading(context); + // // Here Need Work + // Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => TicketDetailedScreen(url: url, jwtToken: ssoToken.data!.accessToken))); + // } + // //} + // } else { + // Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); + // } + }), ], ); }, diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 7c19b58..0a30857 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -1,20 +1,59 @@ +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/api/eit_api_client.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/get_accural_ticket_balance_model.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/ui/screens/ticket/ticket_detailed_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'; 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 +65,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 +73,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 - ? ServicesMenuShimmer() + 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 + ? const 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 +232,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 +256,30 @@ 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") { + //Ticket Work + if (pro.ticketBookingResponse != null && pro.ticketBookingResponse!.success) { + Utils.showLoading(context); + SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: pro.ticketBookingResponse!.clientId); + if (ssoToken != null) { + dynamic url = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); + await pro.fetchTicketAccuralBalance(context, DateTime.now()); + pro.ticketHistoryTransactionList = await EITApiClient().getEITTransactions("HMG_TICKET_ITENARY_HR_EIT_SS", isCompleteList: true); + + Utils.hideLoading(context); + // Here Need Work + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => TicketDetailedScreen(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; } @@ -253,10 +310,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: const ServicesMenuShimmer()); }, separatorBuilder: (cxt, index) => 9.width, itemCount: 4, diff --git a/lib/ui/leave_balance/leave_balance_screen.dart b/lib/ui/leave_balance/leave_balance_screen.dart index 9fb925c..85354f9 100644 --- a/lib/ui/leave_balance/leave_balance_screen.dart +++ b/lib/ui/leave_balance/leave_balance_screen.dart @@ -64,47 +64,58 @@ class _LeaveBalanceState extends State { context, title: LocaleKeys.leaveBalance.tr(), ), - body: absenceTransList == null - ? const SizedBox() - : (absenceTransList!.isEmpty - ? Utils.getNoDataWidget(context).paddingOnly(top: 50) - : ListView( - physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.all(21), - children: [ - BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true, selectedEmp: employeeId, showLoading: false), - 12.height, - ListView.separated( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: EdgeInsets.zero, - itemBuilder: (cxt, int index) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.startDateT.tr(), absenceTransList![index].sTARTDATE ?? ""), - ItemDetailViewCol(LocaleKeys.endDateT.tr(), absenceTransList![index].eNDDATE ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.absenceType.tr(), absenceTransList![index].aBSENCETYPE ?? ""), - ItemDetailViewCol(LocaleKeys.absenceCategory.tr(), absenceTransList![index].aBSENCECATEGORY ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.days.tr(), absenceTransList![index].aBSENCEDAYS?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.hours.tr(), absenceTransList![index].aBSENCEHOURS?.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.approvalStatus.tr(), absenceTransList![index].aPPROVALSTATUS ?? ""), - ItemDetailViewCol(LocaleKeys.absenceStatus.tr(), absenceTransList![index].aBSENCESTATUS ?? ""), - isItLast: true, - ), - ], - ).objectContainerView(), - separatorBuilder: (cxt, index) => 12.height, - itemCount: absenceTransList!.length), - ], - )), + body:SingleChildScrollView(child:Column( + children: [ + Padding( + padding: const EdgeInsets.all(21.0), + child: BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true, selectedEmp: employeeId, showLoading: false), + ), + 12.height, + absenceTransList == null + ? const SizedBox() + : (absenceTransList!.isEmpty + ? Utils.getNoDataWidget(context).paddingOnly(top: 50) + : ListView( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.all(21), + + children: [ + // BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true, selectedEmp: employeeId, showLoading: false), + // 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: EdgeInsets.zero, + itemBuilder: (cxt, int index) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.startDateT.tr(), absenceTransList![index].sTARTDATE ?? ""), + ItemDetailViewCol(LocaleKeys.endDateT.tr(), absenceTransList![index].eNDDATE ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.absenceType.tr(), absenceTransList![index].aBSENCETYPE ?? ""), + ItemDetailViewCol(LocaleKeys.absenceCategory.tr(), absenceTransList![index].aBSENCECATEGORY ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.days.tr(), absenceTransList![index].aBSENCEDAYS?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.hours.tr(), absenceTransList![index].aBSENCEHOURS?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.approvalStatus.tr(), absenceTransList![index].aPPROVALSTATUS ?? ""), + ItemDetailViewCol(LocaleKeys.absenceStatus.tr(), absenceTransList![index].aBSENCESTATUS ?? ""), + isItLast: true, + ), + ], + ).objectContainerView(), + separatorBuilder: (cxt, index) => 12.height, + itemCount: absenceTransList!.length), + ], + )), + ], + )), floatingActionButton: Container( height: 54, width: 54, diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 94724fc..13d8853 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -17,17 +17,21 @@ import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/notifications.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; +import 'package:mohem_flutter_app/dialogs/otp_dialog.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/models/basic_member_information_model.dart'; import 'package:mohem_flutter_app/models/check_mobile_app_version_model.dart'; +import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/models/member_login_list_model.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/input_widget.dart'; +import 'package:safe_device/safe_device.dart'; // import 'package:safe_device/safe_device.dart'; import 'package:wifi_iot/wifi_iot.dart'; @@ -55,10 +59,12 @@ class _LoginScreenState extends State { bool? isAppOpenBySystem; bool isJailBroken = false; - bool isRealDevice = false; - bool isOnExternalStorage = false; + bool isRealDevice = true; bool isDevelopmentModeEnable = false; + BasicMemberInformationModel? _basicMemberInformation; + GenericResponseModel? genericResponseModel; + // late HmsApiAvailability hmsApiAvailability; @override @@ -66,26 +72,30 @@ class _LoginScreenState extends State { super.initState(); // hmsApiAvailability = HmsApiAvailability(); // checkFirebaseToken(); - // if (kReleaseMode) { - // checkDeviceSafety(); - // } + if (kReleaseMode) { + checkDeviceSafety(); + } } - // void checkDeviceSafety() async { - // try { - // isJailBroken = await SafeDevice.isJailBroken; - // isRealDevice = await SafeDevice.isRealDevice; - // if (Platform.isAndroid) { - // isOnExternalStorage = await SafeDevice.isOnExternalStorage; - // isDevelopmentModeEnable = await SafeDevice.isDevelopmentModeEnable; - // } - // if (isJailBroken || !isRealDevice || isOnExternalStorage || isDevelopmentModeEnable) { - // Navigator.pushNamedAndRemoveUntil(context, AppRoutes.unsafeDeviceScreen, (_) => false); - // } - // } catch (error) { - // print(error); - // } - // } + void checkDeviceSafety() { + try { + SafeDevice.isJailBroken.then((bool value) { + isJailBroken = value; + }); + SafeDevice.isRealDevice.then((value) { + isRealDevice = value; + }); + + if (Platform.isAndroid) { + // isOnExternalStorage = await SafeDevice.isOnExternalStorage; + // SafeDevice.isDevelopmentModeEnable.then((value) { + // isDevelopmentModeEnable = value; + // }); + } + } catch (error) { + print(error); + } + } @override void dispose() { @@ -110,10 +120,20 @@ class _LoginScreenState extends State { print("GOOGLE PLAY STOREEEE!!!!"); await Firebase.initializeApp(); _firebaseMessaging = FirebaseMessaging.instance; - firebaseToken = await _firebaseMessaging.getToken(); - print(firebaseToken); + try { + firebaseToken = await _firebaseMessaging.getToken(); + } catch (ex) { + firebaseToken = ""; + } AppNotifications().init(firebaseToken, context); - checkLoginInfo(); + + if (isJailBroken || !isRealDevice) { + Utils.hideLoading(context); + Navigator.pushNamedAndRemoveUntil(context, AppRoutes.unsafeDeviceScreen, (_) => false); + } else { + checkLoginInfo(); + } + await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true); } // }); @@ -191,6 +211,8 @@ class _LoginScreenState extends State { } Utils.saveStringFromPrefs(SharedPrefsConsts.password, password.text); } catch (ex) { + print(ex); + print(ex.toString()); Utils.hideLoading(context); Utils.handleException(ex, context, (msg) { Utils.confirmDialog( @@ -199,7 +221,8 @@ class _LoginScreenState extends State { onTap: () async { if (msg.toLowerCase().contains("password has expired")) { Navigator.pop(context); - await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: username.text); + // await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: username.text); + performForgotPassword(); } else { Navigator.pop(context); } @@ -209,6 +232,53 @@ class _LoginScreenState extends State { } } + void performForgotPassword() async { + // if (username.text.isEmpty) { + // return; + // } + Utils.showLoading(context); + try { + _basicMemberInformation = await LoginApiClient().getBasicUserInformation("CS", username.text); + genericResponseModel = await LoginApiClient().sendPublicActivationCode(_basicMemberInformation?.pMOBILENUMBER, username.text); + Utils.hideLoading(context); + OtpDialog( + context, + 1, + int.tryParse(_basicMemberInformation?.pMOBILENUMBER ?? ""), + (value, TextEditingController _pinPutController) async { + Utils.showLoading(context); + try { + GenericResponseModel? genericResponseModel = await LoginApiClient().checkPublicActivationCode(value, username.text); + if (genericResponseModel?.errorMessage != null) { + Utils.showToast(genericResponseModel?.errorMessage ?? ""); + return; + } + Utils.hideLoading(context); + await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: username.text); + Navigator.pop(context); + // Navigator.pop(context); + } catch (ex) { + print(ex); + _pinPutController.clear(); + otpFieldClear.value = ""; + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + }, + () => { + Navigator.pop(context), + }, + onResendCode: () { + performForgotPassword(); + }, + ).displayDialog(context); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + @override Widget build(BuildContext context) { if (isAppOpenBySystem == null) { @@ -277,9 +347,12 @@ class _LoginScreenState extends State { 9.height, Align( alignment: Alignment.centerRight, - child: LocaleKeys.forgotPassword.tr().toText12(isUnderLine: true, color: MyColors.textMixColor).onPress(() { - Navigator.pushNamed(context, AppRoutes.forgotPassword); - }), + child: LocaleKeys.forgotPassword.tr().toText12(isUnderLine: true, color: MyColors.textMixColor).onPress( + () { + // Navigator.pushNamed(context, AppRoutes.forgotPassword); + performForgotPassword(); + }, + ), ), 20.height, // DefaultButton( diff --git a/lib/ui/login/new_password_screen.dart b/lib/ui/login/new_password_screen.dart index 9efee64..70b7456 100644 --- a/lib/ui/login/new_password_screen.dart +++ b/lib/ui/login/new_password_screen.dart @@ -103,19 +103,19 @@ class _NewPasswordScreenState extends State { 8.height, passwordConstraintsUI(LocaleKeys.doNotAddRepeatingLetters.tr(), checkRepeatedChars(password.text)), // 8.height, - // passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')), + // passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'^[a-zA-Z0-9]+$')), 8.height, passwordConstraintsUI(LocaleKeys.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text), ], ).expanded, DefaultButton( - LocaleKeys.update.tr(), - (!isPasswordCompliant(password.text, 8)) - ? null - : () async { - setNewPassword(); - }) - .insideContainer + LocaleKeys.update.tr(), + (!isPasswordCompliant(password.text, 8)) + ? null + : () async { + setNewPassword(); + }, + ).insideContainer ], ), ); diff --git a/lib/ui/login/verify_last_login_screen.dart b/lib/ui/login/verify_last_login_screen.dart index c48d1f3..5c76092 100644 --- a/lib/ui/login/verify_last_login_screen.dart +++ b/lib/ui/login/verify_last_login_screen.dart @@ -4,8 +4,9 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:local_auth/auth_strings.dart'; import 'package:local_auth/local_auth.dart'; +import 'package:local_auth_darwin/local_auth_darwin.dart'; +import 'package:local_auth_android/local_auth_android.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -57,25 +58,30 @@ class _VerifyLastLoginScreenState extends State { @override Widget build(BuildContext context) { - mobileLoginInfoListModel ??= ModalRoute.of(context)!.settings.arguments as GetMobileLoginInfoListModel; - // String empName = AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; - String empName = mobileLoginInfoListModel!.employeeName!; + if (ModalRoute.of(context)!.settings.arguments != null) { + mobileLoginInfoListModel ??= ModalRoute.of(context)!.settings.arguments as GetMobileLoginInfoListModel; + // String empName = AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; + String empName = mobileLoginInfoListModel!.employeeName!; + } return Scaffold( appBar: AppBar( + surfaceTintColor: Colors.transparent, backgroundColor: Colors.transparent, automaticallyImplyLeading: false, title: (mobileLoginInfoListModel?.businessCardPrivilege ?? false) ? LocaleKeys.viewBusinessCard.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { - showMDialog(context, child: BusinessCardDialog()); + showMDialog(context, child: const BusinessCardDialog()); }) : Container(), actions: [ Center( - child: LocaleKeys.employeeDigitalID.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { - showMDialog(context, child: EmployeeDigitialIdDialog()); - })), - 21.width + + child: LocaleKeys.employeeDigitalID.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { + showMDialog(context, child: EmployeeDigitialIdDialog()); + }), + ), + 21.width, ], ), body: Column( @@ -91,7 +97,7 @@ class _VerifyLastLoginScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.welcomeBack.tr().toText12(), - mobileLoginInfoListModel!.employeeName!.toText24(isBold: true), + mobileLoginInfoListModel?.employeeName?.toText24(isBold: true) ?? const SizedBox.shrink(), 10.height, LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText16(), Container( @@ -99,24 +105,14 @@ class _VerifyLastLoginScreenState extends State { margin: const EdgeInsets.only(top: 23, bottom: 23), alignment: Alignment.center, padding: const EdgeInsets.only(left: 17, right: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, - border: Border.all( - color: const Color(0xffefefef), - width: 1, - ), - ), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, - children: [ - LocaleKeys.lastLoginDetails.tr().toText16(), - DateUtil.formatDateToDate(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn!), false).toText12(), - ], + children: [LocaleKeys.lastLoginDetails.tr().toText16(), DateUtil.formatDateToDate(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn ?? DateTime.now().toString()), false).toText12()], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -124,10 +120,10 @@ class _VerifyLastLoginScreenState extends State { children: [ LocaleKeys.verificationType.tr().toText10(color: MyColors.grey57Color), getVerificationType(mobileLoginInfoListModel!.loginType!).toText12(), - Expanded(child: SizedBox()), + const Expanded(child: SizedBox()), DateUtil.formatDateToTime(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn!)).toText12(), ], - ) + ), ], ), ), @@ -138,15 +134,10 @@ class _VerifyLastLoginScreenState extends State { physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.only(top: 9), shrinkWrap: true, - children: [ - if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(3), - if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(4), - getButton(2), - getButton(1), - ], - ) + children: [if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(3), if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(4), getButton(2), getButton(1)], + ), ], - ) + ), // else // Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Image.asset( @@ -184,12 +175,9 @@ class _VerifyLastLoginScreenState extends State { // ]), ], ).expanded, - DefaultButton( - LocaleKeys.useAnotherAccount.tr(), - () { - Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: false); - }, - ).insideContainer, + DefaultButton(LocaleKeys.useAnotherAccount.tr(), () { + Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: false); + }).insideContainer, ], ), ); @@ -219,11 +207,26 @@ class _VerifyLastLoginScreenState extends State { } Future loginWithFaceIDAndBiometrics() async { - IOSAuthMessages iosStrings = - const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); + + IOSAuthMessages iosStrings = const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); + + // IOSAuthMessages iosStrings = const IOSAuthMessages( + // cancelButton: 'cancel', + // goToSettingsButton: 'settings', + // goToSettingsDescription: 'Please set up your Touch ID.', + // lockOut: 'Please reenable your Touch ID', + // ); + bool authenticated = false; try { - authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, biometricOnly: true, iOSAuthStrings: iosStrings); + authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', options: const AuthenticationOptions( + useErrorDialogs: true, stickyAuth: true, biometricOnly: true, + ), + authMessages: [ + iosStrings, + const AndroidAuthMessages(), + ], + ); } on PlatformException catch (e) { print(e); Utils.hideLoading(context); @@ -233,7 +236,22 @@ class _VerifyLastLoginScreenState extends State { } Widget _loginOptionButton(String _title, String _icon, int _flag, int? _loginIndex) { - bool isDisable = ((_flag == 3 && !checkBiometricIsAvailable(BiometricType.face)) || (_flag == 4 && !checkBiometricIsAvailable(BiometricType.fingerprint))); +// <<<<<<< HEAD + bool isDisable = false; + if(_flag >= 3 && _flag <= 4) { + bool isFaceEnabled = (_flag == 3 && (checkBiometricIsAvailable(BiometricType.face) || + checkBiometricIsAvailable(BiometricType.weak))); + + bool isThumbEnabled = + (_flag == 4 && (checkBiometricIsAvailable(BiometricType.fingerprint) || + checkBiometricIsAvailable(BiometricType.strong))); + + isDisable = !(isFaceEnabled || isThumbEnabled); + } +// ======= +// bool isDisable = (_flag == 3 && !checkBiometricIsAvailable(BiometricType.face) || +// _flag == 4 && !checkBiometricIsAvailable(BiometricType.fingerprint) && _flag == 4 && !checkBiometricIsAvailable(BiometricType.face)); +// // >>>>>>> master return InkWell( onTap: isDisable ? null @@ -282,15 +300,7 @@ class _VerifyLastLoginScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SvgPicture.asset( - _icon, - height: 38, - width: 38, - color: isDisable ? MyColors.darkTextColor.withOpacity(0.7) : null, - ), - _title.toText16(height: 20/16) - ], + children: [SvgPicture.asset(_icon, height: 38, width: 38, color: isDisable ? MyColors.darkTextColor.withOpacity(0.7) : null), _title.toText16(height: 20 / 16)], ), ), ); @@ -334,8 +344,12 @@ class _VerifyLastLoginScreenState extends State { await LoginApiClient().checkMobileAppVersion(); await LoginApiClient().memberLogin(AppState().getUserName!, AppState().password!); if (!isDirectLogin) { - BasicMemberInformationModel? memberInformationModel = - await LoginApiClient().mohemmSendActivationCodeByOTPNotificationType(0, AppState().memberLoginList?.pMOBILENUMBER, sendVerificationFlat, AppState().getUserName); + BasicMemberInformationModel? memberInformationModel = await LoginApiClient().mohemmSendActivationCodeByOTPNotificationType( + 0, + AppState().memberLoginList?.pMOBILENUMBER, + sendVerificationFlat, + AppState().getUserName, + ); } if (isDirectLogin) performDirectApiCall(_title, _icon, _flag, "", null); if (!isDirectLogin) Utils.hideLoading(context); @@ -348,9 +362,7 @@ class _VerifyLastLoginScreenState extends State { Utils.showLoading(context); performDirectApiCall(_title, _icon, _flag, value, _pinPutController); }, - () => { - Navigator.pop(context), - }, + () => {Navigator.pop(context)}, onResendCode: () { performApiCall(_title, _icon, _flag, sendVerificationFlat, isDirectLogin: isDirectLogin); }, @@ -366,14 +378,15 @@ class _VerifyLastLoginScreenState extends State { try { GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(true, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW( - AppState().memberLoginList?.pEMAILADDRESS ?? "", - genericResponseModel?.pSESSIONID ?? 0, - genericResponseModel?.memberInformationList![0].eMPLOYEENAME ?? "", - _flag, - AppState().memberLoginList?.pMOBILENUMBER ?? "", - AppState().getUserName!, - AppState().getIsHuawei ? AppState().getHuaweiPushToken : mobileLoginInfoListModel!.deviceToken!, - Platform.isAndroid ? "android" : "ios"); + AppState().memberLoginList?.pEMAILADDRESS ?? "", + genericResponseModel?.pSESSIONID ?? 0, + genericResponseModel?.memberInformationList![0].eMPLOYEENAME ?? "", + _flag, + AppState().memberLoginList?.pMOBILENUMBER ?? "", + AppState().getUserName!, + AppState().getIsHuawei ? AppState().getHuaweiPushToken : mobileLoginInfoListModel!.deviceToken!, + Platform.isAndroid ? "android" : "ios", + ); AppState().setMemberInformationListModel = genericResponseModel!.memberInformationList?.first; AppState().setPrivilegeListModel = genericResponseModel!.privilegeList ?? []; if (genericResponseModel.errorMessage != null) { @@ -390,6 +403,13 @@ class _VerifyLastLoginScreenState extends State { } Utils.hideLoading(context); Utils.handleException(ex, context, null); + dynamic errorCode = ex; + if (errorCode.error.errorStatusCode == 699) { + Future.delayed(const Duration(seconds: 2), () { + Navigator.pop(context); + Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false); + }); + } } } @@ -404,5 +424,4 @@ class _VerifyLastLoginScreenState extends State { // // isLoading = isTrue; // }); // } - } diff --git a/lib/ui/login/verify_login_screen.dart b/lib/ui/login/verify_login_screen.dart index 0147472..e0015e0 100644 --- a/lib/ui/login/verify_login_screen.dart +++ b/lib/ui/login/verify_login_screen.dart @@ -4,7 +4,8 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:local_auth/auth_strings.dart'; +import 'package:local_auth_darwin/local_auth_darwin.dart'; +import 'package:local_auth_android/local_auth_android.dart'; import 'package:local_auth/local_auth.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; @@ -90,6 +91,7 @@ class _VerifyLoginScreenState extends State { Future _getAvailableBiometrics() async { try { _availableBioMetricType = await auth.getAvailableBiometrics(); + print("the available biometric are ${_availableBioMetricType.length}"); } on PlatformException catch (e) { // AppToast.showErrorToast(message: e.message); print(e); @@ -516,7 +518,11 @@ class _VerifyLoginScreenState extends State { const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); bool authenticated = false; try { - authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, biometricOnly: true, iOSAuthStrings: iosStrings); + authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', + options: const AuthenticationOptions(useErrorDialogs: true, stickyAuth: true, biometricOnly: true,), authMessages: [ + iosStrings, + const AndroidAuthMessages(), + ],); } on PlatformException catch (e) { print(e); Utils.hideLoading(context); @@ -526,7 +532,17 @@ class _VerifyLoginScreenState extends State { } Widget _loginOptionButton(String _title, String _icon, int _flag, int? _loginIndex) { - bool isDisable = ((_flag == 3 && !checkBiometricIsAvailable(BiometricType.face)) || (_flag == 4 && !checkBiometricIsAvailable(BiometricType.fingerprint))); + bool isDisable = false; + if(_flag >= 3 && _flag <= 4) { + bool isFaceEnabled = (_flag == 3 && (checkBiometricIsAvailable(BiometricType.face) || + checkBiometricIsAvailable(BiometricType.weak))); + + bool isThumbEnabled = + (_flag == 4 && (checkBiometricIsAvailable(BiometricType.fingerprint) || + checkBiometricIsAvailable(BiometricType.strong))); + + isDisable = !(isFaceEnabled || isThumbEnabled); + } return InkWell( onTap: isDisable ? null @@ -596,8 +612,13 @@ class _VerifyLoginScreenState extends State { bool checkBiometricIsAvailable(BiometricType biometricType) { bool isAvailable = false; + print("the given biometric is $biometricType"); + for (int i = 0; i < _availableBioMetricType.length; i++) { + print("the current biometric is ${_availableBioMetricType[i]}"); + if (biometricType == _availableBioMetricType[i]) { + print("the data is available $biometricType"); isAvailable = true; break; } @@ -654,6 +675,15 @@ class _VerifyLoginScreenState extends State { otpFieldClear.value = ""; Utils.hideLoading(context); Utils.handleException(ex, context, null); + dynamic errorCode = ex; + if(errorCode.error.errorStatusCode ==699){ + Future.delayed(const Duration(seconds: 2), () + { + Navigator.pop(context); + Navigator.pushNamedAndRemoveUntil( + context, AppRoutes.login, (Route route) => false); + }); + } } }, () => { diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index ed241af..ce8476b 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -14,6 +14,7 @@ import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_generic_model.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; import 'package:mohem_flutter_app/models/marathon/question_model.dart'; +import 'package:mohem_flutter_app/models/marathon/tutorial_notification_model.dart'; import 'package:mohem_flutter_app/models/marathon/winner_model.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; @@ -605,4 +606,15 @@ class MarathonProvider extends ChangeNotifier { AppState().setIsDemoMarathon = true; await callNextQuestionApi(); } + + bool isTutorialLoading = false; + TutorialNotificationModel? tutorial; + + Future getMarathonTutorial() async { + isTutorialLoading = true; + notifyListeners(); + tutorial = await MarathonApiClient().getMarathonTutorial(); + isTutorialLoading = false; + notifyListeners(); + } } diff --git a/lib/ui/marathon/marathon_tutorial_viewer_screen.dart b/lib/ui/marathon/marathon_tutorial_viewer_screen.dart new file mode 100644 index 0000000..0cdc8d8 --- /dev/null +++ b/lib/ui/marathon/marathon_tutorial_viewer_screen.dart @@ -0,0 +1,241 @@ +import 'dart:convert'; +import 'dart:io' as Io; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/index.dart'; +import 'package:lottie/lottie.dart'; +import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/file_process.dart'; +import 'package:mohem_flutter_app/classes/lottie_consts.dart'; +import 'package:mohem_flutter_app/classes/utils.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/itg/advertisement.dart' as ads; +import 'package:mohem_flutter_app/models/marathon/tutorial_notification_model.dart'; +import 'package:mohem_flutter_app/ui/chat/common.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:provider/provider.dart'; +import 'package:video_player/video_player.dart'; + +class MarathonTutorialViewerScreen extends StatefulWidget { + const MarathonTutorialViewerScreen({Key? key}) : super(key: key); + + @override + _MarathonTutorialViewerScreenState createState() => _MarathonTutorialViewerScreenState(); +} + +class _MarathonTutorialViewerScreenState extends State { + late Future _futureController; + VideoPlayerController? _controller; + bool skip = false; + + bool isVideo = false; + bool isImage = false; + bool isAudio = false; + bool isPdf = false; + + String link = ""; + + String ext = ''; + late File imageFile; + ads.Advertisement? advertisementData; + dynamic data; + String? masterID; + int videoDuration = 0; + + ValueNotifier videoLength = ValueNotifier(0); + + void checkFileTypes(String link) { + ext = "." + link.split(".").last.toLowerCase(); + if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif") { + isImage = true; + } else if (ext == ".pdf") { + isPdf = true; + } else { + if (ext == ".aac") { + isAudio = true; + } + isVideo = true; + _futureController = createVideoPlayer(link); + } + + setState(() {}); + } + + Future processImage(String encodedBytes) async { + try { + Uint8List decodedBytes = base64Decode(encodedBytes.split("base64,").last); + Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 + imageFile = Io.File("${appDocumentsDirectory.path}/addImage$ext"); + imageFile.writeAsBytesSync(decodedBytes); + } catch (e) { + logger.d(e); + } + } + + Future createVideoPlayer(String link) async { + try { + VideoPlayerController controller = VideoPlayerController.networkUrl(Uri.parse(link)); + await controller.initialize(); + await controller.play(); + await controller.setVolume(1.0); + await controller.setLooping(false); + controller.addListener(() { + controller.position.then((value) { + videoLength.value = value!.inMilliseconds; + // if(controller.value.isCompleted) { + // videoLength.value = 0; + // } + }); + }); + return controller; + } catch (e) { + print(e); + return VideoPlayerController.network("https://apimohemmweb.cloudsolutions.com.sa/ErmAttachment/compressedvideo.mp4"); + } + } + + bool showControls = false; + + void showVideoControls() { + showControls = !showControls; + setState(() {}); + } + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + _controller?.dispose(); + super.dispose(); + } + + TutorialNotificationModel? tutorial; + + @override + Widget build(BuildContext context) { + if (tutorial == null) { + tutorial ??= context.read().tutorial; + link = tutorial!.filePath!; + checkFileTypes(link); + } + + return Scaffold( + backgroundColor: Colors.black, + appBar: AppBarWidget(context, title: tutorial!.fileName!, showHomeButton: false), + body: Stack( + children: [ + if (isVideo) + FutureBuilder( + future: _futureController, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) { + _controller = snapshot.data as VideoPlayerController; + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: isAudio + ? Lottie.asset(MyLottieConsts.audioPlaybackLottie) + : AspectRatio( + aspectRatio: _controller!.value.aspectRatio, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + VideoPlayer(_controller!), + AnimatedContainer( + duration: const Duration(milliseconds: 250), + color: Colors.black.withOpacity(showControls ? .4 : .0), + child: AnimatedOpacity( + opacity: showControls ? 1 : 0, + duration: const Duration(milliseconds: 250), + child: Column( + children: [ + Icon(_controller!.value.isPlaying ? Icons.pause : Icons.play_arrow, color: Colors.white) + .onPress(() { + if (!showControls) { + showVideoControls(); + return; + } + + if (_controller!.value.isPlaying) { + _controller!.pause(); + } + // else if (_controller!.value.isCompleted) { + // videoLength.value = 0; + // _controller!.play(); + // } + else { + _controller!.play(); + } + setState(() {}); + }) + .center + .expanded, + ValueListenableBuilder( + valueListenable: videoLength, + builder: (context, val, child) { + return SeekBar( + duration: _controller!.value.duration, + position: Duration(milliseconds: val), + bufferedPosition: Duration(), + onChanged: (duration) { + _controller!.seekTo(duration); + }, + ); + }), + ], + ), + ), + ).onPress(() { + showVideoControls(); + }), + ], + ), + ), + ), + 30.height, + ], + ); + } else { + return const Center( + child: CircularProgressIndicator( + color: Colors.white, + ), + ); + } + }, + ), + if (isImage) Image.network(link).center, + if (isPdf) + DefaultButton(LocaleKeys.open.tr(), () async { + try { + Utils.showLoading(context); + await FileProcess.downloadFileFromUrl(link, tutorial!.fileName!).then((path) { + Utils.hideLoading(context); + FileProcess.openFile(path, isFullPath: true); + }); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + }).paddingAll(21).center + ], + ), + ); + } +} diff --git a/lib/ui/marathon/widgets/countdown_timer_main_screen.dart b/lib/ui/marathon/widgets/countdown_timer_main_screen.dart index ef828da..e9818c2 100644 --- a/lib/ui/marathon/widgets/countdown_timer_main_screen.dart +++ b/lib/ui/marathon/widgets/countdown_timer_main_screen.dart @@ -13,19 +13,15 @@ import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; class CountdownTimerForMainScreen extends StatelessWidget { final int timeToMarathon; final MarathonProvider provider; - + final bool isEvent; CountdownTimerForMainScreen({ Key? key, required this.provider, required this.timeToMarathon, + this.isEvent =false, }) : super(key: key); - final TextStyle styleTextHome = TextStyle( - color: MyColors.white.withOpacity(0.45), - fontStyle: FontStyle.italic, - fontWeight: FontWeight.w800, - letterSpacing: -0.4, - ); + final TextStyle styleDigitHome = TextStyle( height: 22 / 27, @@ -75,7 +71,13 @@ class CountdownTimerForMainScreen extends StatelessWidget { text, minFontSize: 7, maxFontSize: 8, - style: styleTextHome, + style: TextStyle( + color: isEvent ? MyColors.white : MyColors.white.withOpacity(0.45), + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w800, + letterSpacing: -0.4, + ), + ); } diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 20da2c8..00453b2 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/leave_balance_api_client.dart'; import 'package:mohem_flutter_app/api/my_attendance_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.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'; @@ -20,6 +21,8 @@ import 'package:mohem_flutter_app/models/submit_eit_transaction_list_model.dart' import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; @@ -36,7 +39,7 @@ class _DynamicInputScreenState extends State { GenericResponseModel? genericResponseModel; List? getEitDffStructureList; DynamicListViewParams? dynamicParams; - + String? selectedReplacementEmployee; @override void initState() { super.initState(); @@ -45,10 +48,17 @@ class _DynamicInputScreenState extends State { void getTransactionsStructure() async { try { Utils.showLoading(context); - genericResponseModel = await MyAttendanceApiClient().getEitDffStructure(dynamicParams!.dynamicId, dynamicParams!.selectedEmp); + if (dynamicParams?.pContactRelationshipId == null) { + genericResponseModel = await MyAttendanceApiClient().getEitDffStructure(dynamicParams!.dynamicId, dynamicParams!.selectedEmp); + getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; + } else { + genericResponseModel = await MyAttendanceApiClient().getCEIDffStructure(dynamicParams!.dynamicId, null); + getEitDffStructureList = genericResponseModel?.getCEIDFFStructureList ?? []; + } + dESCFLEXCONTEXTCODE = genericResponseModel!.pDESCFLEXCONTEXTCODE ?? ""; descFlexConTextTitle = genericResponseModel!.pDESCFLEXCONTEXTNAME ?? ""; - getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; + // getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; //getEitDffStructureList = getEitDffStructureList!.where((element) => element.dISPLAYFLAG != "N").toList(); Utils.hideLoading(context); setState(() {}); @@ -85,18 +95,29 @@ class _DynamicInputScreenState extends State { // } // } // } - return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: tempVar.toString()).toJson(); + return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: DateUtil.replaceArabicNumber(tempVar)).toJson(); }).toList(); values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_ACTION", nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: "NEW_ROW").toJson()); - values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_EXTRA_INFO_ID", nUMBERVALUE: -1, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); - values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); - genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp); - SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp); + if (dynamicParams!.pContactRelationshipId == null) { + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_EXTRA_INFO_ID", nUMBERVALUE: -1, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); + } else { + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "CONTACT_EXTRA_INFO_ID", nUMBERVALUE: -1, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "CEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); + } + SubmitEITTransactionList submitEITTransactionList; + if (dynamicParams!.pContactRelationshipId == null) { + genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp); + submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp); + } else { + submitEITTransactionList = await MyAttendanceApiClient().submitCEITransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, pContactRelationID: dynamicParams!.pContactRelationshipId); + } Utils.hideLoading(context); await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, - arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit',isAttachmentMandatory: dynamicParams!.isAttachmentMandatory)); + arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit', + isAttachmentMandatory: dynamicParams!.isAttachmentMandatory)); if (!AppState().cancelRequestTrancsection) { return; } @@ -132,8 +153,27 @@ class _DynamicInputScreenState extends State { .toJson()) .toList(); + String? selectedEmp = dynamicParams!.selectedEmp; + bool hasParentId = false; + + if (segmentId.isNotEmpty && selectedEmp == null) { + for (var element in getEitDffStructureList!) { + try { + if (element.sEGMENTNAME == segmentId && selectedEmp == null) { + var selectedElement = element; + if (selectedElement.vALIDATIONTYPE == "Y" || selectedElement.vALIDATIONTYPE == "D") { + hasParentId = true; + break; + } + } + } catch (ex) { + print("err:$ex"); + } + } + } + List eServicesResponseModel = await MyAttendanceApiClient().getValueSetValues(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values, - empID: dynamicParams!.selectedEmp, parentValue: structureList.eSERVICESDV!.pVALUECOLUMNNAME); + empID: selectedEmp, parentValue: structureList.eSERVICESDV!.pVALUECOLUMNNAME, hasParent: hasParentId); List abc = genericResponseModel?.getEITDFFStructureList ?? []; getEitDffStructureList = abc; int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); @@ -646,42 +686,96 @@ class _DynamicInputScreenState extends State { ).paddingOnly(bottom: 12); } } else { - return PopupMenuButton( - child: DynamicTextFieldWidget( - (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), - model.eSERVICESDV?.pVALUECOLUMNNAME ?? "", - isEnable: false, - isPopup: true, - isInputTypeNum: true, - isReadOnly: model.rEADONLY == "Y", - ).paddingOnly(bottom: 12), - itemBuilder: (_) => >[ - if (model.rEADONLY != "Y") - for (int i = 0; i < model.eSERVICESVS!.length; i++) - PopupMenuItem( - value: i, - child: Column( - children: [ - Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), - const PopupMenuDivider(), - ], - )), - ], - onSelected: (int popipIndex) async { - ESERVICESDV eservicesdv = ESERVICESDV( - pIDCOLUMNNAME: model.eSERVICESVS![popipIndex].iDCOLUMNNAME, - pRETURNMSG: "null", - pRETURNSTATUS: "null", //getEitDffStructureList![popipIndex].dEFAULTVALUE, - pVALUECOLUMNNAME: model.eSERVICESVS![popipIndex].vALUECOLUMNNAME); - getEitDffStructureList![index].eSERVICESDV = eservicesdv; - setState(() {}); - if (model.cHILDSEGMENTSVSSplited?.isNotEmpty ?? false) { - await calGetValueSetValues(model); - } - if (model.cHILDSEGMENTSDVSplited?.isNotEmpty ?? false) { - await getDefaultValues(model); - } - }); + //condition need to be added here. + if(model.vSSRCHFLAG =='Y'){ + return DynamicTextFieldWidget( + LocaleKeys.selectEmployee.tr(), + "", + // selectedReplacementEmployee == null ? LocaleKeys.searchForEmployee + // .tr() : selectedReplacementEmployee!.employeeDisplayName ?? "", + isEnable: false, + onTap: () { + showMyBottomSheet( + context, + + callBackFunc: () {}, + child: SearchEmployeeBottomSheet( + title: LocaleKeys.searchForEmployee.tr(), + apiMode: LocaleKeys.delegate.tr(), + fromDynamicScreen: true, + fromChat: false, + onSelectEmployee: (_selectedEmployee) { + // Navigator.pop(context); + // selectedReplacementEmployee = _selectedEmployee; + ESERVICESDV eservicesdv = ESERVICESDV( + pIDCOLUMNNAME:_selectedEmployee.userName, + pRETURNMSG: "null", + pRETURNSTATUS: "null", //getEitDffStructureList![popipIndex].dEFAULTVALUE, + pVALUECOLUMNNAME:_selectedEmployee.employeeDisplayName); + getEitDffStructureList![index].eSERVICESDV = eservicesdv; + + setState(() {}); + }, + onSearchClick: (String empID) async{ + ESERVICESDV eservicesdv = + ESERVICESDV(pSRCHVALUECOLUMNNAME: empID, pRETURNMSG: "null", pRETURNSTATUS: "null", pVALUECOLUMNNAME: ""); + getEitDffStructureList![index].eSERVICESDV = eservicesdv; + setState(() {}); + if (model.cHILDSEGMENTSVSSplited?.isNotEmpty ?? false) { + await calGetValueSetValuesSearch(model, empID); + } + if (model.cHILDSEGMENTSDVSplited?.isNotEmpty ?? false) { + await getDefaultValues(model); + } + + }, + ), + ); + }, + ); + + }else { + return PopupMenuButton( + child: DynamicTextFieldWidget( + (model.sEGMENTPROMPT ?? "") + + (model.rEQUIREDFLAG == "Y" ? "*" : ""), + model.eSERVICESDV?.pVALUECOLUMNNAME ?? "", + isEnable: false, + isPopup: true, + isInputTypeNum: true, + isReadOnly: model.rEADONLY == "Y", + ).paddingOnly(bottom: 12), + itemBuilder: (_) => + >[ + if (model.rEADONLY != "Y") + for (int i = 0; i < model.eSERVICESVS!.length; i++) + PopupMenuItem( + value: i, + child: Column( + children: [ + Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), + const PopupMenuDivider(), + ], + )), + ], + onSelected: (int popipIndex) async { + ESERVICESDV eservicesdv = ESERVICESDV( + pIDCOLUMNNAME: model.eSERVICESVS![popipIndex].iDCOLUMNNAME, + pRETURNMSG: "null", + pRETURNSTATUS: "null", + //getEitDffStructureList![popipIndex].dEFAULTVALUE, + pVALUECOLUMNNAME: model.eSERVICESVS![popipIndex] + .vALUECOLUMNNAME); + getEitDffStructureList![index].eSERVICESDV = eservicesdv; + setState(() {}); + if (model.cHILDSEGMENTSVSSplited?.isNotEmpty ?? false) { + await calGetValueSetValues(model); + } + if (model.cHILDSEGMENTSDVSplited?.isNotEmpty ?? false) { + await getDefaultValues(model); + } + }); + } } } else { return const SizedBox(); @@ -773,7 +867,7 @@ class _DynamicInputScreenState extends State { onTap: () async { if ((getEitDffStructureList![index].eSERVICESDV?.pVALUECOLUMNNAME != null)) { var timeString = getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!.split(":"); - selectedDate = DateTime(0, 0, 0, int.parse(timeString[0]), int.parse(timeString[1])); + selectedDate = DateTime(0, 0, 0, int.parse(timeString[0]), int.parse((timeString[1]))); //DateTime.parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!); } @@ -861,7 +955,8 @@ class _DynamicInputScreenState extends State { context: context, initialTime: time, builder: (cxt, child) { - return MediaQuery(data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true), child: child ?? Container()); + return MediaQuery( + data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true), child: Localizations.override(context: context, locale: const Locale('en', 'US'), child: child ?? Container())); }); if (picked != null && picked != time) { @@ -875,4 +970,65 @@ class _DynamicInputScreenState extends State { } return time; } + Future calGetValueSetValuesSearch(GetEITDFFStructureList structureList,String userID, {bool showLoading = true}) async { + try { + if (showLoading) Utils.showLoading(context); + for (int i = 0; i < (structureList.cHILDSEGMENTSVSSplited?.length ?? 0); i++) { + List> values = []; + String segmentId = structureList.cHILDSEGMENTSVSSplited![i]; + + if (dESCFLEXCONTEXTCODE.isEmpty) dESCFLEXCONTEXTCODE = structureList.dESCFLEXCONTEXTCODE!; + List filteredList = getEitDffStructureList?.where((element) => element.cHILDSEGMENTSVSSplited!.contains(segmentId)).toList() ?? []; + + if (filteredList.isEmpty && structureList.cHILDSEGMENTSVSSplited!.isNotEmpty) { + segmentId = structureList.cHILDSEGMENTSVSSplited![0]; + filteredList = getEitDffStructureList?.where((element) => element.cHILDSEGMENTSVSSplited!.contains(segmentId)).toList() ?? []; + } + values = filteredList + .map((e) => GetSetValuesRequestModel( + sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME, pSRCHVALUECOLUMNNAME: userID ) + .toJson()) + .toList(); + + String? selectedEmp = dynamicParams!.selectedEmp; + bool hasParentId = false; + + if (segmentId.isNotEmpty && selectedEmp == null) { + for (var element in getEitDffStructureList!) { + try { + if (element.sEGMENTNAME == segmentId && selectedEmp == null) { + var selectedElement = element; + if (selectedElement.vALIDATIONTYPE == "Y" || selectedElement.vALIDATIONTYPE == "D") { + hasParentId = true; + break; + } + } + } catch (ex) { + print("err:$ex"); + } + } + } + + List eServicesResponseModel = await MyAttendanceApiClient().getValueSetValuesSearch(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values, + empID: selectedEmp, parentValue: structureList.eSERVICESDV!.pVALUECOLUMNNAME, hasParent: hasParentId); + List abc = genericResponseModel?.getEITDFFStructureList ?? []; + getEitDffStructureList = abc; + int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); + getEitDffStructureList![index].eSERVICESVS!.clear(); + getEitDffStructureList![index].eSERVICESDV = ESERVICESDV(); + if (eServicesResponseModel.isNotEmpty) getEitDffStructureList![index].eSERVICESVS!.addAll(eServicesResponseModel); + // getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; + //getEitDffStructureList = getEitDffStructureList!.where((element) => element.dISPLAYFLAG != "N").toList(); + } + if (showLoading) { + await Future.delayed(const Duration(seconds: 1)); + Utils.hideLoading(context); + } + + setState(() {}); + } catch (ex) { + if (showLoading) Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } } diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index 94a201f..54b250d 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -24,11 +24,13 @@ class DynamicListViewParams { List? collectionNotificationList; final String? selectedEmp; + final int? pContactRelationshipId; DynamicListViewParams( this.title, this.dynamicId, { this.selectedEmp, + this.pContactRelationshipId, this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = '', this.colsURL = '', @@ -59,10 +61,14 @@ class _DynamicListViewScreenState extends State { super.initState(); } - void getTransactions() async { + void getTransactions({bool isCei = false}) async { try { Utils.showLoading(context); - getEITTransactionList = await MyAttendanceApiClient().getEitTransaction(dynamicParams!.dynamicId, dynamicParams!.selectedEmp); + if (isCei) { + getEITTransactionList = await MyAttendanceApiClient().getCeiTransaction(dynamicParams!.dynamicId, dynamicParams!.pContactRelationshipId); + } else { + getEITTransactionList = await MyAttendanceApiClient().getEitTransaction(dynamicParams!.dynamicId, dynamicParams!.selectedEmp); + } getEITTransactionList?.forEach((element) { element.collectionTransaction = element.collectionTransaction?.where((elemen) => elemen.dISPLAYFLAG == "Y").toList() ?? []; }); @@ -97,8 +103,13 @@ class _DynamicListViewScreenState extends State { Widget build(BuildContext context) { if (dynamicParams == null) { dynamicParams = ModalRoute.of(context)!.settings.arguments as DynamicListViewParams; - isTicketRequest = dynamicParams!.dynamicId == "HMG_TKT_NEW_EIT_SS"; - getTransactions(); + if (dynamicParams?.pContactRelationshipId == null) { + isTicketRequest = dynamicParams!.dynamicId == "HMG_TKT_NEW_EIT_SS"; + getTransactions(); + } else { + isTicketRequest = false; + getTransactions(isCei: true); + } } Widget dataWidget = ListView( physics: const BouncingScrollPhysics(), diff --git a/lib/ui/my_attendance/services_menu_list_screen.dart b/lib/ui/my_attendance/services_menu_list_screen.dart index 44aac6a..a074cad 100644 --- a/lib/ui/my_attendance/services_menu_list_screen.dart +++ b/lib/ui/my_attendance/services_menu_list_screen.dart @@ -64,6 +64,8 @@ class ServicesMenuListScreen extends StatelessWidget { if (servicesMenuData.list[index].requestType == "EIT") { Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(servicesMenuData.list[index].prompt!, servicesMenuData.list[index].functionName!, selectedEmp: servicesMenuData.selectedEmp)); + } else if (servicesMenuData.list[index].requestType == "CEI") { + Navigator.pushNamed(context, AppRoutes.childEducation, arguments: servicesMenuData.list[index]); } else { if (servicesMenuData.list[index].requestType == "TERMINATION") { Navigator.pushNamed(context, AppRoutes.endEmploymentScreen, diff --git a/lib/ui/my_team/view_attendance.dart b/lib/ui/my_team/view_attendance.dart index a45f35c..96e673d 100644 --- a/lib/ui/my_team/view_attendance.dart +++ b/lib/ui/my_team/view_attendance.dart @@ -15,7 +15,7 @@ import 'package:mohem_flutter_app/models/get_time_card_summary_list_model.dart'; import 'package:mohem_flutter_app/models/my_team/get_employee_subordinates_list.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/circular_step_progress_bar.dart'; -import 'package:month_picker_dialog_2/month_picker_dialog_2.dart'; +import 'package:month_picker_dialog/month_picker_dialog.dart'; import 'package:pie_chart/pie_chart.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; @@ -169,8 +169,6 @@ class _ViewAttendanceState extends State { initialDate: formattedDate, firstDate: DateTime(searchYear - 2), lastDate: DateTime.now(), - confirmText: Text(LocaleKeys.confirm.tr()), - cancelText: Text(LocaleKeys.cancel.tr()), ).then( (selectedDate) { if (selectedDate != null) { diff --git a/lib/ui/parking_qr/parking_qr.dart b/lib/ui/parking_qr/parking_qr.dart new file mode 100644 index 0000000..641f84a --- /dev/null +++ b/lib/ui/parking_qr/parking_qr.dart @@ -0,0 +1,106 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/get_employee_parking_details_model.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; + +class ParkingQrScreen extends StatefulWidget { + const ParkingQrScreen({Key? key}) : super(key: key); + + @override + _RequestDetailsState createState() => _RequestDetailsState(); +} + +class _RequestDetailsState extends State { + GetEmployeeParking? qrData; + + @override + void initState() { + super.initState(); + getTicketDetails(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget(context, title: LocaleKeys.parkingQr.tr()), + body: + qrData?.getEmployeeParking == null + ? Center(child: Text(LocaleKeys.noDataAvailable.tr())) + : SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Center( + child: Container( + padding: const EdgeInsets.all(20.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [BoxShadow(color: Colors.grey.withValues(alpha: 0.2), spreadRadius: 5, blurRadius: 10, offset: const Offset(0, 3))], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // QR Code Image + if (qrData!.getEmployeeParking!.qrCodeImageBase64 != null && qrData!.getEmployeeParking!.qrCodeImageBase64!.isNotEmpty) + Image.memory(Utils.dataFromBase64String(qrData!.getEmployeeParking!.qrCodeImageBase64!), width: 300, height: 300, fit: BoxFit.contain) + else + Container( + width: 300, + height: 300, + color: MyColors.lightGreyEFColor, + child: Center(child: Text(LocaleKeys.noDataAvailable.tr(), style: const TextStyle(color: MyColors.grey67Color))), + ), + 10.height, + Container(height: 1, color: MyColors.lightGreyE3Color, margin: const EdgeInsets.symmetric(vertical: 10)), + 20.height, + SizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Employee Code + if (qrData!.getEmployeeParking!.employeeCode != null && qrData!.getEmployeeParking!.employeeCode!.isNotEmpty) ...[ + Text(LocaleKeys.employeeNumber.tr(), style: const TextStyle(fontSize: 14, color: MyColors.grey67Color, fontWeight: FontWeight.w400)), + 8.height, + Text(qrData!.getEmployeeParking!.employeeCode!, style: const TextStyle(fontSize: 18, color: MyColors.darkTextColor, fontWeight: FontWeight.w600)), + 8.height, + ], + if (qrData!.getEmployeeParking!.createdAt != null) ...[ + Text(LocaleKeys.creationDate.tr(), style: const TextStyle(fontSize: 14, color: MyColors.grey67Color, fontWeight: FontWeight.w400)), + 8.height, + Text( + DateFormat('dd MMM yyyy, hh:mm a').format(qrData!.getEmployeeParking!.createdAt!), + style: const TextStyle(fontSize: 16, color: MyColors.darkTextColor, fontWeight: FontWeight.w500), + ), + ], + ], + ), + ), + ], + ), + ), + ), + ), + ), + ); + } + + void getTicketDetails() async { + try { + Utils.showLoading(context); + qrData = await DashboardApiClient().getEmployeeParkingQrCode(); + Utils.hideLoading(context); + setState(() {}); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } +} diff --git a/lib/ui/profile/delete_family_member.dart b/lib/ui/profile/delete_family_member.dart index 3b73512..f478b53 100644 --- a/lib/ui/profile/delete_family_member.dart +++ b/lib/ui/profile/delete_family_member.dart @@ -115,8 +115,8 @@ class _DeleteFamilyMemberState extends State { padding: EdgeInsets.only(left: 50, right: 50), child: TextButton( style: TextButton.styleFrom( - primary: MyColors.white, - onSurface: MyColors.white, + foregroundColor: MyColors.white, + surfaceTintColor: MyColors.white, backgroundColor: MyColors.gradiantEndColor, ), onPressed: () { diff --git a/lib/ui/screens/child_education/child_education_assistance.dart b/lib/ui/screens/child_education/child_education_assistance.dart new file mode 100644 index 0000000..283dab3 --- /dev/null +++ b/lib/ui/screens/child_education/child_education_assistance.dart @@ -0,0 +1,58 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/profile_api_client.dart'; +import 'package:mohem_flutter_app/classes/colors.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/models/dashboard/menu_entries.dart'; +import 'package:mohem_flutter_app/models/get_employee_contacts.model.dart'; +import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; + +class ChildEducationAssistance extends StatelessWidget { + ChildEducationAssistance({Key? key}) : super(key: key); + + GetMenuEntriesList? menuEntry; + + @override + Widget build(BuildContext context) { + menuEntry ??= ModalRoute.of(context)!.settings.arguments as GetMenuEntriesList; + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget(context, title: menuEntry!.prompt!), + body: FutureBuilder( + future: ProfileApiClient().getEmployeeContacts(), + builder: (BuildContext cxt, AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasData) { + List empContactList = snapshot.data!; + return ListView.separated( + padding: const EdgeInsets.all(21), + separatorBuilder: (BuildContext cxt, int index) => 12.height, + itemCount: empContactList.length, + itemBuilder: (BuildContext context, int index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + "${empContactList[index].cONTACTNAME}".toText16(color: MyColors.grey3AColor), + "${LocaleKeys.dateOfBirth.tr()}: ${empContactList[index].dATEOFBIRTH?.split(" ").first ?? ""}".toText14(color: MyColors.grey3AColor, weight: FontWeight.w400), + "${empContactList[index].rELATIONSHIP}".toText11(color: MyColors.textMixColor), + ], + ).objectContainerView(disablePadding: false, center: false).onPress(() { + Navigator.pushNamed(context, AppRoutes.dynamicScreen, + arguments: DynamicListViewParams(empContactList[index].cONTACTNAME!, menuEntry!.functionName!, pContactRelationshipId: empContactList[index].cONTACTRELATIONSHIPID)); + }); + }); + } else { + return LocaleKeys.noDataAvailable.tr().toText16().center; + } + }, + ), + ); + } +} diff --git a/lib/ui/screens/courses/courses_screen.dart b/lib/ui/screens/courses/courses_screen.dart new file mode 100644 index 0000000..598b6cf --- /dev/null +++ b/lib/ui/screens/courses/courses_screen.dart @@ -0,0 +1,333 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/inAppWebView.dart'; +import 'package:mohem_flutter_app/classes/utils.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/models/dashboard/courses_response_model.dart'; +import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/theme/colors.dart' as theme_colors; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/sso_webview_widget.dart'; +import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +class CoursesScreen extends StatefulWidget { + const CoursesScreen({Key? key}) : super(key: key); + + @override + _CoursesScreenState createState() => _CoursesScreenState(); +} + +class _CoursesScreenState extends State { + late DashboardProviderModel data; + final RefreshController _refreshController = RefreshController(initialRefresh: false); + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + data = Provider.of(context, listen: false); + _onRefresh(); + }); + } + + void _onRefresh() async { + await data.fetchCourses(context); + _refreshController.refreshCompleted(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBarWidget( + context, + title: LocaleKeys.courses.tr(), + ), + body: Consumer( + builder: (context, provider, child) { + return SmartRefresher( + enablePullDown: true, + enablePullUp: false, + controller: _refreshController, + onRefresh: _onRefresh, + child: provider.isCoursesLoading + ? _buildShimmerLoading() + : provider.coursesList.isEmpty + ? _buildEmptyState() + : _buildCoursesList(provider.coursesList), + ); + }, + ), + ); + } + + Widget _buildShimmerLoading() { + return ListView.builder( + padding: const EdgeInsets.all(21), + itemCount: 5, + itemBuilder: (context, index) { + return Container( + margin: const EdgeInsets.only(bottom: 12), + height: 150, + 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( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 20, + width: 200, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(4), + ), + ).toShimmer(), + 12.height, + Container( + height: 14, + width: 100, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(4), + ), + ).toShimmer(), + const Spacer(), + Container( + height: 40, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(6), + ), + ).toShimmer(), + ], + ).paddingAll(14), + ); + }, + ); + } + + Widget _buildEmptyState() { + return Utils.getNoDataWidget(context); + } + + Widget _buildCoursesList(List courses) { + return ListView.separated( + physics: const BouncingScrollPhysics(), + shrinkWrap: true, + padding: const EdgeInsets.all(21), + itemBuilder: (BuildContext context, int index) { + return _buildCourseCard(courses[index]); + }, + separatorBuilder: (BuildContext context, int index) => 12.height, + itemCount: courses.length, + ); + } + + Widget _buildCourseCard(CourseStatus course) { + bool isArabic = AppState().isArabic(context); + String courseName = isArabic && course.cNameAr != null && course.cNameAr!.isNotEmpty + ? course.cNameAr! + : course.cFullname ?? ''; + + String status = course.cStatus ?? 'Unknown'; + Color statusColor = _getStatusColor(status); + + return InkWell( + onTap: () => _openCourse(course.cUrl, course.token), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Course Title + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: MyColors.lightGreyEFColor, + borderRadius: BorderRadius.circular(8), + ), + child: const Icon( + Icons.school_rounded, + color: MyColors.gradiantStartColor, + size: 20, + ), + ), + 12.width, + Expanded( + child: courseName.toText14(isBold: true, color: MyColors.darkTextColor), + ), + ], + ), + 12.height, + // Status Badge + Row( + children: [ + Icon( + _getStatusIcon(status), + size: 16, + color: statusColor, + ), + 6.width, + LocaleKeys.status.tr().toText11(color: MyColors.grey98Color), + 8.width, + Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: statusColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: statusColor.withOpacity(0.3), + width: 1, + ), + ), + child: status.toText10(color: statusColor, isBold: true), + ), + ], + ), + 10.height, + // Start Date + if (course.cEnddate != null && course.cEnddate!.isNotEmpty) + Row( + children: [ + const Icon( + Icons.calendar_month_rounded, + size: 16, + color: MyColors.darkIconColor, + ), + 6.width, + LocaleKeys.endDateT.tr().toText11(color: MyColors.grey98Color), + 8.width, + Expanded( + child: _formatDate(course.cEnddate!).toText11( + color: MyColors.darkTextColor, + isBold: true, + ), + ), + ], + ), + if (course.cStartdate != null && course.cStartdate!.isNotEmpty) 14.height, + // Open Button + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + LocaleKeys.open.tr().toText12(color: MyColors.gradiantStartColor, isUnderLine: true), + 6.width, + RotatedBox( + quarterTurns: AppState().isArabic(context) ? 2 : 4, + child: SvgPicture.asset( + "assets/images/arrow_next.svg", + color: MyColors.gradiantStartColor, + width: 16, + height: 16, + ), + ), + ], + ), + ], + ).objectContainerView(), + ); + } + + + IconData _getStatusIcon(String status) { + if (status.toLowerCase().contains('passed')) { + return Icons.check_circle_rounded; + } else if (status.toLowerCase().contains('not passed') || status.toLowerCase().contains('failed')) { + return Icons.cancel_rounded; + } else if (status.toLowerCase().contains('in progress')) { + return Icons.pending_rounded; + } else { + return Icons.info_rounded; + } + } + + Color _getStatusColor(String status) { + if (status.toLowerCase().contains('passed') && !status.toLowerCase().contains('not passed')) { + return Colors.green; + } else if (status.toLowerCase().contains('not passed') || status.toLowerCase().contains('failed')) { + return Colors.red; + } else if (status.toLowerCase().contains('in progress')) { + return Colors.yellow[700]!; + } else { + return MyColors.grey98Color; + } + } + + DateTime? _parseDate(String? date) { + if (date == null || date.isEmpty) return null; + try { + return DateTime.parse(date.replaceAll(' ', 'T')); + } catch (e) { + try { + DateFormat format = DateFormat('yyyy-MM-dd HH:mm:ss'); + return format.parse(date); + } catch (e) { + return null; + } + } + } + + String _formatDate(String date) { + DateTime? dateTime = _parseDate(date); + if (dateTime == null) return date; + + bool isArabic = AppState().isArabic(context); + DateFormat format = DateFormat('dd MMM yyyy, hh:mm a', isArabic ? 'ar' : 'en'); + return format.format(dateTime); + } + + void _openCourse(String? url, String? jwtToken) { + + + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => SsoLoginWebView(url: url, jwtToken: jwtToken))); + //Utils.showToast(LocaleKeys.courseUrlNotAvailable.tr()); + + + // return; + // } + // + // MyInAppBrowser browser = MyInAppBrowser( + // onExitCallback: () {}, + // onLoadStartCallback: (String url) {}, + // ); + // + // var settings = InAppBrowserClassSettings( + // webViewSettings: InAppWebViewSettings( + // useShouldOverrideUrlLoading: false, + // transparentBackground: false, + // ), + // browserSettings: InAppBrowserSettings( + // hideUrlBar: true, + // hideTitleBar: false, + // toolbarTopBackgroundColor: theme_colors.primaryColor, + // ), + // ); + // + // browser.openUrlRequest( + // urlRequest: URLRequest(url: WebUri(url)), + // settings: settings, + // ); + } + + @override + void dispose() { + _refreshController.dispose(); + super.dispose(); + } +} diff --git a/lib/ui/screens/event_activity/activity_event_card.dart b/lib/ui/screens/event_activity/activity_event_card.dart new file mode 100644 index 0000000..56450b5 --- /dev/null +++ b/lib/ui/screens/event_activity/activity_event_card.dart @@ -0,0 +1,115 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/consts.dart'; +import 'package:mohem_flutter_app/classes/decorations_helper.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/marathon/marathon_model.dart'; +import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; +import 'package:provider/provider.dart'; +import 'package:shimmer/shimmer.dart'; + +class ActivityEventDetailsCard extends StatelessWidget { + final DashboardProviderModel model; + + const ActivityEventDetailsCard({Key? key, required this.model}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + decoration: MyDecorations.shadowDecoration, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CachedNetworkImage( + imageUrl: model.eventActivity!.detailImageURL!, + height: 200, + placeholder: (BuildContext context, String url) => const LinearProgressIndicator( + value: 0.7, + minHeight: 200, + + valueColor: AlwaysStoppedAnimation(Colors.white), + backgroundColor: Color(0xff196D73), + ).toShimmer(), + fit: BoxFit.contain,width: double.infinity , + cacheKey: UniqueKey().toString(), + ), + + ], + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20,), + Text( + displayLocalizedContent( + isPhoneLangArabic: AppState().isArabic(context), + selectedLanguage: 3, + englishContent: model.eventActivity?.titleEn ?? "", + arabicContent: model.eventActivity?.titleAr ?? "", + ), + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: isTablet ? 30 : 20, + fontWeight: FontWeight.bold, + color:const Color(0xff3C3838), + // height: 42 / 30, + ), + + ).paddingOnly(left: 10, right: 10, bottom: 2), + + Row(children:[ + SvgPicture.asset("assets/images/highlight.svg"), + Text( + displayLocalizedContent( + isPhoneLangArabic: AppState().isArabic(context), + selectedLanguage: 3, + englishContent: model.eventActivity?.shortDescEn ?? "", + arabicContent: model.eventActivity?.shortDescAr ?? "", + ), + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: isTablet ? 20 : 14, + fontWeight: FontWeight.bold, + color:const Color(0xff2BB8A8), + // height: 32 / 24, + ), + + ).paddingOnly(left: 10, right: 10) + ]).paddingOnly(bottom: 25), + + LocaleKeys.about.tr().toText16(color: const Color(0xff3C3838)).paddingOnly(bottom: 5), + Text( + displayLocalizedContent( + isPhoneLangArabic: AppState().isArabic(context), + selectedLanguage: 3, + englishContent: model.eventActivity?.longDescEn ?? "", + arabicContent: model.eventActivity?.longDescAr ?? "", + ), + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: isTablet ? 18 : 12, + fontWeight: FontWeight.bold, + color:const Color(0xff3C3838), + // height: 32 / 24, + ), + + ).paddingOnly(bottom: 10) + ], + ) + ]); + } +} diff --git a/lib/ui/screens/event_activity/activity_footer.dart b/lib/ui/screens/event_activity/activity_footer.dart new file mode 100644 index 0000000..8db2175 --- /dev/null +++ b/lib/ui/screens/event_activity/activity_footer.dart @@ -0,0 +1,94 @@ +// ignore_for_file: always_specify_types + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.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/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer_main_screen.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class ActivityEventFooter extends StatelessWidget { + final DashboardProviderModel provider; + + const ActivityEventFooter({ + Key? key, + required this.provider, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + + int remainingTime = DateTime.now().millisecondsSinceEpoch + DateUtil.convertStringToDateMarathon(provider.eventActivity!.startOn!).difference(DateTime.now()).inMilliseconds; + + return Column(children: [ + CountdownTimer( + endTime: remainingTime, + widgetBuilder: (context, time) { + if (time == null) { + return DefaultButton( + LocaleKeys.start.tr(), + () => launchUrl(Uri.parse(provider.eventActivity!.url!)), + color: MyColors.greenColor, + ).insideContainer; + } + return Container( + height: 58, + padding: const EdgeInsets.only( + top: 15, bottom: 15, right: 30, left: 30), + margin: const EdgeInsets.only(top: 5, bottom: 5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6.0), + gradient: + const LinearGradient( + transform: GradientRotation(.83), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor + ], + ), + ), + child: CountdownTimerForMainScreen( + timeToMarathon: DateUtil + .convertStringToDateMarathon(provider.eventActivity!.startOn!) + .millisecondsSinceEpoch, + provider: context.read(), + isEvent: true, + )); + + }, + onEnd: (){ + + }, + endWidget: DefaultButton( + LocaleKeys.start.tr(), + () => launchUrl(Uri.parse(provider.eventActivity!.url!)), + color: MyColors.greenColor, + ).insideContainer, + + ) + // if (remainingTimeInMinutes < 0) + // + // else + // + // + // , + + ]); + + } + + +} diff --git a/lib/ui/screens/event_activity/event_activity.dart b/lib/ui/screens/event_activity/event_activity.dart new file mode 100644 index 0000000..f523eb6 --- /dev/null +++ b/lib/ui/screens/event_activity/event_activity.dart @@ -0,0 +1,49 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/extensions/int_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/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_details_card.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_footer.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_timer_card.dart'; +import 'package:mohem_flutter_app/ui/screens/event_activity/activity_event_card.dart'; +import 'package:mohem_flutter_app/ui/screens/event_activity/activity_footer.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:provider/provider.dart'; + +class EventActivityScreen extends StatelessWidget { + const EventActivityScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + DashboardProviderModel provider = context.read(); + return Scaffold( + appBar: AppBarWidget( + context, + title: LocaleKeys.details.tr(), + onHomeTapped: () { + Navigator.pop(context); + + }, + onBackTapped: () { + Navigator.pop(context); + }, + ), + body: Column( + children: [ + ListView( + padding: const EdgeInsets.all(21), + children: [ + ActivityEventDetailsCard(model: provider), + 20.height, + ], + ).expanded, + 1.divider, + ActivityEventFooter(provider: provider), + ], + ), + ); + } +} diff --git a/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart b/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart index 44b3833..e7d2fde 100644 --- a/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart +++ b/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart @@ -150,7 +150,9 @@ class _MowadhafhiHRRequestState extends State { isReadOnly: false, onChange: (String value) { debugPrint(value); - description = value; + setState(() { + description = value; + }); }, ), ], @@ -171,7 +173,7 @@ class _MowadhafhiHRRequestState extends State { } bool checkValidation() { - if (selectedServiceType == null || selectedDepartment == null || selectedSection == null || selectedTopic == null) { + if (selectedServiceType == null || selectedDepartment == null || selectedSection == null || selectedTopic == null || description == "") { return false; } else { return true; diff --git a/lib/ui/screens/mowadhafhi/request_details.dart b/lib/ui/screens/mowadhafhi/request_details.dart index aa22bdd..a104f51 100644 --- a/lib/ui/screens/mowadhafhi/request_details.dart +++ b/lib/ui/screens/mowadhafhi/request_details.dart @@ -1,3 +1,8 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:io' as Io; +import 'dart:typed_data'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/mowadhafhi/mowadhafhi_api_client.dart'; @@ -6,9 +11,16 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_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/mowadhafhi/get_ticket_details.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_transaction_attachment_model.dart'; +import 'package:mohem_flutter_app/ui/screens/mowadhafhi/view_transaction_attachment.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; +import 'package:open_filex/open_filex.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; class MowadhafhiRequestDetails extends StatefulWidget { const MowadhafhiRequestDetails({Key? key}) : super(key: key); @@ -21,6 +33,9 @@ class _RequestDetailsState extends State { String? itgTicketID; List getTicketsByEmployeeList = []; List getTicketTransactionsList = []; + GetTransactionAttachmentModel? getTransactionAttachmentModel; + + late File imageFile; @override void initState() { @@ -43,7 +58,7 @@ class _RequestDetailsState extends State { backgroundColor: Colors.white, appBar: AppBarWidget( context, - title: LocaleKeys.mowadhafhiRequest.tr(), + title: LocaleKeys.mowadhafhiRequest.tr(), ), body: SingleChildScrollView( child: getTicketsByEmployeeList.length != 0 @@ -76,16 +91,16 @@ class _RequestDetailsState extends State { ], ), 8.height, - LocaleKeys.ticketReference.tr().toText12(color: MyColors.grey98Color), + LocaleKeys.ticketReference.tr().toText12(color: MyColors.grey98Color), getTicketsByEmployeeList![0].ticketReferenceNo!.toText14(color: MyColors.grey57Color), 8.height, - LocaleKeys.section.tr().toText12(color: MyColors.grey98Color), + LocaleKeys.section.tr().toText12(color: MyColors.grey98Color), getTicketsByEmployeeList![0].sectionName!.toText14(color: MyColors.grey57Color), 8.height, - LocaleKeys.topic.tr().toText12(color: MyColors.grey98Color), + LocaleKeys.topic.tr().toText12(color: MyColors.grey98Color), getTicketsByEmployeeList![0].topicName!.toText14(color: MyColors.grey57Color), 8.height, - LocaleKeys.description.tr().toText12(color: MyColors.grey98Color), + LocaleKeys.description.tr().toText12(color: MyColors.grey98Color), getTicketsByEmployeeList![0].description!.toText14(color: MyColors.grey57Color), ], ), @@ -128,15 +143,31 @@ class _RequestDetailsState extends State { Row( children: [ LocaleKeys.actionBy.tr().toText14(color: MyColors.grey57Color), + ": ".toText14(), getTicketTransactionsList![index].actionBy!.toText14(color: MyColors.grey57Color), ], ), + Row( + children: [ + LocaleKeys.actions.tr().toText14(color: MyColors.grey57Color), + ": ".toText14(), + getTicketTransactionsList![index].statusDisplayText!.toText14(color: MyColors.grey57Color), + ], + ), getTicketTransactionsList![index].comments!.toText14(color: MyColors.grey98Color), 12.height, + if (getTicketTransactionsList[index].attachments != null) + InkWell( + onTap: () { + print(getTicketTransactionsList[index].attachments![0].attachmentId); + getTransactionAttachment(getTicketTransactionsList[index].attachments![0].attachmentId!); + }, + child: LocaleKeys.attachments.tr().toText14(color: MyColors.gradiantEndColor, isUnderLine: true), + ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - getTicketTransactionsList![0].actionDate!.split(" ")[0].toText12(color: MyColors.grey70Color), + getTicketTransactionsList![index].actionDate!.split(" ")[0].toText12(color: MyColors.grey70Color), ], ), ], @@ -212,4 +243,58 @@ class _RequestDetailsState extends State { Utils.handleException(ex, context, null); } } + + void getTransactionAttachment(int attachmentID) async { + try { + Utils.showLoading(context); + getTransactionAttachmentModel = await MowadhafhiApiClient().getTransactionAttachments(attachmentID); + Utils.hideLoading(context); + handleTransactionAttachment(); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + Future _createFileFromString(String encodedStr, String ext) async { + Uint8List bytes = base64.decode(encodedStr); + String dir = (await getApplicationDocumentsDirectory()).path; + File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); + await file.writeAsBytes(bytes); + return file.path; + } + + void handleTransactionAttachment() async { + Permission.storage.isGranted.then((isGranted) { + if (!isGranted) { + Permission.manageExternalStorage.request().then((granted) async { + if (granted == PermissionStatus.granted) { + String ext = ''; + String? rFile = getTransactionAttachmentModel!.base64String; + String? rFileExt = getTransactionAttachmentModel!.fileName; + + ext = rFileExt!.split(".").last.toLowerCase(); + try { + String path = await _createFileFromString(rFile!.split("base64,").last ?? "", ext ?? ""); + await OpenFilex.open(path).catchError((err) { + print(err); + }); + } catch (ex) { + Utils.showToast("Cannot open file."); + } + } else { + showDialog( + context: context, + builder: (BuildContext cxt) => ConfirmDialog( + message: "You need to give storage permission to view files.", + onTap: () { + Navigator.pop(context); + }, + ), + ); + } + }); + } + }); + } } diff --git a/lib/ui/screens/mowadhafhi/view_transaction_attachment.dart b/lib/ui/screens/mowadhafhi/view_transaction_attachment.dart new file mode 100644 index 0000000..e6ef8bc --- /dev/null +++ b/lib/ui/screens/mowadhafhi/view_transaction_attachment.dart @@ -0,0 +1,34 @@ +import 'dart:io'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; + +class ViewTransactionAttachment extends StatelessWidget { + final File imageFile; + + const ViewTransactionAttachment({Key? key, required this.imageFile}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget( + context, + title: LocaleKeys.mowadhafhiRequest.tr(), + ), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.file(imageFile), + 50.height, + ], + ), + ), + ); + } +} diff --git a/lib/ui/screens/my_documents/my_documents_fragment.dart b/lib/ui/screens/my_documents/my_documents_fragment.dart index 6bc46f7..5a9c88d 100644 --- a/lib/ui/screens/my_documents/my_documents_fragment.dart +++ b/lib/ui/screens/my_documents/my_documents_fragment.dart @@ -79,7 +79,7 @@ class _MyDocumentsFragmentState extends State { Navigator.pushNamed( context, AppRoutes.addDynamicInput, - arguments: DynamicListViewParams(documentfilteredList[index].dOCUMENTTYPE!, documentfilteredList[index].fUNCTIONNAME!, + arguments: DynamicListViewParams(documentfilteredList[index].dOCUMENTTYPENAME!, documentfilteredList[index].fUNCTIONNAME!, selectedEmp: AppState().getUserName, isAttachmentMandatory: true), ); }); 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 b4cb242..be0582c 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 { @@ -61,13 +61,7 @@ class _OffersAndDiscountsDetailsState extends State { // transitionOnUserGestures: true, child: RepaintBoundary( key: _globalKey, - child: ClipRRect( - borderRadius: BorderRadius.circular(6), - child: Image.network( - getOffersList[0].bannerImage ?? "", - fit: BoxFit.contain, - ), - ).paddingAll(12), + child: ClipRRect(borderRadius: BorderRadius.circular(6), child: Image.network(getOffersList[0].bannerImage ?? "", fit: BoxFit.contain)).paddingAll(12), ), ), 8.height, @@ -76,7 +70,7 @@ class _OffersAndDiscountsDetailsState extends State { : getOffersList[0].titleEn!.toText22(isBold: true, color: const Color(0xff2B353E)).center, Html( data: AppState().isArabic(context) ? getOffersList[0].descriptionAr! : getOffersList[0].descriptionEn ?? "", - onLinkTap: (String? url, RenderContext context, Map attributes, _) { + onLinkTap: (String? url, Map attributes, _) { launchUrl(Uri.parse(url!)); }, ), @@ -87,19 +81,20 @@ class _OffersAndDiscountsDetailsState extends State { children: [ getOffersList[0].discountDescription!.toText16(isBold: true), InkWell( - onTap: () { - _shareOfferAsImage(); - }, - child: const Icon(Icons.share, color: MyColors.darkIconColor).paddingOnly(bottom: 4)) + onTap: () { + _shareOfferAsImage(); + }, + child: const Icon(Icons.share, color: MyColors.darkIconColor).paddingOnly(bottom: 4), + ), ], ).paddingOnly(left: 8, right: 8), getOffersList[0].isHasLocation == "true" ? InkWell( - onTap: () {}, - child: Row( - children: [const Icon(Icons.map_sharp, color: MyColors.darkIconColor).paddingOnly(bottom: 4), "Offer Location".toText16(isUnderLine: true).paddingOnly(left: 8)], - ).paddingOnly(left: 8, right: 8, top: 8), - ) + onTap: () {}, + child: Row( + children: [const Icon(Icons.map_sharp, color: MyColors.darkIconColor).paddingOnly(bottom: 4), "Offer Location".toText16(isUnderLine: true).paddingOnly(left: 8)], + ).paddingOnly(left: 8, right: 8, top: 8), + ) : 12.height, ], ).objectContainerView().paddingOnly(left: 21, right: 21, top: 21), @@ -127,18 +122,14 @@ 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()); } } void _scrollToTop() { - _scrollController.animateTo( - 0, - duration: const Duration(milliseconds: 500), - curve: Curves.linear, - ); + _scrollController.animateTo(0, duration: const Duration(milliseconds: 500), curve: Curves.linear); } List getItemsForSaleWidgets() { @@ -155,18 +146,9 @@ 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, - child: ClipRRect( - borderRadius: BorderRadius.circular(6), - child: Image.network( - getOffersList.bannerImage ?? "", - fit: BoxFit.contain, - ), - ), - ), + child: AspectRatio(aspectRatio: 148 / 127, child: ClipRRect(borderRadius: BorderRadius.circular(6), child: Image.network(getOffersList.bannerImage ?? "", fit: BoxFit.contain))), ), 5.height, getOffersList.titleEn!.toText16(isBold: true, color: const Color(0xff2B353E), maxlines: 1), @@ -180,10 +162,7 @@ class _OffersAndDiscountsDetailsState extends State { // 16.height, getOffersList.discountDescription!.toText14(isBold: true, maxlines: 1), 8.height, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [checkDate(getOffersList.endDate!), SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4)], - ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [checkDate(getOffersList.endDate!), SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4)]), ], ).objectContainerView().onPress(() { this.getOffersList[0] = getOffersList; diff --git a/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart b/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart index fd2c19e..dbc2366 100644 --- a/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart +++ b/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart @@ -39,7 +39,7 @@ class _OffersAndDiscountsHomeState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, - appBar: AppBarWidget(context, title: LocaleKeys.offerAndDiscounts.tr(), showHomeButton: true), + appBar: AppBarWidget(context, title: LocaleKeys.offerAndDiscounts.tr(), showHomeButton: true, showLogo: false, logoPath: "assets/icons/mazaya_brand.svg"), body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/ui/screens/ticket/ticket_detailed_screen.dart b/lib/ui/screens/ticket/ticket_detailed_screen.dart new file mode 100644 index 0000000..c4d232f --- /dev/null +++ b/lib/ui/screens/ticket/ticket_detailed_screen.dart @@ -0,0 +1,188 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.dart'; +import 'package:mohem_flutter_app/classes/utils.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/models/dashboard/get_accural_ticket_balance_model.dart'; +import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/balances_dashboard_widget.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; +import 'package:mohem_flutter_app/widgets/sso_webview_widget.dart'; +import 'package:provider/provider.dart'; + +class TicketDetailedScreen extends StatefulWidget { + final String? url; + final String? jwtToken; + + const TicketDetailedScreen({super.key, this.url, this.jwtToken}); + + @override + State createState() => _TicketDetailedScreenState(); +} + +class _TicketDetailedScreenState extends State { + DashboardProviderModel? dashboardProviderModel; + late DateTime accrualDateTime; + + @override + void initState() { + dashboardProviderModel = Provider.of(context, listen: false); + accrualDateTime = DateTime.now(); + super.initState(); + } + + void changeAccrualDate(bool showLoading) async { + try { + if (showLoading) Utils.showLoading(context); + await dashboardProviderModel?.fetchTicketAccuralBalance(context, accrualDateTime); + if (showLoading) Utils.hideLoading(context); + setState(() {}); + } catch (ex) { + if (showLoading) Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget(context, title:LocaleKeys.ticketDetails.tr()), + body: Column( + children: [ + ListView( + padding: const EdgeInsets.all(21), + physics: const BouncingScrollPhysics(), + children: [ + if (dashboardProviderModel == null && dashboardProviderModel?.accrualTicketBalanceList == null) ...[Utils.getNoDataWidget(context).paddingOnly(top: 50)] else ...[ + Container( + padding: const EdgeInsets.all(16.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12.0), + boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.2), spreadRadius: 2, blurRadius: 5, offset: const Offset(0, 3))], + ), + child: Column( + children: [ + Row( + children: [ + LocaleKeys.currentTicketBalance.tr().toText20().expanded, + Row( + children: [ + const Icon(Icons.calendar_month_rounded, color: MyColors.darkIconColor, size: 16), + 5.width, + DateUtil.formatDateToDate(accrualDateTime, AppState().isArabic(context)).toText13(isUnderLine: true), + 8.width, + ], + ).onPress(() async { + DateTime selectedDate = await Utils.selectDate(context, accrualDateTime); + if (selectedDate != accrualDateTime) { + accrualDateTime = selectedDate; + changeAccrualDate(true); + } + }), + ], + ), + 8.height, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + dashboardProviderModel!.accrualTicketBalanceList!.map((GetTicketAccuralBalanceModel item) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 6.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + item.accuralPlanCode.toString().replaceAll('_', ' ').toCamelCase.toText14(), + item.accrualNetEntitlement.toString().toText16(color: MyColors.textMixColor, isBold: true), + ], + ), + ); + }).toList(), + ), + ], + ), + ), + const SizedBox(height: 21), + dashboardProviderModel == null && dashboardProviderModel!.ticketHistoryTransactionList == null + ? const SizedBox() + : ListView( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + children: [ + LocaleKeys.ticketHistory.tr().toText20().expanded, + 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: EdgeInsets.zero, + itemBuilder: (BuildContext cxt, int cardIndex) { + var transactionDetails = dashboardProviderModel!.ticketHistoryTransactionList![cardIndex]; + const allowedSegmentNames = { + "TICKETS_ROUTE", + "TRAVELER_NAME", + "TICKETS_EFFECTIVE_DATE", + "TICKET_ARRIVAL", + "TICKET_AMOUNT", + "TICKET_COMP_SHARE", + "TICKET_EMP_SHARE", + }; + var uniqueDetails = + transactionDetails + .where((item) => item.dISPLAYFLAG != 'N' && item.sEGMENTPROMPT != null && item.sEGMENTPROMPT!.isNotEmpty && allowedSegmentNames.contains(item.sEGMENTNAME)) + .toList(); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: (uniqueDetails.length / 2).ceil(), + itemBuilder: (context, rowIndex) { + int firstIndex = rowIndex * 2; + int? secondIndex = (firstIndex + 1 < uniqueDetails.length) ? firstIndex + 1 : null; + bool isLastRow = (rowIndex == (uniqueDetails.length / 2).ceil() - 1); + var item1 = uniqueDetails[firstIndex]; + var child1 = ItemDetailViewCol(item1.sEGMENTPROMPT!, item1.vARCHAR2VALUE ?? item1.nUMBERVALUE?.toString() ?? ""); + Widget child2; + if (secondIndex != null) { + var item2 = uniqueDetails[secondIndex]; + child2 = ItemDetailViewCol(item2.sEGMENTPROMPT!, item2.vARCHAR2VALUE ?? item2.nUMBERVALUE?.toString() ?? ""); + } else { + child2 = const SizedBox(); // Empty widget if there is no second item + } + return ItemDetailGrid(child1, child2, isItLast: isLastRow); + }, + ), + ], + ).objectContainerView(); + }, + separatorBuilder: (BuildContext cxt, int index) => 12.height, + itemCount: dashboardProviderModel!.ticketHistoryTransactionList!.length, + ), + ], + ), + ], + ], + ).expanded, + DefaultButton(LocaleKeys.proceedBooking.tr(), () { + if (widget.url != null && widget.jwtToken != null) { + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => SsoLoginWebView(url: widget.url, jwtToken: widget.jwtToken))); + } + }).insideContainer, + ], + ), + ); + } +} diff --git a/lib/ui/termination/end_employement.dart b/lib/ui/termination/end_employement.dart index 8837806..18ae916 100644 --- a/lib/ui/termination/end_employement.dart +++ b/lib/ui/termination/end_employement.dart @@ -18,9 +18,12 @@ import 'package:mohem_flutter_app/models/get_eit_dff_structure_list_model.dart' import 'package:mohem_flutter_app/models/submit_term_transaction_list_model.dart'; import 'package:mohem_flutter_app/models/termination/get_term_cols_structure_list_model.dart'; import 'package:mohem_flutter_app/models/termination/get_term_dff_structure_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; @@ -37,7 +40,7 @@ class _EndEmploymentScreenState extends State { List? termColsList; List? termDffList; DynamicListViewParams? dynamicParams; - + ReplacementList? selectedReplacementEmployee; @override void initState() { super.initState(); @@ -413,9 +416,40 @@ class _EndEmploymentScreenState extends State { await calGetValueSetValues(model); } }, - ).paddingOnly(bottom: 12); + ); } } else { + if(model.sEGMENTNAME =='REPLACEMENT_PERSON') { + return DynamicTextFieldWidget( + LocaleKeys.selectEmployee.tr(), + selectedReplacementEmployee == null ? LocaleKeys.searchForEmployee + .tr() : selectedReplacementEmployee!.employeeDisplayName ?? "", + isEnable: false, + onTap: () { + showMyBottomSheet( + context, + callBackFunc: () {}, + child: SearchEmployeeBottomSheet( + title: LocaleKeys.searchForEmployee.tr(), + apiMode: LocaleKeys.delegate.tr(), + fromChat: false, + onSelectEmployee: (_selectedEmployee) { + // Navigator.pop(context); + selectedReplacementEmployee = _selectedEmployee; + ESERVICESDV eservicesdv = ESERVICESDV( + pIDCOLUMNNAME:_selectedEmployee.userName, + pRETURNMSG: "null", + pRETURNSTATUS: "null", //getEitDffStructureList![popipIndex].dEFAULTVALUE, + pVALUECOLUMNNAME:_selectedEmployee.employeeDisplayName); + termDffList![index].eSERVICESDV = eservicesdv; + + setState(() {}); + }, + ), + ); + }, + ); + }else{ return PopupMenuButton( child: DynamicTextFieldWidget( (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), @@ -436,11 +470,13 @@ class _EndEmploymentScreenState extends State { pRETURNSTATUS: "null", //getEitDffStructureList![popipIndex].dEFAULTVALUE, pVALUECOLUMNNAME: model.eSERVICESVS![popipIndex].vALUECOLUMNNAME); termDffList![index].eSERVICESDV = eservicesdv; + print(eservicesdv); setState(() {}); if (model.cHILDSEGMENTSVSSplited?.isNotEmpty ?? false) { await calGetValueSetValues(model); } }); + } } } else { return const SizedBox(); @@ -455,7 +491,7 @@ class _EndEmploymentScreenState extends State { isPopup: true, isInputTypeNum: true, isReadOnly: model.rEADONLY == "Y", - ).paddingOnly(bottom: 12), + ), itemBuilder: (_) => >[ if (model.rEADONLY != "Y") for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem(value: i, child: Text(model.eSERVICESVS![i].vALUECOLUMNNAME!)), diff --git a/lib/ui/unsafe_device_screen.dart b/lib/ui/unsafe_device_screen.dart index dca8748..dcfe820 100644 --- a/lib/ui/unsafe_device_screen.dart +++ b/lib/ui/unsafe_device_screen.dart @@ -32,15 +32,15 @@ class _UnsafeDeviceScreenState extends State { 50.height, "Sorry".toText24(isBold: true), 21.height, - "You are using Mohemm app on an unsafe device. To be able to use the app with all it's features, Please make sure that the below points are considered: " + "You are using MoheM app on an unsafe device. To be able to use the app with all it's features, Please make sure that the below points are considered: " .toText14(isCenter: true) .paddingOnly(left: 20.0, right: 20.0), 48.height, passwordConstraintsUI("The device is not jailbroken or rooted.", true).paddingOnly(left: 24.0, right: 5.0), - 8.height, - passwordConstraintsUI("The app is not installed on external storage.", true).paddingOnly(left: 24.0, right: 5.0), - 8.height, - passwordConstraintsUI("Development mode is disabled.", true).paddingOnly(left: 24.0, right: 5.0), + // 8.height, + // passwordConstraintsUI("The app is not installed on external storage.", true).paddingOnly(left: 24.0, right: 5.0), + // 8.height, + // passwordConstraintsUI("Development mode is disabled.", true).paddingOnly(left: 24.0, right: 5.0), 21.height, DefaultButton(LocaleKeys.ok.tr(), () async { if (Platform.isAndroid) { diff --git a/lib/ui/work_list/item_history_screen.dart b/lib/ui/work_list/item_history_screen.dart index e88dcba..4bc6579 100644 --- a/lib/ui/work_list/item_history_screen.dart +++ b/lib/ui/work_list/item_history_screen.dart @@ -2,7 +2,8 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:easy_localization/src/public_ext.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart'; @@ -22,7 +23,7 @@ import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart' import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; -import 'package:open_file/open_file.dart'; +import 'package:open_filex/open_filex.dart'; import 'package:path_provider/path_provider.dart'; class ItemHistoryScreenParams { @@ -60,13 +61,21 @@ class _ItemHistoryScreenState extends State { int tabIndex = 0; PageController controller = PageController(); + final ScrollController _horizontalScrollController = ScrollController(); + final ScrollController _horizontalHeaderScrollController = ScrollController(); + @override void initState() { super.initState(); + _horizontalScrollController.addListener(() { + _horizontalHeaderScrollController.jumpTo(_horizontalScrollController.offset); + }); } @override void dispose() { + _horizontalScrollController.dispose(); + _horizontalHeaderScrollController.dispose(); super.dispose(); actionHistoryList.clear(); } @@ -129,23 +138,231 @@ class _ItemHistoryScreenState extends State { } } + TableRow rowChildren(GetPoItemHistoryList poData, int index) { + return TableRow( + decoration: BoxDecoration(color: index % 2 == 0 ? Colors.white : Colors.grey[100]), + children: [ + rowCell(poData.cREATIONDATE!, index), + rowCell(poData.pURCHASEPRICE!.toString(), index), + rowCell(poData.sUPPLIER!, index), + rowCell(poData.pONUMBER!.toString(), index), + rowCell(poData.oUNAME!, index), + rowCell(poData.rEVISIONNUM!.toString(), index), + rowCell(poData.bUYER!, index), + rowCell(poData.uOM!, index), + rowCell(poData.qUANTITYORDERED!.toString(), index), + rowCell(poData.qUANTITYRECEIVED!.toString(), index), + rowCell(poData.bONUSQUANTITY!.toString(), index), + rowCell(poData.dISCOUNTPERCENTAGE!.toString(), index), + rowCell(poData.bALANCEQUANTITY!.toString(), index), + rowCell(poData.nETPRICE!.toString(), index), + rowCell(poData.cLOSEDCODE!, index), + ], + ); + } + + Widget rowCell(String data, int index) { + return TableCell( + verticalAlignment: TableCellVerticalAlignment.middle, + child: Center( + child: Text( + data, + style: TextStyle(fontSize: 12, color: MyColors.normalTextColor, fontWeight: FontWeight.w500), + ), + + // data.toText12(color: MyColors.normalTextColor), + ).paddingAll(8)); + } + + Widget headerCell(String data) { + return Container( + padding: const EdgeInsets.only(top: 16, bottom: 16, left: 8, right: 8), + width: 120, + alignment: Alignment.center, + decoration: BoxDecoration(color: Colors.grey[300]), + child: data.toText14(color: MyColors.darkIconColor), + ); + } + + List gradientColors = [MyColors.gradiantEndColor, MyColors.gradiantEndColor]; + + LineChartData drawLineChart(List spots, List reversedList) { + return LineChartData( + lineTouchData: LineTouchData(enabled: true, touchTooltipData: LineTouchTooltipData()), + gridData: FlGridData( + show: true, + drawHorizontalLine: true, + drawVerticalLine: true, + verticalInterval: 1, + horizontalInterval: 1, + getDrawingVerticalLine: (value) { + return FlLine(color: Color(0xff37434d), strokeWidth: .3); + }, + getDrawingHorizontalLine: (value) { + return FlLine(color: Color(0xff37434d), strokeWidth: .3); + }, + ), + titlesData: FlTitlesData( + show: true, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 30, + interval: 1, + getTitlesWidget: (double value, TitleMeta meta) { + return SideTitleWidget( + axisSide: meta.axisSide, + child: Text(reversedList[int.parse(meta.formattedValue)].cREATIONDATE!, style: TextStyle(fontSize: 10)), + ); + })), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 30, + interval: 1, + getTitlesWidget: (double value, TitleMeta meta) { + return SideTitleWidget( + axisSide: meta.axisSide, + child: Text(meta.formattedValue, style: TextStyle(fontSize: 10)), + ); + })), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + rightTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 15, + getTitlesWidget: (double value, TitleMeta meta) { + return SideTitleWidget( + axisSide: meta.axisSide, + child: Text("", style: TextStyle(fontSize: 10)), + ); + })), + ), + borderData: FlBorderData(show: true, border: Border.all(color: const Color(0xff37434d))), + minX: 0, + maxX: poItemHistoryList.length.toDouble() - 1, + minY: poItemHistoryList.map((e) => e.pURCHASEPRICE!.toDouble()).reduce((curr, next) => curr < next ? curr : next) - 1, + maxY: poItemHistoryList.map((e) => e.pURCHASEPRICE!.toDouble()).reduce((curr, next) => curr > next ? curr : next) + 1, + lineBarsData: [ + LineChartBarData( + spots: spots, + isCurved: true, + gradient: LinearGradient( + colors: [ + ColorTween(begin: gradientColors[0], end: gradientColors[1]).lerp(0.2)!, + ColorTween(begin: gradientColors[0], end: gradientColors[1]).lerp(0.2)!, + ], + ), + barWidth: 2, + isStrokeCapRound: true, + dotData: FlDotData(show: true), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + ColorTween(begin: gradientColors[0], end: gradientColors[1]).lerp(0.2)!.withOpacity(0.1), + ColorTween(begin: gradientColors[0], end: gradientColors[1]).lerp(0.2)!.withOpacity(0.1), + ], + ), + ), + ), + ], + ); + } + @override Widget build(BuildContext context) { loadData(); + Widget? chartWidget; + + if (_screenParams!.isItemHistory && poItemHistoryList.isNotEmpty) { + try { + List reversedList = poItemHistoryList.reversed.toList(); + List dataPoints = List.generate( + reversedList.length, + (index) => FlSpot(index.toDouble(), reversedList[index].pURCHASEPRICE!.toDouble()), + ); + + double chartWidth = dataPoints.length * 70.0; + chartWidget = Column( + mainAxisSize: MainAxisSize.min, + children: [ + LocaleKeys.graphicalAnalysis.tr().toText14(color: MyColors.darkIconColor), + SizedBox( + height: 400, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Container( + width: chartWidth, + padding: const EdgeInsets.all(16.0), + child: LineChart(drawLineChart(dataPoints, reversedList)), + ), + ), + ), + ], + ); + } catch (ex) {} + } + return Scaffold( appBar: AppBarWidget(context, title: _screenParams?.title ?? ""), backgroundColor: Colors.white, - body: ListView( - padding: _screenParams!.isPRInfo ? const EdgeInsets.all(0) : const EdgeInsets.all(21), - physics: const NeverScrollableScrollPhysics(), - children: [ - if (_screenParams!.isPRInfo) prLinesDataView(), - if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData(), - if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData(), - if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData(), - if (moItemHistoryList.isEmpty && poItemHistoryList.isEmpty && quotationAnalysisList.isEmpty && !_screenParams!.isPRInfo) Utils.getNoDataWidget(context), - ], - ), + body: (_screenParams!.isItemHistory && poItemHistoryList.isNotEmpty) + ? Column( + children: [ + if (chartWidget != null) chartWidget, + if (poItemHistoryList.isNotEmpty) ...[ + LocaleKeys.itemHistoryAnalysis.tr().toText14(color: MyColors.darkIconColor), + 16.height, + SingleChildScrollView( + scrollDirection: Axis.horizontal, + physics: const NeverScrollableScrollPhysics(), + controller: _horizontalHeaderScrollController, + child: Row( + children: [ + headerCell(LocaleKeys.creationDate.tr()), + headerCell(LocaleKeys.purchasePrice.tr()), + headerCell(LocaleKeys.supplier.tr()), + headerCell(LocaleKeys.pOno.tr()), + headerCell(LocaleKeys.oprUnit.tr()), + headerCell(LocaleKeys.revision.tr()), + headerCell(LocaleKeys.buyer.tr()), + headerCell(LocaleKeys.uom.tr()), + headerCell(LocaleKeys.qtyOrdered.tr()), + headerCell(LocaleKeys.qtyReceived.tr()), + headerCell(LocaleKeys.bonusQty.tr()), + headerCell(LocaleKeys.discountPer.tr()), + headerCell(LocaleKeys.balQty.tr()), + headerCell(LocaleKeys.netPrice.tr()), + headerCell(LocaleKeys.closureStatus.tr()), + ], + ), + ), + SingleChildScrollView( + scrollDirection: Axis.vertical, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + controller: _horizontalScrollController, + child: Table( + defaultColumnWidth: const FixedColumnWidth(120.0), + children: [for (int index = 0; index < poItemHistoryList.length; index++) rowChildren(poItemHistoryList[index], index)], + ), + ), + ).expanded, + ], + ], + ) + : ListView( + padding: _screenParams!.isPRInfo ? const EdgeInsets.all(0) : const EdgeInsets.all(21), + // physics: const NeverScrollableScrollPhysics(), + children: [ + if (_screenParams!.isPRInfo) prLinesDataView(), + if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData(), + if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData(), + if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData(), + if (moItemHistoryList.isEmpty && poItemHistoryList.isEmpty && quotationAnalysisList.isEmpty && !_screenParams!.isPRInfo) Utils.getNoDataWidget(context), + ], + ), ); } @@ -278,7 +495,7 @@ class _ItemHistoryScreenState extends State { ).objectContainerView().onPress(() async { try { String path = await _createFileFromString(getAttachmentList[index].fILEDATA ?? "", getAttachmentList[index].fILECONTENTTYPE ?? ""); - OpenFile.open(path); + OpenFilex.open(path); } catch (ex) { Utils.showToast("Cannot open file."); } diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index 5d48c53..fdfe19c 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:lottie/lottie.dart'; import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -11,11 +12,15 @@ 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/models/dashboard/itg_forms_model.dart'; +import 'package:mohem_flutter_app/models/itg/itg_summary_data.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/allowed_actions_model.dart'; +import 'package:mohem_flutter_app/models/itg_forms_models/itg_forms_attachments_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/itg_request_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/request_detail_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/work_list/itg_fragments/approval_level_fragment.dart'; +import 'package:mohem_flutter_app/ui/work_list/itg_fragments/attachments_fragment.dart'; import 'package:mohem_flutter_app/ui/work_list/itg_fragments/request_detail_fragment.dart'; import 'package:mohem_flutter_app/ui/work_list/sheets/delegate_sheet.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; @@ -42,10 +47,15 @@ class _ItgDetailScreenState extends State { bool isCloseAvailable = false; bool isApproveAvailable = false; bool isRejectAvailable = false; + bool isGenerateAvailable = false; List allowedActionList = []; + List itgFormAttachmentsList = []; late DashboardProviderModel providerData; + ItgTimeCardSummaryData? timeCardSummaryData; + + bool isAttachmentLoaded = false; @override void initState() { @@ -66,34 +76,72 @@ class _ItgDetailScreenState extends State { Utils.showLoading(context); itgRequest = await WorkListApiClient().getITGFormDetails(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? ""); allowedActionList = itgRequest?.allowedActions ?? []; + if (allowedActionList.isNotEmpty) { isCloseAvailable = allowedActionList.any((element) => element.action == "CLOSE"); isApproveAvailable = itgRequest!.allowedActions!.any((element) => element.action == "Approve"); isRejectAvailable = itgRequest!.allowedActions!.any((element) => element.action == "Reject"); + isGenerateAvailable = itgRequest!.allowedActions!.any((element) => element.action == "Generate"); } - Utils.hideLoading(context); - setState(() { - controller.jumpToPage(0); - }); + + String rawDate = itgRequest!.fieldGoups![1].fields![1].value!; + String month = rawDate.split('/').first; + String year = rawDate.split('/').last; + String formattedString = "${getMonthName(month)}-$year"; + + if (requestDetails!.requestType == "Timesheet Request") { + dynamic data = await WorkListApiClient().getITGTimeCardDetails("Timesheet Request", formattedString, itgRequest!.fieldGoups![0].fields![1].value ?? ""); + if (data != null) { + var decodedDta = jsonDecode(data); + // var decodedDta = jsonDecode( + // "{\"returN_STATUS\":\"S\",\"returN_MSG\":\"null\",\"summeries\":[{\"employeE_NUMBER\":\"410123\",\"assignmenT_NUMBER\":\"410123\",\"employeE_NAME\":\"Samiullah Abdulqadir\",\"hirE_DATE\":\"2024-07-21T00:00:00\",\"actuaL_TERMINATION_DATE\":null,\"perioD_DAYS\":31,\"schedulE_DAYS\":20,\"ofF_DAYS\":9,\"noN_SCHEDULED_DAYS\":0,\"noT_ANALAYZED_DAYS\":0,\"attendeD_DAYS\":20,\"absenT_DAYS\":0,\"missinG_SWIPES_DAYS\":0,\"scheduleD_HRS\":\"120\",\"actuaL_HRS\":\"121.96\",\"excesS_HRS\":\"2.61\",\"comP_OFF_W_HRS\":\"0\",\"comP_OFF_H_HRS\":\"0\",\"comP_OFF_N_HRS\":\"0\",\"timebacK_HRS\":\"2.61\",\"shortagE_HRS\":\".65\",\"latE_IN_HRS\":\".1\",\"earlY_OUT_HRS\":\".65\",\"uncovereD_SHORTAGE_HRS\":0.65,\"halF_DAY_LEAVES\":0,\"sicK_LEAVES\":0,\"publiC_HOLIDAYS\":2,\"worK_FROM_HOME_DAYS\":0,\"businesS_TRIPS\":0,\"unauthorizeD_LEAVES\":0,\"unpaiD_LEAVES\":0,\"paiD_LEAVES\":0}],\"details\":[{\"schedulE_DATE\":\"2025-03-01T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-02T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"09:58\",\"shT_ACTUAL_END_DATETIME\":\"16:01\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:03\",\"excesS_HRS\":\"00:03\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-03T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:11\",\"shT_ACTUAL_END_DATETIME\":\"16:11\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-04T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:08\",\"shT_ACTUAL_END_DATETIME\":\"16:12\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:04\",\"excesS_HRS\":\"00:04\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-05T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:09\",\"shT_ACTUAL_END_DATETIME\":\"16:12\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:03\",\"excesS_HRS\":\"00:03\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-06T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"09:53\",\"shT_ACTUAL_END_DATETIME\":\"15:54\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:01\",\"excesS_HRS\":\"00:01\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-07T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-08T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-09T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:06\",\"shT_ACTUAL_END_DATETIME\":\"16:08\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:02\",\"excesS_HRS\":\"00:02\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-10T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"11:06\",\"shT_ACTUAL_END_DATETIME\":\"17:06\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:06\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"Y\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-11T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:09\",\"shT_ACTUAL_END_DATETIME\":\"16:12\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:03\",\"excesS_HRS\":\"00:03\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-12T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:37\",\"shT_ACTUAL_END_DATETIME\":\"16:38\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:01\",\"excesS_HRS\":\"00:01\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-13T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"09:53\",\"shT_ACTUAL_END_DATETIME\":\"16:08\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:15\",\"excesS_HRS\":\"00:15\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-14T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-15T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-16T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:52\",\"shT_ACTUAL_END_DATETIME\":\"16:54\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:02\",\"excesS_HRS\":\"00:02\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-17T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:49\",\"shT_ACTUAL_END_DATETIME\":\"17:00\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:11\",\"excesS_HRS\":\"00:11\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-18T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:40\",\"shT_ACTUAL_END_DATETIME\":\"16:59\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:19\",\"excesS_HRS\":\"00:19\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-19T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:46\",\"shT_ACTUAL_END_DATETIME\":\"17:03\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:17\",\"excesS_HRS\":\"00:17\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-20T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:52\",\"shT_ACTUAL_END_DATETIME\":\"16:55\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:03\",\"excesS_HRS\":\"00:03\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-21T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-22T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-23T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:54\",\"shT_ACTUAL_END_DATETIME\":\"17:13\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:19\",\"excesS_HRS\":\"00:19\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-24T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:40\",\"shT_ACTUAL_END_DATETIME\":\"16:51\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:11\",\"excesS_HRS\":\"00:11\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-25T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:49\",\"shT_ACTUAL_END_DATETIME\":\"17:04\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:15\",\"excesS_HRS\":\"00:15\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-26T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:55\",\"shT_ACTUAL_END_DATETIME\":\"17:23\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:28\",\"excesS_HRS\":\"00:28\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-27T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:56\",\"shT_ACTUAL_END_DATETIME\":\"16:17\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"05:21\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:39\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:39\",\"remarks\":null,\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"Y\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"Y\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-28T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-29T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-30T00:00:00\",\"shifT_NAME\":\"08:00 - 17:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"13:00 - 14:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\" From: 30-03-2025 To : 02-04-2025\\n\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-31T00:00:00\",\"shifT_NAME\":\"08:00 - 17:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"13:00 - 14:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\" From: 30-03-2025 To : 02-04-2025\\n\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"}]}", + // ); + timeCardSummaryData = ItgTimeCardSummaryData.fromJson(decodedDta); + Future.delayed(Duration.zero); + setState(() { + controller.jumpToPage(0); + }); + Utils.hideLoading(context); + } + } else { + timeCardSummaryData = ItgTimeCardSummaryData(); + Utils.hideLoading(context); + setState(() { + controller.jumpToPage(0); + }); + } + } catch (ex) { + setState(() {}); Utils.hideLoading(context); - Utils.handleException(ex, context, null); + // var decodedDta = jsonDecode( + // "{\"returN_STATUS\":\"S\",\"returN_MSG\":\"null\",\"summeries\":[{\"employeE_NUMBER\":\"410123\",\"assignmenT_NUMBER\":\"410123\",\"employeE_NAME\":\"Samiullah Abdulqadir\",\"hirE_DATE\":\"2024-07-21T00:00:00\",\"actuaL_TERMINATION_DATE\":null,\"perioD_DAYS\":31,\"schedulE_DAYS\":20,\"ofF_DAYS\":9,\"noN_SCHEDULED_DAYS\":0,\"noT_ANALAYZED_DAYS\":0,\"attendeD_DAYS\":20,\"absenT_DAYS\":0,\"missinG_SWIPES_DAYS\":0,\"scheduleD_HRS\":\"120\",\"actuaL_HRS\":\"121.96\",\"excesS_HRS\":\"2.61\",\"comP_OFF_W_HRS\":\"0\",\"comP_OFF_H_HRS\":\"0\",\"comP_OFF_N_HRS\":\"0\",\"timebacK_HRS\":\"2.61\",\"shortagE_HRS\":\".65\",\"latE_IN_HRS\":\".1\",\"earlY_OUT_HRS\":\".65\",\"uncovereD_SHORTAGE_HRS\":0.65,\"halF_DAY_LEAVES\":0,\"sicK_LEAVES\":0,\"publiC_HOLIDAYS\":2,\"worK_FROM_HOME_DAYS\":0,\"businesS_TRIPS\":0,\"unauthorizeD_LEAVES\":0,\"unpaiD_LEAVES\":0,\"paiD_LEAVES\":0}],\"details\":[{\"schedulE_DATE\":\"2025-03-01T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-02T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"09:58\",\"shT_ACTUAL_END_DATETIME\":\"16:01\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:03\",\"excesS_HRS\":\"00:03\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-03T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:11\",\"shT_ACTUAL_END_DATETIME\":\"16:11\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-04T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:08\",\"shT_ACTUAL_END_DATETIME\":\"16:12\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:04\",\"excesS_HRS\":\"00:04\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-05T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:09\",\"shT_ACTUAL_END_DATETIME\":\"16:12\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:03\",\"excesS_HRS\":\"00:03\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-06T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"09:53\",\"shT_ACTUAL_END_DATETIME\":\"15:54\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:01\",\"excesS_HRS\":\"00:01\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-07T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-08T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-09T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:06\",\"shT_ACTUAL_END_DATETIME\":\"16:08\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:02\",\"excesS_HRS\":\"00:02\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-10T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"11:06\",\"shT_ACTUAL_END_DATETIME\":\"17:06\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:06\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"Y\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-11T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:09\",\"shT_ACTUAL_END_DATETIME\":\"16:12\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:03\",\"excesS_HRS\":\"00:03\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-12T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:37\",\"shT_ACTUAL_END_DATETIME\":\"16:38\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:01\",\"excesS_HRS\":\"00:01\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-13T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"09:53\",\"shT_ACTUAL_END_DATETIME\":\"16:08\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:15\",\"excesS_HRS\":\"00:15\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-14T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-15T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-16T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:52\",\"shT_ACTUAL_END_DATETIME\":\"16:54\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:02\",\"excesS_HRS\":\"00:02\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-17T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:49\",\"shT_ACTUAL_END_DATETIME\":\"17:00\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:11\",\"excesS_HRS\":\"00:11\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-18T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:40\",\"shT_ACTUAL_END_DATETIME\":\"16:59\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:19\",\"excesS_HRS\":\"00:19\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-19T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:46\",\"shT_ACTUAL_END_DATETIME\":\"17:03\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:17\",\"excesS_HRS\":\"00:17\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-20T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:52\",\"shT_ACTUAL_END_DATETIME\":\"16:55\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:03\",\"excesS_HRS\":\"00:03\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-21T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-22T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-23T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:54\",\"shT_ACTUAL_END_DATETIME\":\"17:13\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:19\",\"excesS_HRS\":\"00:19\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-24T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:40\",\"shT_ACTUAL_END_DATETIME\":\"16:51\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:11\",\"excesS_HRS\":\"00:11\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-25T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:49\",\"shT_ACTUAL_END_DATETIME\":\"17:04\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:15\",\"excesS_HRS\":\"00:15\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-26T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:55\",\"shT_ACTUAL_END_DATETIME\":\"17:23\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"06:28\",\"excesS_HRS\":\"00:28\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":null,\"excesS_FLAG\":\"Y\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"Y\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-27T00:00:00\",\"shifT_NAME\":\"10:00 - 16:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":\"10:56\",\"shT_ACTUAL_END_DATETIME\":\"16:17\",\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"06:00\",\"actuaL_HRS\":\"05:21\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:39\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:39\",\"remarks\":null,\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"Y\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"Y\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-28T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-29T00:00:00\",\"shifT_NAME\":\"00:00 - 00:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"00:00 - 00:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\"Off Shift\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-30T00:00:00\",\"shifT_NAME\":\"08:00 - 17:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"13:00 - 14:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\" From: 30-03-2025 To : 02-04-2025\\n\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"},{\"schedulE_DATE\":\"2025-03-31T00:00:00\",\"shifT_NAME\":\"08:00 - 17:00\",\"shifT_TYPE\":\"Regular\",\"breaK_NAME\":\"13:00 - 14:00\",\"actuaL_WOB_HRS\":\"00:00\",\"shT_ACTUAL_START_DATETIME\":null,\"shT_ACTUAL_END_DATETIME\":null,\"approveD_START_DATETIME\":null,\"approveD_END_DATETIME\":null,\"scheduleD_HRS\":\"00:00\",\"actuaL_HRS\":\"00:00\",\"excesS_HRS\":\"00:00\",\"comP_OFF_N_HRS\":\"00:00\",\"comP_OFF_W_HRS\":\"00:00\",\"comP_OFF_H_HRS\":\"00:00\",\"timebacK_HRS\":null,\"shortagE_HRS\":\"00:00\",\"latE_IN_HRS\":\"00:00\",\"earlY_OUT_HRS\":\"00:00\",\"remarks\":\" From: 30-03-2025 To : 02-04-2025\\n\",\"excesS_FLAG\":\"N\",\"comP_OFF_FLAG\":\"N\",\"timebacK_FLAG\":\"N\",\"shortagE_FLAG\":\"N\",\"latE_IN_FLAG\":\"N\",\"earlY_OUT_FLAG\":\"N\",\"missinG_SWIPES_FLAG\":\"N\"}]}", + // ); + // timeCardSummaryData = ItgTimeCardSummaryData.fromJson(decodedDta); + // Utils.handleException(ex, context, null); } } - void getDataFromState() { + String getMonthName(String monthNumber) { + const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + int index = int.tryParse(monthNumber) ?? 0; + return (index >= 1 && index <= 12) ? monthNames[index - 1] : "Invalid Month"; + } + + void getDataFromState() async { if (requestDetails == null) { animationIndex = animationIndex + 1; requestDetails = AppState().requestAllList![AppState().itgWorkListIndex!]; // ModalRoute.of(context)!.settings.arguments as WorkListResponseModel; providerData.itgFormsModel!.totalCount = providerData.itgFormsModel!.totalCount! - 1; getItgData(); + Utils.hideLoading(context); + getItgRequestAttachments(); } } @override Widget build(BuildContext context) { getDataFromState(); - return Scaffold( appBar: AppBarWidget(context, title: LocaleKeys.details.tr()), backgroundColor: Colors.white, @@ -101,10 +149,7 @@ class _ItgDetailScreenState extends State { duration: const Duration(milliseconds: 500), switchInCurve: Curves.easeInToLinear, transitionBuilder: (Widget child, Animation animation) { - Animation custom = Tween( - begin: const Offset(1.0, 0.0), - end: Offset.zero, - ).animate(animation); + Animation custom = Tween(begin: const Offset(1.0, 0.0), end: Offset.zero).animate(animation); return ClipRect( child: SlideTransition( position: custom, @@ -121,26 +166,11 @@ class _ItgDetailScreenState extends State { Container( padding: const EdgeInsets.only(left: 21, right: 21, top: 16, bottom: 16), decoration: const BoxDecoration( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(25), - bottomRight: Radius.circular(25), - ), - gradient: LinearGradient( - transform: GradientRotation(.83), - begin: Alignment.topRight, - end: Alignment.bottomLeft, - colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ], - ), + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(25), bottomRight: Radius.circular(25)), + gradient: LinearGradient(transform: GradientRotation(.83), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [MyColors.gradiantEndColor, MyColors.gradiantStartColor]), ), child: Row( - children: [ - myTab(LocaleKeys.requestDetails.tr(), 0), - myTab(LocaleKeys.approvalLevel.tr(), 1), - myTab(LocaleKeys.requesterDetails.tr(), 2), - ], + children: [myTab(LocaleKeys.requestDetails.tr(), 0), myTab(LocaleKeys.approvalLevel.tr(), 1), myTab(LocaleKeys.requesterDetails.tr(), 2), myTab(LocaleKeys.attachments.tr(), 3)], ), ), PageView( @@ -151,73 +181,47 @@ class _ItgDetailScreenState extends State { }); }, children: [ - RequestDetailFragment(fields: itgRequest?.fieldGoups?[1].fields ?? []), - ApprovalLevelfragment( - wFHistory: itgRequest?.wFHistory ?? [], - voidCallback: reloadITG, + RequestDetailFragment( + fields: itgRequest?.fieldGoups?[1].fields ?? [], + fieldGoups: itgRequest?.fieldGoups ?? [], + taskID: itgRequest?.fieldGoups?[0].fields?[0].value ?? "", + summaryData: timeCardSummaryData, ), + ApprovalLevelfragment(wFHistory: itgRequest?.wFHistory ?? [], voidCallback: reloadITG), RequestDetailFragment(fields: itgRequest?.fieldGoups?[0].fields ?? []), + isAttachmentLoaded + ? itgFormAttachmentsList.isEmpty + ? Utils.getNoDataWidget(context) + : ITGAttachmentsFragment(itgFormAttachmentsList) + : showLoadingAnimation(), ], ).expanded, if (isApproveAvailable || isRejectAvailable || isCloseAvailable) Container( padding: const EdgeInsets.only(top: 14, bottom: 14, left: 21, right: 21), - decoration: const BoxDecoration( - color: Colors.white, - border: Border( - top: BorderSide( - color: MyColors.lightGreyEFColor, - width: 1.0, - ), - ), - ), + decoration: const BoxDecoration(color: Colors.white, border: Border(top: BorderSide(color: MyColors.lightGreyEFColor, width: 1.0))), child: Row( children: [ - if (isRejectAvailable) - DefaultButton( - LocaleKeys.reject.tr(), - () => performAction("REJECTED"), - colors: const [ - Color(0xffE47A7E), - Color(0xffDE6D71), - ], - ).expanded, + if (isRejectAvailable) DefaultButton(LocaleKeys.reject.tr(), () => performAction("REJECTED"), colors: const [Color(0xffE47A7E), Color(0xffDE6D71)]).expanded, if (isApproveAvailable && isRejectAvailable) 8.width, - if (isApproveAvailable) - DefaultButton( - LocaleKeys.approve.tr(), - () => performAction("APPROVED"), - colors: const [ - Color(0xff28C884), - Color(0xff1BB271), - ], - ).expanded, - if (isCloseAvailable) - DefaultButton( - LocaleKeys.ok.tr(), - () => performAction("CLOSE"), - colors: const [ - Color(0xff32D892), - Color(0xff1AB170), - ], - ).expanded, + if (isApproveAvailable) DefaultButton(LocaleKeys.approve.tr(), () => performAction("APPROVED"), colors: const [Color(0xff28C884), Color(0xff1BB271)]).expanded, + if ((isApproveAvailable || isRejectAvailable) && isGenerateAvailable) 8.width, + if (isGenerateAvailable) DefaultButton(LocaleKeys.generate.tr(), () => performAction("Generate"), colors: const [Color(0xff28C884), Color(0xff1BB271)]).expanded, + if (isCloseAvailable) DefaultButton(LocaleKeys.ok.tr(), () => performAction("CLOSE"), colors: const [Color(0xff32D892), Color(0xff1AB170)]).expanded, 8.width, Container( height: 43, width: 43, - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: MyColors.lightGreyE6Color, - ), + decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.lightGreyE6Color), child: Icon(showFabOptions ? Icons.more_vert_rounded : Icons.more_horiz_rounded, color: MyColors.darkIconColor), ).onPress(() { setState(() { showFabOptions = true; }); - }) + }), ], ), - ) + ), ], ), IgnorePointer( @@ -262,28 +266,26 @@ class _ItgDetailScreenState extends State { ], ), ), - floatingActionButton: (!isApproveAvailable && !isRejectAvailable && !isCloseAvailable) - ? Container( - height: 43, - width: 43, - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: MyColors.lightGreyE6Color, - ), - child: Icon(showFabOptions ? Icons.more_vert_rounded : Icons.more_horiz_rounded, color: MyColors.darkIconColor), - ).onPress(() { - setState(() { - showFabOptions = true; - }); - }) - : null, + floatingActionButton: + (!isApproveAvailable && !isRejectAvailable && !isCloseAvailable && !isGenerateAvailable) + ? Container( + height: 43, + width: 43, + decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.lightGreyE6Color), + child: Icon(showFabOptions ? Icons.more_vert_rounded : Icons.more_horiz_rounded, color: MyColors.darkIconColor), + ).onPress(() { + setState(() { + showFabOptions = true; + }); + }) + : null, ); } List viewApiButtonsList(List allowedActionList) { List fabs = []; for (int i = 0; i < allowedActionList.length; i++) { - if (allowedActionList[i].action! == "Reject" || allowedActionList[i].action! == "Approve" || allowedActionList[i].action! == "CLOSE") { + if (allowedActionList[i].action! == "Reject" || allowedActionList[i].action! == "Approve" || allowedActionList[i].action! == "CLOSE" || allowedActionList[i].action! == "Generate") { continue; } fabs.add(myFab(getFabActionTitle(allowedActionList[i].action!), getFabActionImages(allowedActionList[i].action!)).paddingOnly(bottom: 12).onPress(() => handleFabAction(allowedActionList[i]))); @@ -354,29 +356,33 @@ class _ItgDetailScreenState extends State { void handleFabAction(AllowedActions action) { switch (action.action) { case "Delegate": - showMyBottomSheet(context, + showMyBottomSheet( + context, + callBackFunc: reloadITG, + child: DelegateSheet( + title: LocaleKeys.delegate.tr(), + apiMode: action.action!, + notificationID: null, + actionHistoryList: null, + wFHistory: itgRequest?.wFHistory ?? [], callBackFunc: reloadITG, - child: DelegateSheet( - title: LocaleKeys.delegate.tr(), - apiMode: action.action!, - notificationID: null, - actionHistoryList: null, - wFHistory: itgRequest?.wFHistory ?? [], - callBackFunc: reloadITG, - )); + ), + ); break; case "RequestInformation": - showMyBottomSheet(context, + showMyBottomSheet( + context, + callBackFunc: reloadITG, + child: DelegateSheet( + title: LocaleKeys.request_info.tr(), + apiMode: action.action!, + notificationID: null, + actionHistoryList: null, + wFHistory: itgRequest?.wFHistory ?? [], callBackFunc: reloadITG, - child: DelegateSheet( - title: LocaleKeys.request_info.tr(), - apiMode: action.action!, - notificationID: null, - actionHistoryList: null, - wFHistory: itgRequest?.wFHistory ?? [], - callBackFunc: reloadITG, - )); + ), + ); break; case "Doable": performAction("APPROVED"); @@ -405,20 +411,13 @@ class _ItgDetailScreenState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - title.toText12(color: isSelected ? Colors.white : Colors.white.withOpacity(.74), isCenter: true), + title.toText11(color: isSelected ? Colors.white : Colors.white.withOpacity(.74), isCenter: true), 4.height, - Container( - height: 8, - width: 8, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: isSelected ? Colors.white : Colors.transparent, - ), - ).onPress(() { + Container(height: 8, width: 8, decoration: BoxDecoration(shape: BoxShape.circle, color: isSelected ? Colors.white : Colors.transparent)).onPress(() { setState(() { showFabOptions = true; }); - }) + }), ], ).onPress(() { controller.jumpToPage(index); @@ -438,23 +437,10 @@ class _ItgDetailScreenState extends State { padding: const EdgeInsets.all(12), decoration: const BoxDecoration( shape: BoxShape.circle, - gradient: LinearGradient( - transform: GradientRotation(.46), - begin: Alignment.topRight, - end: Alignment.bottomLeft, - colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ], - ), + gradient: LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [MyColors.gradiantEndColor, MyColors.gradiantStartColor]), ), - child: isIconAsset - ? SvgPicture.asset(icon) - : Image.memory( - base64Decode(icon), - fit: BoxFit.cover, - ), - ) + child: isIconAsset ? SvgPicture.asset(icon) : Image.memory(base64Decode(icon), fit: BoxFit.cover), + ), ], ); } @@ -462,23 +448,58 @@ class _ItgDetailScreenState extends State { void performAction(String actionMode) { showDialog( context: context, - builder: (cxt) => ITGCommentsDialog( - message: LocaleKeys.writeComment.tr(), - actionMode: actionMode, - onTap: (note) { - if (actionMode == "APPROVED") { - performApproveAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); - } else if (actionMode == "Answer") { - performAnswerAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); - } else { - performRejectAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); - } - }, - ), + builder: + (cxt) => ITGCommentsDialog( + message: LocaleKeys.writeComment.tr(), + actionMode: actionMode, + onTap: (note) { + if (actionMode == "APPROVED") { + performApproveAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); + } else if (actionMode == "Answer") { + performAnswerAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); + } else if (actionMode == "Generate") { + performGenerateQrAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); + } else { + performRejectAction(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); + } + }, + ), ); } - void performAnswerAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { + void performGenerateQrAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { + try { + Utils.showLoading(context); + ITGRequest? itgRequest = await WorkListApiClient().requestActionITGRequest( + requestType, + taskId, + itemId, + employeeNumber, + "", + comments, + AppState().memberInformationList?.eMPLOYEEEMAILADDRESS ?? "", + ); + Utils.hideLoading(context); + Utils.showToast(LocaleKeys.yourChangeHasBeenSavedSuccessfully.tr()); + // Navigator.pop(context, "delegate_reload"); + AppState().requestAllList!.removeAt(AppState().itgWorkListIndex!); + if (AppState().requestAllList!.isEmpty) { + Navigator.pop(context, "delegate_reload"); + } else { + if (AppState().requestAllList!.length <= AppState().itgWorkListIndex!) { + Navigator.pop(context, "delegate_reload"); + } else { + requestDetails = null; + getDataFromState(); + } + } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + void performAnswerAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { try { Utils.showLoading(context); ITGRequest? itgRequest = await WorkListApiClient().answerITGRequest(requestType, taskId, itemId, employeeNumber, "", comments); @@ -502,7 +523,7 @@ class _ItgDetailScreenState extends State { } } - void performRejectAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { + void performRejectAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { try { Utils.showLoading(context); ITGRequest? itgRequest = await WorkListApiClient().rejectITGRequest(requestType, taskId, itemId, employeeNumber, comments); @@ -526,7 +547,7 @@ class _ItgDetailScreenState extends State { } } - void performApproveAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { + void performApproveAction(String requestType, taskId, itemId, String employeeNumber, String comments) async { try { Utils.showLoading(context); ITGRequest? itgRequest = await WorkListApiClient().approveITGRequest(requestType, taskId, itemId, employeeNumber, comments); @@ -576,6 +597,28 @@ class _ItgDetailScreenState extends State { } } + Widget showLoadingAnimation() { + return Lottie.asset('assets/lottie/loading.json', repeat: true, reverse: false); + } + + void getItgRequestAttachments() async { + try { + isAttachmentLoaded = false; + itgFormAttachmentsList.clear(); + List _itgFormAttachmentsList = + (await WorkListApiClient().getITGFormAttachments(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? ""))!; + if (!isAttachmentLoaded) { + itgFormAttachmentsList = _itgFormAttachmentsList; + } + setState(() { + isAttachmentLoaded = true; + }); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + void reloadITG() { animationIndex = animationIndex + 1; AppState().requestAllList!.removeAt(AppState().itgWorkListIndex!); diff --git a/lib/ui/work_list/itg_fragments/approval_level_fragment.dart b/lib/ui/work_list/itg_fragments/approval_level_fragment.dart index 09e44d4..9d7e94a 100644 --- a/lib/ui/work_list/itg_fragments/approval_level_fragment.dart +++ b/lib/ui/work_list/itg_fragments/approval_level_fragment.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.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'; @@ -20,7 +21,11 @@ class ApprovalLevelfragment extends StatelessWidget { @override Widget build(BuildContext context) { - if (wFHistory.isNotEmpty) wFHistory = wFHistory.reversed.toList(); + if (wFHistory.isNotEmpty) { + //TODO: This COde is Written For Future. If Needed Enable to Filter The Empty Action Requests. + // wFHistory = wFHistory.where((item) => item.action != null && item.action!.isNotEmpty).toList(); + wFHistory = wFHistory.reversed.toList(); + } return Container( width: double.infinity, height: double.infinity, @@ -28,7 +33,7 @@ class ApprovalLevelfragment extends StatelessWidget { itemCount: wFHistory.length, padding: const EdgeInsets.all(21), itemBuilder: (context, index) { - return showItem(context, wFHistory[index]); + return showItem(context, wFHistory[index], index); }, separatorBuilder: (BuildContext context, int index) { return 12.height; @@ -37,7 +42,7 @@ class ApprovalLevelfragment extends StatelessWidget { ); } - Widget showItem(BuildContext context, WFHistory history) { + Widget showItem(BuildContext context, WFHistory history, int index) { return Container( width: double.infinity, decoration: BoxDecoration( @@ -89,7 +94,9 @@ class ApprovalLevelfragment extends StatelessWidget { 8.width, if (history.date!.isNotEmpty) history.date!.toText12(color: MyColors.lightTextColor), ], - ) + ), + 10.height, + getActionDuration(index).toText11(maxLine: 1, color: const Color(0xff1FA269)) ], ), ) @@ -143,8 +150,34 @@ class ApprovalLevelfragment extends StatelessWidget { ); } + String getActionDuration(int index) { + if (wFHistory[index].action!.toLowerCase() == "submit" || wFHistory[index].action!.toLowerCase() == "submitted") { + return ""; + // DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(wFHistory[index].date!); + // Duration duration = DateTime.now().difference(dateTimeFrom); + // return "Action duration: " + DateUtil.formatDuration(duration); + } else if (wFHistory[index].employeeID == AppState().memberInformationList?.eMPLOYEENUMBER) { + if (wFHistory[index + 1].date!.isEmpty || wFHistory[index + 1].date! == "") { + return ""; + } else { + DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(wFHistory[index + 1].date!, isITG: true); + Duration duration = DateTime.now().difference(dateTimeFrom); + return "Action duration: " + DateUtil.formatDuration(duration); + } + } else { + if (wFHistory[index].date!.isEmpty || wFHistory[index].action!.toLowerCase() == "NO ACTION" || wFHistory[index + 1].date! == "") { + return ""; + } else { + DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(wFHistory[index].date!, isITG: true); + DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(wFHistory[index + 1].date!, isITG: true); + Duration duration = dateTimeTo.difference(dateTimeFrom); + return "Action duration: " + DateUtil.formatDuration(duration); + } + } + } + Color getStatusColor(String code) { - if (code.toLowerCase() == "submit") { + if (code.toLowerCase() == "submit" || code.toLowerCase() == "submitted") { return MyColors.grey3AColor; } else if (code.toLowerCase() == "pending") { return MyColors.yellowColor; @@ -152,7 +185,7 @@ class ApprovalLevelfragment extends StatelessWidget { return MyColors.redColor; } else if (code.toLowerCase() == "approved" || code.toLowerCase() == "auto-approve" || code.toLowerCase() == "auto-approved" || code.toLowerCase() == "doable" || code.toLowerCase() == "answer") { return MyColors.greenColor; - } else if (code.toLowerCase() == "requested information" || code.toLowerCase() == "assign" || code.toLowerCase() == "reassign") { + } else if (code.toLowerCase() == "requested information" || code.toLowerCase() == "request information" || code.toLowerCase() == "assign" || code.toLowerCase() == "reassign") { return MyColors.orange; } else { return MyColors.whiteColor; diff --git a/lib/ui/work_list/itg_fragments/attachments_fragment.dart b/lib/ui/work_list/itg_fragments/attachments_fragment.dart new file mode 100644 index 0000000..d31e897 --- /dev/null +++ b/lib/ui/work_list/itg_fragments/attachments_fragment.dart @@ -0,0 +1,78 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/classes/utils.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/models/itg_forms_models/itg_forms_attachments_model.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; +import 'package:open_filex/open_filex.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class ITGAttachmentsFragment extends StatelessWidget { + List itgFormAttachmentsList; + + ITGAttachmentsFragment(this.itgFormAttachmentsList); + + @override + Widget build(BuildContext context) { + return ListView.separated( + itemCount: itgFormAttachmentsList.length, + itemBuilder: (context, index) { + return Row( + children: [ + SvgPicture.asset(determineFileIcon(itgFormAttachmentsList[index].fileType ?? "")), + 12.width, + (itgFormAttachmentsList[index].fileName ?? "").toText16().expanded, + ], + ).objectContainerView().onPress(() async { + try { + String path = await _createFileFromString(itgFormAttachmentsList[index].fileBase64 ?? "", itgFormAttachmentsList[index].fileType ?? ""); + OpenFilex.open(path); + } catch (ex) { + Utils.showToast("Cannot open file."); + } + }); + }, + separatorBuilder: (BuildContext context, int index) => 12.height, + ).paddingAll(21); + } + + String determineFileIcon(String fileContentType) { + String icon = ""; + switch (fileContentType) { + case "pdf": + icon = "assets/images/pdf.svg"; + break; + case "xls": + icon = "assets/images/xls.svg"; + break; + case "xlsx": + icon = "assets/images/xls.svg"; + break; + case "png": + icon = "assets/images/png.svg"; + break; + case "jpg": + icon = "assets/images/jpg.svg"; + break; + case "jpeg": + icon = "assets/images/jpg.svg"; + break; + } + return icon; + } + + Future _createFileFromString(String encodedStr, String ext) async { + Uint8List bytes = base64.decode(encodedStr); + String dir = (await getApplicationDocumentsDirectory()).path; + File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); + await file.writeAsBytes(bytes); + return file.path; + } +} diff --git a/lib/ui/work_list/itg_fragments/request_detail_fragment.dart b/lib/ui/work_list/itg_fragments/request_detail_fragment.dart index 72b20d4..6cd3ea5 100644 --- a/lib/ui/work_list/itg_fragments/request_detail_fragment.dart +++ b/lib/ui/work_list/itg_fragments/request_detail_fragment.dart @@ -1,87 +1 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.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/models/itg_forms_models/fields_model.dart'; -import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; - -class RequestDetailFragment extends StatelessWidget { - List fields; - - RequestDetailFragment({Key? key, this.fields = const []}) : super(key: key); - double itemHeight = 0; - double itemWidth = 0; - @override - Widget build(BuildContext context) { - var size = MediaQuery.of(context).size; - itemHeight = (size.height - kToolbarHeight - 24) / 9; - itemWidth = size.width / 2; - List uiList = [detailView()]; - return Container( - width: double.infinity, - height: double.infinity, - child: fields.isEmpty - ? LocaleKeys.noDataAvailable.tr().toText16().center - : ListView( - padding: const EdgeInsets.all(21), - children: uiList, - ), - ); - } - - Widget detailView() { - bool isOdd = false; - if (fields.length % 2 != 0) { - isOdd = true; - fields.add(new Fields()); - } - return GridView.builder( - itemCount: fields.length, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - if (fields[index].value == null) { - return ItemDetailViewGridItem( - index, - fields[index].title, fields[index].multipleValue?.join(", ") ?? "", - isNeedToShowEmptyDivider: (fields.length == index + 1) - ? isOdd - ? true - : false - : false, - type: fields[index].type, - ); - } - return ItemDetailViewGridItem( - index, - fields[index].title, - fields[index].value ?? "", - isNeedToShowEmptyDivider: (fields.length == index + 1) - ? isOdd - ? true - : false - : false, - type: fields[index].type, - ); - }, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - childAspectRatio: (itemWidth / itemHeight), - ), - ).objectContainerView(); - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) { - if (fields[index].value == null) { - return ItemDetailView(fields[index].title!, fields[index].multipleValue?.join(", ") ?? ""); - } - return ItemDetailView(fields[index].title!, fields[index].value ?? ""); - }, - separatorBuilder: (cxt, index) => 4.height, - itemCount: fields.length) - .objectContainerView(); - } -} +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.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/models/itg/itg_summary_data.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/field_goups_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/fields_model.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; class RequestDetailFragment extends StatelessWidget { List fields; List? fieldGoups; String taskID; ItgTimeCardSummaryData? summaryData; RequestDetailFragment({Key? key, this.fields = const [], this.fieldGoups = const [], this.taskID = "", this.summaryData}) : super(key: key); double itemHeight = 0; double itemWidth = 0; @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; itemHeight = (size.height - kToolbarHeight - 24) / 9; itemWidth = size.width / 2; List uiList = [detailView(fields)]; return Column( mainAxisSize: MainAxisSize.min, children: [ Expanded( child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(21), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: double.infinity, // height: double.infinity, child: fields.isEmpty ? LocaleKeys.noDataAvailable.tr().toText16().center : ListView(shrinkWrap: true, children: uiList), ), 12.height, if (taskID.toLowerCase().contains("vida")) Column( children: [ fieldGoups![2].title!.toText14(), 6.height, detailView(fieldGoups![2].fields!), 12.height, fieldGoups![3].title!.toText14(), 6.height, detailView(fieldGoups![3].fields!), 12.height, fieldGoups![4].title!.toText14(), 6.height, detailView(fieldGoups![4].fields!), ], ), if (summaryData != null && summaryData!.summeries != null && summaryData!.summeries!.isNotEmpty) buildStatsDashboard(summaryData: summaryData), ], ), ), ), ), ], ); } Widget leaveTypeHorizontalList() { return SizedBox( // height: 120, child: ListView( shrinkWrap: true, scrollDirection: Axis.vertical, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0), children: [ _buildLeaveTypeChip( title: 'Half-Day Leave', value: summaryData?.summeries?.first.unpaiDLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/calendar-remove.svg", ), const SizedBox(height: 12), _buildLeaveTypeChip( title: 'Unauthorised Leave', value: summaryData?.summeries?.first.unauthorizeDLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/knight-shield.svg", ), const SizedBox(height: 12), _buildLeaveTypeChip(title: 'Sick Leave', value: summaryData?.summeries?.first.sicKLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/stethoscope.svg"), const SizedBox(height: 12), _buildLeaveTypeChip(title: 'Paid Leave', value: summaryData?.summeries?.first.paiDLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/calendar.svg"), const SizedBox(height: 12), _buildLeaveTypeChip( title: 'Unpaid Leave', value: summaryData?.summeries?.first.unpaiDLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/money-not-found.svg", ), const SizedBox(height: 12), _buildLeaveTypeChip( title: 'Public Holidays', value: summaryData?.summeries?.first.publiCHolidays.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/finger-print-remove.svg", ), ], ), ); } Widget _buildLeaveTypeChip({required String title, required String value, required Color textColor, Color? valueColor, String? topIcon, String? bottomIcon, Widget? child}) { return Container( padding: const EdgeInsets.all(10), height: 110, decoration: BoxDecoration( color: const Color(0xFFEAF1F4), borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 4), ) ], ), child: child ?? Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (topIcon != null) ...[ Row( children: [ Expanded(child: title.toText13(color: textColor)), SvgPicture.asset(topIcon, width: 24), ], ), const SizedBox(height: 21), ] else ...[ title.toText13(color: textColor), const SizedBox(height: 8), ], Row(children: [value.toText24(color: valueColor ?? textColor, isBold: true), const SizedBox(width: 10), if (bottomIcon != null) SvgPicture.asset(bottomIcon, width: 24)]), ], ), ); } Widget buildStatsDashboard({required ItgTimeCardSummaryData? summaryData}) { return Column( children: [ // First row with 2 boxes Row( children: [ buildStatBox( title: 'Missing Swipes', value: summaryData?.summeries?.first.missinGSwipesDays.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/finger-print-remove.svg", ), const SizedBox(width: 15), buildStatBox(title: 'Total Shortage', value: summaryData?.summeries?.first.shortagEHrs ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/time-quarter-pass.svg"), ], ), const SizedBox(height: 15), // Second row with 2 boxes Row( children: [ buildLateInEarlyOutBox( lateInValue: summaryData?.summeries?.first.latEInHrs ?? "0", earlyOutValue: summaryData?.summeries?.first.earlYOutHrs ?? "0", topIcon: "assets/icons/itg/coming-soon.svg", ), const SizedBox(width: 15), buildStatBox( title: 'Uncovered Shortage', value: summaryData?.summeries?.first.uncovereDShortageHrs.toString() ?? "0", textColor: const Color(0xFF3B3D4A), valueColor: const Color(0xFFEB5757), topIcon: "assets/icons/itg/time-quarter.svg", bottomIcon: "assets/icons/itg/alert.svg", ), ], ), const SizedBox(height: 15), Row( children: [ buildStatBox( title: 'Half-Day Leave', value: summaryData?.summeries?.first.unpaiDLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/calendar-remove.svg", ), const SizedBox(width: 15), buildStatBox( title: 'Unauthorised Leave', value: summaryData?.summeries?.first.unauthorizeDLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/knight-shield.svg", ), ], ), const SizedBox(height: 15), Row( children: [ buildStatBox( title: 'Sick Leave', value: summaryData?.summeries?.first.sicKLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/stethoscope.svg", ), const SizedBox(width: 15), buildStatBox( title: 'Paid Leave', value: summaryData?.summeries?.first.paiDLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/calendar.svg", ), ], ), const SizedBox(height: 15), Row( children: [ buildStatBox( title: 'Unpaid Leave', value: summaryData?.summeries?.first.unpaiDLeaves.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/money-not-found.svg", ), const SizedBox(width: 15), buildStatBox( title: 'Public Holidays', value: summaryData?.summeries?.first.publiCHolidays.toString() ?? "0", textColor: const Color(0xFF3B3D4A), topIcon: "assets/icons/itg/finger-print-remove.svg", ), ], ), const SizedBox(height: 15), ], ); } Widget buildStatBox({required String title, required String value, required Color textColor, Color? valueColor, String? topIcon, String? bottomIcon, Widget? child}) { return Expanded( child: Container( padding: const EdgeInsets.all(10), height: 110, decoration: BoxDecoration( color: const Color(0xFFEAF1F4), borderRadius: BorderRadius.circular(8), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 4))], ), child: child ?? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (topIcon != null) ...[ Row(children: [Expanded(child: title.toText13(color: textColor)), SvgPicture.asset(topIcon, width: 24)]), Expanded(child: SizedBox(),), ] else ...[ title.toText13(color: textColor), const SizedBox(height: 8), ], Row(children: [value.toText24(color: valueColor ?? textColor, isBold: true), const SizedBox(width: 10), if (bottomIcon != null) SvgPicture.asset(bottomIcon, width: 20)]), ], ), ), ); } Widget buildLateInEarlyOutBox({required String lateInValue, required String earlyOutValue, required String topIcon}) { return buildStatBox( title: 'Late In / Early Out', textColor: const Color(0xFFEB5757), topIcon: topIcon, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: ["Late In / Early Out".toText13(color: const Color(0xFF3B3D4A)), const Expanded(child: SizedBox()), SvgPicture.asset(topIcon, width: 24)]), Expanded(child: SizedBox(),), RichText( text: TextSpan( style: const TextStyle(fontSize: 13), children: [ const TextSpan(text: 'Late In : ', style: TextStyle(color: Color(0xFF767676), fontSize: 14)), TextSpan(text: lateInValue, style: const TextStyle(color: Color(0xFF3B3D4A), fontSize: 16, fontWeight: FontWeight.w700)), ], ), ), RichText( text: TextSpan( style: const TextStyle(fontSize: 13), children: [ const TextSpan(text: 'Early Out : ', style: TextStyle(color: Color(0xFF767676), fontSize: 14)), TextSpan(text: earlyOutValue, style: const TextStyle(color: Color(0xFF3B3D4A), fontSize: 16, fontWeight: FontWeight.w700)), ], ), ), ], ), value: '', ); } Widget detailView(List fieldsF) { List fields = List.from(fieldsF); bool isOdd = false; if (fields.length % 2 != 0) { isOdd = true; fields.add(new Fields()); } int descriptionFormatIndex = fields.indexWhere((element) => element.title == "Description Format" || element.title == "Description Format"); // todo add arabic in future Widget? descriptionFormatView; if (descriptionFormatIndex >= 0) { Fields descriptionFormat = fields[descriptionFormatIndex]; fields.removeAt(descriptionFormatIndex); descriptionFormatView = ItemDetailViewGridItem( 2, descriptionFormat.title, descriptionFormat.value == null ? (descriptionFormat.multipleValue?.join(", ") ?? "") : descriptionFormat.value ?? "", type: descriptionFormat.type, maxLine: 0, ); } return Column( mainAxisSize: MainAxisSize.min, children: [ GridView.builder( itemCount: fields.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { if (fields[index].value == null) { return ItemDetailViewGridItem( index, fields[index].title, fields[index].multipleValue?.join(", ") ?? "", isNeedToShowEmptyDivider: (fields.length == index + 1) ? isOdd ? true : false : false, type: fields[index].type, ); } return ItemDetailViewGridItem( index, fields[index].title, fields[index].value ?? "", isNeedToShowEmptyDivider: (fields.length == index + 1) ? isOdd ? true : false : false, type: fields[index].type, ); }, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: (itemWidth / itemHeight)), ), if (descriptionFormatView != null) descriptionFormatView, ], ).objectContainerView(); return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (cxt, index) { if (fields[index].value == null) { return ItemDetailView(fields[index].title!, fields[index].multipleValue?.join(", ") ?? ""); } return ItemDetailView(fields[index].title!, fields[index].value ?? ""); }, separatorBuilder: (cxt, index) => 4.height, itemCount: fields.length, ).objectContainerView(); } } \ No newline at end of file diff --git a/lib/ui/work_list/sheets/delegate_sheet.dart b/lib/ui/work_list/sheets/delegate_sheet.dart index d505099..d72b041 100644 --- a/lib/ui/work_list/sheets/delegate_sheet.dart +++ b/lib/ui/work_list/sheets/delegate_sheet.dart @@ -264,93 +264,93 @@ class _DelegateSheetState extends State { width: double.infinity, child: selectedFavLetter == null && favLetters != null ? Container( - width: double.infinity, - alignment: Alignment.center, - child: "Please select letter to see Fav results".toText12(), - ) + width: double.infinity, + alignment: Alignment.center, + child: "Please select letter to see Fav results".toText12(), + ) : favUsersList != null - ? ListView.separated( - itemBuilder: (context, index) { - return showFavUserItem(favUsersList![index]); - }, - separatorBuilder: (context, index) { - return Container( - color: MyColors.borderColor, - width: double.infinity, - height: 1, - margin: EdgeInsets.only(top: 8, bottom: 8), - ).onPress(() {}); - }, - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: favUsersList!.length, - padding: EdgeInsets.only(top: 8, bottom: 8), - ) - : isNeedEnableTextField && replacementList == null - ? Container( - width: double.infinity, - alignment: Alignment.center, - child: "Search User".toText12(), - ) - : isNeedEnableTextField && replacementList!.length == 0 - ? Container( - width: double.infinity, - alignment: Alignment.center, - child: "No Data Found".toText12(), - ) - : isNeedEnableTextField - ? ListView.separated( - itemBuilder: (context, index) { - return showInputUserItem(replacementList![index]); - }, - separatorBuilder: (context, index) { - return Container( - color: MyColors.borderE3Color, - width: double.infinity, - height: 1, - margin: EdgeInsets.only(top: 8, bottom: 8), - ); - }, - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: replacementList!.length, - padding: EdgeInsets.only(top: 8, bottom: 8), - ) - : (widget.wFHistory != null - ? ListView.separated( - itemBuilder: (context, index) { - return showItgItem(widget.wFHistory![index]); - }, - separatorBuilder: (context, index) { - return Container( - color: MyColors.borderE3Color, - width: double.infinity, - height: 1, - margin: EdgeInsets.only(top: 8, bottom: 8), - ); - }, - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: widget.wFHistory!.length, - padding: EdgeInsets.only(top: 8, bottom: 8), - ) - : ListView.separated( - itemBuilder: (context, index) { - return showItem(widget.actionHistoryList![index]); - }, - separatorBuilder: (context, index) { - return Container( - color: MyColors.borderE3Color, - width: double.infinity, - height: 1, - margin: EdgeInsets.only(top: 8, bottom: 8), - ); - }, - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: widget.actionHistoryList!.length, - padding: EdgeInsets.only(top: 8, bottom: 8), - )), + ? ListView.separated( + itemBuilder: (context, index) { + return showFavUserItem(favUsersList![index]); + }, + separatorBuilder: (context, index) { + return Container( + color: MyColors.borderColor, + width: double.infinity, + height: 1, + margin: EdgeInsets.only(top: 8, bottom: 8), + ).onPress(() {}); + }, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: favUsersList!.length, + padding: EdgeInsets.only(top: 8, bottom: 8), + ) + : isNeedEnableTextField && replacementList == null + ? Container( + width: double.infinity, + alignment: Alignment.center, + child: "Search User".toText12(), + ) + : isNeedEnableTextField && replacementList!.length == 0 + ? Container( + width: double.infinity, + alignment: Alignment.center, + child: "No Data Found".toText12(), + ) + : isNeedEnableTextField + ? ListView.separated( + itemBuilder: (context, index) { + return showInputUserItem(replacementList![index]); + }, + separatorBuilder: (context, index) { + return Container( + color: MyColors.borderE3Color, + width: double.infinity, + height: 1, + margin: EdgeInsets.only(top: 8, bottom: 8), + ); + }, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: replacementList!.length, + padding: EdgeInsets.only(top: 8, bottom: 8), + ) + : (widget.wFHistory != null + ? ListView.separated( + itemBuilder: (context, index) { + return showItgItem(widget.wFHistory![index]); + }, + separatorBuilder: (context, index) { + return Container( + color: MyColors.borderE3Color, + width: double.infinity, + height: 1, + margin: EdgeInsets.only(top: 8, bottom: 8), + ); + }, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: widget.wFHistory!.length, + padding: EdgeInsets.only(top: 8, bottom: 8), + ) + : ListView.separated( + itemBuilder: (context, index) { + return showItem(widget.actionHistoryList![index]); + }, + separatorBuilder: (context, index) { + return Container( + color: MyColors.borderE3Color, + width: double.infinity, + height: 1, + margin: EdgeInsets.only(top: 8, bottom: 8), + ); + }, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: widget.actionHistoryList!.length, + padding: EdgeInsets.only(top: 8, bottom: 8), + )), ), ), if (favLetters != null) @@ -392,7 +392,7 @@ class _DelegateSheetState extends State { ), DefaultButton( "Cancel", - () { + () { Navigator.pop(context); }, textColor: Colors.black, @@ -500,28 +500,28 @@ class _DelegateSheetState extends State { children: [ actionHistory.employeeImage != "" ? CircularAvatar( - url: actionHistory.employeeImage, - height: 40, - width: 40, - isImageBase64: (actionHistory.employeeImage != null || actionHistory.employeeImage!.isNotEmpty) ? true : false, - ) + url: actionHistory.employeeImage, + height: 40, + width: 40, + isImageBase64: (actionHistory.employeeImage != null || actionHistory.employeeImage!.isNotEmpty) ? true : false, + ) : isImageLoaded - ? CircularAvatar( - height: 40, - width: 40, - isImageBase64: false, - ) - : ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(50), - ), - child: Image.network( - "https://play-lh.googleusercontent.com/NPo88ojmhah4HDiposucJmfQIop4z4xc8kqJK9ITO9o-yCab2zxIp7PPB_XPj2iUojo", - fit: BoxFit.cover, - height: 40, - width: 40, - ).toShimmer(), - ), + ? CircularAvatar( + height: 40, + width: 40, + isImageBase64: false, + ) + : ClipRRect( + borderRadius: const BorderRadius.all( + Radius.circular(50), + ), + child: Image.network( + "https://play-lh.googleusercontent.com/NPo88ojmhah4HDiposucJmfQIop4z4xc8kqJK9ITO9o-yCab2zxIp7PPB_XPj2iUojo", + fit: BoxFit.cover, + height: 40, + width: 40, + ).toShimmer(), + ), 16.width, Expanded( child: (actionHistory.employeeDisplayName ?? "").toText12(), diff --git a/lib/ui/work_list/sheets/selected_item_sheet.dart b/lib/ui/work_list/sheets/selected_item_sheet.dart index 2efe88b..9b98c8b 100644 --- a/lib/ui/work_list/sheets/selected_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_item_sheet.dart @@ -175,7 +175,7 @@ class SelectedItemSheet extends StatelessWidget { if (favoriteReplacements != null) empID = favoriteReplacements!.userName; if (replacementList != null) empID = replacementList!.userName; try { - memberInformationListModel = await WorkListApiClient().getUserInformation(-999, empID!); + memberInformationListModel = await WorkListApiClient().getNotificationUserInformation(-999, empID!, notificationID!); if (actionHistoryList != null) empID = actionHistoryList!.eMPLOYEEIMAGE = memberInformationListModel!.eMPLOYEEIMAGE ?? AppState().getBase64ImageEmp; if (favoriteReplacements != null) empID = favoriteReplacements!.employeeImage = memberInformationListModel!.eMPLOYEEIMAGE ?? AppState().getBase64ImageEmp; if (replacementList != null) empID = replacementList!.employeeImage = memberInformationListModel!.eMPLOYEEIMAGE ?? AppState().getBase64ImageEmp; diff --git a/lib/ui/work_list/sheets/update_continue_sheet.dart b/lib/ui/work_list/sheets/update_continue_sheet.dart index 1240de2..42632a8 100644 --- a/lib/ui/work_list/sheets/update_continue_sheet.dart +++ b/lib/ui/work_list/sheets/update_continue_sheet.dart @@ -38,7 +38,7 @@ class _UpdateContinueSheetState extends State { var size = MediaQuery.of(context).size; itemHeight = (size.height - kToolbarHeight - 24) / 9; itemWidth = size.width / 2; - return Column( + return Column( children: [ if ((widget.workListData?.sUBJECT ?? "").isNotEmpty) widget.workListData!.sUBJECT!.toText14().paddingOnly(top: 10, right: 21, left: 21, bottom: 21), ListView.separated( diff --git a/lib/ui/work_list/work_list_screen.dart b/lib/ui/work_list/work_list_screen.dart index 9dea0a1..d659ea6 100644 --- a/lib/ui/work_list/work_list_screen.dart +++ b/lib/ui/work_list/work_list_screen.dart @@ -36,49 +36,106 @@ class WorkListScreen extends StatefulWidget { class _WorkListScreenState extends State { List workListItemTypes = [ WorkListItemTypeModelData( - value: 0, - name: 'HR', - fullName: LocaleKeys.humanResource.tr(), - active: false, - color: [Color(0xff32D892), Color(0xff1AB170)], - icon: "assets/images/miss_swipe.svg", - key: 'HRSSA', - disable: false), + value: 0, + name: 'HR', + fullName: LocaleKeys.humanResource.tr(), + active: false, + color: [Color(0xff32D892), Color(0xff1AB170)], + icon: "assets/images/miss_swipe.svg", + key: 'HRSSA', + disable: false, + ), WorkListItemTypeModelData( - value: 0, name: 'MR', fullName: LocaleKeys.moveOrder.tr(), active: false, color: [Color(0xff58DCFA), Color(0xff3CB9D5)], icon: "assets/images/miss_swipe.svg", key: 'INVMOA', disable: false), + value: 0, + name: 'MR', + fullName: LocaleKeys.moveOrder.tr(), + active: false, + color: [Color(0xff58DCFA), Color(0xff3CB9D5)], + icon: "assets/images/miss_swipe.svg", + key: 'INVMOA', + disable: false, + ), WorkListItemTypeModelData( - value: 0, - name: 'PR', - fullName: LocaleKeys.purchaseRequisition.tr(), - active: false, - color: [Color(0xff48EACF), Color(0xff3DCAB3)], - icon: "assets/images/miss_swipe.svg", - key: 'REQAPPRV', - disable: false), + value: 0, + name: 'PR', + fullName: LocaleKeys.purchaseRequisition.tr(), + active: false, + color: [Color(0xff48EACF), Color(0xff3DCAB3)], + icon: "assets/images/miss_swipe.svg", + key: 'REQAPPRV', + disable: false, + ), WorkListItemTypeModelData( - value: 0, - name: 'PO', - fullName: LocaleKeys.purchaseOrder.tr(), - active: false, - color: [Color(0xff5099E3), Color(0xff3670AA)], - icon: "assets/images/miss_swipe.svg", - key: 'POAPPRV', - disable: false), + value: 0, + name: 'PO', + fullName: LocaleKeys.purchaseOrder.tr(), + active: false, + color: [Color(0xff5099E3), Color(0xff3670AA)], + icon: "assets/images/miss_swipe.svg", + key: 'POAPPRV', + disable: false, + ), WorkListItemTypeModelData( - value: 0, name: 'ITG', fullName: LocaleKeys.ITGForms.tr(), active: false, color: [Color(0xffEB8C90), Color(0xffDE6C70)], icon: "assets/images/miss_swipe.svg", key: 'ITG', disable: false), + value: 0, + name: 'ITG', + fullName: LocaleKeys.ITGForms.tr(), + active: false, + color: [Color(0xffEB8C90), Color(0xffDE6C70)], + icon: "assets/images/miss_swipe.svg", + key: 'ITG', + disable: false, + ), WorkListItemTypeModelData( - value: 0, - name: 'IC', - fullName: LocaleKeys.itemCreation.tr(), - active: false, - color: [Color(0xff32D892), Color(0xff1AB170)], - icon: "assets/images/miss_swipe.svg", - key: 'INVITEM', - disable: false), + value: 0, + name: 'IC', + fullName: LocaleKeys.itemCreation.tr(), + active: false, + color: [Color(0xff32D892), Color(0xff1AB170)], + icon: "assets/images/miss_swipe.svg", + key: 'INVITEM', + disable: false, + ), WorkListItemTypeModelData( - value: 0, name: 'STAMP', fullName: LocaleKeys.stamp.tr(), active: false, color: [Color(0xff32D892), Color(0xff1AB170)], icon: "assets/images/miss_swipe.svg", key: 'STAMP', disable: false), + value: 0, + name: 'STAMP', + fullName: LocaleKeys.stamp.tr(), + active: false, + color: [Color(0xff32D892), Color(0xff1AB170)], + icon: "assets/images/miss_swipe.svg", + key: 'STAMP', + disable: false, + ), WorkListItemTypeModelData( - value: 0, name: 'COC', fullName: LocaleKeys.itemCreation.tr(), active: false, color: [Color(0xff787299), Color(0xff1AB170)], icon: "assets/images/miss_swipe.svg", key: 'COC', disable: true) + value: 0, + name: 'COC', + fullName: LocaleKeys.itemCreation.tr(), + active: false, + color: [Color(0xff787299), Color(0xff1AB170)], + icon: "assets/images/miss_swipe.svg", + key: 'COC', + disable: true, + ), + WorkListItemTypeModelData( + value: 0, + name: 'Payment Req', + fullName: LocaleKeys.paymentRequest.tr(), + active: false, + color: [Color(0xff42d7bf), Color(0xff42d7bf)], + icon: "assets/images/PR.svg", + key: 'PAY_REQ', + disable: false, + ), + WorkListItemTypeModelData( + value: 0, + name: 'FA Disposal Request ', + fullName: LocaleKeys.faRequest.tr(), + active: false, + color: [Color(0xff42d7bf), Color(0xff42d7bf)], + icon: "assets/images/miss_swipe.svg", + key: 'HMG_FA_D', + disable: false, + ), + ]; int? workListItemIndex; @@ -168,6 +225,7 @@ class _WorkListScreenState extends State { }); requestAllList = requestAllList + (itgFormsModel?.requestType![i].requestDetails ?? []); } + AppState().setRequestAllList = requestAllList; itgFormsModel?.requestType!.insert(0, RequestType(requestDetails: requestAllList, requestTypeCode: "all", requestTypeName: "All")); if ((itgFormsModel?.requestType?.length ?? 0) > 0) { @@ -196,10 +254,7 @@ class _WorkListScreenState extends State { _refreshController.refreshCompleted(); Utils.showLoading(context); pageNumber = 1; - List dataOnRefresh = await Future.wait([ - providerData.fetchWorkListCounter(context, showLoading: false), - getWorkList(showLoading: false, isCallingFromRefresh: true), - ]); + List dataOnRefresh = await Future.wait([providerData.fetchWorkListCounter(context, showLoading: false), getWorkList(showLoading: false, isCallingFromRefresh: true)]); calculateCounter(); Utils.hideLoading(context); setState(() {}); @@ -229,131 +284,137 @@ class _WorkListScreenState extends State { return Scaffold( backgroundColor: Colors.white, appBar: AppBarWidget(context, title: LocaleKeys.workList.tr(), showWorkListSettingButton: true), - body: workListItemIndex == null - ? Utils.getNoDataWidget(context) - : SizedBox( - width: double.infinity, - height: double.infinity, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 40, - child: ListView.separated( - controller: _controller, - itemBuilder: (context, index) { - return Container( - padding: const EdgeInsets.only(left: 21, right: 21, top: 8, bottom: 8), - alignment: Alignment.center, - decoration: BoxDecoration(borderRadius: BorderRadius.circular(6), color: workListItemIndex == index ? MyColors.darkIconColor : MyColors.lightGreyEAColor), - child: ("${workListItemTypes[index].name} ${workListItemTypes[index].value > 0 ? "(${workListItemTypes[index].value})" : ""}") - .toText12(color: workListItemIndex == index ? MyColors.white : MyColors.black), - ).onPress(() { - if (pNotificationType != 1) { - pNotificationType = 1; - } - if (workListItemIndex != index && !workListItemTypes[index].disable) { - workListItemIndex = index; - pageNumber = 1; - if (workListItemTypes[index].value == 0) { - workList = []; - itgRequestTypeIndex = null; - } else { - workList = null; + body: + workListItemIndex == null + ? Utils.getNoDataWidget(context) + : SizedBox( + width: double.infinity, + height: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 40, + child: ListView.separated( + controller: _controller, + itemBuilder: (context, index) { + return Container( + padding: const EdgeInsets.only(left: 21, right: 21, top: 8, bottom: 8), + alignment: Alignment.center, + decoration: BoxDecoration(borderRadius: BorderRadius.circular(6), color: workListItemIndex == index ? MyColors.darkIconColor : MyColors.lightGreyEAColor), + child: ("${workListItemTypes[index].name} ${workListItemTypes[index].value > 0 ? "(${workListItemTypes[index].value})" : ""}").toText12( + color: workListItemIndex == index ? MyColors.white : MyColors.black, + ), + ).onPress(() { + if (pNotificationType != 1) { + pNotificationType = 1; } - setState(() {}); - if (workListItemTypes[index].value > 0) { - getWorkList(); + if (workListItemIndex != index && !workListItemTypes[index].disable) { + workListItemIndex = index; + pageNumber = 1; + if (workListItemTypes[index].value == 0) { + workList = []; + itgRequestTypeIndex = null; + } else { + workList = null; + } + setState(() {}); + if (workListItemTypes[index].value > 0) { + getWorkList(); + } } - } - }); - }, - separatorBuilder: (context, index) => 8.width, - shrinkWrap: true, - itemCount: workListItemTypes.length, - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.only(left: 21, right: 21), + }); + }, + separatorBuilder: (context, index) => 8.width, + shrinkWrap: true, + itemCount: workListItemTypes.length, + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.only(left: 21, right: 21), + ), + ).paddingOnly(top: 21, bottom: 21), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + workListItemTypes[workListItemIndex!].fullName.toSectionHeading().paddingOnly(left: 21, right: 21), + LocaleKeys.advancedSearch + .tr() + .toText14(isUnderLine: true, color: MyColors.textMixColor) + .onPress(() { + openBottomSheet(context); + }) + .paddingOnly(left: 21, right: 21), + ], ), - ).paddingOnly(top: 21, bottom: 21), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - workListItemTypes[workListItemIndex!].fullName.toSectionHeading().paddingOnly(left: 21, right: 21), - LocaleKeys.advancedSearch.tr().toText14(isUnderLine: true, color: MyColors.textMixColor).onPress(() { - openBottomSheet(context); - }).paddingOnly(left: 21, right: 21) - ], - ), - SmartRefresher( + SmartRefresher( enablePullDown: true, enablePullUp: false, - header: const MaterialClassicHeader( - color: MyColors.gradiantEndColor, - ), + header: const MaterialClassicHeader(color: MyColors.gradiantEndColor), controller: _refreshController, onRefresh: _onRefresh, scrollController: _scrollController, child: SingleChildScrollView( physics: const BouncingScrollPhysics(), - child: itgRequestTypeIndex != null - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // todo this is commented for temporary purpose, have issue when selecting any itg category and click any item showing wrong details - // SizedBox( - // height: 40, - // child: ListView.separated( - // itemBuilder: (context, index) { - // RequestType type = itgFormsModel!.requestType![index]; - // return Container( - // padding: const EdgeInsets.only(left: 21, right: 21, top: 8, bottom: 8), - // alignment: Alignment.center, - // decoration: BoxDecoration(borderRadius: BorderRadius.circular(30), color: itgRequestTypeIndex == index ? MyColors.darkIconColor : MyColors.lightGreyEAColor), - // child: ("${type.requestTypeName}").toText12(color: itgRequestTypeIndex == index ? MyColors.white : MyColors.black), - // ).onPress(() { - // if (itgRequestTypeIndex != index) { - // itgRequestTypeIndex = index; - // setState(() {}); - // } - // }); - // }, - // separatorBuilder: (context, index) => 8.width, - // shrinkWrap: true, - // itemCount: itgFormsModel?.requestType?.length ?? 0, - // scrollDirection: Axis.horizontal, - // padding: const EdgeInsets.only(left: 21, right: 21), - // ), - // ).paddingOnly(top: 16, bottom: 16), - ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - return itgRowItem(workListItemTypes[workListItemIndex!], itgFormsModel!.requestType![itgRequestTypeIndex!].requestDetails![index], index); - }, - separatorBuilder: (context, index) => 12.height, - itemCount: itgFormsModel!.requestType![itgRequestTypeIndex!].requestDetails?.length ?? 0, - padding: const EdgeInsets.all(21), - ), - ], - ) - : workList != null + child: + itgRequestTypeIndex != null + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // todo this is commented for temporary purpose, have issue when selecting any itg category and click any item showing wrong details + // SizedBox( + // height: 40, + // child: ListView.separated( + // itemBuilder: (context, index) { + // RequestType type = itgFormsModel!.requestType![index]; + // return Container( + // padding: const EdgeInsets.only(left: 21, right: 21, top: 8, bottom: 8), + // alignment: Alignment.center, + // decoration: BoxDecoration(borderRadius: BorderRadius.circular(30), color: itgRequestTypeIndex == index ? MyColors.darkIconColor : MyColors.lightGreyEAColor), + // child: ("${type.requestTypeName}").toText12(color: itgRequestTypeIndex == index ? MyColors.white : MyColors.black), + // ).onPress(() { + // if (itgRequestTypeIndex != index) { + // itgRequestTypeIndex = index; + // setState(() {}); + // } + // }); + // }, + // separatorBuilder: (context, index) => 8.width, + // shrinkWrap: true, + // itemCount: itgFormsModel?.requestType?.length ?? 0, + // scrollDirection: Axis.horizontal, + // padding: const EdgeInsets.only(left: 21, right: 21), + // ), + // ).paddingOnly(top: 16, bottom: 16), + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return itgRowItem(workListItemTypes[workListItemIndex!], itgFormsModel!.requestType![itgRequestTypeIndex!].requestDetails![index], index); + }, + separatorBuilder: (context, index) => 12.height, + itemCount: itgFormsModel!.requestType![itgRequestTypeIndex!].requestDetails?.length ?? 0, + padding: const EdgeInsets.all(21), + ), + ], + ) + : workList != null ? ((workList!).isEmpty ? Utils.getNoDataWidget(context).paddingOnly(top: 100) : ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - return rowItem(workListItemTypes[workListItemIndex!], workList![index], index); - }, - separatorBuilder: (context, index) => 12.height, - itemCount: workList?.length ?? 0, - padding: const EdgeInsets.all(21), - )) + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return rowItem(workListItemTypes[workListItemIndex!], workList![index], index); + }, + separatorBuilder: (context, index) => 12.height, + itemCount: workList?.length ?? 0, + padding: const EdgeInsets.all(21), + )) : const SizedBox(), - )).expanded, - ], + ), + ).expanded, + ], + ), ), - ), ); } @@ -385,13 +446,7 @@ class _WorkListScreenState extends State { decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], + boxShadow: [BoxShadow(color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3))], ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -506,13 +561,7 @@ class _WorkListScreenState extends State { decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], + boxShadow: [BoxShadow(color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3))], ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -552,10 +601,6 @@ class _WorkListScreenState extends State { } void _animateToIndex(int index, double width) { - _controller.animateTo( - index * width, - duration: const Duration(seconds: 1), - curve: Curves.fastOutSlowIn, - ); + _controller.animateTo(index * width, duration: const Duration(seconds: 1), curve: Curves.fastOutSlowIn); } } diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index c80f1b4..6bf8ea9 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -23,12 +23,15 @@ import 'package:mohem_flutter_app/models/get_stamp_ms_notification_body_list_mod import 'package:mohem_flutter_app/models/get_stamp_ns_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart'; +import 'package:mohem_flutter_app/models/termination/termination_notification_body.dart'; import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; +import 'package:mohem_flutter_app/models/worklist/get_fad_notifications.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_address_notification_body_list.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/payment_details_list.dart'; import 'package:mohem_flutter_app/models/worklist_response_model.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/ui/work_list/sheets/delegate_sheet.dart'; @@ -44,8 +47,6 @@ import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dialogs/accept_reject_input_dialog.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; -import 'package:mohem_flutter_app/models/termination/termination_notification_body.dart'; - class WorkListDetailScreen extends StatefulWidget { WorkListDetailScreen({Key? key}) : super(key: key); @@ -61,6 +62,7 @@ class _WorkListDetailScreenState extends State { int animationIndex = 0; PageController controller = PageController(); bool showFabOptions = false; + bool isShowActions = false; WorkListResponseModel? workListData; MemberInformationListModel? memberInformationListModel; @@ -84,14 +86,14 @@ class _WorkListDetailScreenState extends State { List? getAddressNotificationBodyList = []; List? getTerminationNotificationBodyList = []; - GenericResponseModel? getBasicNTFBody; GenericResponseModel? getICBody; GenericResponseModel? subordinatesLeavesModel; GetPoNotificationBodyList? getPoNotificationBody; GetPrNotificationBodyList? getPrNotificationBody; GetItemCreationNtfBodyList? getItemCreationNtfBody; - + GetPaymentNotificationBodyList? getPaymentNotificationBodyList; + GetFaDisposalNtfDetails? getFADNotificationBody; bool isCloseAvailable = false; bool isApproveAvailable = false; bool isRejectAvailable = false; @@ -129,7 +131,7 @@ class _WorkListDetailScreenState extends State { getAbsenceCollectionNotificationBodyList!.clear(); getContactNotificationBodyList = null; getAddressNotificationBodyList!.clear(); - + getPaymentNotificationBodyList = null; if (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") { getUserInformation(); } @@ -142,6 +144,8 @@ class _WorkListDetailScreenState extends State { if (workListData!.iTEMTYPE == "HRSSA") { if (workListData!.rEQUESTTYPE == "EIT") { getEitNotificationBody(); + } else if (workListData!.rEQUESTTYPE == "CEI") { + getCEINotificationBody(); } else if (workListData!.rEQUESTTYPE == "PHONE_NUMBERS") { getPhonesNotificationBody(); } else if (workListData!.rEQUESTTYPE == "BASIC_DETAILS") { @@ -152,7 +156,7 @@ class _WorkListDetailScreenState extends State { getContactNotificationBody(); } else if (workListData!.rEQUESTTYPE == "ADDRESS") { getAddressNotificationBody(); - } else if(workListData!.rEQUESTTYPE =='TERMINATION'){ + } else if (workListData!.rEQUESTTYPE == 'TERMINATION') { getTerminationNotificationBody(); } } @@ -171,6 +175,12 @@ class _WorkListDetailScreenState extends State { if (workListData!.iTEMTYPE == "REQAPPRV") { getPRNotification(); } + if (workListData!.iTEMTYPE == "PAY_REQ") { + getPaymentNotification(); + } + if (workListData!.iTEMTYPE == "HMG_FA_D") { + getFADNotification(); + } if (controller.hasClients) { controller.jumpToPage(0); @@ -245,7 +255,7 @@ class _WorkListDetailScreenState extends State { if ((workListData?.sUBJECT ?? "").isNotEmpty) workListData!.sUBJECT!.toText14().paddingOnly(top: 20, right: 21, left: 21), PageView( controller: controller, - onPageChanged: (pageIndex) { + onPageChanged: (int pageIndex) { setState(() { tabIndex = pageIndex; }); @@ -264,9 +274,11 @@ class _WorkListDetailScreenState extends State { getAbsenceCollectionNotificationBodyList: getAbsenceCollectionNotificationBodyList, getContactNotificationBodyList: getContactNotificationBodyList, getPrNotificationBodyList: getPrNotificationBody, - getTerminationNotificationBodyList:getTerminationNotificationBodyList + getTerminationNotificationBodyList: getTerminationNotificationBodyList, + getPaymentNotificationBodyList: getPaymentNotificationBodyList, + getFADNotificationBodyList: getFADNotificationBody ), - (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") + (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP" || workListData!.iTEMTYPE == "PAY_REQ") ? DetailFragment(workListData, memberInformationListModel) : RequestFragment( moNotificationBodyList: getMoNotificationBodyList, @@ -280,6 +292,7 @@ class _WorkListDetailScreenState extends State { : ActionsFragment( workListData!.nOTIFICATIONID, actionHistoryList, + isShowActions, voidCallback: reloadWorkList, ) : showLoadingAnimation(), @@ -291,50 +304,52 @@ class _WorkListDetailScreenState extends State { ], ).expanded, if (isApproveAvailable || isRejectAvailable || isCloseAvailable) - Container( - padding: const EdgeInsets.only(top: 14, bottom: 14, left: 21, right: 21), - decoration: const BoxDecoration( - color: Colors.white, - border: Border( - top: BorderSide(color: MyColors.lightGreyEFColor, width: 1.0), + SafeArea( + child: Container( + padding: const EdgeInsets.only(top: 14, bottom: 14, left: 21, right: 21), + decoration: const BoxDecoration( + color: Colors.white, + border: Border( + top: BorderSide(color: MyColors.lightGreyEFColor, width: 1.0), + ), + ), + child: Row( + children: [ + if (isRejectAvailable) + DefaultButton( + LocaleKeys.reject.tr(), + () => performAction(rejectAction), + colors: const [Color(0xffE47A7E), Color(0xffDE6D71)], + ).expanded, + if (isApproveAvailable && isRejectAvailable) 8.width, + if (isApproveAvailable) + DefaultButton( + LocaleKeys.approve.tr(), + () => performAction(approveAction), + colors: const [Color(0xff28C884), Color(0xff1BB271)], + ).expanded, + if (isCloseAvailable) + DefaultButton( + LocaleKeys.ok.tr(), + () => performAction("CLOSE"), + colors: const [Color(0xff32D892), Color(0xff1AB170)], + ).expanded, + 8.width, + Container( + height: 43, + width: 43, + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: MyColors.lightGreyE6Color, + ), + child: Icon(showFabOptions ? Icons.more_vert_rounded : Icons.more_horiz_rounded, color: MyColors.darkIconColor), + ).onPress(() { + setState(() { + showFabOptions = true; + }); + }) + ], ), - ), - child: Row( - children: [ - if (isRejectAvailable) - DefaultButton( - LocaleKeys.reject.tr(), - () => performAction(rejectAction), - colors: const [Color(0xffE47A7E), Color(0xffDE6D71)], - ).expanded, - if (isApproveAvailable && isRejectAvailable) 8.width, - if (isApproveAvailable) - DefaultButton( - LocaleKeys.approve.tr(), - () => performAction(approveAction), - colors: const [Color(0xff28C884), Color(0xff1BB271)], - ).expanded, - if (isCloseAvailable) - DefaultButton( - LocaleKeys.ok.tr(), - () => performAction("CLOSE"), - colors: const [Color(0xff32D892), Color(0xff1AB170)], - ).expanded, - 8.width, - Container( - height: 43, - width: 43, - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: MyColors.lightGreyE6Color, - ), - child: Icon(showFabOptions ? Icons.more_vert_rounded : Icons.more_horiz_rounded, color: MyColors.darkIconColor), - ).onPress(() { - setState(() { - showFabOptions = true; - }); - }) - ], ), ) ], @@ -499,6 +514,12 @@ class _WorkListDetailScreenState extends State { case "APPROVE": performAction(notificationButton.bUTTONACTION!); break; + case "TRY_APPROVE_AGAIN": + performAction(notificationButton.bUTTONACTION!); + break; + case "SEND_BACK_TO_PREPARER": + performAction(notificationButton.bUTTONACTION!); + break; case "UPDATE_ACTION": showMyBottomSheet( context, @@ -513,6 +534,7 @@ class _WorkListDetailScreenState extends State { case "CONTINUE_ACTION": showMyBottomSheet( context, + type: "CONTINUE_ACTION", callBackFunc: reloadWorkList, child: UpdateContinueSheet( workListData: workListData, @@ -586,7 +608,7 @@ class _WorkListDetailScreenState extends State { Future performNetworkCall(BuildContext context, {String? email, String? userId}) async { showDialog( context: context, - builder: (cxt) => ConfirmDialog( + builder: (BuildContext cxt) => ConfirmDialog( message: LocaleKeys.wantToReject.tr(), okTitle: LocaleKeys.reject.tr(), onTap: () async { @@ -666,29 +688,45 @@ class _WorkListDetailScreenState extends State { } void performAction(String actionMode, {String? title}) { + String question = ""; + if (actionMode == "ANSWER_INFO") { + List list = actionHistoryList.where((element) => element.aCTIONCODE == "REQUEST_INFO").toList(); + if (list.isNotEmpty) { + question = "${list.first.aCTION}: ${list.first.nOTE}"; + } + } showDialog( context: context, - builder: (cxt) => AcceptRejectInputDialog( - message: title != null ? null : LocaleKeys.requestedItems.tr(), + builder: (BuildContext cxt) => AcceptRejectInputDialog( + message: question, title: title, notificationGetRespond: notificationNoteInput, actionMode: actionMode, - onTap: (note) { + onTap: (String note) { + List> responseAttribute = []; + + for (var element in getNotificationRespondAttributes!) { + responseAttribute.add({ + "ATTRIBUTE_NAME": element!.attributeName, + if (element!.attributeType == "number") "ATTRIBUTE_NUMBER_VALUE": note else if (element!.attributeType == "VARCHAR2") "ATTRIBUTE_TEXT_VALUE": note + }); + } + Map payload = { "P_ACTION_MODE": actionMode, "P_APPROVER_INDEX": null, "P_COMMENTS": note, "P_FORWARD_TO_USER_NAME": "", "P_NOTIFICATION_ID": workListData!.nOTIFICATIONID, - "RespondAttributeList": [ - if (notificationNoteInput != null) - { - "ATTRIBUTE_NAME": notificationNoteInput!.attributeName, - if (notificationNoteInput!.attributeType == "number") "ATTRIBUTE_NUMBER_VALUE": note else if (notificationNoteInput!.attributeType == "VARCHAR2") "ATTRIBUTE_TEXT_VALUE": note - } - ], + "RespondAttributeList": responseAttribute, }; - if (actionMode == "APPROVED" || actionMode == "APPROVE" || actionMode == "CLOSE" || actionMode == "ANSWER_INFO" || actionMode == "RFC") { + if (actionMode == "APPROVED" || + actionMode == "APPROVE" || + actionMode == "CLOSE" || + actionMode == "ANSWER_INFO" || + actionMode == "RFC" || + actionMode == "TRY_APPROVE_AGAIN" || + actionMode == "SEND_BACK_TO_PREPARER") { performNotificationAction(payload); } else if (note.isNotEmpty && (actionMode != "APPROVED" || actionMode != "APPROVE")) { performNotificationAction(payload); @@ -739,6 +777,24 @@ class _WorkListDetailScreenState extends State { } } + void getCEINotificationBody() async { + try { + if (apiCallCount == 0) Utils.showLoading(context); + apiCallCount++; + getEitCollectionNotificationBodyList!.clear(); + getEitCollectionNotificationBodyList = await WorkListApiClient().GetCeiNotificationBody(workListData!.nOTIFICATIONID); + apiCallCount--; + if (apiCallCount == 0) { + Utils.hideLoading(context); + setState(() {}); + } + } catch (ex) { + apiCallCount--; + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + void getEitNotificationBody() async { try { if (apiCallCount == 0) Utils.showLoading(context); @@ -762,7 +818,7 @@ class _WorkListDetailScreenState extends State { if (apiCallCount == 0) Utils.showLoading(context); apiCallCount++; memberInformationListModel = null; - memberInformationListModel = await WorkListApiClient().getUserInformation(-999, workListData!.sELECTEDEMPLOYEENUMBER!); + memberInformationListModel = await WorkListApiClient().getNotificationUserInformation(-999, workListData!.sELECTEDEMPLOYEENUMBER!, workListData!.nOTIFICATIONID!); apiCallCount--; if (apiCallCount == 0) { Utils.hideLoading(context); @@ -862,15 +918,14 @@ class _WorkListDetailScreenState extends State { Utils.handleException(ex, context, null); } } + void getTerminationNotificationBody() async { try { - if (apiCallCount == 0) - apiCallCount++; + if (apiCallCount == 0) apiCallCount++; getTerminationNotificationBodyList = await WorkListApiClient().getTerminationNotificationBodyList(workListData!.nOTIFICATIONID); Utils.hideLoading(context); apiCallCount--; if (apiCallCount == 0) { - setState(() {}); } } catch (ex) { @@ -880,8 +935,6 @@ class _WorkListDetailScreenState extends State { } } - - void getStampNotificationBody() async { try { if (apiCallCount == 0) Utils.showLoading(context); @@ -971,6 +1024,40 @@ class _WorkListDetailScreenState extends State { } } + void getPaymentNotification() async { + try { + if (apiCallCount == 0) Utils.showLoading(context); + apiCallCount++; + getPaymentNotificationBodyList = await WorkListApiClient().getPaymentNotificationBody(workListData!.nOTIFICATIONID!, -999); + apiCallCount--; + if (apiCallCount == 0) { + Utils.hideLoading(context); + setState(() {}); + } + } catch (ex) { + apiCallCount--; + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + Future getFADNotification() async { + try { + if (apiCallCount == 0) Utils.showLoading(context); + apiCallCount++; + getFADNotificationBody = await WorkListApiClient().getFADNotificationBody(workListData!.nOTIFICATIONID); + apiCallCount--; + if (apiCallCount == 0) { + Utils.hideLoading(context); + setState(() {}); + } + } catch (ex) { + apiCallCount--; + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + void notificationGetRespondAttributes() async { try { if (apiCallCount == 0) Utils.showLoading(context); @@ -999,21 +1086,29 @@ class _WorkListDetailScreenState extends State { notificationButtonsList.clear(); notificationButtonsList = await WorkListApiClient().getNotificationButtons(workListData!.nOTIFICATIONID!); if (notificationButtonsList.isNotEmpty) { - isCloseAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "CLOSE"); - isApproveAvailable = notificationButtonsList.any((element) { + isCloseAvailable = notificationButtonsList.any((GetNotificationButtonsList element) => element.bUTTONACTION == "CLOSE"); + isApproveAvailable = notificationButtonsList.any((GetNotificationButtonsList element) { if (element.bUTTONACTION == "APPROVED" || element.bUTTONACTION == "APPROVE") { approveAction = element.bUTTONACTION!; return true; } return false; }); - isRejectAvailable = notificationButtonsList.any((element) { + isRejectAvailable = notificationButtonsList.any((GetNotificationButtonsList element) { if (element.bUTTONACTION == "REJECTED" || element.bUTTONACTION == "REJECT") { rejectAction = element.bUTTONACTION!; return true; } return false; }); + + if(notificationButtonsList.any((GetNotificationButtonsList element) => element.bUTTONACTION == "DELEGATE" || element.bUTTONACTION == "REQUEST_INFO" )) { + isShowActions = true; + } else { + isShowActions = false; + } + + } apiCallCount--; if (apiCallCount == 0) { @@ -1031,7 +1126,10 @@ class _WorkListDetailScreenState extends State { try { isActionHistoryLoaded = false; actionHistoryList.clear(); - actionHistoryList = await WorkListApiClient().getActionHistory(workListData!.nOTIFICATIONID!); + List _actionHistoryList = await WorkListApiClient().getActionHistory(workListData!.nOTIFICATIONID!); + if (!isActionHistoryLoaded) { + actionHistoryList = _actionHistoryList; + } setState(() { isActionHistoryLoaded = true; }); @@ -1044,7 +1142,10 @@ class _WorkListDetailScreenState extends State { try { isAttachmentLoaded = false; getAttachmentList.clear(); - getAttachmentList = await WorkListApiClient().getAttachments(workListData!.nOTIFICATIONID!); + List _getAttachmentList = await WorkListApiClient().getAttachments(workListData!.nOTIFICATIONID!); + if (!isAttachmentLoaded) { + getAttachmentList = _getAttachmentList; + } setState(() { isAttachmentLoaded = true; }); diff --git a/lib/ui/work_list/worklist_fragments/actions_fragment.dart b/lib/ui/work_list/worklist_fragments/actions_fragment.dart index 1d88129..97e540c 100644 --- a/lib/ui/work_list/worklist_fragments/actions_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/actions_fragment.dart @@ -17,8 +17,9 @@ class ActionsFragment extends StatelessWidget { int? notificationID; List actionHistoryList; VoidCallback voidCallback; + bool isShowActions = false; - ActionsFragment(this.notificationID, this.actionHistoryList, {Key? key, required this.voidCallback}) : super(key: key); + ActionsFragment(this.notificationID, this.actionHistoryList, this.isShowActions, {Key? key, required this.voidCallback}) : super(key: key); @override Widget build(BuildContext context) { @@ -113,42 +114,41 @@ class ActionsFragment extends StatelessWidget { ], ).paddingOnly(top: 19, left: 16, right: 16, bottom: 12), Container(width: double.infinity, height: 1, color: MyColors.lightGreyEFColor), - Row( - children: [ - LocaleKeys.request_info.tr().toText12(color: MyColors.grey67Color).center.paddingOnly(top: 6, bottom: 6).onPress(() { - showMyBottomSheet( - context, - callBackFunc: voidCallback, - child: SelectedItemSheet(LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: notificationID, actionHistoryList: actionHistory), - ); - }).expanded, - Container(width: 1, height: 30, color: MyColors.lightGreyEFColor), - LocaleKeys.delegate.tr().toText12(color: MyColors.gradiantEndColor).center.paddingOnly(top: 6, bottom: 6).onPress(() { - if (actionHistory.uSERNAME == AppState().memberInformationList?.eMPLOYEENUMBER) { - showMyBottomSheet(context, + isShowActions + ? Row( + children: [ + LocaleKeys.request_info.tr().toText12(color: MyColors.grey67Color).center.paddingOnly(top: 6, bottom: 6).onPress(() { + showMyBottomSheet( + context, callBackFunc: voidCallback, - child: DelegateSheet( - title: LocaleKeys.delegate.tr(), - apiMode: "DELEGATE", - notificationID: notificationID, - actionHistoryList: actionHistoryList, + child: SelectedItemSheet(LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: notificationID, actionHistoryList: actionHistory), + ); + }).expanded, + Container(width: 1, height: 30, color: MyColors.lightGreyEFColor), + LocaleKeys.delegate.tr().toText12(color: MyColors.gradiantEndColor).center.paddingOnly(top: 6, bottom: 6).onPress(() { + if (actionHistory.uSERNAME == AppState().memberInformationList?.eMPLOYEENUMBER) { + showMyBottomSheet( + context, callBackFunc: voidCallback, - )); - return; - } - showMyBottomSheet( - context, - callBackFunc: voidCallback, - child: SelectedItemSheet( - LocaleKeys.comments.tr(), - apiMode: "DELEGATE", - actionHistoryList: actionHistory, - notificationID: notificationID, - ), - ); - }).expanded, - ], - ), + child: DelegateSheet( + title: LocaleKeys.delegate.tr(), + apiMode: "DELEGATE", + notificationID: notificationID, + actionHistoryList: actionHistoryList, + callBackFunc: voidCallback, + ), + ); + return; + } + showMyBottomSheet( + context, + callBackFunc: voidCallback, + child: SelectedItemSheet(LocaleKeys.comments.tr(), apiMode: "DELEGATE", actionHistoryList: actionHistory, notificationID: notificationID), + ); + }).expanded, + ], + ) + : const SizedBox(), ], ), ], @@ -167,10 +167,14 @@ class ActionsFragment extends StatelessWidget { Duration duration = DateTime.now().difference(dateTimeFrom); return "Action duration: " + DateUtil.formatDuration(duration); } else { - DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index].nOTIFICATIONDATE!); - DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index + 1].nOTIFICATIONDATE!); - Duration duration = dateTimeTo.difference(dateTimeFrom); - return "Action duration: " + DateUtil.formatDuration(duration); + if (actionHistoryList[index].nOTIFICATIONDATE!.isEmpty || actionHistoryList[index].aCTIONCODE! == "NO ACTION") { + return ""; + } else { + DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index].nOTIFICATIONDATE!); + DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index + 1].nOTIFICATIONDATE!); + Duration duration = dateTimeTo.difference(dateTimeFrom); + return "Action duration: " + DateUtil.formatDuration(duration); + } } } diff --git a/lib/ui/work_list/worklist_fragments/attachments_fragment.dart b/lib/ui/work_list/worklist_fragments/attachments_fragment.dart index bc1bde6..e1381ac 100644 --- a/lib/ui/work_list/worklist_fragments/attachments_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/attachments_fragment.dart @@ -9,8 +9,10 @@ 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/models/get_attachement_list_model.dart'; -import 'package:open_file/open_file.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; +import 'package:open_filex/open_filex.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; class AttachmentsFragment extends StatelessWidget { final List getAttachmentList; @@ -31,8 +33,9 @@ class AttachmentsFragment extends StatelessWidget { ).objectContainerView().onPress(() async { try { String path = await _createFileFromString(getAttachmentList[index].fILEDATA ?? "", getAttachmentList[index].fILECONTENTTYPE ?? ""); - OpenFile.open(path); - } catch (ex) {Utils.showToast("Cannot open file."); + OpenFilex.open(path); + } catch (ex) { + Utils.showToast("Cannot open file."); } }); }, diff --git a/lib/ui/work_list/worklist_fragments/info_fragments.dart b/lib/ui/work_list/worklist_fragments/info_fragments.dart index 7e1cd1c..541d347 100644 --- a/lib/ui/work_list/worklist_fragments/info_fragments.dart +++ b/lib/ui/work_list/worklist_fragments/info_fragments.dart @@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dar import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/get_stamp_ms_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/get_stamp_ns_notification_body_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/get_fad_notifications.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_address_notification_body_list.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; @@ -19,8 +20,8 @@ import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_bo import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist_response_model.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; - import 'package:mohem_flutter_app/models/termination/termination_notification_body.dart'; +import 'package:mohem_flutter_app/models/worklist/payment_details_list.dart'; class InfoFragment extends StatelessWidget { WorkListResponseModel? workListData; @@ -28,36 +29,45 @@ class InfoFragment extends StatelessWidget { List? getStampMsNotifications; List? getStampNsNotifications; List itemCreationHeader; - List? getEitCollectionNotificationBodyList; + List? + getEitCollectionNotificationBodyList; List? getPhonesNotificationBodyList; List? getBasicDetNtfBodyList; - List? getAbsenceCollectionNotificationBodyList; + List? + getAbsenceCollectionNotificationBodyList; GetContactNotificationBodyList? getContactNotificationBodyList; GetPrNotificationBodyList? getPrNotificationBodyList; List? getAddressNotificationBodyList = []; - List? getTerminationNotificationBodyList =[]; + List? getTerminationNotificationBodyList = []; + GetPaymentNotificationBodyList? getPaymentNotificationBodyList; + GetFaDisposalNtfDetails? getFADNotificationBodyList; InfoFragment( {this.workListData, - this.poHeaderList = const [], - this.itemCreationHeader = const [], - this.getStampMsNotifications, - this.getStampNsNotifications, - this.getEitCollectionNotificationBodyList, - this.getPhonesNotificationBodyList, - this.getBasicDetNtfBodyList, - this.getAbsenceCollectionNotificationBodyList, - this.getContactNotificationBodyList, - this.getPrNotificationBodyList, - this.getAddressNotificationBodyList, - this.getTerminationNotificationBodyList + this.poHeaderList = const [], + this.itemCreationHeader = const [], + this.getStampMsNotifications, + this.getStampNsNotifications, + this.getEitCollectionNotificationBodyList, + this.getPhonesNotificationBodyList, + this.getBasicDetNtfBodyList, + this.getAbsenceCollectionNotificationBodyList, + this.getContactNotificationBodyList, + this.getPrNotificationBodyList, + this.getAddressNotificationBodyList, + this.getTerminationNotificationBodyList, + this.getPaymentNotificationBodyList, + this.getFADNotificationBodyList }); double itemHeight = 0; double itemWidth = 0; + + + @override Widget build(BuildContext context) { - var size = MediaQuery.of(context).size; + Size size = MediaQuery.of(context).size; itemHeight = (size.height - kToolbarHeight - 24) / 9; itemWidth = size.width / 2; @@ -68,36 +78,65 @@ class InfoFragment extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.from.tr(), workListData!.fROMUSER ?? ""), + ItemDetailViewCol( + LocaleKeys.from.tr(), workListData!.fROMUSER ?? ""), ItemDetailViewCol(LocaleKeys.to.tr(), workListData!.tOUSER ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.sent.tr(), workListData!.bEGINDATE ?? ""), - ItemDetailViewCol(LocaleKeys.closed.tr(), workListData!.eNDDATE ?? ""), + ItemDetailViewCol( + LocaleKeys.sent.tr(), workListData!.bEGINDATE ?? ""), + ItemDetailViewCol( + LocaleKeys.closed.tr(), workListData!.eNDDATE ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.id.tr(), workListData!.nOTIFICATIONID?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.responder.tr(), workListData!.rESPONDER ?? ""), + ItemDetailViewCol(LocaleKeys.id.tr(), + workListData!.nOTIFICATIONID?.toString() ?? ""), + ItemDetailViewCol( + LocaleKeys.responder.tr(), workListData!.rESPONDER ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.subject.tr(), workListData!.sUBJECT ?? ""), + ItemDetailViewCol( + LocaleKeys.subject.tr(), workListData!.sUBJECT ?? ""), Container(), isItLast: true, ), ], ).objectContainerView(), - if (getPrNotificationBodyList != null) getPRNotificationBodyListWidget(getPrNotificationBodyList!), - if (getStampMsNotifications?.isNotEmpty ?? false) getStampMsNotificationsListView(getStampMsNotifications ?? []), - if (getStampNsNotifications?.isNotEmpty ?? false) getStampNsNotificationsListView(getStampNsNotifications ?? []), + if (getPrNotificationBodyList != null) + getPRNotificationBodyListWidget(getPrNotificationBodyList!), + if (getStampMsNotifications?.isNotEmpty ?? false) + getStampMsNotificationsListView(getStampMsNotifications ?? []), + if (getStampNsNotifications?.isNotEmpty ?? false) + getStampNsNotificationsListView(getStampNsNotifications ?? []), if (poHeaderList.isNotEmpty) getPoNotificationsListView(), if (itemCreationHeader.isNotEmpty) getItemCreationHeaderView(), - if (getEitCollectionNotificationBodyList?.isNotEmpty ?? false) getEitNotificationsListView(getEitCollectionNotificationBodyList ?? []), - if (getPhonesNotificationBodyList?.isNotEmpty ?? false) getPhonesNotificationBodyListWidget(getPhonesNotificationBodyList ?? []).objectContainerView(title: "Mobile Numbers"), - if (getBasicDetNtfBodyList?.isNotEmpty ?? false) getBasicDetNtfBodyListWidget(getBasicDetNtfBodyList ?? []).objectContainerView(title: "Basic Information"), - if (getAbsenceCollectionNotificationBodyList?.isNotEmpty ?? false) getAbsenceCollectionNotificationBodyListWidget(getAbsenceCollectionNotificationBodyList ?? []), - if (getContactNotificationBodyList != null) getContactNotificationBodyListWidget(getContactNotificationBodyList ?? GetContactNotificationBodyList()).objectContainerView(), - if (getAddressNotificationBodyList?.isNotEmpty ?? false) getAddressNotificationBodyListWidget(getAddressNotificationBodyList!), - if (getTerminationNotificationBodyList?.isNotEmpty ?? false) getTerminationNotificationBodyListWidget(getTerminationNotificationBodyList!), + if (getEitCollectionNotificationBodyList?.isNotEmpty ?? false) + getEitNotificationsListView(getEitCollectionNotificationBodyList ?? []), + if (getPhonesNotificationBodyList?.isNotEmpty ?? false) + getPhonesNotificationBodyListWidget(getPhonesNotificationBodyList ?? []) + .objectContainerView(title: "Mobile Numbers"), + if (getBasicDetNtfBodyList?.isNotEmpty ?? false) + getBasicDetNtfBodyListWidget(getBasicDetNtfBodyList ?? []) + .objectContainerView(title: "Basic Information"), + if (getAbsenceCollectionNotificationBodyList?.isNotEmpty ?? false) + getAbsenceCollectionNotificationBodyListWidget( + getAbsenceCollectionNotificationBodyList ?? []), + if (getContactNotificationBodyList != null) + getContactNotificationBodyListWidget(getContactNotificationBodyList ?? + GetContactNotificationBodyList()) + .objectContainerView(), + if (getAddressNotificationBodyList?.isNotEmpty ?? false) + getAddressNotificationBodyListWidget(getAddressNotificationBodyList!), + if (getTerminationNotificationBodyList?.isNotEmpty ?? false) + getTerminationNotificationBodyListWidget( + getTerminationNotificationBodyList!), + if (getPaymentNotificationBodyList != null) + getPaymentNotificationBodyListWidget(getPaymentNotificationBodyList ?? + GetPaymentNotificationBodyList()), + if (getFADNotificationBodyList != null) + getFANotificationBodyListWidget(getFADNotificationBodyList ?? + GetFaDisposalNtfDetails()) + .objectContainerView(), ]; return Container( width: double.infinity, @@ -105,9 +144,9 @@ class InfoFragment extends StatelessWidget { child: uiList.isEmpty ? LocaleKeys.noDataAvailable.tr().toText16().center : ListView( - padding: const EdgeInsets.all(21), - children: uiList, - ), + padding: const EdgeInsets.all(21), + children: uiList, + ), ); } @@ -115,146 +154,197 @@ class InfoFragment extends StatelessWidget { return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Column( - children: [ - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.description.tr(), workListData!.fROMUSER ?? ""), - ItemDetailViewCol(LocaleKeys.from.tr(), workListData!.fROMUSER ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.to.tr(), workListData!.tOUSER ?? ""), - ItemDetailViewCol(LocaleKeys.sent.tr(), workListData!.bEGINDATE ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.closed.tr(), workListData!.eNDDATE ?? ""), - ItemDetailViewCol(LocaleKeys.id.tr(), workListData!.nOTIFICATIONID?.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.supplier.tr(), poHeaderList[index].vENDORNAME ?? ""), - ItemDetailViewCol(LocaleKeys.site.tr(), poHeaderList[index].vENDORSITECODE ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.buyer.tr(), poHeaderList[index].bUYER ?? ""), - ItemDetailViewCol(LocaleKeys.preparer.tr(), poHeaderList[index].pREPARER ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.creationDate.tr(), poHeaderList[index].cREATIONDATE ?? ""), - ItemDetailViewCol(LocaleKeys.shipToLocation.tr(), poHeaderList[index].sHIPTOLOCATIONNAME ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.quotationNumber.tr(), poHeaderList[index].qUOTATIONNUMBER ?? ""), - ItemDetailViewCol(LocaleKeys.quotationDate.tr(), poHeaderList[index].qUOTATIONDATE ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.paymentTerms.tr(), poHeaderList[index].pAYMENTTERMS ?? ""), - ItemDetailViewCol(LocaleKeys.currency.tr(), poHeaderList[index].cURRENCYNAME ?? ""), - isItLast: true, - ), - ], - ).objectContainerView(title: LocaleKeys.infoDetail.tr()), - 12.height, - Column( - children: [ - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.grossAmount.tr(), poHeaderList[index].gROSSAMOUNT?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.discountAmount.tr(), poHeaderList[index].dISCOUNTAMOUNT?.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.customDuty.tr(), poHeaderList[index].cUSTOMDUTY?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.shipHandle.tr(), poHeaderList[index].sHIPHANDLE?.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.otherCharges.tr(), poHeaderList[index].oTHERCHARGES?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.totalPOAmountWithVAT.tr(), poHeaderList[index].lOCCURTOTPOAMT.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.totalPOAmountInWords.tr(), poHeaderList[index].tOTPOAMTWORD ?? ""), - Container(), - isItLast: true, - ), - ], - ).objectContainerView(title: LocaleKeys.amount_detail.tr()), - ], - ), - separatorBuilder: (cxt, index) => 4.height, - itemCount: poHeaderList.length); - } - - // Widget getAbsenceCollectionNotificationsListView(List list) { - // List dataList = list.isEmpty ? [] : (list.first.collectionNotification ?? []); - // return ListView.separated( - // shrinkWrap: true, - // physics: const NeverScrollableScrollPhysics(), - // itemBuilder: (cxt, index) => ItemDetailView(dataList[index].sEGMENTPROMPT!, dataList[index].sEGMENTVALUEDSP!), - // separatorBuilder: (cxt, index) => 4.height, - // itemCount: dataList.length); - // } - - Widget getStampMsNotificationsListView(List list) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => Column( - mainAxisSize: MainAxisSize.min, + itemBuilder: (BuildContext cxt, int index) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Column( children: [ ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.employeeNumber.tr(), list[index].eMPLOYEENUMBER.toString()), - ItemDetailViewCol(LocaleKeys.assignmentNumber.tr(), list[index].aSSIGNMENTNUMBER.toString()), + ItemDetailViewCol(LocaleKeys.description.tr(), + workListData!.fROMUSER ?? ""), + ItemDetailViewCol( + LocaleKeys.from.tr(), workListData!.fROMUSER ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.employeeName.tr(), list[index].eMPLOYEENAME.toString()), - ItemDetailViewCol(LocaleKeys.scheduleDate.tr(), DateUtil.formatDateToDate(DateUtil.convertStringToDate(list[index].sCHEDULEDATE.toString()), false)), + ItemDetailViewCol( + LocaleKeys.to.tr(), workListData!.tOUSER ?? ""), + ItemDetailViewCol( + LocaleKeys.sent.tr(), workListData!.bEGINDATE ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.shiftType.tr(), list[index].sHTTYPEDESC.toString()), - ItemDetailViewCol(LocaleKeys.shift.tr(), list[index].sHTNAME.toString()), + ItemDetailViewCol( + LocaleKeys.closed.tr(), workListData!.eNDDATE ?? ""), + ItemDetailViewCol(LocaleKeys.id.tr(), + workListData!.nOTIFICATIONID?.toString() ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.breakText.tr(), list[index].bREAKNAME.toString()), - ItemDetailViewCol(LocaleKeys.actualSwipeStart.tr(), list[index].sHTACTUALSTARTTIME.toString()), + ItemDetailViewCol(LocaleKeys.supplier.tr(), + poHeaderList[index].vENDORNAME ?? ""), + ItemDetailViewCol(LocaleKeys.site.tr(), + poHeaderList[index].vENDORSITECODE ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.actualSwipeEnd.tr(), list[index].sHTACTUALENDTIME.toString()), - ItemDetailViewCol(LocaleKeys.approvedSwipeStart.tr(), list[index].aPPROVEDSTARTTIME.toString()), + ItemDetailViewCol(LocaleKeys.buyer.tr(), + poHeaderList[index].bUYER ?? ""), + ItemDetailViewCol(LocaleKeys.preparer.tr(), + poHeaderList[index].pREPARER ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.approvedSwipeStartReason.tr(), list[index].aPPROVEDSTARTREASON.toString()), - ItemDetailViewCol(LocaleKeys.approvedSwipeEnd.tr(), ""), + ItemDetailViewCol(LocaleKeys.creationDate.tr(), + poHeaderList[index].cREATIONDATE ?? ""), + ItemDetailViewCol(LocaleKeys.shipToLocation.tr(), + poHeaderList[index].sHIPTOLOCATIONNAME ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.approvedSwipeEndReason.tr(), list[index].aPPROVEDENDREASONDESC.toString()), - Container(), + ItemDetailViewCol(LocaleKeys.quotationNumber.tr(), + poHeaderList[index].qUOTATIONNUMBER ?? ""), + ItemDetailViewCol(LocaleKeys.quotationDate.tr(), + poHeaderList[index].qUOTATIONDATE ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.paymentTerms.tr(), + poHeaderList[index].pAYMENTTERMS ?? ""), + ItemDetailViewCol(LocaleKeys.currency.tr(), + poHeaderList[index].cURRENCYNAME ?? ""), isItLast: true, ), ], - ).objectContainerView(), - separatorBuilder: (cxt, index) => 1.height.paddingOnly(top: 8, bottom: 8), - itemCount: list.length); - } - - Widget getStampNsNotificationsListView(List list) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => Column( - mainAxisSize: MainAxisSize.min, + ).objectContainerView(title: LocaleKeys.infoDetail.tr()), + 12.height, + Column( children: [ ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.employeeNumber.tr(), list[index].eMPLOYEENUMBER.toString()), - ItemDetailViewCol(LocaleKeys.assignmentNumber.tr(), list[index].aSSIGNMENTNUMBER.toString()), + ItemDetailViewCol(LocaleKeys.grossAmount.tr(), + poHeaderList[index].gROSSAMOUNT?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.discountAmount.tr(), + poHeaderList[index].dISCOUNTAMOUNT?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.customDuty.tr(), + poHeaderList[index].cUSTOMDUTY?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.shipHandle.tr(), + poHeaderList[index].sHIPHANDLE?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.otherCharges.tr(), + poHeaderList[index].oTHERCHARGES?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.totalPOAmountWithVAT.tr(), + poHeaderList[index].lOCCURTOTPOAMT.toString() ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.employeeName.tr(), list[index].eMPLOYEENAME.toString()), - ItemDetailViewCol(LocaleKeys.scheduleDate.tr(), DateUtil.formatDateToDate(DateUtil.convertStringToDate(list[index].sCHEDULEDATE.toString()), false)), + ItemDetailViewCol(LocaleKeys.totalPOAmountInWords.tr(), + poHeaderList[index].tOTPOAMTWORD ?? ""), + Container(), isItLast: true, ), ], - ).objectContainerView(), - separatorBuilder: (cxt, index) => 1.height.paddingOnly(top: 8, bottom: 8), + ).objectContainerView(title: LocaleKeys.amount_detail.tr()), + ], + ), + separatorBuilder: (BuildContext cxt, int index) => 4.height, + itemCount: poHeaderList.length); + } + + // Widget getAbsenceCollectionNotificationsListView(List list) { + // List dataList = list.isEmpty ? [] : (list.first.collectionNotification ?? []); + // return ListView.separated( + // shrinkWrap: true, + // physics: const NeverScrollableScrollPhysics(), + // itemBuilder: (cxt, index) => ItemDetailView(dataList[index].sEGMENTPROMPT!, dataList[index].sEGMENTVALUEDSP!), + // separatorBuilder: (cxt, index) => 4.height, + // itemCount: dataList.length); + // } + + Widget getStampMsNotificationsListView( + List list) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext cxt, int index) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.employeeNumber.tr(), + list[index].eMPLOYEENUMBER.toString()), + ItemDetailViewCol(LocaleKeys.assignmentNumber.tr(), + list[index].aSSIGNMENTNUMBER.toString()), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.employeeName.tr(), + list[index].eMPLOYEENAME.toString()), + ItemDetailViewCol( + LocaleKeys.scheduleDate.tr(), + DateUtil.formatDateToDate( + DateUtil.convertStringToDate( + list[index].sCHEDULEDATE.toString()), + false)), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.shiftType.tr(), + list[index].sHTTYPEDESC.toString()), + ItemDetailViewCol( + LocaleKeys.shift.tr(), list[index].sHTNAME.toString()), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.breakText.tr(), + list[index].bREAKNAME.toString()), + ItemDetailViewCol(LocaleKeys.actualSwipeStart.tr(), + list[index].sHTACTUALSTARTTIME.toString()), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.actualSwipeEnd.tr(), + list[index].sHTACTUALENDTIME.toString()), + ItemDetailViewCol(LocaleKeys.approvedSwipeStart.tr(), + list[index].aPPROVEDSTARTTIME.toString()), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.approvedSwipeStartReason.tr(), + list[index].aPPROVEDSTARTREASON.toString()), + ItemDetailViewCol(LocaleKeys.approvedSwipeEnd.tr(), ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.approvedSwipeEndReason.tr(), + list[index].aPPROVEDENDREASONDESC.toString()), + Container(), + isItLast: true, + ), + ], + ).objectContainerView(), + separatorBuilder: (BuildContext cxt, int index) => + 1.height.paddingOnly(top: 8, bottom: 8), + itemCount: list.length); + } + + Widget getStampNsNotificationsListView( + List list) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext cxt, int index) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.employeeNumber.tr(), + list[index].eMPLOYEENUMBER.toString()), + ItemDetailViewCol(LocaleKeys.assignmentNumber.tr(), + list[index].aSSIGNMENTNUMBER.toString()), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.employeeName.tr(), + list[index].eMPLOYEENAME.toString()), + ItemDetailViewCol( + LocaleKeys.scheduleDate.tr(), + DateUtil.formatDateToDate( + DateUtil.convertStringToDate( + list[index].sCHEDULEDATE.toString()), + false)), + isItLast: true, + ), + ], + ).objectContainerView(), + separatorBuilder: (BuildContext cxt, int index) => + 1.height.paddingOnly(top: 8, bottom: 8), itemCount: list.length); } @@ -262,43 +352,65 @@ class InfoFragment extends StatelessWidget { return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.operatingUnit.tr(), itemCreationHeader[index].oPERATINGUNIT?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.category.tr(), itemCreationHeader[index].cATEGORY?.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.requester.tr(), itemCreationHeader[index].rEQUESTER?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.analyzedBy.tr(), itemCreationHeader[index].aNALYZEDBY?.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.approvedDate.tr(), itemCreationHeader[index].aPPROVEDDATE?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.itemType.tr(), itemCreationHeader[index].iTEMTYPE?.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.relatedTo.tr(), itemCreationHeader[index].rELATEDTO?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.requestDate.tr(), DateUtil.formatDateToDate(DateUtil.convertStringToDate(itemCreationHeader[index].rEQUESTDATE.toString()), false)), - ), - ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.analyzedDate.tr(), itemCreationHeader[index].aNALYZEDDATE?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.urgent.tr(), itemCreationHeader[index].uRGENTFLAGDISP?.toString() ?? ""), - ), - ], - ).objectContainerView(), - separatorBuilder: (cxt, index) => 18.height, + itemBuilder: (BuildContext cxt, int index) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.operatingUnit.tr(), + itemCreationHeader[index].oPERATINGUNIT?.toString() ?? + ""), + ItemDetailViewCol(LocaleKeys.category.tr(), + itemCreationHeader[index].cATEGORY?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.requester.tr(), + itemCreationHeader[index].rEQUESTER?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.analyzedBy.tr(), + itemCreationHeader[index].aNALYZEDBY?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.approvedDate.tr(), + itemCreationHeader[index].aPPROVEDDATE?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.itemType.tr(), + itemCreationHeader[index].iTEMTYPE?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.relatedTo.tr(), + itemCreationHeader[index].rELATEDTO?.toString() ?? ""), + ItemDetailViewCol( + LocaleKeys.requestDate.tr(), + DateUtil.formatDateToDate( + DateUtil.convertStringToDate( + itemCreationHeader[index].rEQUESTDATE.toString()), + false)), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.analyzedDate.tr(), + itemCreationHeader[index].aNALYZEDDATE?.toString() ?? ""), + ItemDetailViewCol( + LocaleKeys.urgent.tr(), + itemCreationHeader[index].uRGENTFLAGDISP?.toString() ?? + ""), + ), + ], + ).objectContainerView(), + separatorBuilder: (BuildContext cxt, int index) => 18.height, itemCount: itemCreationHeader.length); } //HR multiple type requests - Widget getEitNotificationsListView(List list) { + Widget getEitNotificationsListView( + List list) { return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) { - List dataList = list.isEmpty ? [] : (list[index].collectionNotification ?? []); - dataList = dataList.where((o) => o.displayFlag == "Y").toList(); + itemBuilder: (BuildContext cxt, int index) { + List dataList = + list.isEmpty ? [] : (list[index].collectionNotification ?? []); + dataList = dataList + .where((CollectionNotificationEit o) => o.displayFlag == "Y") + .toList(); bool isOdd = false; if (dataList.length % 2 != 0) { isOdd = true; @@ -308,28 +420,30 @@ class InfoFragment extends StatelessWidget { itemCount: dataList.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) => ItemDetailViewGridItem( - index, - dataList[index].segmentPrompt, - dataList[index].segmentValueDsp, - isNeedToShowEmptyDivider: (dataList.length == index + 1) - ? isOdd + itemBuilder: (BuildContext context, int index) => + ItemDetailViewGridItem( + index, + dataList[index].segmentPrompt, + dataList[index].segmentValueDsp, + isNeedToShowEmptyDivider: (dataList.length == index + 1) + ? isOdd ? true : false - : false, - ), + : false, + ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: (itemWidth / itemHeight), ), ).objectContainerView(); }, - separatorBuilder: (cxt, index) => 12.height, + separatorBuilder: (BuildContext cxt, int index) => 12.height, itemCount: list.length, ); } - Widget getPhonesNotificationBodyListWidget(List list) { + Widget getPhonesNotificationBodyListWidget( + List list) { bool isOdd = false; if (list.length % 2 != 0) { isOdd = true; @@ -339,14 +453,14 @@ class InfoFragment extends StatelessWidget { itemCount: list.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) => ItemDetailViewGridItem( + itemBuilder: (BuildContext context, int index) => ItemDetailViewGridItem( index, LocaleKeys.subject.tr(), list[index].proposedPhoneNumber ?? "", isNeedToShowEmptyDivider: (list.length == index + 1) ? isOdd - ? true - : false + ? true + : false : false, ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( @@ -359,8 +473,9 @@ class InfoFragment extends StatelessWidget { child: ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => ItemDetailViewCol(LocaleKeys.subject.tr(), list[index].proposedPhoneNumber ?? ""), - separatorBuilder: (cxt, index) => 4.height, + itemBuilder: (BuildContext cxt, int index) => ItemDetailViewCol( + LocaleKeys.subject.tr(), list[index].proposedPhoneNumber ?? ""), + separatorBuilder: (BuildContext cxt, int index) => 4.height, itemCount: list.length), ); } @@ -375,14 +490,14 @@ class InfoFragment extends StatelessWidget { itemCount: list.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) => ItemDetailViewGridItem( + itemBuilder: (BuildContext context, int index) => ItemDetailViewGridItem( index, list[index].segmentPrompt, list[index].segmentValueDsp, isNeedToShowEmptyDivider: (list.length == index + 1) ? isOdd - ? true - : false + ? true + : false : false, ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( @@ -395,19 +510,24 @@ class InfoFragment extends StatelessWidget { child: ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => ItemDetailViewCol(list[index].segmentPrompt!, list[index].segmentValueDsp!), - separatorBuilder: (cxt, index) => 4.height, + itemBuilder: (BuildContext cxt, int index) => ItemDetailViewCol( + list[index].segmentPrompt!, list[index].segmentValueDsp!), + separatorBuilder: (BuildContext cxt, int index) => 4.height, itemCount: list.length), ); } - Widget getAbsenceCollectionNotificationBodyListWidget(List list) { + Widget getAbsenceCollectionNotificationBodyListWidget( + List list) { return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) { - List dataList = list.isEmpty ? [] : (list[index].collectionNotification ?? []); - dataList = dataList.where((o) => o.dISPLAYFLAG == "Y").toList(); + itemBuilder: (BuildContext cxt, int index) { + List dataList = + list.isEmpty ? [] : (list[index].collectionNotification ?? []); + dataList = dataList + .where((CollectionNotificationAbsence o) => o.dISPLAYFLAG == "Y") + .toList(); bool isOdd = false; if (dataList.length % 2 != 0) { isOdd = true; @@ -418,52 +538,69 @@ class InfoFragment extends StatelessWidget { itemCount: dataList.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) => ItemDetailViewGridItem( - index, - dataList[index].sEGMENTPROMPT, - dataList[index].sEGMENTVALUEDSP, - isNeedToShowEmptyDivider: (dataList.length == index + 1) - ? isOdd + itemBuilder: (BuildContext context, int index) => + ItemDetailViewGridItem( + index, + dataList[index].sEGMENTPROMPT, + dataList[index].sEGMENTVALUEDSP, + isNeedToShowEmptyDivider: (dataList.length == index + 1) + ? isOdd ? true : false - : false, - ), + : false, + ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: (itemWidth / itemHeight), ), ).objectContainerView(); return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => dataList[index].dISPLAYFLAG == "Y" ? ItemDetailViewCol(dataList[index].sEGMENTPROMPT!, dataList[index].sEGMENTVALUEDSP!) : Container(), - separatorBuilder: (cxt, index) => dataList[index].dISPLAYFLAG == "Y" ? 4.height : 0.height, - itemCount: dataList.length) + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext cxt, int index) => + dataList[index].dISPLAYFLAG == "Y" + ? ItemDetailViewCol(dataList[index].sEGMENTPROMPT!, + dataList[index].sEGMENTVALUEDSP!) + : Container(), + separatorBuilder: (BuildContext cxt, int index) => + dataList[index].dISPLAYFLAG == "Y" ? 4.height : 0.height, + itemCount: dataList.length) .objectContainerView(); }, - separatorBuilder: (cxt, index) => 12.height, + separatorBuilder: (BuildContext cxt, int index) => 12.height, itemCount: list.length, ); } - Widget getPRNotificationBodyListWidget(GetPrNotificationBodyList getPrNotificationBodyList) { + Widget getPRNotificationBodyListWidget( + GetPrNotificationBodyList getPrNotificationBodyList) { return Column( children: [ - getPrNotificationBodyList.pINFORMATION != null ? getPrNotificationBodyList.pINFORMATION.toString().toText14(color: MyColors.textMixColor).objectContainerView() : Container(), + getPrNotificationBodyList.pINFORMATION != null + ? getPrNotificationBodyList.pINFORMATION + .toString() + .toText14(color: MyColors.textMixColor) + .objectContainerView() + : Container(), 12.height, Column( children: [ ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.from.tr(), workListData!.fROMUSER ?? ""), + ItemDetailViewCol( + LocaleKeys.from.tr(), workListData!.fROMUSER ?? ""), ItemDetailViewCol(LocaleKeys.to.tr(), workListData!.tOUSER ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.sent.tr(), workListData!.bEGINDATE ?? ""), - ItemDetailViewCol(LocaleKeys.closed.tr(), workListData!.eNDDATE ?? ""), + ItemDetailViewCol( + LocaleKeys.sent.tr(), workListData!.bEGINDATE ?? ""), + ItemDetailViewCol( + LocaleKeys.closed.tr(), workListData!.eNDDATE ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.id.tr(), workListData!.nOTIFICATIONID?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.responder.tr(), workListData!.rESPONDER ?? ""), + ItemDetailViewCol(LocaleKeys.id.tr(), + workListData!.nOTIFICATIONID?.toString() ?? ""), + ItemDetailViewCol( + LocaleKeys.responder.tr(), workListData!.rESPONDER ?? ""), ), Column( children: getPRHeaderValues(), @@ -474,12 +611,14 @@ class InfoFragment extends StatelessWidget { ); } - Widget getAddressNotificationBodyListWidget(List getAddressNotificationBodyList) { + Widget getAddressNotificationBodyListWidget( + List getAddressNotificationBodyList) { bool isOdd = false; try { if (getAddressNotificationBodyList.length % 2 != 0) { isOdd = true; - getAddressNotificationBodyList.add(GetAddressNotificationBodyList(sEGMENTPROMPT: "--", sEGMENTVALUEDSP: "--")); + getAddressNotificationBodyList.add(GetAddressNotificationBodyList( + sEGMENTPROMPT: "--", sEGMENTVALUEDSP: "--")); } } catch (e) {} @@ -487,14 +626,15 @@ class InfoFragment extends StatelessWidget { itemCount: getAddressNotificationBodyList!.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) => ItemDetailViewGridItem( + itemBuilder: (BuildContext context, int index) => ItemDetailViewGridItem( index, getAddressNotificationBodyList[index].sEGMENTPROMPT, getAddressNotificationBodyList[index].sEGMENTVALUEDSP, - isNeedToShowEmptyDivider: (getAddressNotificationBodyList.length == index + 1) + isNeedToShowEmptyDivider: + (getAddressNotificationBodyList.length == index + 1) ? isOdd - ? true - : false + ? true + : false : false, ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( @@ -504,13 +644,14 @@ class InfoFragment extends StatelessWidget { ).objectContainerView(); } - - Widget getTerminationNotificationBodyListWidget(List getterminationNotificationBodyList) { + Widget getTerminationNotificationBodyListWidget( + List getterminationNotificationBodyList) { bool isOdd = false; try { if (getterminationNotificationBodyList.length % 2 != 0) { isOdd = true; - getterminationNotificationBodyList.add(TerminationNotificationBody(sEGMENTPROMPT: "--", sEGMENTVALUEDSP: "--")); + getterminationNotificationBodyList.add(TerminationNotificationBody( + sEGMENTPROMPT: "--", sEGMENTVALUEDSP: "--")); } } catch (e) {} @@ -518,11 +659,12 @@ class InfoFragment extends StatelessWidget { itemCount: getterminationNotificationBodyList!.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) => ItemDetailViewGridItem( + itemBuilder: (BuildContext context, int index) => ItemDetailViewGridItem( index, getterminationNotificationBodyList[index].sEGMENTPROMPT, getterminationNotificationBodyList[index].sEGMENTVALUEDSP, - isNeedToShowEmptyDivider: (getterminationNotificationBodyList.length == index + 1) + isNeedToShowEmptyDivider: + (getterminationNotificationBodyList.length == index + 1) ? isOdd ? true : false @@ -535,22 +677,25 @@ class InfoFragment extends StatelessWidget { ).objectContainerView(); } - - List getPRHeaderValues() { List pRHeaders = []; - getPrNotificationBodyList!.pRHeader!.forEach((element) { - pRHeaders.add(ItemDetailGrid(ItemDetailViewCol(element.hDRATTRIBUTENAME!, element.hDRATTRIBUTEVALUE!), Container())); + getPrNotificationBodyList!.pRHeader!.forEach((PRHeader element) { + pRHeaders.add(ItemDetailGrid( + ItemDetailViewCol( + element.hDRATTRIBUTENAME!, element.hDRATTRIBUTEVALUE!), + Container())); }); return pRHeaders; } - Widget getContactNotificationBodyListWidget(GetContactNotificationBodyList data) { + Widget getContactNotificationBodyListWidget( + GetContactNotificationBodyList data) { bool isOdd = false; try { if (data.contactNotificationBody!.length % 2 != 0) { isOdd = true; - data.contactNotificationBody!.add(ContactNotificationBody(segmentPrompt: "--", segmentValueDsp: "--")); + data.contactNotificationBody!.add(ContactNotificationBody( + segmentPrompt: "--", segmentValueDsp: "--")); } } catch (e) {} @@ -558,14 +703,15 @@ class InfoFragment extends StatelessWidget { itemCount: data.contactNotificationBody!.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) => ItemDetailViewGridItem( + itemBuilder: (BuildContext context, int index) => ItemDetailViewGridItem( index, data.contactNotificationBody![index].segmentPrompt, data.contactNotificationBody![index].segmentValueDsp, - isNeedToShowEmptyDivider: (data.contactNotificationBody!.length == index + 1) + isNeedToShowEmptyDivider: + (data.contactNotificationBody!.length == index + 1) ? isOdd - ? true - : false + ? true + : false : false, ), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( @@ -578,9 +724,329 @@ class InfoFragment extends StatelessWidget { child: ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => ItemDetailViewCol(data.contactNotificationBody![index].segmentPrompt!, data.contactNotificationBody![index].segmentValueDsp!), - separatorBuilder: (cxt, index) => 4.height, + itemBuilder: (BuildContext cxt, int index) => ItemDetailViewCol( + data.contactNotificationBody![index].segmentPrompt!, + data.contactNotificationBody![index].segmentValueDsp!), + separatorBuilder: (BuildContext cxt, int index) => 4.height, itemCount: data.contactNotificationBody!.length), ); + } + + Widget getPaymentNotificationBodyListWidget( + GetPaymentNotificationBodyList? data) { + return Column( + children: [ + 12.height, + if (data!.paymentDetailsList!.isNotEmpty) + Column( + children: [ + LocaleKeys.paymentDetails.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.requestNumber.tr(), data.paymentDetailsList![0].requestNumber ?? ""), + ItemDetailViewCol( LocaleKeys.requesterEmpNum.tr(), + data.paymentDetailsList![0].requesterEmployeeNumber ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol( LocaleKeys.requestDate.tr(), + DateUtil.formatDateToDate( + DateUtil.convertStringToDate(data.paymentDetailsList![0].requestDate!), false) ?? ""), + ItemDetailViewCol( + LocaleKeys.requesterEmpName.tr(), data.paymentDetailsList![0].requesterEmployeeName ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol( LocaleKeys.prepareEmpNum.tr(), + data.paymentDetailsList![0].prepareEmployeeNumber ?? ""), + ItemDetailViewCol( + LocaleKeys.requesterPositionName.tr(), data.paymentDetailsList![0].requesterPositionName ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol( LocaleKeys.prepareEmpName.tr(), + data.paymentDetailsList![0].prepareEmployeeName ?? ""), + ItemDetailViewCol( + LocaleKeys.requesterPayrollName.tr(), data.paymentDetailsList![0].requesterPayrollName ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol( LocaleKeys.preparePositionName.tr(), + data.paymentDetailsList![0].preparePositionName ?? ""), + ItemDetailViewCol( + LocaleKeys.requesterPositionName.tr(), data.paymentDetailsList![0].requesterPositionName ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol( LocaleKeys.prepareEmpName.tr(), + data.paymentDetailsList![0].prepareEmployeeName ?? ""), + ItemDetailViewCol( + LocaleKeys.requesterPayrollName.tr(), data.paymentDetailsList![0].requesterPayrollName ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol( LocaleKeys.preparePositionName.tr(), + data.paymentDetailsList![0].preparePositionName ?? ""), + ItemDetailViewCol( LocaleKeys.requesterOperatingUnit.tr(), + data.paymentDetailsList![0].requesterOperatingUnits ?? "") + ), + + ], + ).objectContainerView(), + if (data!.paymentDetailsList!.isNotEmpty) + Column( + children: [ + LocaleKeys.general.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.payingORGName.tr(), data.paymentDetailsList![0].payingOrganizationName ?? ""), + ItemDetailViewCol(LocaleKeys.requestAmount.tr(), + data.paymentDetailsList![0].requestAmount ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.paymentMethodName.tr(), + data.paymentDetailsList![0].paymentMethodName ?? ""), + ItemDetailViewCol( + LocaleKeys.currency.tr(), data.paymentDetailsList![0].currency ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.typeofPayment.tr(), + data.paymentDetailsList![0].typeOfPayment ?? ""), + ItemDetailViewCol( + LocaleKeys.paymentDetails.tr(), data.paymentDetailsList![0].paymentDetails ?? ""), + ), + + ], + ).objectContainerView(), + + if (data!.beneficieryList!.isNotEmpty) + Column( + children: [ + LocaleKeys.beneficiaryDetails.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.beneficiaryName.tr(), data.beneficieryList![0].beneficiaryName ?? ""), + ItemDetailViewCol(LocaleKeys.idIqama.tr(), + data.beneficieryList![0].iqamaNumber ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.beneficiaryBankName.tr(), + data.beneficieryList![0] .beneficiaryBankName ?? ""), + ItemDetailViewCol( + LocaleKeys.sadadNumber.tr(), data.beneficieryList![0].saddadNumber ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.beneficiaryIBAN.tr(), + data.beneficieryList![0].beneficiaryIban ?? ""), + Container(), + ), + + ], + ).objectContainerView(), + + if (data!.purchaseOrdersList!.isNotEmpty && data.purchaseOrdersList![0].poAmount !=null) + Column( + children: [ + LocaleKeys.purchaseOrders.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.poNumber.tr(), data.purchaseOrdersList![0].poNumber ?? ""), + ItemDetailViewCol(LocaleKeys.pOAmount.tr(), + data.purchaseOrdersList![0].poAmount.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.supplierName.tr(), + data.purchaseOrdersList![0].supplierName ?? ""), + ItemDetailViewCol( + LocaleKeys.approvalDate.tr(), data.purchaseOrdersList![0].poApprovalDate!=null ? DateUtil.formatDateToDate( + DateUtil.convertStringToDate(data.purchaseOrdersList![0].poApprovalDate), false) :"" ), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.requestNumber.tr(), + data.purchaseOrdersList![0].prNumber?? ""), + ItemDetailViewCol(LocaleKeys.versionStatus.tr(), + data.purchaseOrdersList![0].versionStatus?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.supplierNo.tr(), + data.purchaseOrdersList![0].supplierNumber?? ""), + Container(), + ), + ], + ).objectContainerView(), + + if (data!.supplierInformationList!.isNotEmpty && data.supplierInformationList![0].supplierNumber !="") + Column( + children: [ + LocaleKeys.supplierInfo.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.supplierNo.tr(), data.supplierInformationList![0].supplierNumber ?? ""), + ItemDetailViewCol(LocaleKeys.supplierName.tr(), + data.supplierInformationList![0].supplierName.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.supplierAcNo.tr(), + data.supplierInformationList![0].supplierBankAccountNumber ?? ""), + ItemDetailViewCol( + LocaleKeys.supplierAcName.tr(), data.supplierInformationList![0].supplierBankAccountName ?? + "" ), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.supplierCRNo.tr(), + data.supplierInformationList![0].crNumber?? ""), + ItemDetailViewCol( LocaleKeys.supplierIBAN.tr(), data.supplierInformationList![0].supplierBankIban ?? + "" ), + ), + + ], + ).objectContainerView(), + // + if (data!.refundInvoiceList!.isNotEmpty && data.refundInvoiceList![0].patientNumber !="" ) + Column( + children: [ + LocaleKeys.patientRefundInvoice.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.patientNumber.tr(), data.refundInvoiceList![0].patientNumber?? ""), + ItemDetailViewCol(LocaleKeys.hospitalClinic.tr(), + data.refundInvoiceList![0].hospitalClinic.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.patientName.tr(), + data.refundInvoiceList![0].patientName ?? ""), + ItemDetailViewCol( + LocaleKeys.amount.tr(), data.refundInvoiceList![0].amount.toString() ?? + "" ), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.invoiceDate.tr(), + DateUtil.formatDateToDate( + DateUtil.convertStringToDate( data.refundInvoiceList![0].invoicedDate), false)?? ""), + + ItemDetailViewCol( LocaleKeys.refundInvoice.tr(), data.refundInvoiceList![0].invoiceNumber ?? + "" ), + ), + + ], + ).objectContainerView(), + + ], + + ); + } + + Widget getFANotificationBodyListWidget( + GetFaDisposalNtfDetails? data) { + return Column( + children: [ + 12.height, + + if (data!.pFaHeader!.isNotEmpty) + Column( + children: [ + LocaleKeys.faHeader.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.requestNo.tr(), + data.pFaHeader![0].requestNo.toString() ?? ""), + ItemDetailViewCol( + LocaleKeys.stats.tr(), data.pFaHeader![0].status ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.bookTypeCode.tr(), data.pFaHeader![0].bookTypeCode ?? ""), + ItemDetailViewCol(LocaleKeys.categoryCode.tr(), + data.pFaHeader![0].categoryCode ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.categoryGroup.tr(), + data.pFaHeader![0].categoryGroup ?? ""), + ItemDetailViewCol( + LocaleKeys.comments.tr(), data.pFaHeader![0].comments ?? ""), + ), + + + ], + ).objectContainerView(), + if (data!.pFaLines!.isNotEmpty) + Column( + children: [ + LocaleKeys.faLINES.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol( LocaleKeys.requestNo.tr(), + data.pFaLines![0].requestNo.toString() ?? ""), + ItemDetailViewCol( + LocaleKeys.quantity.tr(), data.pFaLines![0].quantity.toString() ?? "" ), + + ), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.assetNumber.tr(), data.pFaLines![0].assetNumber.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.assetDescription.tr(), + data.pFaLines![0].assetDescription ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.barCodeNumber.tr(), + data.pFaLines![0] .barcodeNumber.toString() ?? ""), + ItemDetailViewCol( + LocaleKeys.datePlaceInService.tr(), DateUtil.formatDateToDate( + DateUtil.convertStringToDate( data.pFaLines![0].datePlacedInService ?? ""), false)), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.departmentName.tr(), + data.pFaLines![0].department ?? ""), + ItemDetailViewCol(LocaleKeys.serialNumber.tr(), + data.pFaLines![0].serialNumber ?? "") , + ), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.disposedDate.tr(), DateUtil.formatDateToDate( + DateUtil.convertStringToDate( data.pFaLines![0].disposedDate ?? ""), false)), + ItemDetailViewCol(LocaleKeys.netBookValue.tr(), + data.pFaLines![0].netBookValue.toString() ?? ""), + + ), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.poNumber.tr(), data.pFaLines![0].poNumber.toString() ?? "" ), + ItemDetailViewCol(LocaleKeys.purchasedPrice.tr(), + data.pFaLines![0].purchasePrice.toString() ?? ""), + + ), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.usefulLife.tr(), data.pFaLines![0].usefulLife.toString() ?? "" ), + ItemDetailViewCol(LocaleKeys.yearsUsed.tr(), + data.pFaLines![0].yearsUsed.toString() ?? ""), + + ), + ], + ).objectContainerView(), + + if (data!.pFaBuyers!.isNotEmpty) + Column( + children: [ + LocaleKeys.buyer.tr().toText14(color: MyColors.textMixColor), + ItemDetailGrid( + ItemDetailViewCol( + LocaleKeys.requestNo.tr(), data.pFaBuyers![0].requestNo.toString() ?? ""), + ItemDetailViewCol( LocaleKeys.amount.tr(), + data.pFaBuyers![0].amount.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.buyerNumber.tr(), + data.pFaBuyers![0].buyerName!), + ItemDetailViewCol( + LocaleKeys.buyerNumber.tr(), data.pFaBuyers![0].buyerNumber ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol( LocaleKeys.highestBidder.tr(), + data.pFaBuyers![0].highestBidder ?? ""), + ItemDetailViewCol( + LocaleKeys.remarks.tr(), data.pFaBuyers![0].remarks ?? ""), + ), + + ], + ).objectContainerView(), + + ]); + + + + } } diff --git a/lib/widgets/AnimatedProgressBar.dart b/lib/widgets/AnimatedProgressBar.dart new file mode 100644 index 0000000..c0bf3d1 --- /dev/null +++ b/lib/widgets/AnimatedProgressBar.dart @@ -0,0 +1,176 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +/// Animated progress bar. Behaves like implicitly animated widget. +/// Check basic implicit animated Flutter widgets like [AnimatedContainer] +/// It animates [value] changes. +/// Requires [duration] to set filling duration timer +/// [onEnd] callback to trigger additional actions (e.g. another animation) +/// at the end of the current animation +/// [color] or [gradient] to fill the progress bar. Only one parameter is allowed. +/// Optional [backgroundColor], defaults to transparent +/// Optional [width] defaults to 200.0 +/// Optional [height] defaults to 10.0 +/// Optional [curve] defaults to [Curves.linear] +class AnimatedProgressBar extends ImplicitlyAnimatedWidget { + const AnimatedProgressBar({ + key, + required duration, + required this.value, + this.width = 200.0, + this.height = 10.0, + this.color, + this.gradient, + this.backgroundColor = Colors.transparent, + curve = Curves.linear, + onEnd, + }) : super(key: key, duration: duration, curve: curve, onEnd: onEnd); + + ///progress bar width + final double width; + + ///progress bar height + final double height; + + ///current progress value + final double? value; + + ///progress bar gradient parameter + final Gradient? gradient; + + ///progress bar color parameter + final Color? color; + + ///progress bar color parameter + final Color backgroundColor; + + @override + AnimatedWidgetBaseState createState() => _AnimatedBarState(); +} + +class _AnimatedBarState extends AnimatedWidgetBaseState { + Tween? _progressValue; + + @override + void forEachTween(TweenVisitor visitor) { + _progressValue = visitor(_progressValue, widget.value, (value) => Tween(begin: value)) as Tween?; + } + + @override + Widget build(BuildContext context) { + return ProgressBar( + value: _progressValue?.evaluate(animation), + width: widget.width, + height: widget.height, + gradient: widget.gradient, + color: widget.color, + backgroundColor: widget.backgroundColor, + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder description) { + super.debugFillProperties(description); + description.add(DiagnosticsProperty('progressValue', _progressValue, showName: false, defaultValue: null)); + } +} + +class ProgressBar extends StatelessWidget { + const ProgressBar({ + Key? key, + required this.value, + this.width = 200.0, + this.height = 10.0, + this.color, + this.backgroundColor = Colors.transparent, + this.gradient, + }) : assert( + gradient == null || color == null, + 'Cannot provide both a color and a gradient', + ), + assert( + gradient != null || color != null, + 'Need to provide color or gradient', + ), + super(key: key); + + ///progress bar width + final double width; + + ///progress bar height + final double height; + + ///current progress value + final double? value; + + ///progress bar gradient parameter + final Gradient? gradient; + + ///progress bar color parameter + final Color? color; + + ///progress bar color parameter + final Color backgroundColor; + + @override + Widget build(BuildContext context) { + return CustomPaint( + size: Size(width, height), + foregroundPainter: ProgressPainter( + value: value!, + color: color, + gradient: gradient, + ), + painter: BackgroundPainter( + backgroundColor: backgroundColor, + ), + ); + } +} + +class BackgroundPainter extends CustomPainter { + const BackgroundPainter({required this.backgroundColor}); + + ///progress bar backgroundColor + final Color backgroundColor; + + @override + void paint(Canvas canvas, Size size) { + Paint paint = Paint()..color = backgroundColor; + canvas.drawRRect(RRect.fromRectAndRadius(Offset.zero & size, Radius.circular(6)), paint); + } + + @override + bool shouldRepaint(covariant BackgroundPainter oldDelegate) => false; +} + +class ProgressPainter extends CustomPainter { + const ProgressPainter({required this.value, this.gradient, this.color}); + + ///current progress bar value + final double value; + + ///progress bar gradient infill + final Gradient? gradient; + + ///progress bar gradient color + final Color? color; + + @override + void paint(Canvas canvas, Size size) { + Paint paint = Paint(); + if (gradient != null) { + paint.shader = gradient?.createShader(Offset.zero & size); + } + if (color != null) { + paint.color = color!; + } + canvas.clipRRect(RRect.fromRectAndRadius(Offset.zero & size, Radius.circular(6))); + canvas.drawRRect(RRect.fromRectAndRadius(Rect.fromLTRB(0, 0, size.width * value, size.height), Radius.circular(6)), paint); + } + + @override + bool shouldRepaint(covariant ProgressPainter oldDelegate) { + return value != oldDelegate.value; + } +} diff --git a/lib/widgets/app_bar_widget.dart b/lib/widgets/app_bar_widget.dart index 6f9898e..277a414 100644 --- a/lib/widgets/app_bar_widget.dart +++ b/lib/widgets/app_bar_widget.dart @@ -1,20 +1,27 @@ import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/classes/colors.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'; -AppBar AppBarWidget(BuildContext context, - {required String title, - bool showHomeButton = true, - bool showWorkListSettingButton = false, - bool showMemberButton = false, - List? actions, - void Function()? onHomeTapped, - void Function()? onBackTapped}) { +AppBar AppBarWidget( + BuildContext context, { + required String title, + bool showHomeButton = true, + bool showLogo = false, + String? logoPath, + bool showWorkListSettingButton = false, + bool showMemberButton = false, + List? actions, + void Function()? onHomeTapped, + void Function()? onBackTapped, +}) { return AppBar( leadingWidth: 0, + automaticallyImplyLeading: false, + surfaceTintColor: Colors.transparent, title: Row( children: [ GestureDetector( @@ -24,8 +31,10 @@ AppBar AppBarWidget(BuildContext context, }, context), child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), ), + if (showLogo) 4.width, + if (showLogo) SvgPicture.asset(logoPath!), 4.width, - title.toText24(color: MyColors.darkTextColor, isBold: true).expanded, + if (!showLogo)title.toText24(color: MyColors.darkTextColor, isBold: true).expanded, ], ), centerTitle: false, @@ -53,7 +62,7 @@ AppBar AppBarWidget(BuildContext context, }, icon: const Icon(Icons.people, color: MyColors.textMixColor), ), - ...actions ?? [] + ...actions ?? [], ], ); } diff --git a/lib/widgets/bottom_sheet.dart b/lib/widgets/bottom_sheet.dart index a15fc3b..d5cb271 100644 --- a/lib/widgets/bottom_sheet.dart +++ b/lib/widgets/bottom_sheet.dart @@ -1,13 +1,19 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; -void showMyBottomSheet(BuildContext context, {required Widget child, required VoidCallback callBackFunc}) { +void showMyBottomSheet(BuildContext context, {required Widget child, required VoidCallback callBackFunc, String? type}) { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (BuildContext context) { return Container( + constraints: BoxConstraints( + maxHeight: type =='CONTINUE_ACTION' ? MediaQuery.of(context).size.height *.75 : double.infinity,), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( @@ -15,8 +21,9 @@ void showMyBottomSheet(BuildContext context, {required Widget child, required Vo topLeft: Radius.circular(25), ), ), + padding: MediaQuery.of(context).viewInsets, clipBehavior: Clip.antiAlias, - child: Column( + child:SingleChildScrollView(child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ @@ -34,7 +41,7 @@ void showMyBottomSheet(BuildContext context, {required Widget child, required Vo 8.height, child, ], - ), + )), ); }, ).then((value) { @@ -46,6 +53,67 @@ void showMyBottomSheet(BuildContext context, {required Widget child, required Vo }); } + + Widget openWorkListBottomSheet(BuildContext context, String? val, String? title){ + return SafeArea( + child: Container( + padding: const EdgeInsets.all(16), + height: MediaQuery.of(context).size.height * 0.3 , // half-screen height + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // ---- Top Row with Title & Close Button ---- + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (title ?? "Details").toText14(isBold: true, color: Color(0xff2BB8A6)), + IconButton( + icon: const Icon(Icons.close, color: Colors.black54, size: 20), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ), + const Divider(height: 1, color: Colors.grey), + const SizedBox(height: 12), + // ---- Scrollable Content ---- + Expanded( + child: SingleChildScrollView( + child: ((val?.isEmpty ?? true) + ? "--" + : val.toString()).toText14(), + ), + ), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xff2BB8A6), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + LocaleKeys.close.tr(), + style: const TextStyle( + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ), + ); +} + class BottomSheetItem extends StatelessWidget { final Function onTap; final IconData icon; diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index d810457..f2f362a 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -30,8 +30,9 @@ class SearchEmployeeBottomSheet extends StatefulWidget { String title, apiMode; List? actionHistoryList; Function(ReplacementList) onSelectEmployee; + Function(String)? onSearchClick; bool fromChat; - + bool? fromDynamicScreen; SearchEmployeeBottomSheet({ required this.title, required this.apiMode, @@ -39,6 +40,8 @@ class SearchEmployeeBottomSheet extends StatefulWidget { this.actionHistoryList, required this.onSelectEmployee, required this.fromChat, + this.fromDynamicScreen =false, + this.onSearchClick, }); @override @@ -152,7 +155,12 @@ class _SearchEmployeeBottomSheetState extends State { 21.height, "Search".toText16(), 11.height, - Row( + widget.fromDynamicScreen! ? Row( + children: [ + radioOption( "UserId" , 0, _selectedSearchIndex), + + ], + ) : Row( children: [ radioOption(widget.fromChat ? "UserId" : "Name", 0, _selectedSearchIndex), radioOption("User Name", 1, _selectedSearchIndex), @@ -164,7 +172,7 @@ class _SearchEmployeeBottomSheetState extends State { children: [ DynamicTextFieldWidget( "Search", - "Search By Username", + widget.fromDynamicScreen! ? "Search By UserID" : "Search By Username", inputAction: TextInputAction.done, suffixIconData: Icons.search, onChange: (text) { @@ -175,8 +183,13 @@ class _SearchEmployeeBottomSheetState extends State { IconButton( constraints: const BoxConstraints(), onPressed: () async { - await SystemChannels.textInput.invokeMethod('TextInput.hide'); - widget.fromChat ? fetchChatUser() : fetchUserByInput(); + if(widget.onSearchClick !=null){ + widget.onSearchClick!(searchText); + }else { + await SystemChannels.textInput.invokeMethod( + 'TextInput.hide'); + widget.fromChat ? fetchChatUser() : fetchUserByInput(); + } }, icon: const Icon(Icons.search), ) diff --git a/lib/widgets/button/default_button.dart b/lib/widgets/button/default_button.dart index 338a13d..ba15fad 100644 --- a/lib/widgets/button/default_button.dart +++ b/lib/widgets/button/default_button.dart @@ -47,28 +47,21 @@ class DefaultButton extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(6.0), gradient: onPress == null - ? const LinearGradient( + ? LinearGradient( colors: [ - Color(0xffEAEAEA), - Color(0xffEAEAEA), + disabledColor ?? Color(0xffEAEAEA), + disabledColor ?? Color(0xffEAEAEA), ], ) : color == MyColors.yellowColorII ? const LinearGradient( - colors: [ - MyColors.yellowColorII, - MyColors.yellowColorII, - ], + colors: [MyColors.yellowColorII, MyColors.yellowColorII], ) : LinearGradient( transform: const GradientRotation(.83), begin: Alignment.topRight, end: Alignment.bottomLeft, - colors: colors ?? - [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ], + colors: colors ?? [MyColors.gradiantEndColor, MyColors.gradiantStartColor], ), ), child: Row( diff --git a/lib/widgets/chat_app_bar_widge.dart b/lib/widgets/chat_app_bar_widge.dart index cc252ec..1291f9f 100644 --- a/lib/widgets/chat_app_bar_widge.dart +++ b/lib/widgets/chat_app_bar_widge.dart @@ -13,6 +13,8 @@ AppBar ChatAppBarWidget(BuildContext context, {required String title, bool showHomeButton = true, ChatUser? chatUser, bool showTyping = false, List? actions, void Function()? onHomeTapped, void Function()? onBackTapped}) { return AppBar( leadingWidth: 0, + automaticallyImplyLeading: false, + surfaceTintColor: Colors.transparent, title: Consumer(builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { return Row( children: [ diff --git a/lib/widgets/glowy_borders/glowy_borders.dart b/lib/widgets/glowy_borders/glowy_borders.dart new file mode 100644 index 0000000..ffdc31b --- /dev/null +++ b/lib/widgets/glowy_borders/glowy_borders.dart @@ -0,0 +1,150 @@ +library glowy_borderspertino.dart; + +import 'dart:math' as math; + +import 'package:flutter/cupertino.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; + +class AnimatedGradientBorder extends StatefulWidget { + const AnimatedGradientBorder( + {Key? key, + required this.child, + required this.gradientColors, + required this.borderRadius, + this.animationTime, + this.borderSize, + this.animationProgress, + this.stretchAlongAxis = false, + this.stretchAxis = Axis.horizontal}); + + final Widget child; + final double? borderSize; + final List gradientColors; + final BorderRadiusGeometry borderRadius; + final int? animationTime; + final double? animationProgress; + final bool stretchAlongAxis; + final Axis stretchAxis; + + @override + State createState() => AnimatedGradientState(); +} + +class AnimatedGradientState extends State with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation _angleAnimation; + + @override + void initState() { + super.initState(); + _controller = AnimationController(vsync: this, duration: Duration(seconds: widget.animationTime ?? 2)); + _controller.addListener(() => setState(() {})); + _angleAnimation = Tween(begin: 0.1, end: 2 * math.pi).animate(_controller); + if (widget.animationProgress != null) { + _controller.forward(); + } else { + _controller.repeat(); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + void didUpdateWidget(covariant AnimatedGradientBorder oldWidget) { + super.didUpdateWidget(oldWidget); + double? animateTo = widget.animationProgress; + if (animateTo != null) { + _controller.animateTo(animateTo); + } else { + _controller.repeat(); + } + } + + @override + Widget build(BuildContext context) { + double? negativeMargin = -1.0 * (widget.borderSize ?? 0); + return Container( + padding: EdgeInsets.all(widget.borderSize ?? 0), + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + color: MyColors.kWhiteColor, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: const Color(0xff000000).withOpacity(.05), + blurRadius: 26, + offset: const Offset(0, -3), + ), + ], + ), + child: Stack(alignment: Alignment.center, clipBehavior: Clip.none, children: [ + Positioned( + top: negativeMargin, + left: negativeMargin, + right: negativeMargin, + bottom: negativeMargin, + child: AnimatedGradientContainer( + gradientColors: widget.gradientColors, + borderRadius: widget.borderRadius, + gradientAngle: _angleAnimation.value, + )), + widget.child, + // BackdropFilter( + // filter: ImageFilter.blur(sigmaX: widget.glowSize ?? 0, sigmaY: widget.glowSize ?? 0), + // child: Stack( + // alignment: Alignment.center, + // clipBehavior: Clip.none, + // children: [ + // Positioned( + // top: negativeMargin, + // right: negativeMargin, + // left: negativeMargin, + // bottom: negativeMargin, + // child: AnimatedGradientContainer( + // gradientColors: widget.gradientColors, + // borderRadius: widget.borderRadius, + // gradientAngle: _angleAnimation.value, + // )), + // if (widget.stretchAlongAxis) + // SizedBox( + // width: widget.stretchAxis == Axis.horizontal ? double.infinity : null, + // height: widget.stretchAxis == Axis.vertical ? double.infinity : null, + // child: widget.child, + // ) + // else + // widget.child, + // ], + // ), + // ), + ]), + ); + } +} + +class AnimatedGradientContainer extends StatelessWidget { + const AnimatedGradientContainer({Key? key, required this.gradientColors, required this.gradientAngle, required this.borderRadius}); + + final List gradientColors; + final double gradientAngle; + final BorderRadiusGeometry borderRadius; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: borderRadius, + gradient: SweepGradient( + colors: [...gradientColors, ...gradientColors.reversed], stops: _generateColorStops([...gradientColors, ...gradientColors.reversed]), transform: GradientRotation(gradientAngle)))); + } + + List _generateColorStops(List colors) { + return colors.asMap().entries.map((entry) { + double percentageStop = entry.key / colors.length; + return percentageStop; + }).toList(); + } +} diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index ef04f84..984d6ad 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -8,21 +8,25 @@ import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/attachment_options.dart'; - +final ImagePicker picker = ImagePicker(); class ImageOptions { + static void showImageOptionsNew(BuildContext context, bool showFilesOption, Function(String, File) image) { + showMyBottomSheet( context, callBackFunc: () {}, child: AttachmentOptions( showFilesOption: showFilesOption, onCameraTap: () async { + if (Platform.isAndroid) { cameraImageAndroid(image); } else { File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); - String fileName = _image.path; - var bytes = File(fileName).readAsBytesSync(); + // XFile? media = await picker.pickMedia(); + String? fileName = _image?.path; + var bytes = File(fileName!).readAsBytesSync(); String base64Encode = base64.encode(bytes); if (base64Encode != null) { image(base64Encode, _image); @@ -33,7 +37,7 @@ class ImageOptions { if (Platform.isAndroid) { galleryImageAndroid(image); } else { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? ""); + File _image = File((await picker.pickMedia())?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); @@ -126,7 +130,7 @@ class ImageOptions { } void galleryImageAndroid(Function(String, File) image) async { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? ""); + File _image = File((await picker.pickMedia())?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); @@ -137,7 +141,7 @@ void galleryImageAndroid(Function(String, File) image) async { } void cameraImageAndroid(Function(String, File) image) async { - File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); + File _image = File((await picker.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); String fileName = _image.path; var bytes = File(fileName).readAsBytesSync(); String base64Encode = base64.encode(bytes); @@ -155,7 +159,7 @@ class _BottomSheet extends StatelessWidget { Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(vertical: 12.0), - decoration: BoxDecoration(color: Theme.of(context).backgroundColor, borderRadius: const BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0))), + decoration: const BoxDecoration( borderRadius: BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0))), child: SafeArea( top: false, child: Column( diff --git a/lib/widgets/item_detail_view_widget.dart b/lib/widgets/item_detail_view_widget.dart index 68b245a..de82afe 100644 --- a/lib/widgets/item_detail_view_widget.dart +++ b/lib/widgets/item_detail_view_widget.dart @@ -1,11 +1,14 @@ import 'dart:convert'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/classes/colors.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/models/itg_forms_models/itg_worklist_table_model.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; class ItemDetailView extends StatelessWidget { final String title; @@ -40,7 +43,7 @@ class ItemDetailViewCol extends StatelessWidget { children: [ "$title:".toText12(isBold: true, color: const Color(0xff2BB8A6), maxLine: 2), 4.width, - (value.isEmpty ? "--" : value).toText12(color: MyColors.normalTextColor, maxLine: 5), + Flexible(child: (value.isEmpty ? "--" : value).toText12(color: MyColors.normalTextColor, maxLine: null)), ], ); } @@ -52,8 +55,10 @@ class ItemDetailViewGridItem extends StatelessWidget { final String? value; final String? type; final bool isNeedToShowEmptyDivider; + final int maxLine; + final bool showSpaceAfterLine; - ItemDetailViewGridItem(this.index, this.title, this.value, {Key? key, this.isNeedToShowEmptyDivider = false, this.type = ""}) : super(key: key); + ItemDetailViewGridItem(this.index, this.title, this.value, {Key? key, this.isNeedToShowEmptyDivider = false, this.showSpaceAfterLine = false, this.type = "", this.maxLine = 6}) : super(key: key); @override Widget build(BuildContext context) { @@ -76,22 +81,57 @@ class ItemDetailViewGridItem extends StatelessWidget { ), ), child: isNeedToShowEmptyDivider - ? Container() + ? SizedBox() : Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, children: [ - title != null ? Flexible(child: "$title:".toText12Auto(isBold: true, color: const Color(0xff2BB8A6))) : Container(), + title != null ? Flexible(child: "$title:".toText12(isBold: true, color: const Color(0xff2BB8A6))) : Container(), 4.width, - type != null - ? type!.toLowerCase() == "table" - ? getStringFromJSON(value!) - : Flexible(child: (value!.isEmpty ? "--" : value).toString().toText12Auto(color: MyColors.normalTextColor)) - : Container(), + type != null + ? type!.toLowerCase() == "table" + ? getStringFromJSON(value!) + // : Flexible(child: (value!.isEmpty ? "--" : value).toString().toText12Auto(color: MyColors.normalTextColor, maxLine: 5)) + : (value!.isEmpty ? "--" : value).toString().toText12(color: MyColors.normalTextColor, maxLine: 2) + : Container(), + if (value!.length > 100) + GestureDetector( + onTap: () { + showModalBottomSheet( + context: context, + enableDrag: true, + isDismissible: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)), + ), + backgroundColor: Colors.white, + builder: (context) { + return openWorkListBottomSheet(context, value, title); + }, + ); + + }, + child: Padding( + padding: const EdgeInsets.only(top: 4), + child: Text( + LocaleKeys.showMore.tr(), + textAlign: TextAlign.right, + style: const TextStyle( + color: Color(0xff2BB8A6), + fontSize: 12, + fontWeight: FontWeight.w600, + + ), + ), + ), + ), ], - ), + + ).paddingOnly(top: showSpaceAfterLine ? 16 : 0, left: 2, right: 2), ); } + } class ItemDetailGrid extends StatelessWidget { @@ -149,3 +189,4 @@ Widget getStringFromJSON(String jsonString) { return Flexible(child: ("-").toString().toText12Auto(color: MyColors.normalTextColor)); } } + diff --git a/lib/widgets/location/Location.dart b/lib/widgets/location/Location.dart index 67d3cdd..fe4e976 100644 --- a/lib/widgets/location/Location.dart +++ b/lib/widgets/location/Location.dart @@ -35,7 +35,7 @@ class Location { }); } - static void getCurrentLocation(Function(Position position, bool isMocked) callback, BuildContext context) { + static void getCurrentLocation(Function(Position position, bool isMocked) callback, Function errorCallBack, BuildContext context) { void done(Position position) { //AppStorage.sp.saveLocation(position); bool isMocked = position.isMocked; @@ -44,8 +44,10 @@ class Location { AppPermissions.location((granted) { if (granted) { - Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium, timeLimit: const Duration(seconds: 5)).then((value) { + Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium, timeLimit: const Duration(seconds: 10)).then((value) { done(value); + }).catchError((err) { + errorCallBack(); }); } else { // AppPermissions diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 982e316..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 { @@ -171,14 +170,21 @@ class _MarkAttendanceWidgetState extends State { if (isEnabled) { location.Location.havePermission((bool permission) { if (permission) { + Utils.showLoading(context); location.Location.getCurrentLocation( (Position position, bool isMocked) { if (isMocked) { + Utils.hideLoading(context); markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); } else { + Utils.hideLoading(context); performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); } }, + () { + Utils.hideLoading(context); + Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); + }, context, ); } else { @@ -218,14 +224,21 @@ class _MarkAttendanceWidgetState extends State { if (isEnabled) { location.Location.havePermission((bool permission) { if (permission) { + Utils.showLoading(context); location.Location.getCurrentLocation( (Position position, bool isMocked) { if (isMocked) { + Utils.hideLoading(context); markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); } else { + Utils.hideLoading(context); performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); } }, + () { + Utils.hideLoading(context); + Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); + }, context, ); } else { @@ -265,14 +278,21 @@ class _MarkAttendanceWidgetState extends State { if (isEnabled) { location.Location.havePermission((bool permission) { if (permission) { + Utils.showLoading(context); location.Location.getCurrentLocation( (Position position, bool isMocked) { if (isMocked) { + Utils.hideLoading(context); markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? ""); } else { + Utils.hideLoading(context); performQrCodeAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? ""); } }, + () { + Utils.hideLoading(context); + Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working."); + }, context, ); } else { @@ -313,7 +333,7 @@ class _MarkAttendanceWidgetState extends State { void getHuaweiCurrentLocation(String attendanceType) async { try { Utils.showLoading(context); - FusedLocationProviderClient locationService = FusedLocationProviderClient(); + FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService(); LocationRequest locationRequest = LocationRequest(); locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY; locationRequest.interval = 500; @@ -377,6 +397,8 @@ class _MarkAttendanceWidgetState extends State { } catch (error) { print("HUAWEI LOCATION ERROR!!!!!"); print(error); + Utils.hideLoading(context); + Utils.handleException(error, context, null); } } diff --git a/lib/widgets/my_video_progress_indicator.dart b/lib/widgets/my_video_progress_indicator.dart new file mode 100644 index 0000000..3593115 --- /dev/null +++ b/lib/widgets/my_video_progress_indicator.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/widgets/AnimatedProgressBar.dart'; +import 'package:video_player/video_player.dart'; + +class MyVideoProgressIndicator extends StatefulWidget { + const MyVideoProgressIndicator( + this.controller, { + Key? key, + this.colors = const VideoProgressColors(), + required this.allowScrubbing, + this.padding = const EdgeInsets.only(top: 5.0), + }) : super(key: key); + + final VideoPlayerController controller; + + final VideoProgressColors colors; + + final bool allowScrubbing; + + final EdgeInsets padding; + + @override + State createState() => _VideoProgressIndicatorState(); +} + +class _VideoProgressIndicatorState extends State { + _VideoProgressIndicatorState() { + listener = () { + if (!mounted) { + return; + } + setState(() {}); + }; + } + + late VoidCallback listener; + + VideoPlayerController get controller => widget.controller; + + VideoProgressColors get colors => widget.colors; + + @override + void initState() { + super.initState(); + controller.addListener(listener); + } + + @override + void deactivate() { + controller.removeListener(listener); + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + Widget progressIndicator; + if (controller.value.isInitialized) { + int duration = controller.value.duration.inMilliseconds; + int position = controller.value.position.inMilliseconds; + + int maxBuffering = 0; + for (DurationRange range in controller.value.buffered) { + int end = range.end.inMilliseconds; + if (end > maxBuffering) { + maxBuffering = end; + } + } + + progressIndicator = Stack( + fit: StackFit.passthrough, + children: [ + // LinearProgressIndicator( + // value: maxBuffering / duration, + // valueColor: AlwaysStoppedAnimation(colors.bufferedColor), + // backgroundColor: colors.backgroundColor, + // minHeight: 8, + // ), + // LinearProgressIndicator( + // value: position / duration, + // valueColor: AlwaysStoppedAnimation(colors.playedColor), + // backgroundColor: Colors.transparent, + // minHeight: 8, + // ), + + AnimatedProgressBar( + value: position / duration, + duration: const Duration(seconds: 2), + height: 43, + width: MediaQuery.of(context).size.width - 120, + gradient: const LinearGradient( + transform: GradientRotation(.83), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), + backgroundColor: Colors.grey.withOpacity(0.6), + ), + ], + ); + } else { + // progressIndicator = LinearProgressIndicator( + // valueColor: AlwaysStoppedAnimation(colors.playedColor), + // backgroundColor: colors.backgroundColor, + // minHeight: 8, + // ); + progressIndicator = AnimatedProgressBar( + value: 1, + duration: const Duration(seconds: 2), + height: 43, + width: MediaQuery.of(context).size.width - 120, + gradient: const LinearGradient( + transform: GradientRotation(.83), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), + backgroundColor: Colors.grey.withOpacity(0.6), + ); + } + Widget paddedProgressIndicator = Padding(padding: widget.padding, child: progressIndicator); + if (widget.allowScrubbing) { + return VideoScrubber(controller: controller, child: paddedProgressIndicator); + } else { + return paddedProgressIndicator; + } + } +} diff --git a/lib/widgets/nfc/nfc_reader_sheet.dart b/lib/widgets/nfc/nfc_reader_sheet.dart index b7b97a7..5e0b62d 100644 --- a/lib/widgets/nfc/nfc_reader_sheet.dart +++ b/lib/widgets/nfc/nfc_reader_sheet.dart @@ -80,6 +80,7 @@ class _NfcLayoutState extends State { Widget scanNfc() { return Container( key: ValueKey(1), + width: double.infinity, child: Column( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/widgets/otp_widget.dart b/lib/widgets/otp_widget.dart index 7994b1e..7196a22 100644 --- a/lib/widgets/otp_widget.dart +++ b/lib/widgets/otp_widget.dart @@ -49,23 +49,23 @@ class OTPWidget extends StatefulWidget { const OTPWidget({ Key? key, - this.maxLength: 4, + this.maxLength = 4, this.controller, - this.pinBoxWidth: 70.0, - this.pinBoxHeight: 70.0, + this.pinBoxWidth = 70.0, + this.pinBoxHeight = 70.0, this.pinTextStyle, this.onDone, - this.defaultBorderColor: Colors.black, - this.textBorderColor: Colors.black, + this.defaultBorderColor = Colors.black, + this.textBorderColor = Colors.black, this.pinTextAnimatedSwitcherTransition, - this.pinTextAnimatedSwitcherDuration: const Duration(), - this.hasError: false, - this.errorBorderColor: Colors.red, + this.pinTextAnimatedSwitcherDuration = const Duration(), + this.hasError = false, + this.errorBorderColor = Colors.red, this.onTextChanged, - this.autoFocus: false, + this.autoFocus = false, this.focusNode, - this.textDirection: TextDirection.ltr, - this.keyboardType: TextInputType.number, + this.textDirection = TextDirection.ltr, + this.keyboardType =TextInputType.number, this.pinBoxOuterPadding = const EdgeInsets.symmetric(horizontal: 4.0), this.pinBoxColor = Colors.white, this.pinBoxBorderWidth = 2.0, diff --git a/lib/widgets/qr_scanner_dialog.dart b/lib/widgets/qr_scanner_dialog.dart index 11e2601..01a92de 100644 --- a/lib/widgets/qr_scanner_dialog.dart +++ b/lib/widgets/qr_scanner_dialog.dart @@ -1,8 +1,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; -import 'package:qr_code_scanner/qr_code_scanner.dart'; class QrScannerDialog extends StatefulWidget { @override @@ -11,8 +11,9 @@ class QrScannerDialog extends StatefulWidget { class _QrScannerDialogState extends State { final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); - Barcode? result; - QRViewController? controller; + // Barcode? result; + // QRViewController? controller; + Barcode? _barcode; bool isPicked = false; @override @@ -26,10 +27,7 @@ class _QrScannerDialogState extends State { children: [ Expanded( flex: 1, - child: QRView( - key: qrKey, - onQRViewCreated: _onQRViewCreated, - ), + child: MobileScanner(key : qrKey,onDetect: _handleBarcode), ), // Expanded( // flex: 1, @@ -55,25 +53,25 @@ class _QrScannerDialogState extends State { ); } - void _onQRViewCreated(QRViewController controller) { - this.controller = controller; - - controller.scannedDataStream.listen((scanData) { + void _handleBarcode(BarcodeCapture barcodes) { + // this.controller = controller; + Barcode? data = barcodes.barcodes.firstOrNull; + if(data == null || isPicked) { + return; + } + // controller.scannedDataStream.listen((scanData) { setState(() { - result = scanData; - if (!isPicked) { + // result = scanData; isPicked = true; - Navigator.pop(context, result!.code); - } + Navigator.pop(context, data.displayValue); }); - }); - controller.pauseCamera(); - controller.resumeCamera(); + // }); + // controller.pauseCamera(); + // controller.resumeCamera(); } @override void dispose() { - controller?.dispose(); super.dispose(); } } diff --git a/lib/widgets/shimmer/dashboard_shimmer_widget.dart b/lib/widgets/shimmer/dashboard_shimmer_widget.dart index c11cf16..7d59899 100644 --- a/lib/widgets/shimmer/dashboard_shimmer_widget.dart +++ b/lib/widgets/shimmer/dashboard_shimmer_widget.dart @@ -8,6 +8,8 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:shimmer/shimmer.dart'; class GetAttendanceTrackingShimmer extends StatelessWidget { + const GetAttendanceTrackingShimmer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Container( @@ -85,6 +87,8 @@ class GetAttendanceTrackingShimmer extends StatelessWidget { } class MenuShimmer extends StatelessWidget { + const MenuShimmer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Container( @@ -122,6 +126,8 @@ class MenuShimmer extends StatelessWidget { } class ServicesHeaderShimmer extends StatelessWidget { + const ServicesHeaderShimmer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Row( @@ -145,6 +151,8 @@ class ServicesHeaderShimmer extends StatelessWidget { } class ServicesMenuShimmer extends StatelessWidget { + const ServicesMenuShimmer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Container( @@ -188,6 +196,75 @@ class ServicesMenuShimmer extends StatelessWidget { } } +class GreetingCardShimmer extends StatelessWidget { + const GreetingCardShimmer({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 100, + decoration: BoxDecoration( + color: const Color(0xFFFAF4E7), + border: Border.all(width: 2, color: const Color(0xFFE7E7E7)), + borderRadius: BorderRadius.circular(20), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 65, + height: 81, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(10), + ), + ).toShimmer(), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 150, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ).toShimmer(), + const SizedBox(height: 8), + Container( + width: 120, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ).toShimmer(), + ], + ).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + width: 60, + height: 12, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ).toShimmer(), + ], + ), + ], + ).paddingOnly(left: 8, right: 8, top: 6, bottom: 12), + ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14); + } +} + + class MarathonBannerShimmer extends StatelessWidget { const MarathonBannerShimmer({Key? key}) : super(key: key); @@ -305,3 +382,4 @@ class ChatHomeShimmer extends StatelessWidget { )); } } + diff --git a/lib/widgets/sso_webview_widget.dart b/lib/widgets/sso_webview_widget.dart new file mode 100644 index 0000000..ee4ed7a --- /dev/null +++ b/lib/widgets/sso_webview_widget.dart @@ -0,0 +1,64 @@ +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({this.url, this.jwtToken}); + + @override + State createState() => _SsoLoginWebViewState(); +} + +class _SsoLoginWebViewState extends State { + late final WebViewController _controller; + String? url; + @override + void initState() { + // TODO: implement initState + + url = widget.url ?? "https://Paxes-release.techmaster.in/SSO/HMG"; + + 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: null, body:SafeArea(child: WebViewWidget(controller: _controller))); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index e3b15bd..7e5a29a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,11 +16,12 @@ 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.3.01+300040 -version: 3.7.7+1 + +version: 3.7.2+300082 +#version: 3.9.3+1 environment: - sdk: ">=2.16.0 <3.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 @@ -40,46 +41,49 @@ dependencies: injector: ^2.0.0 provider: ^6.0.1 easy_localization: ^3.0.0 - http: ^0.13.4 - permission_handler: ^10.2.0 + http: ^1.4.0 + permission_handler: ^12.0.1 flutter_svg: any sizer: ^2.0.15 - local_auth: ^1.1.9 + local_auth: ^2.3.0 fluttertoast: ^8.0.8 - syncfusion_flutter_calendar: ^19.4.48 + syncfusion_flutter_calendar: ^29.1.38 # 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 - image_picker: ^0.8.5+3 - file_picker: ^4.6.1 + +# platform_device_id_plus: ^1.0.7 + mobile_device_identifier: ^0.0.3 + device_info_plus: ^11.5.0 + image_picker: ^1.1.2 + file_picker: ^8.3.1 geolocator: ^9.0.2 - month_year_picker: ^0.2.0+1 - month_picker_dialog_2: 0.5.5 - open_file: ^3.2.1 - wifi_iot: ^0.3.18 + month_year_picker: ^0.5.0+1 + month_picker_dialog: ^6.0.3 +# 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 # flutter_barcode_scanner: ^2.0.0 - qr_code_scanner: ^1.0.1 +# 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 + fl_chart: ^0.66.0 # lottie json animations lottie: any # Marathon Card Swipe appinio_swiper: ^1.1.1 expandable: ^5.0.1 + safe_device: ^1.1.9 # networkImage cached_network_image: ^3.2.2 @@ -88,19 +92,23 @@ dependencies: signalr_netcore: ^1.3.3 logging: ^1.0.1 swipe_to: ^1.0.2 - flutter_webrtc: ^0.9.17 - camera: ^0.10.3 - flutter_local_notifications: ^10.0.0 + flutter_webrtc: ^0.12.11 +# camera: ^0.10.3 + camera: ^0.11.2 + flutter_local_notifications: ^18.0.1 #firebase_analytics: any #Chat Voice Message Recoding & Play - audio_waveforms: ^0.1.5+1 + audio_waveforms: ^1.3.0 rxdart: ^0.27.7 + #Speech to Text + speech_to_text: ^7.0.0 + #Encryption flutter_des: ^2.1.0 - video_player: ^2.5.1 + video_player: 2.7.0 just_audio: ^0.9.30 # safe_device: ^1.1.2 flutter_layout_grid: ^2.0.1 @@ -108,25 +116,41 @@ dependencies: #Huawei 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_location: ^6.14.2+301 +# 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: ^4.2.1 + carousel_slider: ^5.1.1 #Huawei Specified # store_checker: ^1.1.0 - google_api_availability: ^3.0.1 - - in_app_update: 3.0.0 + google_api_availability: ^5.0.1 + google_maps_flutter_web: ^0.5.4 + 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 + nfc_manager: ^3.2.0 + +# saf: ^1.0.3+4 dependency_overrides: - firebase_core_platform_interface: 4.5.1 +# nfc_manager: 3.2.0 +# firebase_core_platform_interface: 4.5.1 dev_dependencies: @@ -159,6 +183,7 @@ flutter: - assets/ - assets/langs/ - assets/icons/ + - assets/icons/itg/ - assets/lottie/ - assets/audio/ - assets/json/