# Conflicts:
#	assets/langs/ar-SA.json
#	assets/langs/en-US.json
#	lib/classes/consts.dart
#	lib/generated/locale_keys.g.dart
#	lib/ui/landing/dashboard_screen.dart
sultan-dev
Sultan khan 3 years ago
commit 61904ca5f7

@ -21,6 +21,12 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'
@ -44,18 +50,24 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.cloudSolutions.mohemmtest"
applicationId "hmg.cloudSolutions.mohem"
minSdkVersion 21
targetSdkVersion 32
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
signingConfig signingConfigs.release
}
}
}

@ -10,7 +10,7 @@
"client_info": {
"mobilesdk_app_id": "1:679409052782:android:dba155ac0859d7fea78a7f",
"android_client_info": {
"package_name": "com.cloudSolutions.mohemmtest"
"package_name": "hmg.cloudSolutions.mohem"
}
},
"oauth_client": [

@ -7,11 +7,12 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="Mohemm"
android:allowBackup="false"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round">
<activity
@ -37,15 +38,21 @@
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#E2E5E7;" d="M128,0c-17.6,0-32,14.4-32,32v448c0,17.6,14.4,32,32,32h320c17.6,0,32-14.4,32-32V128L352,0H128z"/>
<path style="fill:#B0B7BD;" d="M384,128h96L352,0v96C352,113.6,366.4,128,384,128z"/>
<polygon style="fill:#CAD1D8;" points="480,224 384,128 480,128 "/>
<path style="fill:#F15642;" d="M416,416c0,8.8-7.2,16-16,16H48c-8.8,0-16-7.2-16-16V256c0-8.8,7.2-16,16-16h352c8.8,0,16,7.2,16,16
V416z"/>
<g>
<path style="fill:#FFFFFF;" d="M88.368,384c-4.096-2.304-6.656-6.912-4.096-12.288l36.72-71.744c3.456-6.784,12.656-7.04,15.856,0
l36.08,71.744c5.248,9.984-10.24,17.904-14.848,7.936l-5.632-11.248h-47.2l-5.52,11.248C97.712,384,92.992,384.912,88.368,384z
M143.392,351.52l-14.464-31.616l-15.744,31.616H143.392z"/>
<path style="fill:#FFFFFF;" d="M189.184,384c-4.096-2.304-6.656-6.912-4.096-12.288l36.704-71.744
c3.456-6.784,12.672-7.04,15.872,0l36.064,71.744c5.248,9.984-10.24,17.904-14.832,7.936l-5.648-11.248h-47.2l-5.504,11.248
C198.512,384,193.776,384.912,189.184,384z M244.192,351.52l-14.448-31.616l-15.728,31.616H244.192z"/>
<path style="fill:#FFFFFF;" d="M282.416,339.088c0-24.688,15.488-45.904,44.912-45.904c11.136,0,19.952,3.312,29.296,11.376
c3.456,3.184,3.84,8.832,0.384,12.4c-3.456,3.056-8.704,2.688-11.76-0.368c-5.248-5.504-10.624-7.024-17.92-7.024
c-19.696,0-29.168,13.936-29.168,29.536c0,15.872,9.344,30.464,29.168,30.464c7.296,0,14.08-2.96,19.952-8.192
c3.968-3.072,9.472-1.552,11.776,1.536c2.048,2.816,3.056,7.536-1.408,12.016c-8.96,8.336-19.696,9.984-30.336,9.984
C296.368,384.912,282.416,363.792,282.416,339.088z"/>
</g>
<path style="fill:#CAD1D8;" d="M400,432H96v16h304c8.8,0,16-7.2,16-16v-16C416,424.8,408.8,432,400,432z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#E2E5E7;" d="M128,0c-17.6,0-32,14.4-32,32v448c0,17.616,14.4,32,32,32h320c17.6,0,32-14.384,32-32V128L352,0H128z
"/>
<path style="fill:#B0B7BD;" d="M384,128h96L352,0v96C352,113.6,366.4,128,384,128z"/>
<polygon style="fill:#CAD1D8;" points="480,224 384,128 480,128 "/>
<path style="fill:#50BEE8;" d="M416,416c0,8.8-7.2,16-16,16H48c-8.8,0-16-7.2-16-16V256c0-8.8,7.2-16,16-16h352c8.8,0,16,7.2,16,16
V416z"/>
<g>
<path style="fill:#FFFFFF;" d="M117.184,327.84v47.344c0,5.632-4.592,8.832-9.216,8.832c-4.096,0-7.664-3.2-7.664-8.832v-72.032
c0-6.64,5.632-8.832,7.664-8.832c3.712,0,5.888,2.192,8.064,4.608l28.16,38l29.152-39.408c4.24-5.248,14.592-3.2,14.592,5.632
v72.032c0,5.632-3.6,8.832-7.68,8.832c-4.592,0-8.192-3.2-8.192-8.832V327.84l-21.232,26.88c-4.592,5.632-10.352,5.632-14.576,0
L117.184,327.84z"/>
<path style="fill:#FFFFFF;" d="M210.288,303.152c0-4.224,3.328-8.832,8.704-8.832h29.552c16.64,0,31.616,11.136,31.616,32.496
c0,20.224-14.976,31.472-31.616,31.472h-21.36v16.896c0,5.632-3.584,8.832-8.192,8.832c-4.224,0-8.704-3.2-8.704-8.832V303.152z
M227.168,310.448v31.856h21.36c8.576,0,15.36-7.552,15.36-15.488c0-8.96-6.784-16.368-15.36-16.368L227.168,310.448
L227.168,310.448z"/>
<path style="fill:#FFFFFF;" d="M322.064,311.472h-21.872c-10.736,0-10.096-15.984,0-15.984h39.152c7.792,0,11.376,8.96,5.632,14.72
l-21.232,19.824c15.616-1.152,27.888,10.48,27.888,24.816c0,15.728-11.136,29.168-34.544,29.168
c-10.24,0-20.336-4.224-26.224-13.44c-6.144-9.072,7.024-17.776,13.936-8.832c3.328,4.352,8.704,6.528,14.448,6.528
c7.808,0,15.488-3.328,15.488-13.44c0-13.296-16.256-11.248-25.072-10.352c-10.752,2.048-13.936-9.6-7.664-14.448L322.064,311.472z
"/>
</g>
<path style="fill:#CAD1D8;" d="M400,432H96v16h304c8.8,0,16-7.2,16-16v-16C416,424.8,408.8,432,400,432z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

@ -0,0 +1,522 @@
[
{
"id": "b8f10b10-221c-495d-b99b-6a8094892549",
"titleEn": "How many time Uruguay won FIFA World Cups?",
"titleAr": "How many time Uruguay won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/51b598b6-c837-45be-8734-1374978bd426_congratulations-gif.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 1,
"questionOptions": [
{
"id": "772e6062-543c-4ddc-e516-08dae8b36b35",
"titleEn": "1",
"titleAr": "1",
"questionId": "b8f10b10-221c-495d-b99b-6a8094892549",
"sequence": 1,
"image": "null",
"isCorrectOption": false
},
{
"id": "ea3c673e-78c7-41dd-e517-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "b8f10b10-221c-495d-b99b-6a8094892549",
"sequence": 3,
"image": "null",
"isCorrectOption": true
},
{
"id": "7adbdfec-ef77-417e-e518-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "b8f10b10-221c-495d-b99b-6a8094892549",
"sequence": 2,
"image": "null",
"isCorrectOption": false
},
{
"id": "895eab85-e321-4d3e-e519-08dae8b36b35",
"titleEn": "4",
"titleAr": "4",
"questionId": "b8f10b10-221c-495d-b99b-6a8094892549",
"sequence": 4,
"image": "null",
"isCorrectOption": false
}
]
},
{
"id": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0",
"titleEn": "Who is the current FIFA World Cup Winner?",
"titleAr": "Who is the current FIFA World Cup Winner?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/24dddc50-7583-48b4-9fec-8a490d246191_great-thumbs.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "dd0ba127-26ed-4308-e50e-08dae8b36b35",
"titleEn": "Brazil",
"titleAr": "Brazil",
"questionId": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0",
"sequence": 1,
"image": "null",
"isCorrectOption": false
},
{
"id": "4748df31-95f0-4fee-e50f-08dae8b36b35",
"titleEn": "Argentina",
"titleAr": "Argentina",
"questionId": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0",
"sequence": 4,
"image": "null",
"isCorrectOption": true
},
{
"id": "4079d32a-891b-4e83-e510-08dae8b36b35",
"titleEn": "Germany",
"titleAr": "Germany",
"questionId": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0",
"sequence": 3,
"image": "null",
"isCorrectOption": false
},
{
"id": "1c17cfcd-9f19-4020-e511-08dae8b36b35",
"titleEn": "France",
"titleAr": "France",
"questionId": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0",
"sequence": 2,
"image": "null",
"isCorrectOption": false
}
]
},
{
"id": "489659b0-0400-4b64-8ce2-e6fe48db61db",
"titleEn": "How many times England won FIFA World Cups?",
"titleAr": "How many times England won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/a9ffa364-231c-4877-824f-84febac51086_thumbs-up-simon-cowell.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "7f63cd45-ce2c-417f-e502-08dae8b36b35",
"titleEn": "1",
"titleAr": "1",
"questionId": "489659b0-0400-4b64-8ce2-e6fe48db61db",
"sequence": 1,
"image": "null",
"isCorrectOption": true
},
{
"id": "34690bfa-0ffd-453f-e503-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "489659b0-0400-4b64-8ce2-e6fe48db61db",
"sequence": 2,
"image": "null",
"isCorrectOption": false
},
{
"id": "4526efdd-ff6f-4340-e504-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "489659b0-0400-4b64-8ce2-e6fe48db61db",
"sequence": 3,
"image": "null",
"isCorrectOption": false
},
{
"id": "65d06188-fa63-49fd-e505-08dae8b36b35",
"titleEn": "4",
"titleAr": "4",
"questionId": "489659b0-0400-4b64-8ce2-e6fe48db61db",
"sequence": 4,
"image": "null",
"isCorrectOption": false
}
]
},
{
"id": "253fc396-dab9-41ca-82bd-511f98c5dee8",
"titleEn": "How many time Germany won FIFA World Cups?",
"titleAr": "How many time Germany won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/012d6493-3612-42c9-8f6f-84417d4736d4_good-job-well-done.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "dce4999c-5629-45f4-e4f6-08dae8b36b35",
"titleEn": "1",
"titleAr": "1",
"questionId": "253fc396-dab9-41ca-82bd-511f98c5dee8",
"sequence": 1,
"image": "null",
"isCorrectOption": false
},
{
"id": "00913ba1-5ccc-4d7c-e4f7-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "253fc396-dab9-41ca-82bd-511f98c5dee8",
"sequence": 2,
"image": "null",
"isCorrectOption": false
},
{
"id": "9e5f5e89-608e-4fc9-e4f8-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "253fc396-dab9-41ca-82bd-511f98c5dee8",
"sequence": 3,
"image": "null",
"isCorrectOption": false
},
{
"id": "a535cacf-ee4d-4895-e4f9-08dae8b36b35",
"titleEn": "4",
"titleAr": "4",
"questionId": "253fc396-dab9-41ca-82bd-511f98c5dee8",
"sequence": 4,
"image": "null",
"isCorrectOption": true
}
]
},
{
"id": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c",
"titleEn": "How many times Portugal won FIFA World Cups?",
"titleAr": "How many times Portugal won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/ca3f32a1-ed9f-45df-b2fb-3d1df78d5651_congrats-14.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "597c308e-3f09-4a05-e506-08dae8b36b35",
"titleEn": "0",
"titleAr": "0",
"questionId": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c",
"sequence": 1,
"image": "null",
"isCorrectOption": true
},
{
"id": "2face927-7c8e-4945-e507-08dae8b36b35",
"titleEn": "1",
"titleAr": "1",
"questionId": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c",
"sequence": 2,
"image": "null",
"isCorrectOption": false
},
{
"id": "bde21640-798e-4750-e508-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c",
"sequence": 3,
"image": "null",
"isCorrectOption": false
},
{
"id": "9312acac-f0c3-4ed4-e509-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c",
"sequence": 4,
"image": "null",
"isCorrectOption": false
}
]
},
{
"id": "f91774ce-14f0-4af0-9a77-e649bc013b44",
"titleEn": "How many times Spain won FIFA World Cups?",
"titleAr": "How many times Spain won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/6484c5bc-09fd-4586-8036-67868afbe27b_good-job-well-done.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "2f968964-ce91-4478-e512-08dae8b36b35",
"titleEn": "1",
"titleAr": "1",
"questionId": "f91774ce-14f0-4af0-9a77-e649bc013b44",
"sequence": 1,
"image": "null",
"isCorrectOption": true
},
{
"id": "4fed9355-2c9f-458d-e513-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "f91774ce-14f0-4af0-9a77-e649bc013b44",
"sequence": 2,
"image": "null",
"isCorrectOption": false
},
{
"id": "8f232a43-3792-4cd0-e514-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "f91774ce-14f0-4af0-9a77-e649bc013b44",
"sequence": 3,
"image": "null",
"isCorrectOption": false
},
{
"id": "24478e43-bf4c-4852-e515-08dae8b36b35",
"titleEn": "4",
"titleAr": "4",
"questionId": "f91774ce-14f0-4af0-9a77-e649bc013b44",
"sequence": 4,
"image": "null",
"isCorrectOption": false
}
]
},
{
"id": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3",
"titleEn": "How many times France won FIFA World Cups?",
"titleAr": "How many times France won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/24dddc50-7583-48b4-9fec-8a490d246191_great-thumbs.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "9d0743e0-9f3f-48d0-e4fa-08dae8b36b35",
"titleEn": "1",
"titleAr": "1",
"questionId": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3",
"sequence": 1,
"image": "null",
"isCorrectOption": false
},
{
"id": "a81eda99-d9ad-49e0-e4fb-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3",
"sequence": 2,
"image": "null",
"isCorrectOption": true
},
{
"id": "7ca78891-890d-4023-e4fc-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3",
"sequence": 3,
"image": "null",
"isCorrectOption": false
},
{
"id": "d1a98bd9-8afa-49c1-e4fd-08dae8b36b35",
"titleEn": "4",
"titleAr": "4",
"questionId": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3",
"sequence": 4,
"image": "null",
"isCorrectOption": false
}
]
},
{
"id": "3a35855d-3ed7-4d45-8864-9135d71378de",
"titleEn": "How many time Argentina won FIFA World Cups?",
"titleAr": "How many time Argentina won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/24dddc50-7583-48b4-9fec-8a490d246191_great-thumbs.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "f0766816-837f-47e6-e51a-08dae8b36b35",
"titleEn": "1",
"titleAr": "1",
"questionId": "3a35855d-3ed7-4d45-8864-9135d71378de",
"sequence": 1,
"image": "null",
"isCorrectOption": false
},
{
"id": "dc9c68de-afa4-4b63-e51b-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "3a35855d-3ed7-4d45-8864-9135d71378de",
"sequence": 2,
"image": "null",
"isCorrectOption": false
},
{
"id": "52f2d024-8a29-4781-e51c-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "3a35855d-3ed7-4d45-8864-9135d71378de",
"sequence": 3,
"image": "null",
"isCorrectOption": true
},
{
"id": "122636e4-5e98-499e-e51d-08dae8b36b35",
"titleEn": "4",
"titleAr": "4",
"questionId": "3a35855d-3ed7-4d45-8864-9135d71378de",
"sequence": 4,
"image": "null",
"isCorrectOption": false
}
]
},
{
"id": "6c9d809d-683b-4d77-b98e-62a0d083488a",
"titleEn": "How many times Brazil won FIFA World Cups?",
"titleAr": "How many times Brazil won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/a9ffa364-231c-4877-824f-84febac51086_thumbs-up-simon-cowell.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "4e94437a-b10d-46c6-e4fe-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "6c9d809d-683b-4d77-b98e-62a0d083488a",
"sequence": 1,
"image": "null",
"isCorrectOption": false
},
{
"id": "6e0e8baa-c13e-45f1-e4ff-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "6c9d809d-683b-4d77-b98e-62a0d083488a",
"sequence": 2,
"image": "null",
"isCorrectOption": false
},
{
"id": "3065d26a-9aa4-4626-e500-08dae8b36b35",
"titleEn": "4",
"titleAr": "4",
"questionId": "6c9d809d-683b-4d77-b98e-62a0d083488a",
"sequence": 3,
"image": "null",
"isCorrectOption": false
},
{
"id": "6cc3ff60-02cc-4e59-e501-08dae8b36b35",
"titleEn": "5",
"titleAr": "5",
"questionId": "6c9d809d-683b-4d77-b98e-62a0d083488a",
"sequence": 4,
"image": "null",
"isCorrectOption": true
}
]
},
{
"id": "e8c8442e-f370-444d-bee9-f7f75d146e5c",
"titleEn": "How many times Italy won FIFA World Cups?",
"titleAr": "How many times Italy won FIFA World Cups?",
"marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"questionTypeId": 1,
"questionTime": 10,
"nextQuestGap": 5,
"gapType": 0,
"gapText": null,
"gapImage": "Questions/34f3c402-1244-4320-98c2-751cb2a347c5_congrats-1.gif",
"questOptionsLimit": 0,
"remainingParticipantCount": 0,
"questionOptions": [
{
"id": "53d456b7-8f56-4c58-e50a-08dae8b36b35",
"titleEn": "1",
"titleAr": "1",
"questionId": "e8c8442e-f370-444d-bee9-f7f75d146e5c",
"sequence": 1,
"image": "null",
"isCorrectOption": false
},
{
"id": "280df6d7-ca61-4d78-e50b-08dae8b36b35",
"titleEn": "2",
"titleAr": "2",
"questionId": "e8c8442e-f370-444d-bee9-f7f75d146e5c",
"sequence": 2,
"image": "null",
"isCorrectOption": false
},
{
"id": "769939dc-4a46-4f4f-e50c-08dae8b36b35",
"titleEn": "3",
"titleAr": "3",
"questionId": "e8c8442e-f370-444d-bee9-f7f75d146e5c",
"sequence": 3,
"image": "null",
"isCorrectOption": false
},
{
"id": "c389fae7-0019-4922-e50d-08dae8b36b35",
"titleEn": "4",
"titleAr": "4",
"questionId": "e8c8442e-f370-444d-bee9-f7f75d146e5c",
"sequence": 4,
"image": "null",
"isCorrectOption": true
}
]
}
]

@ -0,0 +1,46 @@
{
"id": "979813be-eafa-4d3e-d27e-08dae8a08a3b",
"titleEn": "FIFA World Cup",
"titleAr": "undefined",
"descEn": "FIFA World Cup Description",
"descAr": "undefined",
"questionTime": 10,
"winDeciderTime": 30,
"winnersCount": 1,
"questGapTime": 5,
"startTime": "2022-12-28T10:44:41",
"endTime": null,
"marathoneStatusId": 4,
"scheduleTime": "2022-12-28T10:14:41",
"selectedLanguage": 0,
"projects": {
"id": "b1cd3fa3-bb27-422e-a4c1-08dac09254df",
"nameEn": "Cloud Solutions",
"nameAr": "333شركة حلول السحابة للاتصالات وتقنية المعلومات",
"projectCode": "CS"
},
"sponsors": [
{
"id": "3272b127-b388-4f09-425b-08dac2eb788e",
"nameEn": "Cloud Solutions",
"nameAr": "حل السحابة",
"image": "SponsorImage/b9aed4a8-42b2-45fc-b6f1-47ee0c7b4138_sponsor.jpeg",
"video": "SponsorVideo/9ab678ab-1b4c-4ea4-aaf2-32ce1353d3fe_sample-10s.mp4",
"logo": "SponsorLogo/eb029f0d-bce1-4a61-b0c0-abaa484912a0_sponsor.jpeg",
"videoDuration": null,
"sponsorPrizes": [
{
"id": "e657a18c-6fb2-4099-07c8-08dae89efcd3",
"marathonPrizeEn": "SAR 500",
"marathonPrizeAr": "SAR 500"
}
]
}
],
"questions": null,
"isEmailSent": false,
"totalQuestions": 10,
"cancelReason": null,
"marathonBufferTime": 30,
"currentTime": "2022-12-28T08:03:24.3671803Z"
}

@ -480,6 +480,7 @@
"gameTime": "وقت اللعب:",
"joinMarathon": "انضم إلى ماراثون",
"joinDemoMarathon": "انضم إلى الماراثون التجريبي",
"demo":"تجريبي",
"minutes": "الدقائق",
"seconds": "ثواني",
"note": "ملحوظة:",
@ -489,9 +490,11 @@
"sponsoredBy": "برعاية:",
"question": "سؤال",
"marathoners": "الماراثون",
"marathoner": "ماراثونر",
"prize": "جائزة:",
"winnerSelection": "اختيار الفائز",
"qualifiers": "تصفيات",
"qualifier": "المؤهل",
"getReadyForContest": "استعد للمسابقة القادمة:",
"winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.",
"fingersCrossed": "تشابك الاصابع!!!",
@ -514,8 +517,12 @@
"startingIn": "يبدأ في",
"youAreOutOfContest": "أنت خارج المسابقة.",
"winners": "الفائزين!!!",
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية",
"expireAfter":"تنتهي بعد",
"oneWeek":"أسبوع 1",
"twoWeek":"2 أسبوع"
"twoWeek":"2 أسبوع",
"noUpcoming": "لا يوجد قادم",
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية",
"noWinner": "حزين! لم يفز أحد اليوم.",
"myTeam" : "فريقي",
"youCanPlayDemo": "لكن يمكنك لعب العرض"
}

@ -469,6 +469,7 @@
"gameTime": "Game Time:",
"joinMarathon": "Join Marathon",
"joinDemoMarathon": "Join Demo Marathon",
"demo":"Demo",
"minutes": "Minutes",
"seconds": "Seconds",
"note": "Note:",
@ -478,6 +479,7 @@
"sponsoredBy": "Sponsored By:",
"question": "Question",
"marathoners": "Marathoners",
"marathoner": "Marathoner",
"prize": "Prize:",
"advancedSearch": "Advanced Search",
"openNot": "Open Notifications",
@ -492,6 +494,7 @@
"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!!!",
@ -505,8 +508,8 @@
"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 and as a viewer.",
"wrongAnswer": "Your answer is Incorrect. You are out of the game. But you can continue and as a viewer.",
"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.",
@ -514,8 +517,12 @@
"startingIn": "Starting in",
"youAreOutOfContest": "You are out of the contest.",
"winners": "WINNERS!!!",
"fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.",
"expireAfter":"Expires After",
"oneWeek":"1 Week",
"twoWeek":"2 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"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,5 +1,7 @@
import UIKit
import Flutter
import Firebase
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
@ -7,6 +9,7 @@ import Flutter
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

@ -13,7 +13,7 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>mohem_flutter_app</string>
<string>MOHEMM</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
@ -46,10 +46,14 @@
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to for call.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
@ -69,6 +73,13 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
<string>0000</string>
</array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>TAG</string>

@ -14,11 +14,16 @@ typedef FactoryConstructor<U> = U Function(dynamic);
class APIError {
int? errorCode;
int? errorType;
String? errorMessage;
APIError(this.errorCode, this.errorMessage);
APIError(this.errorCode, this.errorMessage, this.errorType);
Map<String, dynamic> toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage};
Map<String, dynamic> toJson() => {
'errorCode': errorCode,
'errorMessage': errorMessage,
'errorType': errorType,
};
@override
String toString() {
@ -33,14 +38,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']);
apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType']);
}
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']);
apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType']);
}
return APIException(APIException.BAD_REQUEST, error: apiError);
case 401:
@ -78,28 +83,30 @@ class ApiClient {
print("body:$bodyJson");
}
var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes, isFormData: isFormData);
// try {
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
var jsonData = jsonDecode(response.body);
if (jsonData["IsAuthenticated"] != null) {
AppState().setIsAuthenticated = jsonData["IsAuthenticated"];
}
if (jsonData["ErrorMessage"] == null) {
return factoryConstructor(jsonData);
} else {
APIError? apiError;
apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage']);
throw APIException(APIException.BAD_REQUEST, error: apiError);
try {
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
var jsonData = jsonDecode(response.body);
if (jsonData["MessageStatus"] == 2) {
AppState().setIsAuthenticated = false;
}
if (jsonData["ErrorMessage"] == null && jsonData["MessageStatus"] == 1) {
return factoryConstructor(jsonData);
} else {
APIError? apiError;
apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage'], jsonData['ErrorType'] ?? 0);
throw APIException(APIException.BAD_REQUEST, error: apiError);
}
} catch (ex) {
if (ex is APIException) {
rethrow;
} else {
throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex);
}
}
// } catch (ex) {
// if (ex is APIException) {
// rethrow;
// } else {
// throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex);
// }
// }
}
Future<Response> postJsonForResponse<T>(String url, T jsonObject,

@ -30,11 +30,13 @@ class ChatApiClient {
{
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
"isMobile": true,
"deviceToken": AppState().getDeviceToken,
},
);
if (!kReleaseMode) {
print("Status Code is ================" + response.statusCode.toString());
logger.i("res: " + response.body);
logger.i("login-res: " + response.body);
}
if (response.statusCode == 200) {
userLoginResponse = user.userAutoLoginModelFromJson(response.body);
@ -47,17 +49,18 @@ class ChatApiClient {
return userLoginResponse;
}
Future<List<ChatUser>?> getChatMemberFromSearch(String sName, int cUserId) async {
Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync/$sName/$cUserId",
token: AppState().chatDetails!.response!.token,
);
Future<ChatUserModel> getChatMemberFromSearch(String searchParam, int cUserId, int pageNo) async {
ChatUserModel chatUserModel;
Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync", {"employeeNumber": cUserId, "userName": searchParam, "pageNumber": pageNo},
token: AppState().chatDetails!.response!.token);
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return List<ChatUser>.from(json.decode(response.body).map((x) => ChatUser.fromJson(x)));
chatUserModel = chatUserModelFromJson(response.body);
return chatUserModel;
}
//Get User Recent Chats
Future<ChatUserModel> getRecentChats() async {
try {
Response response = await ApiClient().getJsonForResponse(
@ -75,6 +78,7 @@ class ChatApiClient {
}
}
// Get Favorite Users
Future<ChatUserModel> getFavUsers() async {
Response favRes = await ApiClient().getJsonForResponse(
"${ApiConsts.chatFavUser}getFavUserById/${AppState().chatDetails!.response!.id}",
@ -86,6 +90,7 @@ class ChatApiClient {
return ChatUserModel.fromJson(json.decode(favRes.body));
}
//Get User Chat History
Future<Response> getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false, required int paginationVal}) async {
try {
Response response = await ApiClient().getJsonForResponse(
@ -97,10 +102,12 @@ class ChatApiClient {
}
return response;
} catch (e) {
getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal);
throw e;
}
}
//Favorite Users
Future<fav.FavoriteChatUser> favUser({required int userID, required int targetUserID}) async {
Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatFavUser}addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token);
if (!kReleaseMode) {
@ -110,6 +117,7 @@ class ChatApiClient {
return favoriteChatUser;
}
//UnFavorite Users
Future<fav.FavoriteChatUser> unFavUser({required int userID, required int targetUserID}) async {
try {
Response response = await ApiClient().postJsonForResponse(
@ -120,7 +128,6 @@ class ChatApiClient {
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
return favoriteChatUser;
} catch (e) {
@ -129,33 +136,37 @@ class ChatApiClient {
}
}
Future<StreamedResponse> uploadMedia(String userId, File file) async {
// Upload Chat Media
Future<Object?> uploadMedia(String userId, File file) 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.files.add(await MultipartFile.fromPath('files', file.path));
request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'});
StreamedResponse response = await request.send();
if (!kReleaseMode) {}
return response;
String data = await response.stream.bytesToString();
if (!kReleaseMode) {
logger.i("res: " + data);
}
return jsonDecode(data);
}
// Download File For Chat
Future<Uint8List> downloadURL({required String fileName, required String fileTypeDescription}) async {
print(fileName);
print(fileTypeDescription);
print("${ApiConsts.chatMediaImageUploadUrl}download");
print(AppState().chatDetails!.response!.token);
Response response = await ApiClient().postJsonForResponse(
"${ApiConsts.chatMediaImageUploadUrl}download",
{"fileType": fileTypeDescription, "fileName": fileName, "fileSource": 1},
token: AppState().chatDetails!.response!.token,
);
Uint8List data = Uint8List.fromList(response.bodyBytes);
return data;
}
//Get Chat Users & Favorite Images
Future<List<ChatUserImageModel>> getUsersImages({required List<String> encryptedEmails}) async {
List<ChatUserImageModel> imagesData = [];
Response response = await ApiClient().postJsonForResponse(

@ -32,7 +32,7 @@ class ItemsForSaleApiClient {
getSaleCategoriesListObj.titleAr = "الجميع";
getSaleCategoriesListObj.isActive = true;
getSaleCategoriesListObj.content =
'<svg xmlns="http://www.w3.org/2000/svg" width="33.925" height="25.841" viewBox="0 0 33.925 25.841"><g id="More_Select" data-name="More Select"><path d="m30 1h-24a1 1 0 0 0 -1 1v1h21a3 3 0 0 1 3 3v21h1a1 1 0 0 0 1-1v-24a1 1 0 0 0 -1-1z"/><path d="m26 5h-24a1 1 0 0 0 -1 1v24a1 1 0 0 0 1 1h24a1 1 0 0 0 1-1v-24a1 1 0 0 0 -1-1zm-4.747 9.344-8.728 8.726a1 1 0 0 1 -1.414 0l-4.364-4.363a1 1 0 0 1 1.414-1.414l3.657 3.656 8.021-8.019a1 1 0 0 1 1.414 1.414z"/></g></svg>';
'<svg xmlns="http://www.w3.org/2000/svg" width="26.213" height="26.213" viewBox="0 0 26.213 26.213"> <g id="More_Select" data-name="More Select" transform="translate(-1 -1)"> <path id="Path_4860" data-name="Path 4860" d="M26.844,1H5.874A.874.874,0,0,0,5,1.874v.874H23.349A2.621,2.621,0,0,1,25.97,5.369V23.718h.874a.874.874,0,0,0,.874-.874V1.874A.874.874,0,0,0,26.844,1Z" transform="translate(-0.505)" fill="#2bb8a6"/> <path id="Path_4861" data-name="Path 4861" d="M22.844,5H1.874A.874.874,0,0,0,1,5.874v20.97a.874.874,0,0,0,.874.874h20.97a.874.874,0,0,0,.874-.874V5.874A.874.874,0,0,0,22.844,5ZM18.7,13.164,11.07,20.789a.874.874,0,0,1-1.236,0L6.022,16.977a.874.874,0,1,1,1.236-1.236l3.2,3.195,7.008-7.007A.874.874,0,1,1,18.7,13.165Z" transform="translate(0 -0.505)" fill="#125765"/> </g> </svg>';
getSaleCategoriesList.add(getSaleCategoriesListObj);

@ -0,0 +1,25 @@
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:logger/logger.dart' as L;
import 'package:mohem_flutter_app/models/marathon/marathon_model.dart';
import 'package:mohem_flutter_app/models/marathon/question_model.dart';
class DemoMarathonRepo {
L.Logger logger = L.Logger();
Future<MarathonDetailModel> getDemoMarathonDetails() async {
String response = await rootBundle.loadString('assets/json/demo_upcoming_marathon');
var json = jsonDecode(response);
MarathonDetailModel marathonDetailModel = MarathonDetailModel.fromJson(json);
return marathonDetailModel;
}
Future<QuestionModel> getDemoNextQuestion({required int currentQuestionNumber}) async {
String response = await rootBundle.loadString('assets/json/demo_questions_marathon');
List json = jsonDecode(response);
QuestionModel currentQuestion = QuestionModel.fromJson(json.elementAt(currentQuestionNumber));
return currentQuestion;
}
}

@ -1,69 +1,58 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:logger/logger.dart' as L;
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/utils.dart';
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/winner_model.dart';
import 'package:signalr_netcore/hub_connection.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
import 'package:provider/provider.dart';
class MarathonApiClient {
late HubConnection hubConnection;
L.Logger logger = L.Logger();
Future<String> getMarathonToken() async {
String employeeUserName = AppState().getUserName ?? "";
String employeeSession = AppState().postParamsObject?.pSessionId.toString() ?? "";
Map<String, String> jsonObject = <String, String>{"userName": employeeUserName, "password": employeeSession};
Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonParticipantLoginUrl, jsonObject);
var json = jsonDecode(response.body);
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
if (marathonModel.statusCode == 200) {
if (marathonModel.data != null && marathonModel.isSuccessful == true) {
return await ApiClient().postJsonForObject(
(json) {
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
AppState().setMarathonToken = marathonModel.data["token"] ?? "";
return marathonModel.data["token"] ?? "";
} else {
//TODO : DO ERROR HANDLING HERE
return "";
}
} else {
//TODO : DO ERROR HANDLING HERE
return "";
}
},
ApiConsts.marathonParticipantLoginUrl,
jsonObject,
);
}
Future<String> getProjectId() async {
Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonProjectGetUrl, <String, dynamic>{}, token: AppState().getMarathonToken ?? await getMarathonToken());
var json = jsonDecode(response.body);
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
if (marathonModel.statusCode == 200) {
if (marathonModel.data != null && marathonModel.isSuccessful == true) {
logger.i("message: ${marathonModel.data[0]["id"]}");
AppState().setMarathonProjectId = marathonModel.data[0]["id"] ?? "";
return marathonModel.data[0]["id"] ?? "";
} else {
return "";
}
} else {
return "";
}
return await ApiClient().postJsonForObject(
(json) {
MarathonGenericModel responseData = MarathonGenericModel.fromJson(json);
return responseData.data[0]["id"] ?? "";
},
ApiConsts.marathonProjectGetUrl,
<String, dynamic>{},
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
}
Future<MarathonDetailModel> getMarathonDetails() async {
String payrollString = AppState().postParamsObject?.payrollCodeStr.toString() ?? "CS";
Response response = await ApiClient().getJsonForResponse(ApiConsts.marathonUpcomingUrl + payrollString, token: AppState().getMarathonToken ?? await getMarathonToken());
Response response = await ApiClient().getJsonForResponse(
ApiConsts.marathonUpcomingUrl + payrollString,
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
var json = jsonDecode(response.body);
logger.i("json in getMarathonDetails: $json");
@ -89,72 +78,73 @@ class MarathonApiClient {
"marathonId": AppState().getMarathonProjectId!,
};
Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonJoinParticipantUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken());
var json = jsonDecode(response.body);
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
if (marathonModel.statusCode == 208) {
// means participant is already in the marathon i.e already joined
//TODO: NEED TO LOOK UPON THIS
return marathonModel.data["remainingTime"];
}
if (marathonModel.statusCode == 200) {
if (marathonModel.data != null && marathonModel.isSuccessful == true) {
logger.i("joinMarathonAsParticipant: ${marathonModel.data}");
return await ApiClient().postJsonForObject(
(json) {
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
return marathonModel.data["remainingTime"];
} else {
return null;
}
} else {
return null;
}
},
ApiConsts.marathonJoinParticipantUrl,
jsonObject,
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
}
Future<QuestionModel?> getNextQuestion({required String? questionId, required String marathonId}) async {
Future<QuestionModel> getNextQuestion({required String? questionId, required String marathonId}) async {
Map<String, String?> jsonObject = <String, String?>{
"previousQuestionId": questionId,
"marathonId": marathonId,
};
Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonNextQuestionUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken());
var json = jsonDecode(response.body);
logger.i("json in NextQuestion: $json");
var data = json["data"];
if (data != null) {
QuestionModel newQuestion = QuestionModel.fromJson(data);
return newQuestion;
} else {
return null;
}
return await ApiClient().postJsonForObject(
(json) {
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
if (marathonModel.statusCode == 404 || marathonModel.statusCode == 208 || marathonModel.statusCode == 204 || marathonModel.statusCode == 500) {
Utils.confirmDialog(
AppRoutes.navigatorKey.currentContext,
marathonModel.message!,
onTap: () {
AppRoutes.navigatorKey.currentContext!.read<MarathonProvider>().resetValues();
Navigator.of(
AppRoutes.navigatorKey.currentContext!,
).popUntil(ModalRoute.withName(AppRoutes.dashboard));
},
);
}
QuestionModel newQuestion = QuestionModel.fromJson(marathonModel.data);
return newQuestion;
},
ApiConsts.marathonNextQuestionUrl,
jsonObject,
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
}
Future<bool> submitSelectedOption({required String marathonId, required String? questionId, required String? selectedAnswerId}) async {
Map<String, String?> jsonObject = <String, String?>{"marathonId": marathonId, "questionId": questionId, "selectedOptionId" : selectedAnswerId};
Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonSubmitAnswerUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken());
var json = jsonDecode(response.body);
logger.i("json in submitSelectedOption : $json");
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
if (marathonModel.isSuccessful == null) {
return false;
}
return marathonModel.isSuccessful!;
Map<String, String?> jsonObject = <String, String?>{"marathonId": marathonId, "questionId": questionId, "selectedOptionId": selectedAnswerId};
return await ApiClient().postJsonForObject(
(json) {
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
if (marathonModel.data != null) {
bool isOptionCorrect = marathonModel.data["isCorrect"];
return isOptionCorrect;
}
return false;
},
ApiConsts.marathonSubmitAnswerUrl,
jsonObject,
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
}
Future<int?> getQualifiers({required String marathonId}) async {
Map<String, String> params = <String, String>{"marathonId": marathonId};
Response response = await ApiClient().getJsonForResponse(ApiConsts.marathonQualifiersUrl, queryParameters: params, token: AppState().getMarathonToken ?? await getMarathonToken());
Response response = await ApiClient().getJsonForResponse(
ApiConsts.marathonQualifiersUrl,
queryParameters: params,
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
var json = jsonDecode(response.body);
logger.i("json in getQualifiers: $json");
@ -169,7 +159,11 @@ class MarathonApiClient {
Future<List<WinnerModel>?> getSelectedWinner({required String marathonId}) async {
Map<String, String> params = <String, String>{"marathonId": marathonId};
Response response = await ApiClient().getJsonForResponse(ApiConsts.marathonSelectedWinner, queryParameters: params, token: AppState().getMarathonToken ?? await getMarathonToken());
Response response = await ApiClient().getJsonForResponse(
ApiConsts.marathonSelectedWinner,
queryParameters: params,
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
var json = jsonDecode(response.body);
logger.i("json in getSelectedWinner: $json");
@ -188,6 +182,7 @@ class MarathonApiClient {
return null;
}
// late HubConnection hubConnection;
// Future<void> buildHubConnection(BuildContext context, String prizeId) async {
// HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
// hubConnection = HubConnectionBuilder()

@ -30,7 +30,7 @@ class OffersAndDiscountsApiClient {
getSaleCategoriesListObj.categoryNameAr = "الجميع";
getSaleCategoriesListObj.isActive = true;
getSaleCategoriesListObj.content =
'<svg xmlns="http://www.w3.org/2000/svg" width="33.925" height="25.841" viewBox="0 0 33.925 25.841"><g id="More_Select" data-name="More Select"><path d="m30 1h-24a1 1 0 0 0 -1 1v1h21a3 3 0 0 1 3 3v21h1a1 1 0 0 0 1-1v-24a1 1 0 0 0 -1-1z"/><path d="m26 5h-24a1 1 0 0 0 -1 1v24a1 1 0 0 0 1 1h24a1 1 0 0 0 1-1v-24a1 1 0 0 0 -1-1zm-4.747 9.344-8.728 8.726a1 1 0 0 1 -1.414 0l-4.364-4.363a1 1 0 0 1 1.414-1.414l3.657 3.656 8.021-8.019a1 1 0 0 1 1.414 1.414z"/></g></svg>';
'<svg xmlns="http://www.w3.org/2000/svg" width="26.213" height="26.213" viewBox="0 0 26.213 26.213"> <g id="More_Select" data-name="More Select" transform="translate(-1 -1)"> <path id="Path_4860" data-name="Path 4860" d="M26.844,1H5.874A.874.874,0,0,0,5,1.874v.874H23.349A2.621,2.621,0,0,1,25.97,5.369V23.718h.874a.874.874,0,0,0,.874-.874V1.874A.874.874,0,0,0,26.844,1Z" transform="translate(-0.505)" fill="#2bb8a6"/> <path id="Path_4861" data-name="Path 4861" d="M22.844,5H1.874A.874.874,0,0,0,1,5.874v20.97a.874.874,0,0,0,.874.874h20.97a.874.874,0,0,0,.874-.874V5.874A.874.874,0,0,0,22.844,5ZM18.7,13.164,11.07,20.789a.874.874,0,0,1-1.236,0L6.022,16.977a.874.874,0,1,1,1.236-1.236l3.2,3.195,7.008-7.007A.874.874,0,1,1,18.7,13.165Z" transform="translate(0 -0.505)" fill="#125765"/> </g> </svg>';
getSaleCategoriesList.add(getSaleCategoriesListObj);

File diff suppressed because one or more lines are too long

@ -3,8 +3,8 @@ 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 = "https://erptstapp.srca.org.sa"; // SRCA server
static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server
// static String baseUrl = "https://hmgwebservices.com"; // Live server
// static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server
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/";

@ -459,7 +459,7 @@ class DateUtil {
/// get data formatted like 10:30 according to lang
static String formatDateToTimeLang(DateTime date, bool isArabic) {
return DateFormat('HH:mm a', isArabic ? "ar_SA" : "en_US").format(date);
return DateFormat('hh:mm a', isArabic ? "ar_SA" : "en_US").format(date);
}
/// get data formatted like 26/4/2020 10:30

@ -7,4 +7,6 @@ class MyLottieConsts {
static const String marathonWaiting = "assets/lottie/marathon_waiting.json";
static const String wrongAnswerGif = "assets/images/wrong_answer.gif";
static const String congratsGif = "assets/images/congrats.gif";
static const String loadingLottie = "assets/lottie/loading_lottie.json";
static const String noWinnerLottie = "assets/lottie/no_winner.json";
}

@ -0,0 +1,59 @@
import 'dart:convert';
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:permission_handler/permission_handler.dart';
//final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
class AppNotifications {
static final AppNotifications _instance = AppNotifications._internal();
AppNotifications._internal();
factory AppNotifications() => _instance;
// Future<void> requestPermissions() async {
// if (Platform.isIOS) {
// await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(alert: true, badge: true, sound: true);
// } else if (Platform.isAndroid) {
// AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>();
// bool? granted = await androidImplementation?.requestPermission();
// if (granted == false) {
// print("-------------------- Permission Granted ------------------------");
// print(granted);
// await Permission.notification.request();
// }
// }
// }
// Future<void> isAndroidPermGranted() async {
// if (Platform.isAndroid) {
// bool granted = await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.areNotificationsEnabled() ?? false;
// }
// }
void initNotification(String? firebaseToken) async {
// await requestPermissions();
AppState().setDeviceToken = firebaseToken;
// await Permission.notification.isDenied.then((value) {
// if (value) {
// Permission.notification.request();
// }
// });
RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) _handleMessage(initialMessage);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
if (message.notification != null) _handleMessage(message);
});
FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
}
void _handleMessage(RemoteMessage message) {
print("Handle Message");
logger.w(json.encode(message));
}
}

@ -0,0 +1,59 @@
import 'dart:async';
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
// |--> Push Notification Background
Future<dynamic> backgroundMessageHandler(message) async {
print("Firebase backgroundMessageHandler!!!");
}
class PushNotificationHandler {
final BuildContext context;
static PushNotificationHandler? _instance;
PushNotificationHandler(this.context) {
PushNotificationHandler._instance = this;
}
static PushNotificationHandler getInstance() => _instance!;
void init() async {
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
if (Platform.isIOS) {
await Future.delayed(Duration(milliseconds: 3000)).then((value) {
newMessage(message);
});
} else {
newMessage(message);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
if (Platform.isIOS) {
await Future.delayed(Duration(milliseconds: 3000)).then((value) {
newMessage(message);
});
} else {
newMessage(message);
}
});
FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) {
print("Push Notification onTokenRefresh: " + fcm_token);
AppState().setDeviceToken = fcm_token;
});
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
}
void newMessage(RemoteMessage remoteMessage) async {
print("Remote Message: " + remoteMessage.data.toString());
if (remoteMessage.data.isEmpty) {
return;
}
}
}

@ -98,43 +98,58 @@ class Utils {
static void handleException(dynamic exception, cxt, Function(String)? onErrorMessage) {
String errorMessage;
if (exception is APIException) {
if (exception.message == APIException.UNAUTHORIZED) {
return;
if (exception.error.errorType != null && exception.error.errorType == 4) {
Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.appUpdateScreen, (_) => false, arguments: exception.error?.errorMessage);
} else {
if (exception is APIException) {
if (exception.message == APIException.UNAUTHORIZED) {
return;
} else {
errorMessage = exception.error?.errorMessage ?? exception.message;
}
} else {
errorMessage = exception.error?.errorMessage ?? exception.message;
errorMessage = APIException.UNKNOWN;
}
} else {
errorMessage = APIException.UNKNOWN;
}
if (onErrorMessage != null) {
onErrorMessage(errorMessage);
} else {
if (!AppState().isAuthenticated) {
showDialog(
context: cxt,
builder: (cxt) => ConfirmDialog(
message: errorMessage,
onTap: () {
Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route<dynamic> route) => false);
},
),
);
if (onErrorMessage != null) {
onErrorMessage(errorMessage);
} else {
if (cxt != null) {
confirmDialog(cxt, errorMessage);
if (!AppState().isAuthenticated) {
showDialog(
context: cxt,
builder: (cxt) => ConfirmDialog(
message: errorMessage,
onTap: () {
Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route<dynamic> route) => false);
},
),
);
} else {
showToast(errorMessage);
if (cxt != null) {
confirmDialog(cxt, errorMessage);
} else {
showToast(errorMessage);
}
}
}
}
}
static void confirmDialog(cxt, String message) {
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 void confirmDialog(cxt, String message, {VoidCallback? onTap}) {
showDialog(
context: cxt,
builder: (cxt) => ConfirmDialog(
builder: (BuildContext cxt) => ConfirmDialog(
message: message,
onTap: onTap,
),
);
}
@ -310,17 +325,23 @@ class Utils {
}
static String formatDateDefault(String date) {
if (date.toLowerCase().contains("t")) {
date = date.toLowerCase().split("t")[0];
// return DateFormat('yyyy-MM-dd').format(DateFormat('dd-MM-yyyy').parseLoose(date));
return DateFormat('dd-MM-yyyy').format(DateFormat('yyyy-MM-dd').parseLoose(date));
} else {
if(date.toLowerCase().split("-")[1].length == 3) {
return DateFormat('dd-MM-yyyy').format(DateFormat('dd-MMM-yyyy').parseLoose(date));
if (date.isNotEmpty) {
if (date.toLowerCase().contains("t")) {
date = date.toLowerCase().split("t")[0];
if (!date.contains("00:00:00")) {
date = date + ' 00:00:00';
}
return date;
} else {
return DateFormat('dd-MM-yyyy').format(DateFormat('yyyy-MM-dd').parseLoose(date));
if (date.toLowerCase().split("-")[1].length == 3) {
return DateFormat('dd-MM-yyyy').format(DateFormat('dd-MMM-yyyy').parseLoose(date));
} else {
return DateFormat('dd-MM-yyyy').format(DateFormat('yyyy-MM-dd').parseLoose(date));
}
// return DateFormat('yyyy-MM-dd').format(DateFormat('dd-MM-yyyy').parseLoose(date));
}
// return DateFormat('yyyy-MM-dd').format(DateFormat('dd-MM-yyyy').parseLoose(date));
} else {
return date;
}
}
@ -328,13 +349,13 @@ class Utils {
if (!Platform.isIOS) {
await showCupertinoModalPopup(
context: context,
builder: (cxt) => Container(
builder: (BuildContext cxt) => Container(
height: 250,
color: Colors.white,
child: CupertinoDatePicker(
backgroundColor: Colors.white,
mode: CupertinoDatePickerMode.date,
onDateTimeChanged: (value) {
onDateTimeChanged: (DateTime value) {
if (value != null && value != selectedDate) {
selectedDate = value;
}
@ -354,7 +375,7 @@ class Utils {
static void readNFc({required Function(String) onRead}) {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var f;
MifareUltralight f;
if (Platform.isAndroid) {
f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
} else {

@ -1,4 +1,5 @@
import 'package:flutter/material.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';
import 'package:mohem_flutter_app/ui/attendance/vacation_rule_screen.dart';
@ -22,7 +23,6 @@ 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_waiting_screen.dart';
import 'package:mohem_flutter_app/ui/marathon/winner_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';
@ -191,6 +191,7 @@ class AppRoutes {
static const String marathonWaitingScreen = "/marathonWaitingScreen";
static const String unsafeDeviceScreen = "/unsafeDeviceScreen";
static const String appUpdateScreen = "/appUpdateScreen";
static final Map<String, WidgetBuilder> routes = {
login: (BuildContext context) => LoginScreen(),
@ -297,10 +298,10 @@ class AppRoutes {
// Marathon
marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(),
marathonScreen: (BuildContext context) => MarathonScreen(),
marathonWinnerScreen: (BuildContext context) => WinnerScreen(),
marathonSponsorVideoScreen: (BuildContext context) => const SponsorVideoScreen(),
marathonWaitingScreen: (BuildContext context) => const MarathonWaitingScreen(),
unsafeDeviceScreen: (BuildContext context) => const UnsafeDeviceScreen(),
appUpdateScreen: (BuildContext context) => const AppUpdateScreen(),
};
}

@ -13,6 +13,15 @@ extension CapExtension on String {
String get capitalizeFirstofEach => this.trim().length > 0 ? this.trim().toLowerCase().split(" ").map((str) => str.inCaps).join(" ") : "";
}
extension TrimString on String {
String trimString(int minThreshold) {
if (length > minThreshold) {
return "${substring(0, 10)}...${substring(length - 4, length)}";
}
return this;
}
}
extension EmailValidator on String {
Widget get toWidget => Text(this);
@ -90,9 +99,9 @@ extension EmailValidator on String {
style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.52, decoration: isUnderLine ? TextDecoration.underline : null),
);
Widget toText14({Color? color, bool isUnderLine = false, bool isBold = false, FontWeight? weight, int? maxlines, bool isCenter = false}) => Text(
Widget toText14({Color? color, bool isUnderLine = false, bool isBold = false, FontWeight? weight, int? maxlines, TextAlign? textAlign, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : TextAlign.left,
textAlign: isCenter ? TextAlign.center : (textAlign ?? TextAlign.left),
maxLines: maxlines,
style: TextStyle(
color: color ?? MyColors.darkTextColor,
@ -131,8 +140,9 @@ extension EmailValidator on String {
style: TextStyle(fontSize: 19, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -1.14),
);
Widget toText20({Color? color, bool isBold = false}) => Text(
Widget toText20({Color? color, bool isBold = false, bool isCentered = false}) => Text(
this,
textAlign: isCentered ? TextAlign.center : null,
style: TextStyle(fontSize: 20, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4),
);

@ -496,6 +496,7 @@ class CodegenLoader extends AssetLoader{
"gameTime": "وقت اللعب:",
"joinMarathon": "انضم إلى ماراثون",
"joinDemoMarathon": "انضم إلى الماراثون التجريبي",
"demo": "تجريبي",
"minutes": "الدقائق",
"seconds": "ثواني",
"note": "ملحوظة:",
@ -505,9 +506,11 @@ class CodegenLoader extends AssetLoader{
"sponsoredBy": "برعاية:",
"question": "سؤال",
"marathoners": "الماراثون",
"marathoner": "ماراثونر",
"prize": "جائزة:",
"winnerSelection": "اختيار الفائز",
"qualifiers": "تصفيات",
"qualifier": "المؤهل",
"getReadyForContest": "استعد للمسابقة القادمة:",
"winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.",
"fingersCrossed": "تشابك الاصابع!!!",
@ -530,7 +533,11 @@ class CodegenLoader extends AssetLoader{
"startingIn": "يبدأ في",
"youAreOutOfContest": "أنت خارج المسابقة.",
"winners": "الفائزين!!!",
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية"
"noUpcoming": "لا يوجد قادم",
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية",
"noWinner": "حزين! لم يفز أحد اليوم.",
"myTeam": "فريقي",
"youCanPlayDemo": "لكن يمكنك لعب العرض"
};
static const Map<String,dynamic> en_US = {
"mohemm": "Mohemm",
@ -1003,6 +1010,7 @@ static const Map<String,dynamic> en_US = {
"gameTime": "Game Time:",
"joinMarathon": "Join Marathon",
"joinDemoMarathon": "Join Demo Marathon",
"demo": "Demo",
"minutes": "Minutes",
"seconds": "Seconds",
"note": "Note:",
@ -1012,6 +1020,7 @@ static const Map<String,dynamic> en_US = {
"sponsoredBy": "Sponsored By:",
"question": "Question",
"marathoners": "Marathoners",
"marathoner": "Marathoner",
"prize": "Prize:",
"advancedSearch": "Advanced Search",
"openNot": "Open Notifications",
@ -1026,6 +1035,7 @@ static const Map<String,dynamic> en_US = {
"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!!!",
@ -1039,8 +1049,8 @@ static const Map<String,dynamic> en_US = {
"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 and as a viewer.",
"wrongAnswer": "Your answer is Incorrect. You are out of the game. But you can continue and as a viewer.",
"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.",
@ -1048,7 +1058,11 @@ static const Map<String,dynamic> en_US = {
"startingIn": "Starting in",
"youAreOutOfContest": "You are out of the contest.",
"winners": "WINNERS!!!",
"fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified."
"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"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -466,6 +466,7 @@ abstract class LocaleKeys {
static const gameTime = 'gameTime';
static const joinMarathon = 'joinMarathon';
static const joinDemoMarathon = 'joinDemoMarathon';
static const demo = 'demo';
static const minutes = 'minutes';
static const seconds = 'seconds';
static const note = 'note';
@ -475,9 +476,11 @@ abstract class LocaleKeys {
static const sponsoredBy = 'sponsoredBy';
static const question = 'question';
static const marathoners = 'marathoners';
static const marathoner = 'marathoner';
static const prize = 'prize';
static const winnerSelection = 'winnerSelection';
static const qualifiers = 'qualifiers';
static const qualifier = 'qualifier';
static const getReadyForContest = 'getReadyForContest';
static const winnerSelectedRandomly = 'winnerSelectedRandomly';
static const fingersCrossed = 'fingersCrossed';
@ -500,8 +503,12 @@ abstract class LocaleKeys {
static const startingIn = 'startingIn';
static const youAreOutOfContest = 'youAreOutOfContest';
static const winners = 'winners';
static const noUpcoming = 'noUpcoming';
static const fakeLocation = 'fakeLocation';
static const expireAfter = 'expireAfter';
static const oneWeek = 'oneWeek';
static const twoWeek = 'twoWeek';
static const noWinner = 'noWinner';
static const myTeam = 'myTeam';
static const youCanPlayDemo = 'youCanPlayDemo';
}

@ -27,6 +27,7 @@ Logger logger = Logger(
// output: null, // U
);
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {

@ -1,5 +1,10 @@
import 'dart:convert';
import 'dart:io';
ChatUserModel chatUserModelFromJson(String str) => ChatUserModel.fromJson(json.decode(str));
String chatUserModelToJson(ChatUserModel data) => json.encode(data.toJson());
class ChatUserModel {
ChatUserModel({
this.response,
@ -7,16 +12,40 @@ class ChatUserModel {
});
List<ChatUser>? response;
dynamic errorResponses;
List<ErrorResponse>? errorResponses;
factory ChatUserModel.fromJson(Map<String, dynamic> json) => ChatUserModel(
response: json["response"] == null ? null : List<ChatUser>.from(json["response"].map((x) => ChatUser.fromJson(x))),
errorResponses: json["errorResponses"],
errorResponses: json["errorResponses"] == null ? null : List<ErrorResponse>.from(json["errorResponses"].map((x) => ErrorResponse.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"response": response == null ? null : List<dynamic>.from(response!.map((x) => x.toJson())),
"errorResponses": errorResponses,
"errorResponses": errorResponses == null ? null : List<dynamic>.from(errorResponses!.map((x) => x.toJson())),
};
}
class ErrorResponse {
ErrorResponse({
this.fieldName,
this.message,
});
dynamic? fieldName;
String? message;
factory ErrorResponse.fromRawJson(String str) => ErrorResponse.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory ErrorResponse.fromJson(Map<String, dynamic> json) => ErrorResponse(
fieldName: json["fieldName"],
message: json["message"] == null ? null : json["message"],
);
Map<String, dynamic> toJson() => {
"fieldName": fieldName,
"message": message == null ? null : message,
};
}
@ -34,6 +63,8 @@ class ChatUser {
this.isPin,
this.isFav,
this.isAdmin,
this.rKey,
this.totalCount,
this.isTyping,
this.isImageLoaded,
this.isImageLoading,
@ -44,7 +75,7 @@ class ChatUser {
String? userName;
String? email;
dynamic? phone;
dynamic? title;
String? title;
int? userStatus;
dynamic? image;
int? unreadMessageCount;
@ -52,17 +83,23 @@ class ChatUser {
bool? isPin;
bool? isFav;
bool? isAdmin;
dynamic? rKey;
int? totalCount;
bool? isTyping;
bool? isImageLoaded;
bool? isImageLoading;
File? userLocalDownlaodedImage;
factory ChatUser.fromRawJson(String str) => ChatUser.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory ChatUser.fromJson(Map<String, dynamic> json) => ChatUser(
id: json["id"] == null ? null : json["id"],
userName: json["userName"] == null ? null : json["userName"],
email: json["email"] == null ? null : json["email"],
phone: json["phone"],
title: json["title"],
title: json["title"] == null ? null : json["title"],
userStatus: json["userStatus"] == null ? null : json["userStatus"],
image: json["image"],
unreadMessageCount: json["unreadMessageCount"] == null ? null : json["unreadMessageCount"],
@ -70,6 +107,8 @@ class ChatUser {
isPin: json["isPin"] == null ? null : json["isPin"],
isFav: json["isFav"] == null ? null : json["isFav"],
isAdmin: json["isAdmin"] == null ? null : json["isAdmin"],
rKey: json["rKey"],
totalCount: json["totalCount"] == null ? null : json["totalCount"],
isTyping: false,
isImageLoaded: false,
isImageLoading: true,
@ -80,7 +119,7 @@ class ChatUser {
"userName": userName == null ? null : userName,
"email": email == null ? null : email,
"phone": phone,
"title": title,
"title": title == null ? null : title,
"userStatus": userStatus == null ? null : userStatus,
"image": image,
"unreadMessageCount": unreadMessageCount == null ? null : unreadMessageCount,
@ -88,5 +127,7 @@ class ChatUser {
"isPin": isPin == null ? null : isPin,
"isFav": isFav == null ? null : isFav,
"isAdmin": isAdmin == null ? null : isAdmin,
"rKey": rKey,
"totalCount": totalCount == null ? null : totalCount,
};
}

@ -1,7 +1,8 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:just_audio/just_audio.dart';
List<SingleUserChatModel> singleUserChatModelFromJson(String str) => List<SingleUserChatModel>.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x)));
@ -32,7 +33,9 @@ class SingleUserChatModel {
this.userChatReplyResponse,
this.isReplied,
this.isImageLoaded,
this.image});
this.image,
this.voice,
this.voiceController});
int? userChatHistoryId;
int? userChatHistoryLineId;
@ -58,6 +61,8 @@ class SingleUserChatModel {
bool? isReplied;
bool? isImageLoaded;
Uint8List? image;
File? voice;
AudioPlayer? voiceController;
factory SingleUserChatModel.fromJson(Map<String, dynamic> json) => SingleUserChatModel(
userChatHistoryId: json["userChatHistoryId"] == null ? null : json["userChatHistoryId"],
@ -83,7 +88,9 @@ class SingleUserChatModel {
userChatReplyResponse: json["userChatReplyResponse"] == null ? null : UserChatReplyResponse.fromJson(json["userChatReplyResponse"]),
isReplied: false,
isImageLoaded: false,
image: null);
image: null,
voice: null,
voiceController: json["fileTypeId"] == 13 ? AudioPlayer() : null);
Map<String, dynamic> toJson() => {
"userChatHistoryId": userChatHistoryId == null ? null : userChatHistoryId,
@ -143,19 +150,19 @@ class FileTypeResponse {
}
class UserChatReplyResponse {
UserChatReplyResponse({
this.userChatHistoryId,
this.chatEventId,
this.contant,
this.contantNo,
this.fileTypeId,
this.createdDate,
this.targetUserId,
this.targetUserName,
this.fileTypeResponse,
this.isImageLoaded,
this.image,
});
UserChatReplyResponse(
{this.userChatHistoryId,
this.chatEventId,
this.contant,
this.contantNo,
this.fileTypeId,
this.createdDate,
this.targetUserId,
this.targetUserName,
this.fileTypeResponse,
this.isImageLoaded,
this.image,
this.voice});
int? userChatHistoryId;
int? chatEventId;
@ -168,19 +175,22 @@ class UserChatReplyResponse {
FileTypeResponse? fileTypeResponse;
bool? isImageLoaded;
Uint8List? image;
Uint8List? voice;
factory UserChatReplyResponse.fromJson(Map<String, dynamic> json) => UserChatReplyResponse(
userChatHistoryId: json["userChatHistoryId"] == null ? null : json["userChatHistoryId"],
chatEventId: json["chatEventId"] == null ? null : json["chatEventId"],
contant: json["contant"] == null ? null : json["contant"],
contantNo: json["contantNo"] == null ? null : json["contantNo"],
fileTypeId: json["fileTypeId"],
createdDate: json["createdDate"] == null ? null : DateTime.parse(json["createdDate"]),
targetUserId: json["targetUserId"] == null ? null : json["targetUserId"],
targetUserName: json["targetUserName"] == null ? null : json["targetUserName"],
fileTypeResponse: json["fileTypeResponse"] == null ? null : FileTypeResponse.fromJson(json["fileTypeResponse"]),
isImageLoaded: false,
image: null);
userChatHistoryId: json["userChatHistoryId"] == null ? null : json["userChatHistoryId"],
chatEventId: json["chatEventId"] == null ? null : json["chatEventId"],
contant: json["contant"] == null ? null : json["contant"],
contantNo: json["contantNo"] == null ? null : json["contantNo"],
fileTypeId: json["fileTypeId"],
createdDate: json["createdDate"] == null ? null : DateTime.parse(json["createdDate"]),
targetUserId: json["targetUserId"] == null ? null : json["targetUserId"],
targetUserName: json["targetUserName"] == null ? null : json["targetUserName"],
fileTypeResponse: json["fileTypeResponse"] == null ? null : FileTypeResponse.fromJson(json["fileTypeResponse"]),
isImageLoaded: false,
image: null,
voice: null,
);
Map<String, dynamic> toJson() => {
"userChatHistoryId": userChatHistoryId == null ? null : userChatHistoryId,

@ -16,25 +16,28 @@ class MarathonDetailModel {
List<Sponsors>? sponsors;
List<Questions>? questions;
int? totalQuestions;
MarathonDetailModel(
{id,
titleEn,
titleAr,
descEn,
descAr,
winDeciderTime,
winnersCount,
questGapTime,
startTime,
endTime,
marathoneStatusId,
scheduleTime,
selectedLanguage,
projects,
sponsors,
questions,
totalQuestions});
int? marathonBufferTime;
MarathonDetailModel({
id,
titleEn,
titleAr,
descEn,
descAr,
winDeciderTime,
winnersCount,
questGapTime,
startTime,
endTime,
marathoneStatusId,
scheduleTime,
selectedLanguage,
projects,
sponsors,
questions,
totalQuestions,
marathonBufferTime,
});
MarathonDetailModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
@ -50,22 +53,21 @@ class MarathonDetailModel {
marathoneStatusId = json['marathoneStatusId'];
scheduleTime = json['scheduleTime'];
selectedLanguage = json['selectedLanguage'];
projects = json['projects'] != null
? Projects.fromJson(json['projects'])
: null;
projects = json['projects'] != null ? Projects.fromJson(json['projects']) : null;
if (json['sponsors'] != null) {
sponsors = <Sponsors>[];
json['sponsors'].forEach((v) {
sponsors!.add( Sponsors.fromJson(v));
sponsors!.add(Sponsors.fromJson(v));
});
}
if (json['questions'] != null) {
questions = <Questions>[];
json['questions'].forEach((v) {
questions!.add( Questions.fromJson(v));
questions!.add(Questions.fromJson(v));
});
}
totalQuestions = json["totalQuestions"];
marathonBufferTime = json["marathonBufferTime"];
}
Map<String, dynamic> toJson() {
@ -93,6 +95,7 @@ class MarathonDetailModel {
data['questions'] = questions!.map((v) => v.toJson()).toList();
}
data['totalQuestions'] = totalQuestions;
data['marathonBufferTime'] = marathonBufferTime;
return data;
}
@ -132,14 +135,7 @@ class Sponsors {
String? logo;
List<SponsorPrizes>? sponsorPrizes;
Sponsors(
{id,
nameEn,
nameAr,
image,
video,
logo,
sponsorPrizes});
Sponsors({id, nameEn, nameAr, image, video, logo, sponsorPrizes});
Sponsors.fromJson(Map<String, dynamic> json) {
id = json['id'];
@ -151,13 +147,13 @@ class Sponsors {
if (json['sponsorPrizes'] != null) {
sponsorPrizes = <SponsorPrizes>[];
json['sponsorPrizes'].forEach((v) {
sponsorPrizes!.add( SponsorPrizes.fromJson(v));
sponsorPrizes!.add(SponsorPrizes.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = <String, dynamic>{};
Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['nameEn'] = nameEn;
data['nameAr'] = nameAr;
@ -165,8 +161,7 @@ class Sponsors {
data['video'] = video;
data['logo'] = logo;
if (sponsorPrizes != null) {
data['sponsorPrizes'] =
sponsorPrizes!.map((v) => v.toJson()).toList();
data['sponsorPrizes'] = sponsorPrizes!.map((v) => v.toJson()).toList();
}
return data;
}
@ -186,7 +181,7 @@ class SponsorPrizes {
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = <String, dynamic>{};
Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['marathonPrizeEn'] = marathonPrizeEn;
data['marathonPrizeAr'] = marathonPrizeAr;
@ -208,19 +203,7 @@ class Questions {
int? questOptionsLimit;
List? questionOptions;
Questions(
{id,
titleEn,
titleAr,
marathonId,
questionTypeId,
questionTime,
nextQuestGap,
gapType,
gapValue,
gapImage,
questOptionsLimit,
questionOptions});
Questions({id, titleEn, titleAr, marathonId, questionTypeId, questionTime, nextQuestGap, gapType, gapValue, gapImage, questOptionsLimit, questionOptions});
Questions.fromJson(Map<String, dynamic> json) {
id = json['id'];

@ -51,6 +51,7 @@ class QuestionModel {
json['questionOptions'].forEach((v) {
questionOptions!.add(QuestionOptions.fromJson(v));
});
questionOptions!.sort((QuestionOptions a, QuestionOptions b) => a.sequence!.compareTo(b.sequence!));
}
}

@ -8,16 +8,16 @@ class UpdateUserTypesList {
UpdateUserTypesList.fromJson(Map<String, dynamic> json) {
itemID = json['ItemID'];
pFYAENABLEDFALG = json['P_FYAENABLED_FALG'];
pFYIENABLEDFALG = json['P_FYIENABLED_FALG'];
pFYAENABLEDFALG = json['P_FYA_ENABLED_FALG'];
pFYIENABLEDFALG = json['P_FYI_ENABLED_FLAG'];
pITEMTYPE = json['P_ITEM_TYPE'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['ItemID'] = this.itemID;
data['P_FYAENABLED_FALG'] = this.pFYAENABLEDFALG;
data['P_FYIENABLED_FALG'] = this.pFYIENABLEDFALG;
data['P_FYA_ENABLED_FALG'] = this.pFYAENABLEDFALG;
data['P_FYI_ENABLED_FLAG'] = this.pFYIENABLEDFALG;
data['P_ITEM_TYPE'] = this.pITEMTYPE;
return data;
}

File diff suppressed because it is too large Load Diff

@ -3,6 +3,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/api/offers_and_discounts_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/generated/locale_keys.g.dart';
@ -35,8 +36,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
bool isWorkListLoading = true;
int workListCounter = 0;
//Misssing Swipe
bool isMissingSwipeLoading = true;
int missingSwipeCounter = 0;
@ -94,7 +93,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
accrualList = null;
leaveBalanceAccrual = null;
ticketBalance = 0;
isServicesMenusLoading = true;
homeMenus = null;
@ -107,7 +105,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
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/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions),
DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen),
// DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen),
DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword),
];
@ -215,6 +213,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
List findMyTeam = menuList.where((element) => element.menuType == "M").toList();
if (findMyTeam.isNotEmpty) {
AppState().setempStatusIsManager = true;
drawerMenuItemList.insert(2, DrawerMenuItem("assets/images/drawer/my_team.svg", LocaleKeys.myTeamMembers.tr(), AppRoutes.myTeam));
}
} catch (ex) {
@ -245,7 +244,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void getCategoryOffersListAPI(BuildContext context) async {
try {
// Utils.showLoading(context);
getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 6);
getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 10);
isOffersLoading = false;
notifyListeners();
} catch (ex) {

@ -0,0 +1,56 @@
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/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/widgets/button/default_button.dart';
import 'package:url_launcher/url_launcher.dart';
class AppUpdateScreen extends StatefulWidget {
const AppUpdateScreen({Key? key}) : super(key: key);
@override
State<AppUpdateScreen> createState() => _UnsafeDeviceScreenState();
}
class _UnsafeDeviceScreenState extends State<AppUpdateScreen> {
String? dynamicParams;
@override
Widget build(BuildContext context) {
dynamicParams ??= ModalRoute.of(context)!.settings.arguments as String;
return Scaffold(
body: SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
21.height,
Center(child: Image.asset("assets/images/logos/main_mohemm_logo.png", width: 200, height: 50)),
50.height,
"Please Update Your App".toText24(isBold: true),
48.height,
dynamicParams.toString().toText14(isCenter: true).paddingOnly(left: 20.0, right: 20.0),
21.height,
DefaultButton(LocaleKeys.ok.tr(), () async {
if (Platform.isAndroid || Platform.isIOS) {
var appId = Platform.isAndroid ? 'hmg.cloudSolutions.mohem' : '1468856602';
var url = Uri.parse(
Platform.isAndroid ? "market://details?id=$appId" : "https://apps.apple.com/app/id$appId",
);
launchUrl(
url,
mode: LaunchMode.externalApplication,
);
}
}).paddingAll(24)
],
),
),
);
}
}

@ -85,8 +85,8 @@ class _MonthlyAttendanceScreenState extends State<MonthlyAttendanceScreen> {
@override
Widget build(BuildContext context) {
Map<String, double> dataMap = {
"Present": getTimeCardSummaryList?.aTTENDEDDAYS?.toDouble() ?? 75,
"Absent": getTimeCardSummaryList?.aBSENTDAYS?.toDouble() ?? 25,
"Present": getTimeCardSummaryList?.aTTENDEDDAYS?.toDouble() ?? 0,
"Absent": getTimeCardSummaryList?.aBSENTDAYS?.toDouble() ?? 0,
};
return Scaffold(
backgroundColor: Colors.white,
@ -112,7 +112,8 @@ class _MonthlyAttendanceScreenState extends State<MonthlyAttendanceScreen> {
],
).onPress(() async {
showMonthPicker(
context: context, //locale: EasyLocalization.of(context)?.locale,
context: context,
//locale: EasyLocalization.of(context)?.locale,
initialDate: formattedDate,
firstDate: DateTime(searchYear - 2),
lastDate: DateTime.now(),
@ -419,211 +420,211 @@ class _MonthlyAttendanceScreenState extends State<MonthlyAttendanceScreen> {
}
if (details.date!.month == formattedDate.month && details.date!.year == formattedDate.year) {
int val = details.date!.day;
getDayHoursTypeDetailsList?[val - 1].aTTENDEDFLAG == 'Y' ?
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
isScrollControlled: true,
backgroundColor: MyColors.backgroundBlackColor,
builder: (_) {
return DraggableScrollableSheet(
maxChildSize: 0.9,
expand: false,
builder: (_, controller) {
dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE;
DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss").parse(dmyString);
return Column(
children: [
Container(
width: 49,
height: 7,
margin: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: MyColors.darkGreyColor,
),
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 1,
itemBuilder: (_, i) =>
Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(
top: Radius.circular(25.0),
getDayHoursTypeDetailsList?[val - 1].aTTENDEDFLAG == 'Y'
? showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
isScrollControlled: true,
backgroundColor: MyColors.backgroundBlackColor,
builder: (_) {
return DraggableScrollableSheet(
maxChildSize: 0.9,
expand: false,
builder: (_, controller) {
dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE;
DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss").parse(dmyString);
return Column(
children: [
Container(
width: 49,
height: 7,
margin: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: MyColors.darkGreyColor,
),
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 1,
itemBuilder: (_, i) => Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(
top: Radius.circular(25.0),
),
color: MyColors.backgroundBlackColor,
),
color: MyColors.backgroundBlackColor,
),
child: Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${DateFormat("MMMM-dd-yyyy").format(dateTime1).replaceAll('-', " ")}".toText24(isBold: true, color: Colors.white),
LocaleKeys.attendanceDetails.tr().toText16(color: MyColors.greyACColor),
12.height,
CircularStepProgressBar(
totalSteps: 16 * 4,
currentStep: percentage,
width: 224,
height: 236,
selectedColor: MyColors.gradiantEndColor,
unselectedColor: MyColors.grey70Color,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
"${getScheduleShiftsDetailsList!.pERCENTAGE}".toText44(color: Colors.white, isBold: true),
LocaleKeys.completed.tr().toText11(color: MyColors.greyACColor),
28.height,
LocaleKeys.shiftTime.tr().toText11(color: MyColors.greyACColor),
"${getScheduleShiftsDetailsList!.sHTNAME}".toText22(color: Colors.white, isBold: true),
],
child: Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${DateFormat("MMMM-dd-yyyy").format(dateTime1).replaceAll('-', " ")}".toText24(isBold: true, color: Colors.white),
LocaleKeys.attendanceDetails.tr().toText16(color: MyColors.greyACColor),
12.height,
CircularStepProgressBar(
totalSteps: 16 * 4,
currentStep: percentage,
width: 224,
height: 236,
selectedColor: MyColors.gradiantEndColor,
unselectedColor: MyColors.grey70Color,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
"${getScheduleShiftsDetailsList!.pERCENTAGE}".toText44(color: Colors.white, isBold: true),
LocaleKeys.completed.tr().toText11(color: MyColors.greyACColor),
28.height,
LocaleKeys.shiftTime.tr().toText11(color: MyColors.greyACColor),
"${getScheduleShiftsDetailsList!.sHTNAME}".toText22(color: Colors.white, isBold: true),
],
).center,
).center,
).center,
],
).paddingOnly(left: 21, right: 21, top: 27, bottom: 37),
Stack(
children: [
Container(
width: double.infinity,
decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
padding: const EdgeInsets.only(left: 31, right: 31, top: 30, bottom: 29),
child: Column(
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.actualCheckIn.tr().toText11(
color: MyColors.grey67Color,
),
"${getScheduleShiftsDetailsList!.sHTACTUALSTARTTIME}" != ""
? "${getScheduleShiftsDetailsList!.sHTACTUALSTARTTIME}".toText22(color: Colors.black, isBold: true)
: "__".toText22(color: Colors.black, isBold: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.actualCheckOut.tr().toText11(
color: MyColors.grey67Color,
),
"${getScheduleShiftsDetailsList!.sHTACTUALENDTIME}" != ""
? "${getScheduleShiftsDetailsList!.sHTACTUALENDTIME}".toText22(color: Colors.black, isBold: true)
: "__".toText22(color: Colors.black, isBold: true),
],
).expanded,
],
),
25.height,
const Divider(
height: 1,
thickness: 1,
color: MyColors.lightGreyEFColor,
),
25.height,
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.approvedCheckIn.tr().toText11(
color: MyColors.grey67Color,
),
"${getScheduleShiftsDetailsList!.aPPROVEDSTARTTIME}" != ""
? "${getScheduleShiftsDetailsList!.aPPROVEDSTARTTIME}".toText22(color: MyColors.greenColor, isBold: true)
: "__".toText22(color: MyColors.greenColor, isBold: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.approvedCheckOut.tr().toText11(
color: MyColors.grey67Color,
),
"${getScheduleShiftsDetailsList!.aPPROVEDENDTIME}" != ""
? "${getScheduleShiftsDetailsList!.aPPROVEDENDTIME}".toText22(color: MyColors.greenColor, isBold: true)
: "__".toText22(color: MyColors.greenColor, isBold: true),
],
).expanded,
],
),
25.height,
const Divider(
height: 1,
thickness: 1,
color: MyColors.lightGreyEFColor,
),
25.height,
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.lateIn.tr().toText11(
color: MyColors.grey67Color,
),
"${getDayHoursTypeDetailsList[index].lATEINHRS}".toText22(color: MyColors.redColor, isBold: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.excess.tr().toText11(
color: MyColors.grey67Color,
),
"${getDayHoursTypeDetailsList[index].eXCESSHRS}".toText22(color: MyColors.backgroundBlackColor, isBold: true),
],
).expanded,
],
),
25.height,
const Divider(
height: 1,
thickness: 1,
color: MyColors.lightGreyEFColor,
),
25.height,
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.shortage.tr().toText11(
color: MyColors.grey67Color,
),
"${getDayHoursTypeDetailsList[index].sHORTAGEHRS}".toText22(color: MyColors.backgroundBlackColor, isBold: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.earlyOut.tr().toText11(
color: MyColors.grey67Color,
),
"${getDayHoursTypeDetailsList[index].eARLYOUTHRS}".toText22(color: Colors.black, isBold: true),
],
).expanded,
],
),
],
],
).paddingOnly(left: 21, right: 21, top: 27, bottom: 37),
Stack(
children: [
Container(
width: double.infinity,
decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
padding: const EdgeInsets.only(left: 31, right: 31, top: 30, bottom: 29),
child: Column(
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.actualCheckIn.tr().toText11(
color: MyColors.grey67Color,
),
"${getScheduleShiftsDetailsList!.sHTACTUALSTARTTIME}" != ""
? "${getScheduleShiftsDetailsList!.sHTACTUALSTARTTIME}".toText22(color: Colors.black, isBold: true)
: "__".toText22(color: Colors.black, isBold: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.actualCheckOut.tr().toText11(
color: MyColors.grey67Color,
),
"${getScheduleShiftsDetailsList!.sHTACTUALENDTIME}" != ""
? "${getScheduleShiftsDetailsList!.sHTACTUALENDTIME}".toText22(color: Colors.black, isBold: true)
: "__".toText22(color: Colors.black, isBold: true),
],
).expanded,
],
),
25.height,
const Divider(
height: 1,
thickness: 1,
color: MyColors.lightGreyEFColor,
),
25.height,
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.approvedCheckIn.tr().toText11(
color: MyColors.grey67Color,
),
"${getScheduleShiftsDetailsList!.aPPROVEDSTARTTIME}" != ""
? "${getScheduleShiftsDetailsList!.aPPROVEDSTARTTIME}".toText22(color: MyColors.greenColor, isBold: true)
: "__".toText22(color: MyColors.greenColor, isBold: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.approvedCheckOut.tr().toText11(
color: MyColors.grey67Color,
),
"${getScheduleShiftsDetailsList!.aPPROVEDENDTIME}" != ""
? "${getScheduleShiftsDetailsList!.aPPROVEDENDTIME}".toText22(color: MyColors.greenColor, isBold: true)
: "__".toText22(color: MyColors.greenColor, isBold: true),
],
).expanded,
],
),
25.height,
const Divider(
height: 1,
thickness: 1,
color: MyColors.lightGreyEFColor,
),
25.height,
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.lateIn.tr().toText11(
color: MyColors.grey67Color,
),
"${getDayHoursTypeDetailsList[index].lATEINHRS}".toText22(color: MyColors.redColor, isBold: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.excess.tr().toText11(
color: MyColors.grey67Color,
),
"${getDayHoursTypeDetailsList[index].eXCESSHRS}".toText22(color: MyColors.backgroundBlackColor, isBold: true),
],
).expanded,
],
),
25.height,
const Divider(
height: 1,
thickness: 1,
color: MyColors.lightGreyEFColor,
),
25.height,
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.shortage.tr().toText11(
color: MyColors.grey67Color,
),
"${getDayHoursTypeDetailsList[index].sHORTAGEHRS}".toText22(color: MyColors.backgroundBlackColor, isBold: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.earlyOut.tr().toText11(
color: MyColors.grey67Color,
),
"${getDayHoursTypeDetailsList[index].eARLYOUTHRS}".toText22(color: Colors.black, isBold: true),
],
).expanded,
],
),
],
),
),
),
],
),
],
],
),
],
),
),
),
),
),
],
);
},
);
},
):null;
),
],
);
},
);
},
)
: null;
}
}

@ -1,10 +1,10 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/api/api_client.dart';
import 'package:just_audio/just_audio.dart';
import 'package:mohem_flutter_app/api/chat/chat_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
@ -16,32 +16,43 @@ import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart';
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/widgets/bottom_sheet.dart';
import 'package:open_file/open_file.dart';
import 'package:mohem_flutter_app/ui/chat/common.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
// todo: @aamir use extension methods, and use correct widgets.
import 'package:rxdart/rxdart.dart';
class ChatBubble extends StatelessWidget {
ChatBubble({Key? key, required this.dateTime, required this.cItem}) : super(key: key);
final String dateTime;
final SingleUserChatModel cItem;
bool isCurrentUser = false;
bool isSeen = false;
bool isReplied = false;
bool isVoice = false;
int? fileTypeID;
String? fileTypeName;
late ChatProviderModel data;
late ChatProviderModel provider;
String? fileTypeDescription;
bool isDelivered = false;
String userName = '';
late Offset screenOffset;
void makeAssign() {
isCurrentUser = cItem.currentUserId == AppState().chatDetails!.response!.id ? true : false;
isSeen = cItem.isSeen == true ? true : false;
isReplied = cItem.userChatReplyResponse != null ? true : false;
// isVoice = cItem.fileTypeId == 13 && cItem.voiceController != null ? true : false;
fileTypeID = cItem.fileTypeId;
fileTypeName = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeName : "";
fileTypeDescription = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeDescription : "";
@ -49,12 +60,75 @@ class ChatBubble extends StatelessWidget {
userName = AppState().chatDetails!.response!.userName == cItem.currentUserName.toString() ? "You" : cItem.currentUserName.toString();
}
void playVoice(
BuildContext context, {
required SingleUserChatModel data,
}) async {
if (data.voice != null && data.voice!.existsSync()) {
if (Platform.isIOS) {
Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync()));
await data.voiceController!.seek(duration);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.setVolume(1.0);
await data.voiceController!.load();
data.voiceController!.play();
} else {
await data.voiceController!.setFilePath(data!.voice!.path);
Duration? duration = await data.voiceController!.load();
await data.voiceController!.seek(duration);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.play();
}
} else {
Utils.showLoading(context);
Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? ""));
// try {
File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data);
if (sFile.path.isEmpty) {
logger.d("Path Is Emptyyyyyyy");
} else {
logger.d("Path Exsists");
}
data.voice = sFile;
if (Platform.isIOS) {
logger.d("isIOS");
Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync()));
await data.voiceController!.seek(duration);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.setVolume(1.0);
await data.voiceController!.load();
Utils.hideLoading(context);
data.voiceController!.play();
} else {
Duration? duration = await data.voiceController!.setFilePath(sFile.path);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.seek(duration);
Utils.hideLoading(context);
await data.voiceController!.play();
}
}
}
void pausePlaying(BuildContext context, {required SingleUserChatModel data}) async {
await data.voiceController!.pause();
}
void rePlay(BuildContext context, {required SingleUserChatModel data}) async {
if (data.voice != null && data.voice!.existsSync()) {
await data.voiceController!.seek(Duration.zero);
await data.voiceController!.play();
}
}
Stream<PositionData> get _positionDataStream => Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(cItem.voiceController!.positionStream, cItem.voiceController!.bufferedPositionStream,
cItem.voiceController!.durationStream, (Duration position, Duration bufferedPosition, Duration? duration) => PositionData(position, bufferedPosition, duration ?? Duration.zero));
@override
Widget build(BuildContext context) {
Size windowSize = MediaQuery.of(context).size;
screenOffset = Offset(windowSize.width / 2, windowSize.height / 2);
makeAssign();
data = Provider.of<ChatProviderModel>(context, listen: false);
provider = Provider.of<ChatProviderModel>(context, listen: false);
return isCurrentUser ? currentUser(context) : receiptUser(context);
}
@ -79,30 +153,32 @@ class ChatBubble extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5),
(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "")
.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
Directionality(
textDirection: provider.getTextDirection(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : ""),
child: (cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "")
.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
),
],
).expanded,
if (cItem.userChatReplyResponse != null && cItem.userChatReplyResponse!.fileTypeId == 12 ||
cItem.userChatReplyResponse!.fileTypeId == 3 ||
cItem.userChatReplyResponse!.fileTypeId == 4)
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: SizedBox(
height: 32,
width: 32,
child: showImage(
isReplyPreview: true,
if (cItem.userChatReplyResponse != null)
if (cItem.userChatReplyResponse!.fileTypeId == 12 || cItem.userChatReplyResponse!.fileTypeId == 3 || cItem.userChatReplyResponse!.fileTypeId == 4)
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: SizedBox(
height: 32,
width: 32,
child: showImage(
isReplyPreview: false,
fileName: cItem.userChatReplyResponse!.contant!,
fileTypeDescription: cItem.userChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg")
.paddingOnly(left: 10, right: 10, bottom: 16, top: 16),
),
),
fileTypeDescription: cItem.userChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg")),
).paddingOnly(left: 10, right: 10, bottom: 16, top: 16),
],
),
),
).paddingOnly(bottom: 7),
).paddingOnly(bottom: 7).onPress(() {
provider.scrollToMsg(cItem);
}),
if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3)
ClipRRect(
borderRadius: BorderRadius.circular(5.0),
@ -117,18 +193,21 @@ class ChatBubble extends StatelessWidget {
);
}),
),
).paddingOnly(bottom: 4)
).paddingOnly(bottom: 4),
if (fileTypeID == 13 && cItem.voiceController != null)
currentWaveBubble(context, cItem)
else
Row(
children: [
if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8
// || fileTypeID == 2
// || fileTypeID == 2
)
SvgPicture.asset(data.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10),
(cItem.contant ?? "").toText12().expanded,
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)
//|| fileTypeID == 2
)
const Icon(Icons.remove_red_eye, size: 16)
],
),
Align(
@ -157,10 +236,7 @@ class ChatBubble extends StatelessWidget {
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: <Color>[
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
colors: <Color>[MyColors.gradiantEndColor, MyColors.gradiantStartColor],
),
),
child: Column(
@ -181,29 +257,33 @@ class ChatBubble extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5),
(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "")
.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
Directionality(
textDirection: provider.getTextDirection(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : ""),
child: (cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "")
.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
),
],
).expanded,
if (cItem.userChatReplyResponse != null && cItem.userChatReplyResponse!.fileTypeId == 12 ||
cItem.userChatReplyResponse!.fileTypeId == 3 ||
cItem.userChatReplyResponse!.fileTypeId == 4)
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: SizedBox(
height: 32,
width: 32,
child: showImage(
isReplyPreview: true,
fileName: cItem.userChatReplyResponse!.contant!,
fileTypeDescription: cItem.userChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg"),
),
).paddingOnly(left: 10, right: 10, bottom: 16, top: 16)
if (cItem.userChatReplyResponse != null)
if (cItem.userChatReplyResponse!.fileTypeId == 12 || cItem.userChatReplyResponse!.fileTypeId == 3 || cItem.userChatReplyResponse!.fileTypeId == 4)
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: SizedBox(
height: 32,
width: 32,
child: showImage(
isReplyPreview: true,
fileName: cItem.userChatReplyResponse!.contant!,
fileTypeDescription: cItem.userChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg"),
),
).paddingOnly(left: 10, right: 10, bottom: 16, top: 16)
],
),
),
).paddingOnly(bottom: 7),
).paddingOnly(bottom: 7).onPress(() {
provider.scrollToMsg(cItem);
}),
if (fileTypeID == 12 || fileTypeID == 4 || fileTypeID == 3)
ClipRRect(
borderRadius: BorderRadius.circular(5.0),
@ -218,15 +298,17 @@ class ChatBubble extends StatelessWidget {
);
}),
),
).paddingOnly(bottom: 4)
).paddingOnly(bottom: 4),
if (fileTypeID == 13 && cItem.voiceController != null)
recipetWaveBubble(context, cItem)
else
Row(
children: [
if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8
// || fileTypeID == 2
)
SvgPicture.asset(data.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10),
(cItem.contant ?? "").toText12(color: Colors.white).expanded,
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
)
@ -244,9 +326,11 @@ class ChatBubble extends StatelessWidget {
).paddingOnly(right: MediaQuery.of(context).size.width * 0.3);
}
Widget showImage({required bool isReplyPreview, required String fileName, required String fileTypeDescription}) {
if (isReplyPreview) {}
Widget voiceMsg(BuildContext context) {
return Container();
}
Widget showImage({required bool isReplyPreview, required String fileName, required String fileTypeDescription}) {
if (cItem.isImageLoaded! && cItem.image != null) {
return Image.memory(
cItem.image!,
@ -283,64 +367,125 @@ class ChatBubble extends StatelessWidget {
);
}
}
}
class WaveBubble extends StatelessWidget {
final PlayerController playerController;
final VoidCallback onTap;
final bool isPlaying;
const WaveBubble({
Key? key,
required this.playerController,
required this.onTap,
required this.isPlaying,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Widget currentWaveBubble(BuildContext context, SingleUserChatModel data) {
return Container(
margin: const EdgeInsets.all(10),
margin: const EdgeInsets.all(0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
gradient: const LinearGradient(
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: <Color>[
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
border: Border(
left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white),
),
color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: onTap,
icon: Icon(isPlaying ? Icons.stop : Icons.play_arrow),
color: Colors.white,
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
getPlayer(player: data.voiceController!, modelData: data),
StreamBuilder<PositionData>(
stream: _positionDataStream,
builder: (BuildContext context, AsyncSnapshot<PositionData> snapshot) {
PositionData? positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition: positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: data.voiceController!.seek,
).expanded;
},
),
AudioFileWaveforms(
size: Size(MediaQuery.of(context).size.width / 2, 10),
playerController: playerController,
padding: EdgeInsets.zero,
margin: EdgeInsets.zero,
playerWaveStyle: const PlayerWaveStyle(
fixedWaveColor: Colors.white,
liveWaveColor:MyColors.lightGreenColor,
showTop: true,
showBottom: true,
waveCap: StrokeCap.round,
seekLineThickness: 3,
visualizerHeight: 6,
backgroundColor: Colors.transparent
),
],
),
).circle(5);
}
Widget recipetWaveBubble(BuildContext context, SingleUserChatModel data) {
return Container(
margin: const EdgeInsets.all(0),
decoration: BoxDecoration(
border: Border(
left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white),
),
color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30),
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
getPlayer(player: data.voiceController!, modelData: data),
StreamBuilder<PositionData>(
stream: _positionDataStream,
builder: (BuildContext context, AsyncSnapshot<PositionData> snapshot) {
PositionData? positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition: positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: data.voiceController!.seek,
).expanded;
},
),
],
),
).circle(5);
}
Widget getPlayer({required AudioPlayer player, required SingleUserChatModel modelData}) {
return StreamBuilder<PlayerState>(
stream: player!.playerStateStream,
builder: (BuildContext context, AsyncSnapshot<PlayerState> snapshot) {
PlayerState? playerState = snapshot.data;
ProcessingState? processingState = playerState?.processingState;
bool? playing = playerState?.playing;
if (processingState == ProcessingState.loading || processingState == ProcessingState.buffering) {
return Container(
margin: const EdgeInsets.all(8.0),
width: 30.0,
height: 30.0,
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return Icon(
Icons.play_arrow,
size: 30,
color: MyColors.lightGreenColor,
).onPress(() {
playVoice(context, data: modelData);
});
} else if (processingState != ProcessingState.completed) {
return const Icon(
Icons.pause,
size: 30,
color: MyColors.lightGreenColor,
).onPress(() {
pausePlaying(context, data: modelData);
});
} else {
return const Icon(
Icons.replay,
size: 30,
color: MyColors.lightGreenColor,
).onPress(() {
rePlay(context, data: modelData);
});
}
},
);
}
}
class MyCustomStream extends StreamAudioSource {
final Uint8List bytes;
MyCustomStream(this.bytes);
@override
Future<StreamAudioResponse> request([int? start, int? end]) async {
start ??= 0;
end ??= bytes.length;
return StreamAudioResponse(
sourceLength: bytes.length,
contentLength: end - start,
offset: start,
stream: Stream.value(bytes.sublist(start, end)),
contentType: 'audio/aac',
);
}
}

@ -1,6 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@ -18,7 +16,7 @@ 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/call/chat_outgoing_call_screen.dart';
import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/ui/chat/common.dart';
import 'package:mohem_flutter_app/widgets/chat_app_bar_widge.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart';
@ -44,6 +42,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
final RefreshController _rc = RefreshController(initialRefresh: false);
late ChatProviderModel data;
ChatDetailedScreenParams? params;
var textDirection = TextDirection.RTL;
void getMoreChat() async {
if (params != null) {
@ -80,7 +79,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
loadMore: false,
isNewChat: params!.isNewChat!,
);
data.initAudio();
data.initAudio(receiverId: params!.chatUser!.id!);
}
return Scaffold(
@ -89,7 +88,6 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
context,
title: params!.chatUser!.userName.toString().replaceAll(".", " ").capitalizeFirstofEach,
showHomeButton: false,
image: params!.chatUser!.image == null || params!.chatUser!.image.isEmpty ? null : params!.chatUser!.image,
showTyping: true,
chatUser: params!.chatUser,
actions: [
@ -130,7 +128,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
reverse: true,
itemCount: m.userChatHistory.length,
padding: const EdgeInsets.all(21),
separatorBuilder: (cxt, index) => 8.height,
separatorBuilder: (BuildContext cxt, int index) => 8.height,
itemBuilder: (BuildContext context, int i) {
return SwipeTo(
iconColor: MyColors.lightGreenColor,
@ -144,15 +142,24 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
);
},
).onPress(() async {
if (m.userChatHistory[i].fileTypeResponse != null) {
m.getChatMedia(context,
fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!);
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.isMsgReply)
if (m.isReplyMsg)
SizedBox(
height: 82,
child: Row(
@ -174,7 +181,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
],
).expanded,
12.width,
if (m.isMsgReply && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg, m),
if (m.isReplyMsg && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg, m),
12.width,
const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe),
],
@ -183,12 +190,9 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
],
),
),
if (m.isFileSelected && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg")
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,
),
const Divider(height: 1, color: MyColors.lightGreyEFColor),
if (m.isRecoding)
Column(
children: <Widget>[
@ -197,12 +201,10 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
Text(m.buildTimer()).paddingAll(10),
if (m.isRecoding && m.isPlaying)
WaveBubble(
playerController: m.playerController,
onTap: () {
m.playOrPause();
},
isPlaying: m.playerController.playerState == PlayerState.playing)
.expanded
playerController: m.playerController,
isPlaying: m.playerController.playerState == PlayerState.playing,
onTap: () {},
).expanded
else
AudioWaveforms(
waveStyle: const WaveStyle(
@ -234,22 +236,6 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
).paddingAll(10).onPress(() {
m.deleteRecoding();
}),
if (m.isPause)
const Icon(
Icons.mic,
size: 26,
color: MyColors.lightGreenColor,
).paddingOnly(right: 15).onPress(() {
m.resumeRecoding();
}),
if (!m.isPause)
const Icon(
Icons.pause_circle_outline,
size: 26,
color: MyColors.lightGreenColor,
).paddingOnly(right: 15).onPress(() {
m.pauseRecoding();
}),
SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26)
.onPress(
() => m.sendChatMessage(context,
@ -267,10 +253,14 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
Row(
children: [
TextField(
textDirection: m.textDirection,
controller: m.message,
decoration: InputDecoration(
hintText: m.isFileSelected ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(),
hintStyle: TextStyle(color: m.isFileSelected ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14),
hintTextDirection: m.textDirection,
hintText: m.isAttachmentMsg
? m.selectedFile.path.split("/").last
: m.textDirection.name == "rtl" ? "اكتب هنا للرد" :LocaleKeys.typeheretoreply.tr(),
hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
@ -288,7 +278,8 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15)
: null,
),
onChanged: (val) {
onChanged: (String val) {
m.inputBoxDirection(val);
m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!);
},
).expanded,
@ -306,11 +297,11 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
() => m.selectImageToUpload(context),
),
).paddingOnly(right: 15),
Icon(
const Icon(
Icons.mic,
color: MyColors.lightGreenColor,
).paddingOnly(right: 15).onPress(() {
m.startRecoding();
m.startRecoding(context);
}),
SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26)
.onPress(

@ -1,5 +1,6 @@
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';
@ -8,6 +9,7 @@ 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/ui/chat/chat_home_screen.dart';
import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart';
import 'package:mohem_flutter_app/ui/chat/my_team_screen.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:provider/provider.dart';
@ -81,6 +83,7 @@ class _ChatHomeState extends State<ChatHome> {
children: <Widget>[
myTab(LocaleKeys.mychats.tr(), 0),
myTab(LocaleKeys.favorite.tr(), 1),
AppState().getempStatusIsManager ? myTab(LocaleKeys.myTeam.tr(), 2) : const SizedBox(),
],
),
),
@ -95,6 +98,7 @@ class _ChatHomeState extends State<ChatHome> {
children: <Widget>[
ChatHomeScreen(),
ChatFavoriteUsersScreen(),
AppState().getempStatusIsManager ? const MyTeamScreen() : const SizedBox(),
],
).expanded,
],

@ -179,6 +179,7 @@ class _ChatHomeScreenState extends State<ChatHomeScreen> {
m.favoriteUser(
userID: AppState().chatDetails!.response!.id!,
targetUserID: m.searchedChats![index].id!,
fromSearch: false
);
} else if (m.searchedChats![index].isFav == true) {
m.unFavoriteUser(
@ -189,6 +190,7 @@ class _ChatHomeScreenState extends State<ChatHomeScreen> {
m.favoriteUser(
userID: AppState().chatDetails!.response!.id!,
targetUserID: m.searchedChats![index].id!,
fromSearch: false
);
}
},
@ -238,6 +240,7 @@ class _ChatHomeScreenState extends State<ChatHomeScreen> {
),
),
onPressed: () async {
print(AppState().chatDetails!.response!.token);
showMyBottomSheet(
context,
callBackFunc: () {},

@ -0,0 +1,189 @@
import 'dart:math';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
class SeekBar extends StatefulWidget {
final Duration duration;
final Duration position;
final Duration bufferedPosition;
final ValueChanged<Duration>? onChanged;
final ValueChanged<Duration>? onChangeEnd;
const SeekBar({
Key? key,
required this.duration,
required this.position,
required this.bufferedPosition,
this.onChanged,
this.onChangeEnd,
}) : super(key: key);
@override
SeekBarState createState() => SeekBarState();
}
class SeekBarState extends State<SeekBar> {
double? _dragValue;
late SliderThemeData _sliderThemeData;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_sliderThemeData = SliderTheme.of(context).copyWith(
// trackHeight: 2.0,
thumbColor: MyColors.lightGreenColor,
activeTrackColor: MyColors.lightGreenColor,
inactiveTrackColor: MyColors.grey57Color.withOpacity(0.4),
);
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
SliderTheme(
data: _sliderThemeData.copyWith(
thumbShape: HiddenThumbComponentShape(),
),
child: ExcludeSemantics(
child: Slider(
min: 0.0,
max: widget.duration.inMilliseconds.toDouble(),
value: min(widget.bufferedPosition.inMilliseconds.toDouble(), widget.duration.inMilliseconds.toDouble()),
onChanged: (value) {
setState(() {
_dragValue = value;
});
if (widget.onChanged != null) {
widget.onChanged!(Duration(milliseconds: value.round()));
}
},
onChangeEnd: (value) {
if (widget.onChangeEnd != null) {
widget.onChangeEnd!(Duration(milliseconds: value.round()));
}
_dragValue = null;
},
),
),
),
SliderTheme(
data: _sliderThemeData.copyWith(
inactiveTrackColor: Colors.transparent,
),
child: Slider(
min: 0.0,
max: widget.duration.inMilliseconds.toDouble(),
value: min(_dragValue ?? widget.position.inMilliseconds.toDouble(), widget.duration.inMilliseconds.toDouble()),
onChanged: (value) {
setState(() {
_dragValue = value;
});
if (widget.onChanged != null) {
widget.onChanged!(Duration(milliseconds: value.round()));
}
},
onChangeEnd: (value) {
if (widget.onChangeEnd != null) {
widget.onChangeEnd!(Duration(milliseconds: value.round()));
}
_dragValue = null;
},
),
),
],
);
}
}
class PositionData {
final Duration position;
final Duration bufferedPosition;
final Duration duration;
PositionData(this.position, this.bufferedPosition, this.duration);
}
class HiddenThumbComponentShape extends SliderComponentShape {
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) => Size.zero;
@override
void paint(
PaintingContext context,
Offset center, {
required Animation<double> activationAnimation,
required Animation<double> enableAnimation,
required bool isDiscrete,
required TextPainter labelPainter,
required RenderBox parentBox,
required SliderThemeData sliderTheme,
required TextDirection textDirection,
required double value,
required double textScaleFactor,
required Size sizeWithOverflow,
}) {}
}
class WaveBubble extends StatelessWidget {
final PlayerController playerController;
final VoidCallback onTap;
final bool isPlaying;
const WaveBubble({
Key? key,
required this.playerController,
required this.onTap,
required this.isPlaying,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
gradient: const LinearGradient(
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: <Color>[
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: onTap,
icon: Icon(isPlaying ? Icons.stop : Icons.play_arrow),
color: Colors.white,
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
AudioFileWaveforms(
size: Size(MediaQuery.of(context).size.width / 2, 10),
playerController: playerController,
padding: EdgeInsets.zero,
margin: EdgeInsets.zero,
enableSeekGesture: true,
density: 1,
playerWaveStyle: const PlayerWaveStyle(
fixedWaveColor: Colors.white,
liveWaveColor: MyColors.greenColor,
showTop: true,
showBottom: true,
waveCap: StrokeCap.round,
seekLineThickness: 2,
visualizerHeight: 4,
backgroundColor: Colors.transparent,
),
),
],
),
);
}
}

@ -0,0 +1,154 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.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/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart';
class MyTeamScreen extends StatefulWidget {
const MyTeamScreen({Key? key}) : super(key: key);
@override
State<MyTeamScreen> createState() => _MyTeamScreenState();
}
class _MyTeamScreenState extends State<MyTeamScreen> {
late ChatProviderModel provider;
@override
void initState() {
super.initState();
provider = Provider.of<ChatProviderModel>(context, listen: false);
loadMembers();
}
void loadMembers(){
provider.getTeamMembers();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyColors.white,
body: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) {
if (m.isLoading) {
return ChatHomeShimmer(
isDetailedScreen: false,
);
} else {
return m.teamMembersList != null && m.teamMembersList.isNotEmpty
? ListView.separated(
itemCount: m.teamMembersList!.length,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
padding: const EdgeInsets.only(bottom: 80.0),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: Row(
children: [
Stack(
children: <Widget>[
if (m.teamMembersList![index].isImageLoading!)
const SizedBox(
height: 48,
width: 48,
).toShimmer().circle(30),
if (!m.teamMembersList![index].isImageLoading! && m.teamMembersList![index].userLocalDownlaodedImage == null)
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
if (!m.teamMembersList![index].isImageLoading! && m.teamMembersList![index].userLocalDownlaodedImage != null)
Container(
width: 48.0,
height: 48.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.cover,
image: FileImage(m.teamMembersList![index].userLocalDownlaodedImage!),
),
),
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: m.teamMembersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red,
),
).circle(10),
)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(m.teamMembersList[index].userName! ?? "").toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 13),
],
).expanded,
// SizedBox(
// width: 60,
// child: Row(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisAlignment: MainAxisAlignment.end,
// mainAxisSize: MainAxisSize.max,
// children: <Widget>[
// Icon(
// m.teamMembersList![index].isFav! ? Icons.star : Icons.star_border,
// color: m.teamMembersList![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color,
// ).onPress(() {
// if (m.teamMembersList![index].isFav!) {
// m.unFavoriteUser(
// userID: AppState().chatDetails!.response!.id!,
// targetUserID: m.teamMembersList![index].id!,
// );
// }
// }).center,
// ],
// ),
// ),
],
),
).onPress(() {
Navigator.pushNamed(
context,
AppRoutes.chatDetailed,
arguments: ChatDetailedScreenParams(m.teamMembersList![index], true),
).then(
(Object? value) {
m.clearSelections();
},
);
});
},
separatorBuilder: (BuildContext context, int index) => const Divider(color: MyColors.lightGreyE5Color).paddingOnly(left: 70),
).paddingAll(21)
: Column(
children: <Widget>[
Utils.getNoDataWidget(context).expanded,
],
);
}
},
),
);
}
}

@ -48,6 +48,9 @@ class _SuccessDialogState extends State<SuccessDialog> with TickerProviderStateM
width: size,
height: size,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0),
),
child: Lottie.asset(
'assets/lottie/lt_success.json',
repeat: false,

@ -1,11 +1,12 @@
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_countdown_timer/flutter_countdown_timer.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';
@ -41,7 +42,7 @@ class DashboardScreen extends StatefulWidget {
}
}
class _DashboardScreenState extends State<DashboardScreen> {
class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingObserver {
late DashboardProviderModel data;
late MarathonProvider marathonProvider;
late ChatProviderModel cProvider;
@ -53,18 +54,38 @@ class _DashboardScreenState extends State<DashboardScreen> {
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
scheduleMicrotask(() {
data = Provider.of<DashboardProviderModel>(context, listen: false);
marathonProvider = Provider.of<MarathonProvider>(context, listen: false);
cProvider = Provider.of<ChatProviderModel>(context, listen: false);
_bHubCon();
_onRefresh();
});
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
checkSession();
}
}
void checkSession() async {
try {
Utils.showLoading(context);
await DashboardApiClient().getOpenMissingSwipes();
Utils.hideLoading(context);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
chatHubConnection.stop();
}
@ -80,7 +101,6 @@ class _DashboardScreenState extends State<DashboardScreen> {
void _onRefresh() async {
data.initProvider();
_bHubCon();
// data.getITGNotification().then((value) {
// print("--------------------detail_1-----------------");
// print(value!.result!.data!.notificationMasterId);
@ -323,12 +343,104 @@ class _DashboardScreenState extends State<DashboardScreen> {
],
),
],
).paddingOnly(left: 21, right: 21, top: 7),
context.watch<MarathonProvider>().isLoading
? const MarathonBannerShimmer().paddingAll(20)
: MarathonBanner(isMarathonUpcoming: context.watch<MarathonProvider>().isUpComingMarathon).paddingAll(20),
ServicesWidget(),
8.height,
).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(
padding: const EdgeInsets.only(left: 8, right: 8),
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<DashboardProviderModel>(
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),
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext cxt, int index) {
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].bannerImage!,
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),
@ -339,101 +451,12 @@ class _DashboardScreenState extends State<DashboardScreen> {
),
child: 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)),
],
),
],
),
),
LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() {
Navigator.pushNamed(context, AppRoutes.offersAndDiscounts);
})
],
).paddingOnly(left: 21, right: 21),
Consumer<DashboardProviderModel>(
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),
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext cxt, int index) {
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(
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].bannerImage ?? "",
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: 6),
);
},
),
ServicesWidget(),
context.watch<MarathonProvider>().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 8),
],
),
)
),
],
),
),
@ -460,7 +483,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
"assets/icons/create_req.svg",
color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
label: LocaleKeys.createRequest.tr(),
label: LocaleKeys.mowadhafhiRequest.tr(),
),
BottomNavigationBarItem(
icon: Stack(

@ -50,23 +50,23 @@ class _TodayAttendanceScreenState extends State<TodayAttendanceScreen2> {
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
onPressed: () => Navigator.pop(context),
),
actions: [
IconButton(
onPressed: () {
data.fetchAttendanceTracking(context);
},
icon: const Icon(
Icons.ac_unit,
color: Colors.white,
),
)
],
// actions: [
// IconButton(
// onPressed: () {
// data.fetchAttendanceTracking(context);
// },
// icon: const Icon(
// Icons.ac_unit,
// color: Colors.white,
// ),
// )
// ],
),
backgroundColor: MyColors.backgroundBlackColor,
body: Consumer<DashboardProviderModel>(
builder: (context, model, child) {
return (model.isAttendanceTrackingLoading
? Center(child: CircularProgressIndicator())
? const Center(child: CircularProgressIndicator())
: Column(
children: [
Container(

@ -150,13 +150,9 @@ class _AppDrawerState extends State<AppDrawer> {
Widget menuItem(String icon, String title, String routeName, {Color? color, bool closeDrawer = true, VoidCallback? onPress}) {
return Row(
children: [
SvgPicture.asset(
icon,
height: 20,
width: 20,
),
SvgPicture.asset(icon, height: 20, width: 20),
9.width,
title.toText14(color: color).expanded
title.toText14(color: color, textAlign: AppState().isArabic(context) ? TextAlign.right : null).expanded,
],
).paddingOnly(left: 21, top: 10, bottom: 10, right: 21).onPress(closeDrawer
? () async {

@ -1,60 +0,0 @@
import 'dart:ui';
import 'package:flutter/material.dart';
class DrawerItem extends StatefulWidget {
final String title;
final String subTitle;
final IconData icon;
final Color color;
final dynamic assetLink;
const DrawerItem(this.title, {required this.icon, required this.color, this.subTitle = '', this.assetLink});
@override
_DrawerItemState createState() => _DrawerItemState();
}
class _DrawerItemState extends State<DrawerItem> {
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 0, bottom: 5, left: 0, right: 0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
if (widget.assetLink != null)
Container(
height: 20,
width: 20,
child: Image.asset(widget.assetLink),
),
if (widget.assetLink == null)
Icon(
widget.icon,
color: widget.color,
size: 25,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * 0.45,
child: Text(widget.title,
style: TextStyle(
color: widget.color ?? Color(0xFF2E303A),
fontSize: 14,
fontFamily: 'Poppins',
fontWeight: FontWeight.w600,
letterSpacing: -0.84,
)),
),
],
),
),
],
));
}
}

@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/leave_balance_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';
@ -141,12 +142,13 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
empID: selectedID);
Utils.hideLoading(context);
var res = await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submit.pTRANSACTIONID!, "", "add_leave_balance", selectedEmployeeID: selectedID));
if (res != null && res == true) {
Utils.showLoading(context);
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(submit.pTRANSACTIONID!);
Utils.hideLoading(context);
} catch (ex) {

@ -72,7 +72,7 @@ class _LeaveBalanceState extends State<LeaveBalance> {
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(21),
children: [
BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true, selectedEmp: employeeId),
BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true, selectedEmp: employeeId, showLoading: false),
12.height,
ListView.separated(
physics: const NeverScrollableScrollPhysics(),

@ -100,16 +100,16 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
passwordConstraintsUI(LocaleKeys.doNotUseRecentPassword.tr(), true),
8.height,
passwordConstraintsUI(LocaleKeys.atLeastOneLowercase.tr(), checkRegEx(r'[a-z]')),
8.height,
passwordConstraintsUI(LocaleKeys.atLeastOneUppercase.tr(), checkRegEx(r'[A-Z]')),
// 8.height,
// passwordConstraintsUI(LocaleKeys.atLeastOneUppercase.tr(), checkRegEx(r'[A-Z]')),
8.height,
passwordConstraintsUI(LocaleKeys.atLeastOneNumeric.tr(), checkRegEx(r'[0-9]')),
8.height,
passwordConstraintsUI(LocaleKeys.minimum8Characters.tr(), password.text.length >= 8),
8.height,
passwordConstraintsUI(LocaleKeys.doNotAddRepeatingLetters.tr(), checkRepeatedChars(password.text)),
8.height,
passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')),
// 8.height,
// passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')),
8.height,
passwordConstraintsUI(LocaleKeys.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text),
],
@ -131,14 +131,14 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
return false;
}
bool hasUppercase = password.contains(RegExp(r'[A-Z]'));
// bool hasUppercase = password.contains(RegExp(r'[A-Z]'));
bool hasDigits = password.contains(RegExp(r'[0-9]'));
bool hasLowercase = password.contains(RegExp(r'[a-z]'));
bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'));
// bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'));
bool hasMinLength = password.length >= minLength;
bool isMatched = password == confirmPassword.text;
return hasDigits && hasUppercase && hasLowercase && hasSpecialCharacters && hasMinLength && isMatched && checkRepeatedChars(password);
return hasDigits && hasLowercase && hasMinLength && isMatched && checkRepeatedChars(password);
}
bool checkRepeatedChars(String password) {

@ -12,12 +12,15 @@ 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';
import 'package:mohem_flutter_app/classes/consts.dart';
import 'package:mohem_flutter_app/classes/notifications.dart';
import 'package:mohem_flutter_app/classes/push-notification-handler.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/check_mobile_app_version_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';
@ -25,7 +28,9 @@ 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:permission_handler/permission_handler.dart';
import 'package:safe_device/safe_device.dart';
import 'package:wifi_iot/wifi_iot.dart';
class LoginScreen extends StatefulWidget {
LoginScreen({Key? key}) : super(key: key);
@ -93,8 +98,11 @@ class _LoginScreenState extends State<LoginScreen> {
await Firebase.initializeApp();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().initNotification(firebaseToken);
loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios");
if (loginInfo == null) {
await checkPrefs();
_autoLogin = false;
Utils.hideLoading(context);
return;
} else {
@ -105,7 +113,7 @@ class _LoginScreenState extends State<LoginScreen> {
}
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, (errorMsg) {});
Utils.handleException(ex, context, null);
}
}
@ -152,17 +160,21 @@ class _LoginScreenState extends State<LoginScreen> {
}
}
@override
Widget build(BuildContext context) {
if (isAppOpenBySystem == null) {
isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool;
if (!kReleaseMode) {
// username.text = "15444"; // Maha User
// username.text = "15153"; // Tamer User
// password.text = "Abcd@1234";
username.text = "15153"; // Tamer User
password.text = "Abcd@12345";
// username.text = "206535"; // Hashim User
// password.text = "Namira786";
// 13777
// Ab12345cd
}
if (isAppOpenBySystem!) checkFirebaseToken();
}
@ -219,6 +231,14 @@ class _LoginScreenState extends State<LoginScreen> {
Navigator.pushNamed(context, AppRoutes.forgotPassword);
}),
),
20.height,
// DefaultButton(
// "Connect HMG Network",
// () async {
// SystemChannels.textInput.invokeMethod('TextInput.hide');
// connectWithHmgNetwork();
// },
// ),
],
),
)
@ -234,4 +254,30 @@ class _LoginScreenState extends State<LoginScreen> {
),
);
}
void connectWithHmgNetwork() async {
try {
bool isConnected = await WiFiForIoTPlugin.connect("MOHEMM-CONNECT", password: "0987654321", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false);
if (isConnected) {
await WiFiForIoTPlugin.forceWifiUsage(true);
// if (Platform.isIOS) {
// await closeWifiRequest();
// await Future.delayed(Duration(seconds: 6));
// } else {
// await WiFiForIoTPlugin.forceWifiUsage(true);
// }
}
} catch (e) {
print("----------------o----");
print(e);
}
}
Future<bool> closeWifiRequest() async {
if (Platform.isAndroid) {
await WiFiForIoTPlugin.forceWifiUsage(false);
}
return await WiFiForIoTPlugin.disconnect();
}
}

@ -94,16 +94,16 @@ class _NewPasswordScreenState extends State<NewPasswordScreen> {
passwordConstraintsUI(LocaleKeys.doNotUseRecentPassword.tr(), true),
8.height,
passwordConstraintsUI(LocaleKeys.atLeastOneLowercase.tr(), checkRegEx(r'[a-z]')),
8.height,
passwordConstraintsUI(LocaleKeys.atLeastOneUppercase.tr(), checkRegEx(r'[A-Z]')),
// 8.height,
// passwordConstraintsUI(LocaleKeys.atLeastOneUppercase.tr(), checkRegEx(r'[A-Z]')),
8.height,
passwordConstraintsUI(LocaleKeys.atLeastOneNumeric.tr(), checkRegEx(r'[0-9]')),
8.height,
passwordConstraintsUI(LocaleKeys.minimum8Characters.tr(), password.text.length >= 8),
8.height,
passwordConstraintsUI(LocaleKeys.doNotAddRepeatingLetters.tr(), checkRepeatedChars(password.text)),
8.height,
passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')),
// 8.height,
// passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')),
8.height,
passwordConstraintsUI(LocaleKeys.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text),
],
@ -143,14 +143,14 @@ class _NewPasswordScreenState extends State<NewPasswordScreen> {
return false;
}
bool hasUppercase = password.contains(RegExp(r'[A-Z]'));
// bool hasUppercase = password.contains(RegExp(r'[A-Z]'));
bool hasDigits = password.contains(RegExp(r'[0-9]'));
bool hasLowercase = password.contains(RegExp(r'[a-z]'));
bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'));
// bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'));
bool hasMinLength = password.length >= minLength;
bool isMatched = password == confirmPassword.text;
return hasDigits && hasUppercase && hasLowercase && hasSpecialCharacters && hasMinLength && isMatched && checkRepeatedChars(password);
return hasDigits && hasLowercase && hasMinLength && isMatched && checkRepeatedChars(password);
}
bool checkRepeatedChars(String password) {

@ -23,12 +23,14 @@ class MarathonIntroScreen extends StatelessWidget {
ListView(
padding: const EdgeInsets.all(21),
children: <Widget>[
MarathonDetailsCard(provider: provider),
10.height,
MarathonTimerCard(
provider: provider,
timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch,
),
MarathonDetailsCard(marathonDetailModel: provider.isUpComingMarathon ? provider.marathonDetailModel : provider.demoMarathonDetailModel),
20.height,
provider.isUpComingMarathon
? MarathonTimerCard(
provider: provider,
timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch,
)
: const SizedBox(),
],
).expanded,
1.divider,

@ -2,8 +2,8 @@ import 'dart:async';
import 'package:appinio_swiper/appinio_swiper.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/marathon/demo_marathon_repo.dart';
import 'package:mohem_flutter_app/api/marathon/marathon_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/consts.dart';
@ -17,11 +17,12 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart';
import 'package:video_player/video_player.dart';
class MarathonProvider extends ChangeNotifier {
//****************VARIABLES**********
//************************************************ VARIABLES **********************************************************
final AppinioSwiperController swiperController = AppinioSwiperController();
MarathonDetailModel marathonDetailModel = MarathonDetailModel();
MarathonDetailModel demoMarathonDetailModel = MarathonDetailModel();
List<CardContent> cardContentList = <CardContent>[];
QuestionModel currentQuestion = QuestionModel();
List<QuestionCardStatus> answerStatusesList = <QuestionCardStatus>[];
@ -31,12 +32,12 @@ class MarathonProvider extends ChangeNotifier {
String? selectedOptionId;
int? totalQualifiers;
//TODO: THIS BUG NEEDS TO BE FIXED. NOT DONE YET
String? gapTimeImage;
String? gapTimeText;
int? gapTimeType;
bool iAmWinner = false;
bool isGettingQualifiers = false;
bool isPrivilegedWithMarathon = false;
bool _isLoading = false;
@ -54,6 +55,7 @@ class MarathonProvider extends ChangeNotifier {
set isUpComingMarathon(bool value) {
_isUpComingMarathon = value;
notifyListeners();
}
@ -66,6 +68,33 @@ class MarathonProvider extends ChangeNotifier {
notifyListeners();
}
bool _canPlayDemo = true;
bool get canPlayDemo => _canPlayDemo;
set canPlayDemo(bool value) {
_canPlayDemo = value;
notifyListeners();
}
bool _isButtonEnabled = false;
bool get isButtonEnabled => _isButtonEnabled;
set isButtonEnabled(bool value) {
_isButtonEnabled = value;
notifyListeners();
}
bool _isUserWaiting = false;
bool get isUserWaiting => _isUserWaiting;
set isUserWaiting(bool value) {
_isUserWaiting = value;
notifyListeners();
}
bool _isMarathonCompleted = false;
bool get isMarathonCompleted => _isMarathonCompleted;
@ -119,7 +148,9 @@ class MarathonProvider extends ChangeNotifier {
notifyListeners();
}
//****************TIMERS**********
// 9c47d281-c5b5-4b5d-a90a-08dacb8cbdb6
// MarathonI
//************************************************ TIMERS **********************************************************
int sponsorsSecondsCounter = 0;
int totalSponsorVideoSeconds = 0;
@ -144,7 +175,13 @@ class MarathonProvider extends ChangeNotifier {
);
}
int totalSecondsToWaitForMarathon = 20;
int totalSecondsToWaitForMarathon = 30;
set updateTotalSecondsToWaitForMarathon(int value) {
totalSecondsToWaitForMarathon = value;
notifyListeners();
}
Timer timerToWaitForMarathon = Timer.periodic(const Duration(seconds: 1), (Timer timer) {});
void startTimerToWaitForMarathon() {
@ -153,7 +190,13 @@ class MarathonProvider extends ChangeNotifier {
oneSec,
(Timer timer) async {
if (totalSecondsToWaitForMarathon == 0) {
callNextQuestionApi();
if (isUserWaiting) {
MarathonApiClient().joinMarathonAsParticipant().whenComplete(() async {
await callNextQuestionApi();
});
} else {
isButtonEnabled = false;
}
timer.cancel();
return;
} else {
@ -173,23 +216,33 @@ class MarathonProvider extends ChangeNotifier {
timerForQuestion = Timer.periodic(
oneSec,
(Timer timer) async {
// This 2 is just to show the color of answer tile for 2 seconds and then update card status
// This 2 is just to show the color of answer tile for 1 and then update card status
if (totalCurrentQuestionTime - currentGapTime == 1) {
getCorrectAnswerAndUpdateAnswerColor();
}
if (totalCurrentQuestionTime == currentGapTime) {
totalCurrentQuestionTime--;
if (totalCurrentQuestionTime - currentGapTime == -2) {
updateCardStatusToAnswer();
scheduleMicrotask(() async {
await callSubmitOptionApi().then((bool value) async {
if (value) {
await callNextQuestionApi();
}
});
});
// scheduleMicrotask(() async {
// if (AppState().getIsDemoMarathon || isUserOutOfGame) {
// await callNextQuestionApi();
// } else {
// await callSubmitOptionApi().then((bool value) async {
// updateIsUserOutOfGame = !value;
// await callNextQuestionApi();
// });
// }
// });
if (currentQuestionNumber == (AppState().getIsDemoMarathon ? demoMarathonDetailModel.totalQuestions! : marathonDetailModel.totalQuestions!)) {
isGettingQualifiers = true;
updateQuestionCardStatus(QuestionCardStatus.findingWinner);
timer.cancel();
cancelTimer();
notifyListeners();
}
totalCurrentQuestionTime--;
}
if (totalCurrentQuestionTime == 0) {
@ -197,16 +250,10 @@ class MarathonProvider extends ChangeNotifier {
gapTimeText = currentQuestion.gapText;
gapTimeType = currentQuestion.gapType;
updateCardData();
if (currentQuestionNumber - 1 == marathonDetailModel.totalQuestions!) {
callGetQualifiersApi();
updateQuestionCardStatus(QuestionCardStatus.findingWinner);
timer.cancel();
cancelTimer();
notifyListeners();
}
return;
} else {
if (totalCurrentQuestionTime != currentGapTime) {
if (totalCurrentQuestionTime - currentGapTime != -2) {
totalCurrentQuestionTime--;
}
}
@ -224,10 +271,13 @@ class MarathonProvider extends ChangeNotifier {
timerForWinnerSelection = Timer.periodic(
oneSec,
(Timer timer) async {
if (totalSecondsToWaitForWinner == 0) {
if (totalSecondsToWaitForWinner == 1) {
await callGetSelectedWinnersApi().whenComplete(() => updateQuestionCardStatus(QuestionCardStatus.winnerFound));
timer.cancel();
updateQuestionCardStatus(QuestionCardStatus.winnerFound);
return;
} else if (totalSecondsToWaitForWinner == 15) {
totalSecondsToWaitForWinner--;
await callGetQualifiersApi();
} else {
totalSecondsToWaitForWinner--;
}
@ -237,18 +287,26 @@ class MarathonProvider extends ChangeNotifier {
);
}
//****************FUNCTIONS*********
//************************************************ FUNCTIONS **********************************************************
Future<bool> callSubmitOptionApi() async {
return await MarathonApiClient().submitSelectedOption(marathonId: marathonDetailModel.id!, questionId: currentQuestion.id, selectedAnswerId: selectedOptionId);
}
Future<void> callGetQualifiersApi() async {
totalQualifiers = await MarathonApiClient().getQualifiers(marathonId: marathonDetailModel.id!);
if (AppState().getIsDemoMarathon) {
totalQualifiers = isUserOutOfGame ? 0 : 1;
} else {
totalQualifiers = await MarathonApiClient().getQualifiers(marathonId: marathonDetailModel.id!);
}
isGettingQualifiers = false;
notifyListeners();
}
Future<void> callGetSelectedWinnersApi() async {
if (AppState().getIsDemoMarathon) {
return;
}
selectedWinners = await MarathonApiClient().getSelectedWinner(marathonId: marathonDetailModel.id!);
if (selectedWinners != null) {
selectedWinners!.removeWhere((WinnerModel element) {
@ -265,10 +323,14 @@ class MarathonProvider extends ChangeNotifier {
}
Future<void> callNextQuestionApi() async {
if (currentQuestionNumber < marathonDetailModel.totalQuestions!) {
if (currentQuestionNumber < (AppState().getIsDemoMarathon ? demoMarathonDetailModel.totalQuestions! : marathonDetailModel.totalQuestions!)) {
if (currentQuestionNumber == 0) {
Utils.showLoading(AppRoutes.navigatorKey.currentContext!);
currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!))!;
if (!AppState().getIsDemoMarathon) {
Utils.showLoading(AppRoutes.navigatorKey.currentContext!);
}
currentQuestion = AppState().getIsDemoMarathon
? await DemoMarathonRepo().getDemoNextQuestion(currentQuestionNumber: currentQuestionNumber)
: (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!));
gapTimeImage = currentQuestion.gapImage;
gapTimeText = currentQuestion.gapText;
gapTimeType = currentQuestion.gapType;
@ -277,10 +339,11 @@ class MarathonProvider extends ChangeNotifier {
}
startTimerForQuestion();
updateCardData();
Navigator.pushReplacementNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.marathonScreen);
} else {
currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: currentQuestion.id, marathonId: marathonDetailModel.id!))!;
currentQuestion = AppState().getIsDemoMarathon
? await DemoMarathonRepo().getDemoNextQuestion(currentQuestionNumber: currentQuestionNumber)
: (await MarathonApiClient().getNextQuestion(questionId: currentQuestion.id, marathonId: marathonDetailModel.id!));
}
notifyListeners();
}
@ -302,12 +365,21 @@ class MarathonProvider extends ChangeNotifier {
}
void populateQuestionStatusesList() {
if (marathonDetailModel.totalQuestions != null) {
for (int i = 0; i < marathonDetailModel.totalQuestions!; i++) {
answerStatusesList.clear();
if (demoMarathonDetailModel.totalQuestions != null) {
for (int i = 0; i < demoMarathonDetailModel.totalQuestions!; i++) {
answerStatusesList.add(QuestionCardStatus.question);
}
notifyListeners();
}
if (isUpComingMarathon) {
if (marathonDetailModel.totalQuestions != null) {
for (int i = 0; i < marathonDetailModel.totalQuestions!; i++) {
answerStatusesList.add(QuestionCardStatus.question);
}
notifyListeners();
}
}
}
void updateAnswerStatusesList(QuestionCardStatus status) {
@ -325,13 +397,16 @@ class MarathonProvider extends ChangeNotifier {
currentQuestion.questionOptions![i].optionStatus = QuestionsOptionStatus.unSelected;
}
currentQuestion.questionOptions![index].optionStatus = status;
selectedOptionId = currentQuestion.questionOptions![index].id;
selectedOptionIndex = index;
notifyListeners();
}
void updateQuestionCardStatus(QuestionCardStatus status) {
if (status == QuestionCardStatus.wrongAnswer || status == QuestionCardStatus.skippedAnswer) {
updateIsUserOutOfGame = true;
if (AppState().getIsDemoMarathon) {
updateIsUserOutOfGame = true;
}
}
questionCardStatus = status;
notifyListeners();
@ -339,10 +414,31 @@ class MarathonProvider extends ChangeNotifier {
void getCorrectAnswerAndUpdateAnswerColor() {
if (selectedOptionIndex != null) {
if (currentQuestion.questionOptions![selectedOptionIndex!].isCorrectOption!) {
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.correct, selectedOptionIndex!);
} else {
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.wrong, selectedOptionIndex!);
scheduleMicrotask(() async {
if (AppState().getIsDemoMarathon) {
if (currentQuestion.questionOptions![selectedOptionIndex!].isCorrectOption!) {
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.correct, selectedOptionIndex!);
} else {
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.wrong, selectedOptionIndex!);
}
} else {
await callSubmitOptionApi().then((bool value) async {
updateIsUserOutOfGame = !value;
if (value) {
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.correct, selectedOptionIndex!);
} else {
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.wrong, selectedOptionIndex!);
}
});
}
});
} else {
if (!AppState().getIsDemoMarathon) {
scheduleMicrotask(() async {
await callSubmitOptionApi().then((bool value) async {
updateIsUserOutOfGame = !value;
});
});
}
}
}
@ -352,7 +448,16 @@ class MarathonProvider extends ChangeNotifier {
return;
}
if (selectedOptionIndex != null) {
scheduleMicrotask(() async {
await callNextQuestionApi();
});
if (selectedOptionIndex == null) {
updateQuestionCardStatus(QuestionCardStatus.skippedAnswer);
updateAnswerStatusesList(QuestionCardStatus.skippedAnswer);
return;
}
if (AppState().getIsDemoMarathon) {
if (currentQuestion.questionOptions![selectedOptionIndex!].isCorrectOption!) {
updateQuestionCardStatus(QuestionCardStatus.correctAnswer);
updateAnswerStatusesList(QuestionCardStatus.correctAnswer);
@ -360,27 +465,43 @@ class MarathonProvider extends ChangeNotifier {
updateQuestionCardStatus(QuestionCardStatus.wrongAnswer);
updateAnswerStatusesList(QuestionCardStatus.wrongAnswer);
}
} else {
updateQuestionCardStatus(QuestionCardStatus.skippedAnswer);
updateAnswerStatusesList(QuestionCardStatus.skippedAnswer);
return;
}
if (!isUserOutOfGame) {
updateQuestionCardStatus(QuestionCardStatus.correctAnswer);
updateAnswerStatusesList(QuestionCardStatus.correctAnswer);
return;
}
updateQuestionCardStatus(QuestionCardStatus.wrongAnswer);
updateAnswerStatusesList(QuestionCardStatus.wrongAnswer);
}
void resetValues() async {
_currentQuestionNumber = 0;
cardContentList.clear();
itsMarathonTime = false;
timerForWinnerSelection.cancel();
timerForSponsorVideo.cancel();
timerToWaitForMarathon.cancel();
timerForQuestion.cancel();
_isMarathonCompleted = false;
isUserOutOfGame = false;
isButtonEnabled = false;
isUserWaiting = false;
canPlayDemo = true;
totalCurrentQuestionTime = 0;
sponsorsSecondsCounter = 0;
totalSponsorVideoSeconds = 0;
totalSecondsToWaitForMarathon = 20;
totalSecondsToWaitForWinner = 30;
totalSecondsToWaitForMarathon = 30;
AppState().setIsDemoMarathon = false;
currentGapTime = 0;
currentQuestion = QuestionModel();
if (answerStatusesList.isNotEmpty) {
for (int i = 0; i < answerStatusesList.length; i++) {
answerStatusesList[i] = QuestionCardStatus.question;
}
}
notifyListeners();
}
@ -390,7 +511,6 @@ class MarathonProvider extends ChangeNotifier {
}
bool checkIfPrivilegedForMarathon() {
return true;
for (PrivilegeListModel element in AppState().privilegeListModel!) {
if (element.serviceName == "Marathon") {
if (element.previlege != null) {
@ -405,17 +525,23 @@ class MarathonProvider extends ChangeNotifier {
isLoading = true;
notifyListeners();
isPrivilegedWithMarathon = checkIfPrivilegedForMarathon();
demoMarathonDetailModel = await DemoMarathonRepo().getDemoMarathonDetails();
if (isPrivilegedWithMarathon) {
await MarathonApiClient().getMarathonToken().whenComplete(() async {
marathonDetailModel = await MarathonApiClient().getMarathonDetails();
if (marathonDetailModel.id == null) {
isUpComingMarathon = false;
isLoading = false;
notifyListeners();
return;
}
marathonDetailModel = await MarathonApiClient().getMarathonDetails();
updateTotalSecondsToWaitForMarathon = marathonDetailModel.marathonBufferTime ?? 30;
if (marathonDetailModel.id == null) {
isUpComingMarathon = false;
isLoading = false;
populateQuestionStatusesList();
});
notifyListeners();
return;
}
isUpComingMarathon = true;
if (DateTime.parse(marathonDetailModel.startTime!).isAfter(DateTime.now())) {
itsMarathonTime = false;
}
populateQuestionStatusesList();
}
isLoading = false;
notifyListeners();
@ -423,18 +549,15 @@ class MarathonProvider extends ChangeNotifier {
Future<void> onJoinMarathonPressed(BuildContext context) async {
try {
Utils.showLoading(context);
resetValues();
int? remainingTime = await MarathonApiClient().joinMarathonAsParticipant();
if (remainingTime != null) {
totalSecondsToWaitForMarathon = remainingTime;
notifyListeners();
startTimerToWaitForMarathon();
Navigator.pushReplacementNamed(context, AppRoutes.marathonWaitingScreen);
}
isUserWaiting = true;
Navigator.pushReplacementNamed(context, AppRoutes.marathonWaitingScreen);
} catch (e) {
Utils.hideLoading(context);
Utils.confirmDialog(context, e.toString());
}
}
Future<void> onJoinDemoMarathonPressed(BuildContext context) async {
AppState().setIsDemoMarathon = true;
await callNextQuestionApi();
}
}

@ -36,102 +36,188 @@ class MarathonScreen extends StatelessWidget {
}
return gapText.toText18(color: MyColors.darkTextColor, isCentered: true);
}
if (gapType == 2) {
if (gapType == 0) {
if (gapImage == null) {
return Image.asset(MyLottieConsts.congratsGif, height: 200);
}
return Image.network(gapImage, height: 200);
return Image.network(ApiConsts.marathonBaseUrlServices + gapImage, height: 200);
}
return Image.asset(MyLottieConsts.congratsGif, height: 200);
}
Widget getDemoWinnerWidget(BuildContext context, {required MarathonProvider provider}) {
return provider.isUserOutOfGame
? Column(
children: <Widget>[
Lottie.asset(MyLottieConsts.noWinnerLottie),
Center(
child: LocaleKeys.noWinner.tr().toText18(color: MyColors.grey3AColor, isCentered: true),
),
],
)
: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 50,
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50),
),
Align(
alignment: Alignment.center,
child: LocaleKeys.winner.tr().toText32(color: MyColors.white, isBold: true, isCentered: true).paddingOnly(top: 07),
)
],
),
),
16.height,
Column(
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22(
color: MyColors.grey3AColor,
isCentered: true,
),
8.height,
AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color),
],
),
60.height,
if (provider.demoMarathonDetailModel.sponsors != null && provider.demoMarathonDetailModel.sponsors!.isNotEmpty) ...<Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
"${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color),
(AppState().isArabic(context) ? provider.demoMarathonDetailModel.sponsors!.first.nameAr ?? "" : provider.demoMarathonDetailModel.sponsors!.first.nameEn ?? "").toText14(
color: MyColors.darkTextColor,
isBold: true,
),
],
),
5.height,
Image.network(
ApiConsts.marathonBaseUrlServices + provider.demoMarathonDetailModel.sponsors!.first.logo!,
height: 50,
width: 150,
fit: BoxFit.contain,
errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
return Image.asset("assets/images/logos/main_mohemm_logo.png", height: 50, width: 150);
},
)
],
],
),
Lottie.asset(MyLottieConsts.celebrate1Lottie),
],
);
}
Widget getWinnerWidget(BuildContext context, {required MarathonProvider provider}) {
return Container(
width: double.infinity,
decoration: MyDecorations.shadowDecoration,
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
child: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 50,
child: Stack(
child: (AppState().getIsDemoMarathon)
? getDemoWinnerWidget(context, provider: provider)
: provider.selectedWinners == null || (provider.selectedWinners!.isEmpty && !provider.iAmWinner)
? Column(
children: <Widget>[
Align(
alignment: Alignment.center,
child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50),
Lottie.asset(MyLottieConsts.noWinnerLottie),
Center(
child: LocaleKeys.noWinner.tr().toText18(color: MyColors.grey3AColor, isCentered: true),
),
Align(
alignment: Alignment.center,
child: LocaleKeys.winners.tr().toText32(color: MyColors.white, isBold: true, isCentered: true).paddingOnly(top: 07),
)
],
),
),
16.height,
provider.iAmWinner
? Column(
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22(
color: MyColors.grey3AColor,
isCentered: true,
),
8.height,
AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color),
],
)
: const SizedBox(),
36.height,
if (provider.selectedWinners != null) ...<Widget>[
ListView.separated(
shrinkWrap: true,
itemCount: provider.selectedWinners!.length,
separatorBuilder: (BuildContext context, int index) {
return const Divider();
},
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
)
: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
(AppState().isArabic(context) ? provider.selectedWinners![index].nameEn : provider.selectedWinners![index].nameEn)!.toText16(
color: MyColors.grey3AColor,
SizedBox(
height: 50,
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50),
),
Align(
alignment: Alignment.center,
child: ((provider.selectedWinners!.length == 1 && !provider.iAmWinner) || (provider.selectedWinners!.isEmpty && provider.iAmWinner)
? LocaleKeys.winner.tr()
: LocaleKeys.winners.tr())
.toText32(color: MyColors.white, isBold: true, isCentered: true)
.paddingOnly(top: 07),
)
],
),
),
provider.selectedWinners!.first.employeeId!.toText16(color: MyColors.grey57Color),
16.height,
provider.iAmWinner
? Column(
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22(
color: MyColors.grey3AColor,
isCentered: true,
),
8.height,
AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color),
],
)
: const SizedBox(),
36.height,
if (provider.selectedWinners != null) ...<Widget>[
ListView.separated(
shrinkWrap: true,
itemCount: provider.selectedWinners!.length,
separatorBuilder: (BuildContext context, int index) {
return const Divider();
},
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(AppState().isArabic(context) ? provider.selectedWinners![index].nameEn : provider.selectedWinners![index].nameEn)!.toText16(
color: MyColors.grey3AColor,
),
provider.selectedWinners!.first.employeeId!.toText16(color: MyColors.grey57Color),
],
);
},
),
],
60.height,
if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...<Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
"${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color),
(AppState().isArabic(context) ? provider.marathonDetailModel.sponsors!.first.nameAr ?? "" : provider.marathonDetailModel.sponsors!.first.nameEn ?? "").toText14(
color: MyColors.darkTextColor,
isBold: true,
),
],
),
5.height,
Image.network(
ApiConsts.marathonBaseUrlServices + provider.marathonDetailModel.sponsors!.first.logo!,
height: 50,
width: 150,
fit: BoxFit.contain,
errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
return Image.asset("assets/images/logos/main_mohemm_logo.png", height: 50, width: 150);
},
)
],
],
);
},
),
],
60.height,
if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...<Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
"${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color),
(AppState().isArabic(context) ? provider.marathonDetailModel.sponsors!.first.nameAr ?? "" : provider.marathonDetailModel.sponsors!.first.nameEn ?? "").toText14(
color: MyColors.darkTextColor,
isBold: true,
),
Lottie.asset(MyLottieConsts.celebrate1Lottie),
],
),
5.height,
Image.network(
ApiConsts.marathonBaseUrlServices + provider.marathonDetailModel.sponsors!.first.image!,
height: 50,
width: 150,
fit: BoxFit.contain,
errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
return const Center();
},
)
],
],
),
Lottie.asset(MyLottieConsts.celebrate1Lottie),
],
),
);
}
@ -166,6 +252,7 @@ class MarathonScreen extends StatelessWidget {
onHomeTapped: () {
if (provider.questionCardStatus == QuestionCardStatus.winnerFound) {
provider.resetValues();
provider.getMarathonDetailsFromApi();
Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard));
} else {
showDialog(
@ -174,6 +261,7 @@ class MarathonScreen extends StatelessWidget {
message: LocaleKeys.youWantToLeaveMarathon.tr(),
onTap: () {
provider.resetValues();
provider.getMarathonDetailsFromApi();
Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard));
},
),
@ -183,6 +271,7 @@ class MarathonScreen extends StatelessWidget {
onBackTapped: () {
if (provider.questionCardStatus == QuestionCardStatus.winnerFound) {
provider.resetValues();
provider.getMarathonDetailsFromApi();
Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard));
} else {
showDialog(
@ -201,8 +290,8 @@ class MarathonScreen extends StatelessWidget {
body: Column(
children: <Widget>[
ListView(
children: [
20.height,
children: <Widget>[
10.height,
if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...<Widget>[
QualifiersContainer(provider: provider).paddingOnly(left: 21, right: 21),
] else if (provider.questionCardStatus == QuestionCardStatus.winnerFound)
@ -237,7 +326,7 @@ class MarathonScreen extends StatelessWidget {
subTitle: LocaleKeys.youMissedTheQuestion.tr().toText18(color: MyColors.darkTextColor, isCentered: true),
),
onFindingWinner: (BuildContext context) => CustomStatusWidget(
asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168),
asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168, reverse: false),
title: LocaleKeys.fingersCrossed.tr().toText22(color: MyColors.greenColor),
subTitle: LocaleKeys.winnerSelectedRandomly.tr().toText18(color: MyColors.darkTextColor, isCentered: true),
),
@ -248,6 +337,7 @@ class MarathonScreen extends StatelessWidget {
provider.questionCardStatus == QuestionCardStatus.winnerFound
? DefaultButton(LocaleKeys.ok.tr(), () {
provider.resetValues();
provider.getMarathonDetailsFromApi();
Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard));
}).insideContainer
: const SizedBox()

@ -15,16 +15,16 @@ import 'package:video_player/video_player.dart';
class SponsorVideoScreen extends StatelessWidget {
const SponsorVideoScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
MarathonProvider provider = context.watch<MarathonProvider>();
MarathonProvider provider = context.read<MarathonProvider>();
return WillPopScope(
onWillPop: () {
provider.videoController.dispose();
provider.timerForSponsorVideo.cancel();
provider.videoController.pause();
provider.disposeVideoPlayer();
provider.sponsorsSecondsCounter = 0;
provider.totalSponsorVideoSeconds = 0;
provider.timerForSponsorVideo.cancel();
return Future<bool>.value(true);
},
child: Scaffold(
@ -49,47 +49,56 @@ class SponsorVideoScreen extends StatelessWidget {
borderRadius: provider.totalSponsorVideoSeconds == 0 ? null : BorderRadius.circular(15),
),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8),
child: provider.totalSponsorVideoSeconds == 0
? InkWell(
onTap: () {
provider.videoController.dispose();
provider.sponsorsSecondsCounter = 0;
provider.totalSponsorVideoSeconds = 0;
provider.timerForSponsorVideo.cancel();
Navigator.pushReplacementNamed(context, AppRoutes.marathonIntroScreen);
},
child: const Icon(Icons.close, size: 12),
)
: Directionality(
textDirection: ui.TextDirection.ltr,
child: ("${LocaleKeys.ourSponsor.tr()} ${provider.totalSponsorVideoSeconds < 10 ? "0" : ""}${provider.totalSponsorVideoSeconds}").toText12(color: MyColors.darkTextColor),
),
child: Consumer<MarathonProvider>(
builder: (BuildContext context, MarathonProvider provider, Widget? child) {
return provider.totalSponsorVideoSeconds == 0
? InkWell(
onTap: () {
Navigator.pushReplacementNamed(context, AppRoutes.marathonIntroScreen);
provider.videoController.pause();
provider.disposeVideoPlayer();
provider.sponsorsSecondsCounter = 0;
provider.totalSponsorVideoSeconds = 0;
provider.timerForSponsorVideo.cancel();
},
child: const Icon(Icons.close, size: 12),
)
: Directionality(
textDirection: ui.TextDirection.ltr,
child: ("${LocaleKeys.ourSponsor.tr()} ${provider.totalSponsorVideoSeconds < 10 ? "0" : ""}${provider.totalSponsorVideoSeconds}").toText12(color: MyColors.darkTextColor),
);
},
),
),
).paddingOnly(top: 20, right: 18),
//TODO: WE WILL INCREASE THIS 2 BEFORE GOING LIVE
provider.sponsorsSecondsCounter >= 2
? Align(
alignment: Alignment.topLeft,
child: InkWell(
onTap: () {
provider.videoController.dispose();
provider.sponsorsSecondsCounter = 0;
provider.totalSponsorVideoSeconds = 0;
provider.timerForSponsorVideo.cancel();
Navigator.pushReplacementNamed(context, AppRoutes.marathonIntroScreen);
},
child: Container(
decoration: BoxDecoration(color: MyColors.white, borderRadius: BorderRadius.circular(15)),
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 6),
child: Directionality(
textDirection: ui.TextDirection.ltr,
child: LocaleKeys.skip.tr().toText11(color: MyColors.darkTextColor),
Consumer<MarathonProvider>(
builder: (BuildContext context, MarathonProvider provider, Widget? child) {
//TODO: WE WILL INCREASE THIS 2 BEFORE GOING LIVE
return provider.sponsorsSecondsCounter >= 2
? Align(
alignment: Alignment.topLeft,
child: InkWell(
onTap: () {
Navigator.pushReplacementNamed(context, AppRoutes.marathonIntroScreen);
provider.videoController.pause();
provider.disposeVideoPlayer();
provider.sponsorsSecondsCounter = 0;
provider.totalSponsorVideoSeconds = 0;
provider.timerForSponsorVideo.cancel();
},
child: Container(
decoration: BoxDecoration(color: MyColors.white, borderRadius: BorderRadius.circular(15)),
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 6),
child: Directionality(
textDirection: ui.TextDirection.ltr,
child: LocaleKeys.skip.tr().toText11(color: MyColors.darkTextColor),
),
),
),
),
),
).paddingOnly(top: 20, left: 18)
: const SizedBox(),
).paddingOnly(top: 20, left: 18)
: const SizedBox();
},
),
],
),
),

@ -80,24 +80,24 @@ class MarathonWaitingScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LocaleKeys.startingIn.tr().toText16(),
provider.totalSecondsToWaitForMarathon.toString().toText18(color: provider.totalSecondsToWaitForMarathon < 5 ? MyColors.redColor : MyColors.black),
],
),
),
Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
InkWell(
onTap: () {
provider.callNextQuestionApi();
provider.timerToWaitForMarathon.cancel();
},
child: "Join Now".toText16(),
).paddingOnly(bottom: 20),
(provider.totalSecondsToWaitForMarathon < 10 ? "0${provider.totalSecondsToWaitForMarathon.toString()}" : provider.totalSecondsToWaitForMarathon.toString()).toText18(color: provider.totalSecondsToWaitForMarathon < 5 ? MyColors.redColor : MyColors.black),
],
),
),
// Align(
// child: Column(
// mainAxisAlignment: MainAxisAlignment.end,
// children: <Widget>[
// InkWell(
// onTap: () {
// provider.callNextQuestionApi();
// provider.timerToWaitForMarathon.cancel();
// },
// child: "Join Now".toText16(),
// ).paddingOnly(bottom: 20),
// ],
// ),
// ),
],
),
).expanded,

@ -0,0 +1,212 @@
import 'dart:async';
import 'dart:ui' as ui;
import 'package:auto_size_text/auto_size_text.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_countdown_timer/current_remaining_time.dart';
import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
class CountdownTimerForDetailScreen extends StatelessWidget {
final int timeToMarathon;
final MarathonProvider provider;
CountdownTimerForDetailScreen({
Key? key,
required this.provider,
required this.timeToMarathon,
}) : 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,
color: MyColors.white,
fontSize: isTablet ? 30 : 15,
fontStyle: FontStyle.italic,
letterSpacing: -1.44,
fontWeight: FontWeight.bold,
);
final TextStyle styleTextMarathon = const TextStyle(
fontSize: 10,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.w600,
color: MyColors.grey57Color,
letterSpacing: -0.4,
);
final TextStyle styleDigitMarathon = const TextStyle(
height: 23 / 24,
color: MyColors.darkTextColor,
fontSize: 34,
letterSpacing: -1.44,
fontWeight: FontWeight.bold,
);
Widget buildSeparator() {
return AutoSizeText(
" : ",
maxFontSize: 24,
minFontSize: 20,
style: styleDigitMarathon,
);
}
Widget getTimeDigit(String text) {
return AutoSizeText(
text,
maxFontSize: 24,
minFontSize: 20,
style: styleDigitMarathon,
);
}
Widget getTimeText(String text) {
return AutoSizeText(
text,
minFontSize: 7,
maxFontSize: 8,
style: styleTextMarathon,
);
}
Widget buildEmptyWidget() {
return Directionality(
textDirection: ui.TextDirection.ltr,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
children: <Widget>[
getTimeDigit("00"),
getTimeText(LocaleKeys.days.tr()),
],
),
buildSeparator(),
Column(
children: <Widget>[
getTimeDigit("00"),
getTimeText(LocaleKeys.hours.tr()),
],
),
buildSeparator(),
Column(
children: <Widget>[
getTimeDigit("00"),
getTimeText(LocaleKeys.minutes.tr()),
],
),
buildSeparator(),
Column(
children: <Widget>[
getTimeDigit("00"),
getTimeText(LocaleKeys.seconds.tr()),
],
),
],
),
);
}
Widget buildCountdownTimer(CurrentRemainingTime? time) {
if (provider.marathonDetailModel.startTime != null) {
int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes;
if (remainingTimeInMinutes <= 30) {
scheduleMicrotask(() {
provider.canPlayDemo = false;
});
}
}
if (time == null) {
if (!provider.itsMarathonTime) {
scheduleMicrotask(() {
provider.itsMarathonTime = true;
provider.isButtonEnabled = true;
provider.startTimerToWaitForMarathon();
});
}
return provider.itsMarathonTime
? Directionality(
textDirection: ui.TextDirection.ltr,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
children: <Widget>[
getTimeDigit(provider.totalSecondsToWaitForMarathon.toString()),
getTimeText(LocaleKeys.seconds.tr()),
],
),
],
),
)
: buildEmptyWidget();
}
return Directionality(
textDirection: ui.TextDirection.ltr,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
children: <Widget>[
time.days == null ? getTimeDigit("00") : getTimeDigit(time.days! < 10 ? "0${time.days.toString()}" : time.days.toString()),
getTimeText(LocaleKeys.days.tr()),
],
),
buildSeparator(),
Column(
children: <Widget>[
time.hours == null ? getTimeDigit("00") : getTimeDigit(time.hours! < 10 ? "0${time.hours.toString()}" : time.hours.toString()),
getTimeText(LocaleKeys.hours.tr()),
],
),
buildSeparator(),
Column(
children: <Widget>[
time.min == null ? getTimeDigit("00") : getTimeDigit(time.min! < 10 ? "0${time.min.toString()}" : time.min.toString()),
getTimeText(LocaleKeys.minutes.tr()),
],
),
buildSeparator(),
Column(
children: <Widget>[
time.sec == null ? getTimeDigit("00") : getTimeDigit(time.sec! < 10 ? "0${time.sec.toString()}" : time.sec.toString()),
getTimeText(LocaleKeys.seconds.tr()),
],
),
],
),
);
}
@override
Widget build(BuildContext context) {
return CountdownTimer(
// endTime: dummyTime,
endTime: timeToMarathon,
onEnd: null,
widgetBuilder: (BuildContext context, CurrentRemainingTime? time) {
return buildCountdownTimer(time);
},
);
}
}

@ -1,4 +1,3 @@
import 'dart:async';
import 'dart:ui' as ui;
import 'package:auto_size_text/auto_size_text.dart';
@ -11,16 +10,14 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
class BuildCountdownTimer extends StatelessWidget {
class CountdownTimerForMainScreen extends StatelessWidget {
final int timeToMarathon;
final MarathonProvider provider;
final int screenFlag;
BuildCountdownTimer({
CountdownTimerForMainScreen({
Key? key,
required this.provider,
required this.timeToMarathon,
required this.screenFlag,
}) : super(key: key);
final TextStyle styleTextHome = TextStyle(
@ -60,7 +57,7 @@ class BuildCountdownTimer extends StatelessWidget {
" : ",
maxFontSize: 24,
minFontSize: 20,
style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon,
style: styleDigitHome,
);
}
@ -69,7 +66,7 @@ class BuildCountdownTimer extends StatelessWidget {
text,
maxFontSize: 24,
minFontSize: 20,
style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon,
style: styleDigitHome,
);
}
@ -78,7 +75,7 @@ class BuildCountdownTimer extends StatelessWidget {
text,
minFontSize: 7,
maxFontSize: 8,
style: screenFlag == 0 ? styleTextHome : styleTextMarathon,
style: styleTextHome,
);
}
@ -124,14 +121,9 @@ class BuildCountdownTimer extends StatelessWidget {
Widget buildCountdownTimer(CurrentRemainingTime? time) {
if (time == null) {
if (!provider.itsMarathonTime) {
scheduleMicrotask(() {
provider.itsMarathonTime = true;
});
}
return buildEmptyWidget();
}
return Directionality(
textDirection: ui.TextDirection.ltr,
child: Row(

@ -1,3 +1,4 @@
import 'dart:developer';
import 'dart:math' as math;
import 'package:easy_localization/easy_localization.dart';
@ -10,17 +11,19 @@ import 'package:mohem_flutter_app/classes/decorations_helper.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/ui/marathon/marathon_provider.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer_main_screen.dart';
import 'package:provider/provider.dart';
class MarathonBanner extends StatelessWidget {
final bool isMarathonUpcoming;
// It is used to pass a dummy time to test Marathon
int dummyTime = DateTime.now().millisecondsSinceEpoch + 8690;
const MarathonBanner({Key? key, required this.isMarathonUpcoming}) : super(key: key);
class MarathonBanner extends StatelessWidget {
const MarathonBanner({Key? key}) : super(key: key);
Widget getUnPrivilegedMarathon(BuildContext context) {
return Container(
@ -180,13 +183,174 @@ class MarathonBanner extends StatelessWidget {
);
}
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: <Widget>[
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: <Widget>[
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: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
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) {
MarathonProvider provider = context.read<MarathonProvider>();
return provider.isPrivilegedWithMarathon
return !provider.isPrivilegedWithMarathon
? getUnPrivilegedMarathon(context)
: provider.marathonDetailModel.startTime != null
: provider.isUpComingMarathon
? Container(
decoration: MyDecorations.shadowDecoration,
height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11,
@ -265,21 +429,23 @@ class MarathonBanner extends StatelessWidget {
letterSpacing: -0.4,
),
),
Text(
AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "",
style: TextStyle(
fontStyle: FontStyle.italic,
fontSize: isTablet ? 30 : 19,
fontWeight: FontWeight.bold,
color: MyColors.white.withOpacity(0.83),
height: 32 / 22,
Flexible(
child: Text(
(AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "").trimString(15),
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontStyle: FontStyle.italic,
fontSize: isTablet ? 30 : 19,
fontWeight: FontWeight.bold,
color: MyColors.white.withOpacity(0.83),
height: 32 / 22,
),
),
),
isTablet ? 10.height : 3.height,
BuildCountdownTimer(
CountdownTimerForMainScreen(
timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch,
provider: provider,
screenFlag: 0,
),
],
).paddingOnly(
@ -357,7 +523,7 @@ class MarathonBanner extends StatelessWidget {
).onPress(() async {
int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes;
if (remainingTimeInMinutes > 2) {
if (remainingTimeInMinutes > 5 && provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) {
Utils.showLoading(context);
try {
await provider.initializeVideoPlayer().then((_) {
@ -367,7 +533,7 @@ class MarathonBanner extends StatelessWidget {
});
} catch (e) {
if (kDebugMode) {
print("Error in VideoPlayer: ${e.toString()}");
log("Error in VideoPlayer: ${e.toString()}");
}
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen);
@ -376,8 +542,7 @@ class MarathonBanner extends StatelessWidget {
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen);
}
}),
// );
)
: const SizedBox();
: getNoUpcomingMarathonWidget(context);
}
}

@ -6,72 +6,96 @@ 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/models/marathon/marathon_model.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
import 'package:provider/provider.dart';
class MarathonDetailsCard extends StatelessWidget {
final MarathonProvider provider;
final MarathonDetailModel marathonDetailModel;
const MarathonDetailsCard({Key? key, required this.provider}) : super(key: key);
const MarathonDetailsCard({Key? key, required this.marathonDetailModel}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
decoration: MyDecorations.shadowDecoration,
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 14),
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 14),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey77Color),
"${AppState().isArabic(context) ? provider.marathonDetailModel.titleAr : provider.marathonDetailModel.titleEn}".toText20(color: MyColors.textMixColor, isBold: true),
Row(
children: <Widget>[
Flexible(
child: "${AppState().isArabic(context) ? provider.marathonDetailModel.descAr : provider.marathonDetailModel.descEn}".toText14(color: MyColors.grey77Color),
)
],
),
if (provider.marathonDetailModel.sponsors != null) ...<Widget>[
5.height,
provider.marathonDetailModel.sponsors?.first.sponsorPrizes != null
? Row(
children: <Widget>[
"${LocaleKeys.prize.tr()} ".toText16(color: MyColors.grey77Color, isBold: true),
"${AppState().isArabic(context) ? provider.marathonDetailModel.sponsors?.first.sponsorPrizes?.first.marathonPrizeAr : provider.marathonDetailModel.sponsors?.first.sponsorPrizes?.first.marathonPrizeAr}"
.toText16(color: MyColors.greenColor, isBold: true),
],
)
: const SizedBox(),
Row(
children: <Widget>[
"${LocaleKeys.sponsoredBy.tr()} ".toText16(color: MyColors.grey77Color),
"${AppState().isArabic(context) ? provider.marathonDetailModel.sponsors?.first.nameAr : provider.marathonDetailModel.sponsors?.first.nameEn}"
.toText16(color: MyColors.darkTextColor, isBold: true),
],
),
10.height,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
ApiConsts.marathonBaseUrlServices + provider.marathonDetailModel.sponsors!.first.image!,
height: 50,
width: 150,
fit: BoxFit.contain,
errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
return const Center();
},
)
context.read<MarathonProvider>().isUpComingMarathon
? const SizedBox()
: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration: BoxDecoration(color: MyColors.yellowColorII, borderRadius: BorderRadius.circular(100)),
child: LocaleKeys.demo.tr().toText10(color: MyColors.white).paddingAll(4),
),
],
),
]
7.height,
LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey77Color),
"${AppState().isArabic(context) ? marathonDetailModel.titleAr : marathonDetailModel.titleEn}".toText20(color: MyColors.textMixColor, isBold: true),
Row(
children: <Widget>[
Flexible(
child: "${AppState().isArabic(context) ? marathonDetailModel.descAr : marathonDetailModel.descEn}".toText14(color: MyColors.grey77Color),
)
],
),
if (marathonDetailModel.sponsors != null && marathonDetailModel.sponsors!.isNotEmpty) ...<Widget>[
5.height,
marathonDetailModel.sponsors!.first.sponsorPrizes != null
? Row(
children: <Widget>[
"${LocaleKeys.prize.tr()} ".toText16(color: MyColors.grey77Color, isBold: true),
Expanded(
child: SizedBox(
height: 30,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: marathonDetailModel.sponsors!.first.sponsorPrizes!.length,
itemBuilder: (BuildContext context, int index) {
SponsorPrizes prizes = marathonDetailModel.sponsors!.first.sponsorPrizes![index];
return Container(
decoration: BoxDecoration(color: MyColors.backgroundColor, borderRadius: BorderRadius.circular(100), border: Border.all(color: MyColors.grey57Color.withOpacity(0.1))),
child: "${AppState().isArabic(context) ? prizes.marathonPrizeAr : prizes.marathonPrizeEn}"
.toText16(color: MyColors.greenColor, isBold: true)
.paddingOnly(left: 5, right: 5),
).paddingOnly(left: 5);
}),
),
)
],
)
: const SizedBox(),
Row(
children: <Widget>[
"${LocaleKeys.sponsoredBy.tr()} ".toText16(color: MyColors.grey77Color),
"${AppState().isArabic(context) ? marathonDetailModel.sponsors?.first.nameAr : marathonDetailModel.sponsors?.first.nameEn}".toText16(color: MyColors.darkTextColor, isBold: true),
],
),
10.height,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
ApiConsts.marathonBaseUrlServices + marathonDetailModel.sponsors!.first.logo!,
height: 50,
width: 150,
fit: BoxFit.contain,
errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
return Image.asset("assets/images/logos/main_mohemm_logo.png", height: 50, width: 150);
},
)
],
),
]
],
),
);

@ -41,9 +41,15 @@ class MarathonFooter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultButton(
LocaleKeys.joinMarathon.tr(),
!provider.itsMarathonTime ? () => provider.onJoinMarathonPressed(context) : null,
).insideContainer;
return provider.isUpComingMarathon && !provider.canPlayDemo
? DefaultButton(
LocaleKeys.joinMarathon.tr(),
provider.isButtonEnabled ? () => provider.onJoinMarathonPressed(context) : null,
).insideContainer
: DefaultButton(
LocaleKeys.joinDemoMarathon.tr(),
() => provider.onJoinDemoMarathonPressed(context),
color: MyColors.yellowColorII,
).insideContainer;
}
}

@ -1,5 +1,6 @@
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/decorations_helper.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
@ -14,37 +15,67 @@ class MarathonProgressContainer extends StatelessWidget {
const MarathonProgressContainer({Key? key, required this.provider}) : super(key: key);
Widget getDemoMarathonerText() {
if (provider.isUserOutOfGame) {
return "0 ${LocaleKeys.marathoner.tr()}".toText14();
}
return "1 ${LocaleKeys.marathoner.tr()}".toText14();
}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
decoration: MyDecorations.shadowDecoration,
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 13),
padding: EdgeInsets.fromLTRB(13, AppState().getIsDemoMarathon ? 5 : 18, 13, 18),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
AppState().getIsDemoMarathon
? Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration: BoxDecoration(color: MyColors.yellowColorII, borderRadius: BorderRadius.circular(100)),
child: LocaleKeys.demo.tr().toText10(color: MyColors.white).paddingAll(4),
),
],
)
: const SizedBox(),
5.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
decoration: BoxDecoration(color: MyColors.greenColor, borderRadius: BorderRadius.circular(5)),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8),
child: "${provider.currentQuestionNumber.toString()} / ${provider.marathonDetailModel.totalQuestions.toString()} ${LocaleKeys.question.tr()}".toText12(color: MyColors.white),
child:
"${provider.currentQuestionNumber.toString()} / ${AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.totalQuestions.toString() : provider.marathonDetailModel.totalQuestions.toString()} ${LocaleKeys.question.tr()}"
.toText12(color: MyColors.white),
),
"${provider.totalMarathoners} ${LocaleKeys.marathoners.tr()}".toText14(),
AppState().getIsDemoMarathon
? getDemoMarathonerText()
: "${provider.totalMarathoners} ${provider.totalMarathoners == 1 ? LocaleKeys.marathoner.tr() : LocaleKeys.marathoners.tr()}".toText14(),
provider.questionCardStatus == QuestionCardStatus.question
? "00:${(provider.totalCurrentQuestionTime - provider.currentGapTime) < 10 ? "0${provider.totalCurrentQuestionTime - provider.currentGapTime}" : provider.totalCurrentQuestionTime - provider.currentGapTime}"
? "00:${provider.totalCurrentQuestionTime - provider.currentGapTime < 0 ? "00" : (provider.totalCurrentQuestionTime - provider.currentGapTime) < 10 ? "0${provider.totalCurrentQuestionTime - provider.currentGapTime}" : provider.totalCurrentQuestionTime - provider.currentGapTime}"
.toText18(color: provider.totalCurrentQuestionTime - provider.currentGapTime < 5 ? MyColors.redColor : MyColors.black)
: const SizedBox(),
],
),
12.height,
stepper(provider.currentQuestionNumber, provider.answerStatusesList, provider.marathonDetailModel.totalQuestions!, provider.isUserOutOfGame),
stepper(
provider.currentQuestionNumber,
provider.answerStatusesList,
AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.totalQuestions! : provider.marathonDetailModel.totalQuestions!,
provider.isUserOutOfGame,
),
8.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
"${provider.currentQuestionNumber == 1 ? 0 : (((provider.currentQuestionNumber - 1) / provider.marathonDetailModel.totalQuestions!) * 100).toInt()}% ${LocaleKeys.completed.tr()}"
"${provider.currentQuestionNumber == 1 ? 0 : (((provider.currentQuestionNumber - 1) / (AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.totalQuestions! : provider.marathonDetailModel.totalQuestions!)) * 100).toInt()}% ${LocaleKeys.completed.tr()}"
.toText14(),
provider.isUserOutOfGame ? LocaleKeys.youAreOutOfContest.tr().toText13(color: MyColors.redColor) : const SizedBox(),
],
),
],
@ -93,21 +124,28 @@ class MarathonProgressContainer extends StatelessWidget {
Widget roundContainer(Color color, bool isNeedLeftBorder) {
if (isNeedLeftBorder) {
return Row(
children: [
Divider(thickness: 6, color: color).expanded,
children: <Widget>[
Divider(
thickness: 6,
color: color,
).expanded,
Container(
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
width: 10,
height: 10,
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
decoration: BoxDecoration(shape: BoxShape.circle, color: color, border: Border.all(color: color, width: 2)),
),
],
).expanded;
}
return Container(
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
width: 10,
height: 10,
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
decoration: BoxDecoration(shape: BoxShape.circle, color: color, border: Border.all(color: color, width: 2)),
);
}
}

@ -1,7 +1,9 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/decorations_helper.dart';
import 'package:mohem_flutter_app/classes/lottie_consts.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';
@ -20,7 +22,6 @@ class _QualifiersContainerState extends State<QualifiersContainer> {
@override
void initState() {
widget.provider.startTimerForWinnerSelection();
widget.provider.callGetSelectedWinnersApi();
super.initState();
}
@ -42,14 +43,23 @@ class _QualifiersContainerState extends State<QualifiersContainer> {
],
),
10.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
widget.provider.totalQualifiers != null ? widget.provider.totalQualifiers.toString().toText30(color: MyColors.greenColor, isBold: true) : const SizedBox(),
2.width,
LocaleKeys.qualifiers.tr().toText16(color: MyColors.greenColor),
],
),
widget.provider.isGettingQualifiers
? Container(
alignment: Alignment.centerLeft,
child: Lottie.asset(
MyLottieConsts.loadingLottie,
width: 60,
fit: BoxFit.fill,
),
)
: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
widget.provider.totalQualifiers != null ? widget.provider.totalQualifiers.toString().toText30(color: MyColors.greenColor, isBold: true) : const SizedBox(),
2.width,
(widget.provider.totalQualifiers == 1 ? LocaleKeys.qualifier.tr() : LocaleKeys.qualifiers.tr()).toText16(color: MyColors.greenColor),
],
),
],
),
);

@ -9,7 +9,8 @@ import 'package:mohem_flutter_app/classes/lottie_consts.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/ui/marathon/marathon_provider.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer_detail_screen.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_banner.dart';
class MarathonTimerCard extends StatelessWidget {
@ -43,7 +44,11 @@ class MarathonTimerCard extends StatelessWidget {
],
),
Lottie.asset(MyLottieConsts.hourGlassLottie, height: 200),
BuildCountdownTimer(timeToMarathon: timeToMarathon, provider: provider, screenFlag: 1),
CountdownTimerForDetailScreen(
// timeToMarathon: dummyTime,
timeToMarathon: timeToMarathon,
provider: provider,
),
],
),
);

@ -65,7 +65,6 @@ class CardContent extends StatelessWidget {
child: Column(
children: <Widget>[
Container(
height: 78,
width: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
@ -84,9 +83,9 @@ class CardContent extends StatelessWidget {
),
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 13),
padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 15),
child: Text(
AppState().isArabic(context) ? provider.currentQuestion.titleAr ?? "" : provider.currentQuestion.titleEn ?? "",
AppState().isArabic(context) ? "${provider.currentQuestion.titleAr}" ?? "" : provider.currentQuestion.titleEn ?? "",
style: const TextStyle(
color: MyColors.white,
fontSize: 16,
@ -110,7 +109,7 @@ class AnswerContent extends StatelessWidget {
Widget build(BuildContext context) {
MarathonProvider provider = context.watch<MarathonProvider>();
return Container(
padding: const EdgeInsets.symmetric(vertical: 31, horizontal: 13),
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 13),
decoration: const BoxDecoration(
color: MyColors.kWhiteColor,
borderRadius: BorderRadius.only(
@ -126,7 +125,11 @@ class AnswerContent extends StatelessWidget {
return AnswerTileForText(
index: index,
onAnswerTapped: () {
provider.updateCurrentQuestionOptionStatus(QuestionsOptionStatus.selected, index);
if (provider.totalCurrentQuestionTime - provider.currentGapTime <= 1) {
null;
} else {
provider.updateCurrentQuestionOptionStatus(QuestionsOptionStatus.selected, index);
}
},
);
},
@ -169,7 +172,7 @@ class AnswerTileForText extends StatelessWidget {
child: Center(
child: (AppState().isArabic(context) ? provider.currentQuestion.questionOptions![index].titleAr! : provider.currentQuestion.questionOptions![index].titleEn!)
.toText16(color: provider.isUserOutOfGame ? MyColors.darkTextColor : getAnswerTextColor(provider.currentQuestion.questionOptions![index].optionStatus!))
.paddingOnly(top: 17, bottom: 17),
.paddingOnly(top: 13, bottom: 13),
),
),
);

@ -1,93 +0,0 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:lottie/lottie.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/decorations_helper.dart';
import 'package:mohem_flutter_app/classes/lottie_consts.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/widgets/app_bar_widget.dart';
class WinnerScreen extends StatelessWidget {
const WinnerScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyColors.backgroundColor,
appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
60.height,
Container(
width: double.infinity,
decoration: MyDecorations.shadowDecoration,
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
child: Column(
children: <Widget>[
SizedBox(
height: 200,
child: Stack(
children: <Widget>[
Lottie.asset(
MyLottieConsts.celebrate1Lottie,
height: 200,
),
Lottie.asset(
MyLottieConsts.celebrate2Lottie,
height: 200,
),
],
),
),
26.height,
SizedBox(
height: 50,
child: Stack(
children: [
Align(
alignment: Alignment.center,
child: SvgPicture.asset(
"assets/images/winner_ribbon.svg",
height: 50,
),
),
Align(
alignment: Alignment.center,
child: "WINNER".toText32(color: MyColors.white, isBold: true).paddingOnly(top: 07),
)
],
),
),
12.height,
"Muhammad Shrouff".toText22(color: MyColors.grey3AColor),
"837436".toText22(color: MyColors.grey57Color),
80.height,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LocaleKeys.sponsoredBy.tr().toText14(color: MyColors.grey77Color),
" Extra".toText14(color: MyColors.darkTextColor, isBold: true),
],
),
5.height,
Image.asset(
"assets/images/logos/main_mohemm_logo.png",
height: 40,
fit: BoxFit.fill,
width: 150,
)
],
),
).paddingOnly(left: 21, right: 21),
10.height,
],
),
),
);
}
}

@ -1,8 +1,6 @@
import 'dart:convert';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:file_picker/file_picker.dart';
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';
@ -58,6 +56,7 @@ class _RequestSubmitScreenState extends State<RequestSubmitScreen> {
@override
void initState() {
super.initState();
AppState().cancelRequestTrancsection = true;
}
void getApproverList() async {
@ -138,9 +137,9 @@ class _RequestSubmitScreenState extends State<RequestSubmitScreen> {
params!.transactionId,
);
} else {}
Utils.hideLoading(context);
Utils.showToast(LocaleKeys.yourRequestHasBeenSubmittedForApprovals.tr(), longDuration: true);
AppState().cancelRequestTrancsection = false;
Navigator.of(context).popUntil((route) => route.settings.name == AppRoutes.dashboard);
Navigator.pushNamed(context, AppRoutes.workList);
} catch (ex) {
@ -262,7 +261,7 @@ class _RequestSubmitScreenState extends State<RequestSubmitScreen> {
title.toText16().expanded,
6.width,
SimpleButton(LocaleKeys.add.tr(), () async {
ImageOptions.showImageOptionsNew(context, false, (String image, File file) {
ImageOptions.showImageOptionsNew(context, true, (String image, File file) {
setState(() {
attachmentFiles.add(file);
attachments.add(image);

@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
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/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
@ -95,6 +96,9 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
Utils.hideLoading(context);
await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit'));
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(submitEITTransactionList.pTRANSACTIONID!);
Utils.hideLoading(context);
@ -189,7 +193,8 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
// Utils.hideLoading(context);
}
} else if (values.isNotEmpty) {
ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values, empID: dynamicParams!.selectedEmp);
ESERVICESDV defaultValue =
await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values, empID: dynamicParams!.selectedEmp);
int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId);
getEitDffStructureList![index].eSERVICESDV = defaultValue;
}

@ -1,11 +1,16 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/leave_balance_api_client.dart';
import 'package:mohem_flutter_app/api/profile_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/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/dyanmic_forms/validate_eit_transaction_model.dart';
@ -17,11 +22,16 @@ import 'package:mohem_flutter_app/models/profile/get_contact_details_list.dart';
import 'package:mohem_flutter_app/models/profile/submit_contact_transaction_list_model.dart';
import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
import 'package:easy_localization/src/public_ext.dart';
class FamilyMemberScreenParams {
String? actionType;
int relationID;
int? flag;
FamilyMemberScreenParams(this.relationID, {this.actionType, this.flag});
}
class AddUpdateFamilyMember extends StatefulWidget {
const AddUpdateFamilyMember({Key? key}) : super(key: key);
@ -36,10 +46,12 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
List<GetContactDffStructureList?> getContactDffStructureList = [];
List<GetContactDetailsList?> getContactDetailsList = [];
SubmitContactTransactionList? submitContactTransactionList;
dynamic args;
//dynamic args;
FamilyMemberScreenParams? params;
String? date = "MM/DD/YYYY";
var dateTime = DateTime.now().timeZoneOffset;
var dateTime1 = DateTime.now().timeZoneName;
Duration dateTime = DateTime.now().timeZoneOffset;
String dateTime1 = DateTime.now().timeZoneName;
GetApprovesList? getApprovesList;
@ -52,9 +64,9 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
try {
Utils.showLoading(context);
getBasicDetDffStructureList = await ProfileApiClient().getBasicDetDffStructure();
getContactColsStructureList = await ProfileApiClient().getContactColsStructureList(args['actionType']);
getContactColsStructureList = await ProfileApiClient().getContactColsStructureList(params!.actionType.toString());
getContactDffStructureList = await ProfileApiClient().getContactDffStructureList();
if (args['actionType'] == "ADD") {
if (params!.actionType == "ADD") {
getBasicDetDffStructureList?.forEach((element) {
element?.getContactDetailsList = new GetContactDetailsList();
});
@ -64,8 +76,8 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
getContactDffStructureList?.forEach((element) {
element?.getContactDetailsList = new GetContactDetailsList();
});
} else if (args['actionType'] == "UPDATE") {
getContactDetailsList = await ProfileApiClient().getContactDetailsList(args['relationID']);
} else if (params!.actionType == "UPDATE") {
getContactDetailsList = await ProfileApiClient().getContactDetailsList(params!.relationID);
getBasicDetDffStructureList?.forEach((element) {
element?.getContactDetailsList = getContactDetailsList?.singleWhere((userDetail) => userDetail?.aPPLICATIONCOLUMNNAME == element?.aPPLICATIONCOLUMNNAME);
@ -88,8 +100,8 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
@override
Widget build(BuildContext context) {
if (args == null) {
args = ModalRoute.of(context)!.settings.arguments;
if (params == null) {
params = ModalRoute.of(context)!.settings.arguments as FamilyMemberScreenParams;
callAddAndUpdateFamilyMember();
}
return Scaffold(
@ -98,45 +110,48 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
title: LocaleKeys.profile_familyDetails.tr(),
),
backgroundColor: MyColors.backgroundColor,
body: args['flag'] == 1
body: params!.flag == 1
? Column(
children: [
ListView(physics: const BouncingScrollPhysics(), padding: const EdgeInsets.all(21), children: [
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeCols(getContactColsStructureList![parentIndex], parentIndex);
},
separatorBuilder: (cxt, index) => 0.height,
itemCount: getContactColsStructureList!.length),
12.height,
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeBasicDetDff(getBasicDetDffStructureList![parentIndex], parentIndex);
},
separatorBuilder: (cxt, index) => 0.height,
itemCount: getBasicDetDffStructureList!.length),
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeContactDff(getContactDffStructureList![parentIndex], parentIndex);
},
separatorBuilder: (cxt, index) => 0.height,
itemCount: getContactDffStructureList!.length),
]).expanded,
ListView(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(21),
children: [
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeCols(getContactColsStructureList![parentIndex], parentIndex);
},
separatorBuilder: (BuildContext cxt, int index) => 0.height,
itemCount: getContactColsStructureList!.length),
12.height,
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeBasicDetDff(getBasicDetDffStructureList![parentIndex], parentIndex);
},
separatorBuilder: (BuildContext cxt, int index) => 0.height,
itemCount: getBasicDetDffStructureList!.length),
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeContactDff(getContactDffStructureList![parentIndex], parentIndex);
},
separatorBuilder: (BuildContext cxt, int index) => 0.height,
itemCount: getContactDffStructureList!.length),
],
).expanded,
DefaultButton(LocaleKeys.next.tr(), () async {
submitUpdateForm();
}).insideContainer,
],
)
: args['flag'] == 2
: params!.flag == 2
? Column(
children: [
// getContactDetailsList!.isEmpty
ListView(physics: const BouncingScrollPhysics(), padding: const EdgeInsets.all(21), children: [
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
@ -144,7 +159,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeCols(getContactColsStructureList![parentIndex], parentIndex);
},
separatorBuilder: (cxt, index) => 0.height,
separatorBuilder: (BuildContext cxt, int index) => 0.height,
itemCount: getContactColsStructureList!.length),
12.height,
ListView.separated(
@ -153,7 +168,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeBasicDetDff(getBasicDetDffStructureList![parentIndex], parentIndex);
},
separatorBuilder: (cxt, index) => 0.height,
separatorBuilder: (BuildContext cxt, int index) => 0.height,
itemCount: getBasicDetDffStructureList!.length),
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
@ -161,7 +176,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
itemBuilder: (BuildContext cxt, int parentIndex) {
return parseDynamicFormatTypeContactDff(getContactDffStructureList![parentIndex], parentIndex);
},
separatorBuilder: (cxt, index) => 0.height,
separatorBuilder: (BuildContext cxt, int index) => 0.height,
itemCount: getContactDffStructureList!.length),
]).expanded,
DefaultButton(LocaleKeys.next.tr(), () async {
@ -181,27 +196,27 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
if (model.dATATYPE == "VARCHAR2") {
if (model!.objectValuesList?.isNotEmpty ?? false) {
return PopupMenuButton(
child: DynamicTextFieldWidget(
(model!.sEGMENTPROMPT ?? "") + (model!.rEQUIREDFLAG == "Y" ? "*" : ""),
model!.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isEnable: false,
isPopup: true,
).paddingOnly(bottom: 12),
itemBuilder: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < getContactColsStructureList[index]!.objectValuesList!.length; i++)
PopupMenuItem<int>(child: Text(getContactColsStructureList[index]!.objectValuesList![i].mEANING.toString()), value: i),
],
onSelected: (int popupIndex) {
model.getContactDetailsList!.sEGMENTVALUEDSP = getContactColsStructureList[index]!.objectValuesList![popupIndex].mEANING.toString();
model.getContactDetailsList!.vARCHAR2VALUE = getContactColsStructureList[index]!.objectValuesList![popupIndex].cODE.toString();
setState(() {});
});
child: DynamicTextFieldWidget(
(model!.sEGMENTPROMPT ?? "") + (model!.rEQUIREDFLAG == "Y" ? "*" : ""),
model!.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isEnable: false,
isPopup: true,
).paddingOnly(bottom: 12),
itemBuilder: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < getContactColsStructureList[index]!.objectValuesList!.length; i++)
PopupMenuItem<int>(child: Text(getContactColsStructureList[index]!.objectValuesList![i].mEANING.toString()), value: i),
],
onSelected: (int popupIndex) {
model.getContactDetailsList!.sEGMENTVALUEDSP = getContactColsStructureList[index]!.objectValuesList![popupIndex].mEANING.toString();
model.getContactDetailsList!.vARCHAR2VALUE = getContactColsStructureList[index]!.objectValuesList![popupIndex].cODE.toString();
setState(() {});
},
);
} else {
return DynamicTextFieldWidget(
(model!.sEGMENTPROMPT ?? "") + (model!.rEQUIREDFLAG == "Y" ? "*" : ""),
(model!.getContactDetailsList!.sEGMENTVALUEDSP ?? ""),
//isInputTypeNum: true,
onChange: (text) {
onChange: (String text) {
model!.getContactDetailsList!.sEGMENTVALUEDSP = text;
},
).paddingOnly(bottom: 12);
@ -211,7 +226,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
(model!.sEGMENTPROMPT ?? "") + (model!.rEQUIREDFLAG == "Y" ? "*" : ""),
(model!.getContactDetailsList!.sEGMENTVALUEDSP ?? ""),
isInputTypeNum: true,
onChange: (text) {
onChange: (String text) {
model!.getContactDetailsList!.sEGMENTVALUEDSP = text;
},
).paddingOnly(bottom: 12);
@ -223,13 +238,8 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
isEnable: false,
onTap: () async {
DateTime dateValue = await _selectDate(context);
//date = DateFormat('yyyy/MM/dd').format(dateValue);
//date = "2022-10-23T09:17:38.653+03:00";
date = (DateFormat('yyyy-MM-dd').format(dateValue));
model!.getContactDetailsList!.sEGMENTVALUEDSP = date;
print(dateTime);
print(dateTime1);
print(date);
setState(() {});
},
).paddingOnly(bottom: 12);
@ -245,28 +255,28 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
if (model!.fORMATTYPE == "C") {
if (model!.eSERVICESVS?.isNotEmpty ?? false) {
return PopupMenuButton(
child: DynamicTextFieldWidget(
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isEnable: false,
isPopup: true,
).paddingOnly(bottom: 12),
itemBuilder: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < getBasicDetDffStructureList[index]!.eSERVICESVS!.length; i++)
PopupMenuItem<int>(child: Text(getBasicDetDffStructureList[index]!.eSERVICESVS![i].vALUECOLUMNNAME.toString()), value: i),
],
onSelected: (int popupIndex) {
model.getContactDetailsList!.sEGMENTVALUEDSP = getBasicDetDffStructureList[index]!.eSERVICESVS![popupIndex].vALUECOLUMNNAME.toString();
model.getContactDetailsList!.vARCHAR2VALUE = getBasicDetDffStructureList[index]!.eSERVICESVS![popupIndex].iDCOLUMNNAME.toString();
child: DynamicTextFieldWidget(
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isEnable: false,
isPopup: true,
).paddingOnly(bottom: 12),
itemBuilder: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < getBasicDetDffStructureList[index]!.eSERVICESVS!.length; i++)
PopupMenuItem<int>(child: Text(getBasicDetDffStructureList[index]!.eSERVICESVS![i].vALUECOLUMNNAME.toString()), value: i),
],
onSelected: (int popupIndex) {
model.getContactDetailsList!.sEGMENTVALUEDSP = getBasicDetDffStructureList[index]!.eSERVICESVS![popupIndex].vALUECOLUMNNAME.toString();
model.getContactDetailsList!.vARCHAR2VALUE = getBasicDetDffStructureList[index]!.eSERVICESVS![popupIndex].iDCOLUMNNAME.toString();
setState(() {});
});
setState(() {});
},
);
} else {
return DynamicTextFieldWidget(
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
// isInputTypeNum: true,
onChange: (text) {
onChange: (String text) {
model.getContactDetailsList!.sEGMENTVALUEDSP = text;
},
).paddingOnly(bottom: 12);
@ -276,7 +286,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isInputTypeNum: true,
onChange: (text) {
onChange: (String text) {
model.getContactDetailsList!.sEGMENTVALUEDSP = text;
},
).paddingOnly(bottom: 12);
@ -289,8 +299,6 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
onTap: () async {
DateTime dateValue = await _selectDate(context);
date = (DateFormat('yyyy-MM-dd').format(dateValue));
// date = (DateFormat('yyyy-MM-dd').format(dateValue) +"T"+ dateTime.toString() + dateTime1.toString());
// date = DateFormat('yyyy/MM/dd').format(dateValue);
model!.getContactDetailsList!.sEGMENTVALUEDSP = date;
setState(() {});
},
@ -307,27 +315,27 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
if (model!.fORMATTYPE == "C") {
if (model.eSERVICESVS?.isNotEmpty ?? false) {
return PopupMenuButton(
child: DynamicTextFieldWidget(
(model!.sEGMENTPROMPT ?? "") + (model!.rEQUIREDFLAG == "Y" ? "*" : ""),
model!.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isEnable: false,
isPopup: true,
).paddingOnly(bottom: 12),
itemBuilder: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < getContactDffStructureList[index]!.eSERVICESVS!.length; i++)
PopupMenuItem<int>(child: Text(getContactDffStructureList[index]!.eSERVICESVS![i].vALUECOLUMNNAME.toString()), value: i),
],
onSelected: (int popupIndex) {
model.getContactDetailsList!.sEGMENTVALUEDSP = getContactDffStructureList[index]!.eSERVICESVS![popupIndex].vALUECOLUMNNAME.toString();
model.getContactDetailsList!.vARCHAR2VALUE = getContactDffStructureList[index]!.eSERVICESVS![popupIndex].iDCOLUMNNAME.toString();
setState(() {});
});
child: DynamicTextFieldWidget(
(model!.sEGMENTPROMPT ?? "") + (model!.rEQUIREDFLAG == "Y" ? "*" : ""),
model!.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isEnable: false,
isPopup: true,
).paddingOnly(bottom: 12),
itemBuilder: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < getContactDffStructureList[index]!.eSERVICESVS!.length; i++)
PopupMenuItem<int>(child: Text(getContactDffStructureList[index]!.eSERVICESVS![i].vALUECOLUMNNAME.toString()), value: i),
],
onSelected: (int popupIndex) {
model.getContactDetailsList!.sEGMENTVALUEDSP = getContactDffStructureList[index]!.eSERVICESVS![popupIndex].vALUECOLUMNNAME.toString();
model.getContactDetailsList!.vARCHAR2VALUE = getContactDffStructureList[index]!.eSERVICESVS![popupIndex].iDCOLUMNNAME.toString();
setState(() {});
},
);
} else {
return DynamicTextFieldWidget(
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
// isInputTypeNum: true,
onChange: (text) {
onChange: (String text) {
model.getContactDetailsList!.sEGMENTVALUEDSP = text;
},
).paddingOnly(bottom: 12);
@ -337,7 +345,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isInputTypeNum: true,
onChange: (text) {
onChange: (String text) {
model.getContactDetailsList!.sEGMENTVALUEDSP = text;
},
).paddingOnly(bottom: 12);
@ -349,9 +357,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
isEnable: false,
onTap: () async {
DateTime dateValue = await _selectDate(context);
// date = "2022-10-23T09:17:38.653+03:00";
date = (DateFormat('yyyy-MM-dd').format(dateValue));
// date = DateFormat('yyyy/MM/dd').format(dateValue);
model!.getContactDetailsList!.sEGMENTVALUEDSP = date;
setState(() {});
},
@ -367,13 +373,13 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
if (!Platform.isIOS) {
await showCupertinoModalPopup(
context: context,
builder: (cxt) => Container(
builder: (BuildContext cxt) => Container(
height: 250,
color: Colors.white,
child: CupertinoDatePicker(
backgroundColor: Colors.white,
mode: CupertinoDatePickerMode.date,
onDateTimeChanged: (value) {
onDateTimeChanged: (DateTime value) {
if (value != null && value != selectedDate) {
time = value;
}
@ -392,7 +398,6 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
}
void submitUpdateForm() async {
print("submit");
try {
List<Map<String, dynamic>> values1 = getBasicDetDffStructureList!.map((e) {
String? dateVal = '';
@ -441,12 +446,10 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: varChar).toJson();
}).toList();
List<Map<String, dynamic>> values3 = getContactColsStructureList!.map((e) {
// String tempVar = e!.getContactDetailsList!.sEGMENTVALUEDSP ?? "";
String? dateVal = '';
dynamic? varChar1 = '';
String? varChar1 = '';
int? numberVal;
print("e.dATATYPE:${e?.dATATYPE}");
if (e!.dATATYPE == 'VARCHAR2') {
dateVal = null;
numberVal = null;
@ -468,15 +471,18 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
}).toList();
List<Map<String, dynamic>> valuesFinal = [...values1, ...values2, ...values3];
Utils.showLoading(context);
submitContactTransactionList = await ProfileApiClient().submitContactTransactionAddAndUpdate(args['actionType'], args['relationID'] ?? null, valuesFinal);
var transactionId = submitContactTransactionList!.pTRANSACTIONID;
var itemKey = submitContactTransactionList!.pITEMKEY;
submitContactTransactionList = await ProfileApiClient().submitContactTransactionAddAndUpdate(params!.actionType!, params!.relationID, valuesFinal);
Utils.hideLoading(context);
await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.profile_familyDetails.tr(), submitContactTransactionList!.pTRANSACTIONID!, submitContactTransactionList!.pITEMKEY!, 'family_member'));
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(submitContactTransactionList!.pTRANSACTIONID!);
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.profile_familyDetails.tr(), transactionId!.toInt(), itemKey.toString(), 'family_member'));
setState(() {});
} catch (ex) {
print(ex);
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}

@ -1,6 +1,11 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/leave_balance_api_client.dart';
import 'package:mohem_flutter_app/api/profile_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/config/routes.dart';
@ -10,13 +15,12 @@ import 'package:mohem_flutter_app/models/get_approves_list_model.dart';
import 'package:mohem_flutter_app/models/profile/submit_contact_transaction_list_model.dart';
import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
class DeleteFamilyMember extends StatefulWidget {
int relationId;
DeleteFamilyMember(@required this.relationId, {Key? key}) : super(key: key);
@override
@ -26,9 +30,11 @@ class DeleteFamilyMember extends StatefulWidget {
class _DeleteFamilyMemberState extends State<DeleteFamilyMember> {
String pFunctionName = "HR_PERINFO_SS";
String actionType = "DELETE";
// int? contactRelationId;
String? date = "MM/DD/YYYY";
String? datePar;
// String? itemKey;
SubmitContactTransactionList? submitContactTransactionList;
@ -44,12 +50,16 @@ class _DeleteFamilyMemberState extends State<DeleteFamilyMember> {
try {
Utils.showLoading(context);
submitContactTransactionList = await ProfileApiClient().submetConatctTransaction(pFunctionName.toString(), actionType.toString(), widget.relationId!.toInt(), datePar.toString());
var transactionId = submitContactTransactionList!.pTRANSACTIONID;
var itemKey = submitContactTransactionList!.pITEMKEY;
Utils.hideLoading(context);
// getApprovesList = await ProfileApiClient().getApproves(transactionId!.toInt(), itemKey.toString() );
Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.profile_familyDetails.tr(), transactionId!.toInt(), itemKey.toString(), 'family_member'));
await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.profile_familyDetails.tr(), submitContactTransactionList!.pTRANSACTIONID!, submitContactTransactionList!.pITEMKEY!, 'family_member'));
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(submitContactTransactionList!.pTRANSACTIONID!);
Utils.hideLoading(context);
setState(() {});
} catch (ex) {
@ -73,7 +83,8 @@ class _DeleteFamilyMemberState extends State<DeleteFamilyMember> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DynamicTextFieldWidget(
LocaleKeys.endDate.tr(), date.toString(),
LocaleKeys.endDate.tr(),
date.toString(),
isEnable: false,
onTap: () async {
DateTime dateValue = await _selectDate(context);
@ -85,10 +96,9 @@ class _DeleteFamilyMemberState extends State<DeleteFamilyMember> {
],
),
),
DefaultButton(
LocaleKeys.next.tr(), () async {
deleteFamilyMember(datePar);}
).insideContainer,
DefaultButton(LocaleKeys.next.tr(), () async {
deleteFamilyMember(datePar);
}).insideContainer,
],
));
}
@ -145,8 +155,7 @@ class _DeleteFamilyMemberState extends State<DeleteFamilyMember> {
),
);
} else {
DateTime? picked =
await showDatePicker(context: context, initialDate: selectedDate, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101));
DateTime? picked = await showDatePicker(context: context, initialDate: selectedDate, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101));
if (picked != null && picked != selectedDate) {
time = picked;
}

@ -3,8 +3,10 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
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/api/profile_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/int_extensions.dart';
@ -296,8 +298,16 @@ class _DynamicInputScreenState extends State<DynamicInputScreenAddress> {
);
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(dynamicParams!.title, submitPhoneNumbers.pTRANSACTIONID!, submitPhoneNumbers.pITEMKEY!, 'address'));
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(submitPhoneNumbers.pTRANSACTIONID!);
Utils.hideLoading(context);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);

@ -3,8 +3,10 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
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/api/profile_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/int_extensions.dart';
@ -378,7 +380,6 @@ class _DynamicInputScreenState extends State<DynamicInputScreenProfile> {
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());
List<Map<String, dynamic>> valuesCols = getBasicDetColsStructureList!.map((e) {
if (e.dATATYPE == 'NUMBER') {
numberValue = e.userBasicDetail!.nUMBERVALUE ?? 0;
@ -392,11 +393,18 @@ class _DynamicInputScreenState extends State<DynamicInputScreenProfile> {
SubmitBasicDetailsTransactionList submitBasicDetails =
await ProfileApiClient().submitBasicDetailsTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, transactionValues, dynamicParams!.correctOrNew);
print(submitBasicDetails);
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(dynamicParams!.title, submitBasicDetails.pTRANSACTIONID!, submitBasicDetails.pITEMKEY!, 'basicDetails'));
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(submitBasicDetails.pTRANSACTIONID!);
Utils.hideLoading(context);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);

@ -12,6 +12,7 @@ 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/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/ui/profile/add_update_family_member.dart';
import 'package:mohem_flutter_app/ui/profile/profile_screen.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
@ -140,7 +141,7 @@ class _FamilyMembersState extends State<FamilyMembers> {
LocaleKeys.addNewFamilyMember.tr(),
menuEntries.updateButton == 'Y'
? () async {
Navigator.pushNamed(context, AppRoutes.addUpdateFamilyMember, arguments: {"relationID": relationId, "flag": 1, "actionType": "ADD"});
Navigator.pushNamed(context, AppRoutes.addUpdateFamilyMember, arguments: FamilyMemberScreenParams( relationId, flag: 1, actionType: "ADD"));
// ProfileScreen();
}
: null)
@ -166,7 +167,7 @@ class _FamilyMembersState extends State<FamilyMembers> {
Navigator.pushNamed(
context,
AppRoutes.addUpdateFamilyMember,
arguments: {"relationID": relationId, "flag": 2, "actionType": "UPDATE"},
arguments:FamilyMemberScreenParams(relationId, flag: 2, actionType: "UPDATE"),
);
},
);
@ -202,7 +203,7 @@ class _FamilyMembersState extends State<FamilyMembers> {
LocaleKeys.ok.tr(),
),
onPressed: () {
Navigator.pushNamed(context, AppRoutes.deleteFamilyMember, arguments: relationId);
Navigator.pushNamed(context, AppRoutes.deleteFamilyMember, arguments: FamilyMemberScreenParams(relationId));
// continueDynamicForms();
},
);

@ -1,6 +1,8 @@
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/leave_balance_api_client.dart';
import 'package:mohem_flutter_app/api/profile_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/config/routes.dart';
@ -117,8 +119,14 @@ class _PhoneNumbersState extends State<PhoneNumbers> {
setUpdateStatus();
submitPhoneNumbers = await ProfileApiClient().submitPhoneNumbers(widget.getEmployeePhonesList);
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.profile_contactDetails.tr(), submitPhoneNumbers.pTRANSACTIONID!, submitPhoneNumbers.pITEMKEY!, 'phone_numbers'));
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(submitPhoneNumbers.pTRANSACTIONID!);
Utils.hideLoading(context);
}
void setUpdateStatus() {

@ -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/api/termination_dff_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/int_extensions.dart';
@ -135,6 +136,9 @@ class _EndEmploymentScreenState extends State<EndEmploymentScreen> {
Utils.hideLoading(context);
await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitTermTransaction.pTRANSACTIONID!, submitTermTransaction.pITEMKEY!, "endEmployment"));
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(submitTermTransaction.pTRANSACTIONID!);
Utils.hideLoading(context);

@ -1,6 +1,8 @@
import 'package:easy_localization/easy_localization.dart';
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/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
@ -30,6 +32,7 @@ class _UpdateContinueSheetState extends State<UpdateContinueSheet> {
double itemHeight = 0;
double itemWidth = 0;
List<Map<String, dynamic>> validatedValues = [];
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
@ -57,11 +60,7 @@ class _UpdateContinueSheetState extends State<UpdateContinueSheet> {
index,
dataList[index].segmentPrompt,
dataList[index].segmentValueDsp,
isNeedToShowEmptyDivider: (dataList.length == index + 1)
? isOdd
? true
: false
: false,
isNeedToShowEmptyDivider: (dataList.length == index + 1) ? (isOdd ? true : false) : false,
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
@ -95,7 +94,6 @@ class _UpdateContinueSheetState extends State<UpdateContinueSheet> {
}
void performNextAction() async {
//Resubmit EIT Transaction
try {
Utils.showLoading(context);
List<Map<String, dynamic>> values = [];
@ -114,7 +112,6 @@ class _UpdateContinueSheetState extends State<UpdateContinueSheet> {
}
}
}
ResubmitEITRequestResponse resubmitEITRequestResponse = await MyAttendanceApiClient().reSubmitEitTransaction(widget.workListData!.iTEMKEY!, widget.workListData!.nOTIFICATIONID, values);
Utils.hideLoading(context);
await Navigator.pushNamed(
@ -122,6 +119,12 @@ class _UpdateContinueSheetState extends State<UpdateContinueSheet> {
AppRoutes.requestSubmitScreen,
arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), resubmitEITRequestResponse.pTRANSACTIONID!, widget.workListData!.iTEMKEY!, 'eit'),
);
if (!AppState().cancelRequestTrancsection) {
return;
}
Utils.showLoading(context);
await LeaveBalanceApiClient().cancelHrTransaction(resubmitEITRequestResponse.pTRANSACTIONID!);
Utils.hideLoading(context);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);

@ -81,7 +81,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
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)
];
int workListItemIndex = 0;
int? workListItemIndex;
List<WorkListResponseModel>? workList;
int pageNumber = 1;
@ -99,7 +99,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
super.initState();
providerData = Provider.of<DashboardProviderModel>(context, listen: false);
calculateCounter();
getWorkList();
if (workListItemIndex != null) getWorkList();
}
void calculateCounter() {
@ -115,11 +115,17 @@ class _WorkListScreenState extends State<WorkListScreen> {
}
}
});
workListItemTypes.removeWhere((element) => element.value < 1);
if (workListItemTypes.isNotEmpty) {
workListItemIndex = workListItemIndex ?? 0;
} else {
workListItemIndex = null;
}
}
void verifyWorkListCounter() {
workListItemTypes.forEach((workListElement) {
if (workListElement.key == "ITG" && workListItemTypes[workListItemIndex].key == "ITG") {
if (workListElement.key == "ITG" && workListItemTypes[workListItemIndex!].key == "ITG") {
workListElement.value = providerData.itgFormsModel?.totalCount ?? 0;
if ((AppState().requestAllList?.length ?? 0) != workListElement.value) {
workListElement.value = AppState().requestAllList?.length ?? 0;
@ -132,7 +138,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
workListElement.value = providerData.cocFinalCount;
} else {
providerData.getOpenNotificationsList?.forEach((element) {
if ((element.itemType == workListItemTypes[workListItemIndex].key) && element.itemType == workListElement.key) {
if ((element.itemType == workListItemTypes[workListItemIndex!].key) && element.itemType == workListElement.key) {
if ((AppState().workList?.length ?? 0) != (element.openNtfNumber ?? 0)) {
workListElement.value = AppState().workList?.length ?? 0;
providerData.workListCounter = providerData.workListCounter - ((element.openNtfNumber ?? 0) - (AppState().workList?.length ?? 0));
@ -141,17 +147,6 @@ class _WorkListScreenState extends State<WorkListScreen> {
}
}
});
// var tempList = providerData.getOpenNotificationsList?.where((notificationElement) {
// return (notificationElement.itemType == workListItemTypes[workListItemIndex].key) && notificationElement.itemType == workListElement.key;
// }).toList();
// if (tempList!.isNotEmpty) {
// if ((AppState().workList?.length ?? 0) != (tempList.first.openNtfNumber ?? 0)) {
// workListElement.value = AppState().workList?.length ?? 0;
// providerData.workListCounter = providerData.workListCounter - ((tempList.first.openNtfNumber ?? 0) - (AppState().workList?.length ?? 0));
// providerData.notify();
// }
// }
}
});
}
@ -162,7 +157,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
Future<void> getWorkList({bool showLoading = true}) async {
try {
if (showLoading) Utils.showLoading(context);
if (workListItemTypes[workListItemIndex].key == "ITG") {
if (workListItemTypes[workListItemIndex!].key == "ITG") {
itgFormsModel = await WorkListApiClient().getITGTaskCountRequestType();
List<RequestDetails> requestAllList = [];
for (int i = 0; i < (itgFormsModel?.requestType!.length ?? 0); i++) {
@ -178,7 +173,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
}
} else {
itgRequestTypeIndex = null;
workList = await WorkListApiClient().getWorkList(pageNumber, workListItemTypes[workListItemIndex].key, pNotificationType.toString());
workList = await WorkListApiClient().getWorkList(pageNumber, workListItemTypes[workListItemIndex!].key, pNotificationType.toString());
AppState().setWorkList = workList;
}
if (showLoading) Utils.hideLoading(context);
@ -216,127 +211,129 @@ class _WorkListScreenState extends State<WorkListScreen> {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBarWidget(context, title: LocaleKeys.workList.tr(), showWorkListSettingButton: true),
body: 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;
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),
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;
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),
),
).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(
enablePullDown: true,
enablePullUp: false,
header: const MaterialClassicHeader(
color: MyColors.gradiantEndColor,
),
controller: _refreshController,
onRefresh: _onRefresh,
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
? ((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),
))
: const SizedBox(),
)).expanded,
],
),
).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(
enablePullDown: true,
enablePullUp: false,
header: const MaterialClassicHeader(
color: MyColors.gradiantEndColor,
),
controller: _refreshController,
onRefresh: _onRefresh,
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
? ((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),
))
: const SizedBox(),
)).expanded,
],
),
),
);
}
@ -349,25 +346,15 @@ class _WorkListScreenState extends State<WorkListScreen> {
if (shouldReloadData != null) {
if (shouldReloadData.toString() == "delegate_reload") {
providerData.itgFormsModel!.totalCount = providerData.itgFormsModel!.totalCount! - 1;
workListItemIndex = null;
calculateCounter();
getWorkList();
if (workListItemIndex != null) {
getWorkList();
} else {
setState(() {});
}
}
// workList!.remove(data);
// AppState().setWorkList = workList;
// if (data.iTEMTYPE == "ITG") {
//
//
// } else {
// providerData.getOpenNotificationsList?.forEach((element) {
// if (element.itemType == data.iTEMTYPE) {
// element.openNtfNumber = element.openNtfNumber! - 1;
// }
// });
// providerData.workListCounter = providerData.workListCounter - 1;
// providerData.notify();
// }
// calculateCounter();
// if (mounted) setState(() {});
} else {
verifyWorkListCounter();
if (mounted) setState(() {});
@ -466,7 +453,13 @@ class _WorkListScreenState extends State<WorkListScreen> {
if (shouldReloadData != null) {
if (shouldReloadData.toString() == "delegate_reload") {
verifyWorkListCounter();
getWorkList();
workListItemIndex = null;
calculateCounter();
if (workListItemIndex != null) {
getWorkList();
} else {
setState(() {});
}
} else {
workList!.remove(data);
AppState().setWorkList = workList;

@ -81,7 +81,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
GetContactNotificationBodyList? getContactNotificationBodyList;
List<GetAddressNotificationBodyList>? getAddressNotificationBodyList = [];
GenericResponseModel? getBasicNTFBody;
GenericResponseModel? getICBody;
GenericResponseModel? subordinatesLeavesModel;
@ -93,6 +92,9 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
bool isApproveAvailable = false;
bool isRejectAvailable = false;
String approveAction = "";
String rejectAction = "";
bool isAttachmentLoaded = false;
bool isActionHistoryLoaded = false;
@ -169,29 +171,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
if (controller.hasClients) {
controller.jumpToPage(0);
}
// List dataToFetch = await Future.wait([
//
// WorkListApiClient().getActionHistory(workListData!.nOTIFICATIONID!),
// WorkListApiClient().getAttachments(workListData!.nOTIFICATIONID!),
// ]);
//
// notificationButtonsList = dataToFetch[0];
// actionHistoryList = dataToFetch[1];
// getAttachmentList = dataToFetch[2];
// if (notificationButtonsList.isNotEmpty) {
// isCloseAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "CLOSE");
// isApproveAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "APPROVED");
// isRejectAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "REJECTED");
// }
// Utils.hideLoading(context);
// setState(() {});
// } catch (ex) {
// Utils.hideLoading(context);
// Utils.handleException(ex, context, null);
// setState(() {});
// }
}
List<Future> futureRequest = [];
@ -320,14 +299,14 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
if (isRejectAvailable)
DefaultButton(
LocaleKeys.reject.tr(),
() => performAction("REJECTED"),
() => performAction(rejectAction),
colors: const [Color(0xffE47A7E), Color(0xffDE6D71)],
).expanded,
if (isApproveAvailable && isRejectAvailable) 8.width,
if (isApproveAvailable)
DefaultButton(
LocaleKeys.approve.tr(),
() => performAction("APPROVED"),
() => performAction(approveAction),
colors: const [Color(0xff28C884), Color(0xff1BB271)],
).expanded,
if (isCloseAvailable)
@ -417,7 +396,11 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
List<Widget> viewApiButtonsList(List<GetNotificationButtonsList> notificationButtonsList) {
List<Widget> fabs = [];
for (int i = 0; i < notificationButtonsList.length; i++) {
if (notificationButtonsList[i].bUTTONACTION! == "REJECTED" || notificationButtonsList[i].bUTTONACTION! == "APPROVED" || notificationButtonsList[i].bUTTONACTION! == "CLOSE") {
if (notificationButtonsList[i].bUTTONACTION! == "REJECTED" ||
notificationButtonsList[i].bUTTONACTION! == "REJECT" ||
notificationButtonsList[i].bUTTONACTION! == "APPROVED" ||
notificationButtonsList[i].bUTTONACTION! == "APPROVE" ||
notificationButtonsList[i].bUTTONACTION! == "CLOSE") {
continue;
}
fabs.add(myFab(
@ -989,8 +972,20 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
notificationButtonsList = await WorkListApiClient().getNotificationButtons(workListData!.nOTIFICATIONID!);
if (notificationButtonsList.isNotEmpty) {
isCloseAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "CLOSE");
isApproveAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "APPROVED");
isRejectAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "REJECTED");
isApproveAvailable = notificationButtonsList.any((element) {
if (element.bUTTONACTION == "APPROVED" || element.bUTTONACTION == "APPROVE") {
approveAction = element.bUTTONACTION!;
return true;
}
return false;
});
isRejectAvailable = notificationButtonsList.any((element) {
if (element.bUTTONACTION == "REJECTED" || element.bUTTONACTION == "REJECT") {
rejectAction = element.bUTTONACTION!;
return true;
}
return false;
});
}
apiCallCount--;
if (apiCallCount == 0) {

@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/worklist/worklist_api_client.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/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
@ -26,6 +25,7 @@ class _WorklistSettingsState extends State<WorklistSettings> {
List<GetUserItemTypesList> getUserItemTypesList = [];
UpdateUserItemTypesList? updateUserItemTypesList;
@override
void initState() {
super.initState();
userItemTypesList();
@ -47,13 +47,17 @@ class _WorklistSettingsState extends State<WorklistSettings> {
try {
Utils.showLoading(context);
List<Map<String, dynamic>> itemList = [];
for (var element in getUserItemTypesList) {
itemList.add(UpdateUserTypesList(itemID: element.uSERITEMTYPEID, pITEMTYPE: element.iTEMTYPE, pFYAENABLEDFALG: element.fYAENABLEDFALG, pFYIENABLEDFALG: element.fYIENABLEDFLAG).toJson());
for (int index = 0; index < getUserItemTypesList.length; index++) {
itemList.add(UpdateUserTypesList(
itemID: index,
pITEMTYPE: getUserItemTypesList[index].iTEMTYPE,
pFYAENABLEDFALG: getUserItemTypesList[index].fYAENABLEDFALG,
pFYIENABLEDFALG: getUserItemTypesList[index].fYIENABLEDFLAG)
.toJson());
}
updateUserItemTypesList = await WorkListApiClient().updateUserItemTypes(itemList);
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.workList);
setState(() {});
Navigator.pop(context);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
@ -63,87 +67,81 @@ class _WorklistSettingsState extends State<WorklistSettings> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBarWidget(
context,
title: LocaleKeys.worklistSettings.tr(),
),
body: Column(
children: [
ListView(
padding: const EdgeInsets.only(top: 21, left: 21, right: 21),
children: [
LocaleKeys.TurnNotificationsFor.tr().toText22(color: MyColors.blackColor),
16.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.itemType.tr().toText14(color: MyColors.blackColor),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: ["FYA".tr().toText14(color: MyColors.blackColor), 30.width, "FYI".tr().toText14(color: MyColors.blackColor), 30.width],
)
],
),
const Divider(color: MyColors.greyA5Color),
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: getUserItemTypesList == null ? 0 : getUserItemTypesList.length,
itemBuilder: (BuildContext context, int index) {
return Column(children: [
customSwitch(getUserItemTypesList[index]),
Divider(
color: MyColors.greyC4Color,
thickness: 0.5,
),
]);
}),
),
],
).expanded,
DefaultButton(LocaleKeys.save.tr(), () async {
updateUserItem();
}).insideContainer,
],
));
backgroundColor: Colors.white,
appBar: AppBarWidget(
context,
title: LocaleKeys.worklistSettings.tr(),
),
body: Column(
children: [
ListView(
padding: const EdgeInsets.only(top: 21, left: 21, right: 21),
children: [
LocaleKeys.TurnNotificationsFor.tr().toText22(color: MyColors.blackColor),
16.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.itemType.tr().toText14(color: MyColors.blackColor),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: ["FYA".tr().toText14(color: MyColors.blackColor), 30.width, "FYI".tr().toText14(color: MyColors.blackColor), 30.width],
)
],
),
const Divider(color: MyColors.greyA5Color),
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: getUserItemTypesList.length,
separatorBuilder: (cxt, index) => 1.divider,
itemBuilder: (BuildContext context, int index) => customSwitch(getUserItemTypesList[index]),
),
],
).expanded,
DefaultButton(LocaleKeys.save.tr(), () async {
updateUserItem();
}).insideContainer,
],
),
);
}
Widget customSwitch(GetUserItemTypesList list) {
return Padding(
padding: const EdgeInsets.only(top: 21),
padding: const EdgeInsets.only(top: 8, bottom: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
list.iTEMTYPE.toString(),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.blackColor),
),
list.iTEMTYPE!.toText16(),
const Spacer(),
Row(
children: [
CupertinoSwitch(
trackColor: MyColors.grey57Color,
activeColor: MyColors.textMixColor,
value: list?.fYAENABLEDFALG == 'Y' ? true : false,
onChanged: (value) {
setState(() {
list?.fYAENABLEDFALG = value == true ? 'Y' : 'N';
});
}),
CupertinoSwitch(
Transform.scale(
scale: 0.8,
child: CupertinoSwitch(
trackColor: MyColors.grey57Color,
activeColor: MyColors.textMixColor,
value: list.fYAENABLEDFALG == 'Y',
onChanged: (value) {
setState(() {
list.fYAENABLEDFALG = value ? 'Y' : 'N';
});
}),
),
Transform.scale(
scale: 0.8,
child: CupertinoSwitch(
trackColor: MyColors.grey57Color,
activeColor: MyColors.textMixColor,
value: list?.fYIENABLEDFLAG == 'Y' ? true : false,
value: list.fYIENABLEDFLAG == 'Y',
onChanged: (value) {
setState(() {
// list.isFYI = value;
list?.fYIENABLEDFLAG = value == true ? 'Y' : 'N';
list.fYIENABLEDFLAG = value ? 'Y' : 'N';
});
}),
},
),
),
],
)
],

@ -73,7 +73,7 @@ class _BalancesDashboardWidgetState extends State<BalancesDashboardWidget> {
];
} else {
chartModelList = [
PieChartModel(LocaleKeys.adult.tr(), accrualList[1].accrualNetEntitlement ?? 0, MyColors.textMixColor, titleAppend: ""),
PieChartModel(LocaleKeys.adult.tr(), accrualList[1].accrualNetEntitlement?.toDouble() ?? 0, MyColors.textMixColor, titleAppend: ""),
PieChartModel(LocaleKeys.child.tr(), accrualList[2].accrualNetEntitlement?.toDouble() ?? 0, MyColors.backgroundBlackColor, titleAppend: ""),
PieChartModel(LocaleKeys.infants.tr(), accrualList[3].accrualNetEntitlement?.toDouble() ?? 0, MyColors.pinkColor, titleAppend: ""),
];
@ -101,7 +101,7 @@ class _BalancesDashboardWidgetState extends State<BalancesDashboardWidget> {
ticketBalanceAccrualList = Provider.of<DashboardProviderModel>(context, listen: false).accrualList ?? [];
if (ticketBalanceAccrualList!.isNotEmpty) {
chartModelList = [
PieChartModel(LocaleKeys.adult.tr(), ticketBalanceAccrualList![1].accrualNetEntitlement ?? 0, MyColors.textMixColor, titleAppend: ""),
PieChartModel(LocaleKeys.adult.tr(), ticketBalanceAccrualList![1].accrualNetEntitlement?.toDouble() ?? 0, MyColors.textMixColor, titleAppend: ""),
PieChartModel(LocaleKeys.child.tr(), ticketBalanceAccrualList![2].accrualNetEntitlement?.toDouble() ?? 0, MyColors.backgroundBlackColor, titleAppend: ""),
PieChartModel(LocaleKeys.infants.tr(), ticketBalanceAccrualList![3].accrualNetEntitlement?.toDouble() ?? 0, MyColors.pinkColor, titleAppend: ""),
];
@ -185,7 +185,7 @@ class _BalancesDashboardWidgetState extends State<BalancesDashboardWidget> {
Widget getChart(List<PieChartModel> chartModelList) {
List<Color> _colorList = chartModelList.map((e) => e.color).toList();
return PieChart(
dataMap: {for (var e in chartModelList) e.title: e.parsedValue},
dataMap: {for (var e in chartModelList) e.title: e.value},
animationDuration: const Duration(milliseconds: 800),
chartRadius: MediaQuery.of(context).size.width / 3.2,
colorList: _colorList,

@ -20,10 +20,13 @@ import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/get_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart';
import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
class SearchEmployeeBottomSheet extends StatefulWidget {
int? notificationID;
@ -47,6 +50,8 @@ class SearchEmployeeBottomSheet extends StatefulWidget {
class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
TextEditingController username = TextEditingController();
ScrollController sc = ScrollController();
String searchText = "";
List<String>? optionsList = [
@ -61,7 +66,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
List<ReplacementList>? nonFavouriteUserList;
// Chat Items
List<ChatUser>? chatUsersList = [];
late ChatProviderModel provider;
int _selectedSearchIndex = 0;
@ -88,25 +93,54 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
}
void fetchChatUser({bool isNeedLoading = true}) async {
if (provider.pageNo == 1) provider.chatUsersList!.clear();
try {
Utils.showLoading(context);
chatUsersList = await ChatApiClient().getChatMemberFromSearch(
searchText,
int.parse(AppState().chatDetails!.response!.id.toString()),
);
chatUsersList!.removeWhere((element) => element.id == AppState().chatDetails!.response!.id);
await ChatApiClient().getChatMemberFromSearch(searchText, AppState().chatDetails!.response!.id!, provider.pageNo).then((ChatUserModel value) {
if (value.response != null) {
if (provider.pageNo == 1) {
provider.chatUsersList = value.response;
} else {
print("--------------------------Added More----------------------");
provider.chatUsersList!.addAll(value.response!);
}
}
});
provider.chatUsersList!.removeWhere((ChatUser element) => element.id == AppState().chatDetails!.response!.id);
Utils.hideLoading(context);
setState(() {});
} catch (e) {
Utils.hideLoading(context);
Utils.handleException(e, context, null);
}
if (isNeedLoading) Utils.hideLoading(context);
setState(() {});
return null;
}
void scrollListener() async {
if (sc.position.pixels == sc.position.maxScrollExtent) {
provider.pageNo++;
logger.w(provider.chatUsersList!.length);
logger.w(provider.pageNo);
fetchChatUser();
}
}
@override
void initState() {
super.initState();
sc.addListener(scrollListener);
provider = Provider.of<ChatProviderModel>(context, listen: false);
}
@override
void dispose() {
super.dispose();
provider.chatUsersList = [];
provider.pageNo = 1;
}
@override
Widget build(BuildContext context) {
return SizedBox(
@ -123,7 +157,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
11.height,
Row(
children: [
radioOption("Name", 0, _selectedSearchIndex),
radioOption(widget.fromChat ? "UserId" : "Name", 0, _selectedSearchIndex),
radioOption("User Name", 1, _selectedSearchIndex),
radioOption("Email", 2, _selectedSearchIndex),
],
@ -188,73 +222,137 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
],
).expanded,
if (widget.fromChat)
if (chatUsersList != null && widget.fromChat)
chatUsersList!.isEmpty
if (provider.chatUsersList != null && widget.fromChat)
provider.chatUsersList!.isEmpty
? Column(
children: [
20.height,
Utils.getNoDataWidget(context),
],
)
: ListView(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.only(
top: 15,
),
children: <Widget>[
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext cxt, int index) {
return SizedBox(
height: 55,
child: ListTile(
leading: Stack(
children: [
SvgPicture.asset(
: ListView.separated(
itemCount: provider.chatUsersList!.length,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
controller: sc,
padding: const EdgeInsets.only(bottom: 80.0, top: 20),
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 55,
child: Row(
children: [
Stack(
children: <Widget>[
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: chatUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red,
borderRadius: const BorderRadius.all(
Radius.circular(10),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: provider.chatUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red,
),
).circle(10),
)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(provider.chatUsersList![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "")
.toText14(color: MyColors.darkTextColor)
.paddingOnly(left: 11, top: 13),
provider.chatUsersList![index].isTyping!
? 'Typing...'
.toText10(
color: MyColors.textMixColor,
)
.paddingOnly(left: 11.0)
: const SizedBox()
],
).expanded,
SizedBox(
width: 60,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
if (provider.chatUsersList![index].unreadMessageCount! > 0)
Container(
alignment: Alignment.center,
width: 18,
height: 18,
decoration: const BoxDecoration(
color: MyColors.redColor,
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
),
)
child: (provider.chatUsersList![index].unreadMessageCount!.toString())
.toText10(
color: MyColors.white,
)
.center,
).paddingOnly(right: 10).center,
Icon(
provider.chatUsersList![index].isFav != null && provider.chatUsersList![index].isFav == false ? Icons.star_sharp : Icons.star_sharp,
color: provider.chatUsersList![index].isFav != null && provider.chatUsersList![index].isFav == true ? MyColors.yellowColor : MyColors.grey35Color,
).onPress(
() {
if (provider.chatUsersList![index].isFav == null || provider.chatUsersList![index].isFav == false) {
provider
.favoriteUser(
userID: AppState().chatDetails!.response!.id!,
targetUserID: provider.chatUsersList![index].id!,
fromSearch: true
)
.then((value) {
setState(() {});
});
} else if (provider.chatUsersList![index].isFav == true) {
provider
.unFavoriteUser(
userID: AppState().chatDetails!.response!.id!,
targetUserID: provider.chatUsersList![index].id!,
)
.then((value) {
setState(() {});
});
} else {
provider
.favoriteUser(
userID: AppState().chatDetails!.response!.id!,
targetUserID: provider.chatUsersList![index].id!,
fromSearch: true
)
.then((value) {
setState(() {});
});
}
},
).center
],
),
title: (chatUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor),
minVerticalPadding: 0,
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(
context,
AppRoutes.chatDetailed,
arguments: ChatDetailedScreenParams(chatUsersList![index], true),
);
},
),
);
},
separatorBuilder: (BuildContext context, int index) => const Padding(
padding: EdgeInsets.only(right: 10, left: 70, bottom: 0, top: 0),
child: Divider(
color: Color(0xFFE5E5E5),
),
],
),
itemCount: chatUsersList?.length ?? 0,
),
12.height,
],
).onPress(() {
Navigator.pop(context);
Navigator.pushNamed(
context,
AppRoutes.chatDetailed,
arguments: ChatDetailedScreenParams(provider.chatUsersList![index], true),
);
});
},
separatorBuilder: (BuildContext context, int index) => const Divider(color: MyColors.lightGreyE5Color).paddingOnly(left: 59),
).expanded,
],
).paddingOnly(left: 21, right: 21, bottom: 0, top: 21).expanded,
@ -263,6 +361,8 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
LocaleKeys.cancel.tr(),
() {
Navigator.pop(context);
provider.chatUsersList = [];
provider.pageNo = 1;
},
textColor: MyColors.grey3AColor,
colors: const [

@ -11,56 +11,75 @@ import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:provider/provider.dart';
AppBar ChatAppBarWidget(BuildContext context,
{required String title,
bool showHomeButton = true,
String? image,
ChatUser? chatUser,
bool showTyping = false,
List<Widget>? actions,
void Function()? onHomeTapped,
void Function()? onBackTapped}) {
{required String title, bool showHomeButton = true, ChatUser? chatUser, bool showTyping = false, List<Widget>? actions, void Function()? onHomeTapped, void Function()? onBackTapped}) {
return AppBar(
leadingWidth: 0,
title: Row(
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: Feedback.wrapForTap(() {
(onBackTapped == null ? Navigator.maybePop(context) : onBackTapped());
}, context),
child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
),
4.width,
if (image != null)
CircularAvatar(
url: image,
height: 40,
width: 40,
isImageBase64: true,
title: Consumer<ChatProviderModel>(builder: (BuildContext cxt, ChatProviderModel data, Widget? child) {
return Row(
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: Feedback.wrapForTap(() {
(onBackTapped == null ? Navigator.maybePop(context) : onBackTapped());
}, context),
child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
),
if (image != null) 14.width,
SizedBox(
height: 40,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
title.toText20(color: MyColors.darkTextColor, isBold: true).expanded,
if (showTyping)
Consumer<ChatProviderModel>(
builder: (BuildContext cxt, ChatProviderModel data, Widget? child) {
if (chatUser!.isTyping!) {
return ("Typing ...").toText10(color: MyColors.textMixColor);
} else {
return const SizedBox();
}
},
),
],
),
)
],
),
4.width,
if (chatUser != null)
Stack(
children: <Widget>[
if (chatUser.isImageLoading!)
const SizedBox(
height: 48,
width: 48,
).toShimmer().circle(30),
if (!chatUser.isImageLoading! && chatUser.userLocalDownlaodedImage == null)
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
if (!chatUser.isImageLoading! && chatUser.userLocalDownlaodedImage != null)
Container(
width: 48.0,
height: 48.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.cover,
image: FileImage(chatUser.userLocalDownlaodedImage!),
),
),
),
Positioned(
right: 5,
bottom: 1,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: chatUser.userStatus == 1 ? MyColors.green2DColor : Colors.red,
),
).circle(10),
)
],
),
if (chatUser != null) 14.width,
SizedBox(
height: 40,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
title.toText20(color: MyColors.darkTextColor, isBold: true).expanded,
if (showTyping)
if (chatUser!.isTyping!) ("Typing ...").toText10(color: MyColors.textMixColor) else const SizedBox(),
],
),
).expanded
],
);
}),
centerTitle: false,
elevation: 0,
backgroundColor: Colors.white,

@ -20,7 +20,7 @@ class ImageOptions {
if (Platform.isAndroid) {
cameraImageAndroid(image);
} else {
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 10))?.path ?? "");
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? "");
String fileName = _image.path;
var bytes = File(fileName).readAsBytesSync();
String base64Encode = base64.encode(bytes);
@ -33,7 +33,7 @@ class ImageOptions {
if (Platform.isAndroid) {
galleryImageAndroid(image);
} else {
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 10))?.path ?? "");
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? "");
String fileName = _image.path;
var bytes = File(fileName).readAsBytesSync();
String base64Encode = base64.encode(bytes);
@ -114,7 +114,7 @@ class ImageOptions {
}
void galleryImageAndroid(Function(String, File) image) async {
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 10))?.path ?? "");
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 20))?.path ?? "");
String fileName = _image.path;
var bytes = File(fileName).readAsBytesSync();
String base64Encode = base64.encode(bytes);
@ -124,7 +124,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: 10))?.path ?? "");
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? "");
String fileName = _image.path;
var bytes = File(fileName).readAsBytesSync();
String base64Encode = base64.encode(bytes);

@ -12,6 +12,7 @@ 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/generic_response_model.dart';
import 'package:mohem_flutter_app/models/privilege_list_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/ui/dialogs/success_dialog.dart';
import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';
@ -47,7 +48,7 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
void checkAttendanceAvailability() async {
bool isAvailable = await NfcManager.instance.isAvailable();
setState(() {
AppState().privilegeListModel!.forEach((element) {
AppState().privilegeListModel!.forEach((PrivilegeListModel element) {
if (element.serviceName == "enableNFC") {
if (isAvailable) if (element.previlege ?? false) isNfcEnabled = true;
} else if (element.serviceName == "enableQR") {
@ -144,6 +145,7 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
Future<void> performNfcAttendance(DashboardProviderModel model, {String lat = "0", String lng = "0"}) async {
if (Platform.isIOS) {
Utils.readNFc(onRead: (String nfcId) async {
Utils.showLoading(context);
try {
@ -152,7 +154,7 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
Utils.hideLoading(context);
showDialog(
context: context,
builder: (cxt) => ConfirmDialog(
builder: (BuildContext cxt) => ConfirmDialog(
message: g?.errorEndUserMessage ?? "Unexpected error occurred",
onTap: () {
Navigator.pop(context);
@ -161,20 +163,18 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
);
} else {
bool status = await model.fetchAttendanceTracking(context);
if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
Utils.hideLoading(context);
showMDialog(
context,
backgroundColor: Colors.transparent,
isDismissable: false,
isDismissable: true,
child: SuccessDialog(widget.isFromDashboard),
);
}
} catch (ex) {
print(ex);
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {
Utils.confirmDialog(context, msg);
});
Utils.handleException(ex, context, null);
}
});
} else {
@ -186,7 +186,7 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
Utils.hideLoading(context);
showDialog(
context: context,
builder: (cxt) => ConfirmDialog(
builder: (BuildContext cxt) => ConfirmDialog(
message: g?.errorEndUserMessage ?? "Unexpected error occurred",
onTap: () {
Navigator.pop(context);
@ -206,7 +206,7 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
} catch (ex) {
print(ex);
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {
Utils.handleException(ex, context, (String msg) {
Utils.confirmDialog(context, msg);
});
}
@ -218,20 +218,33 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
Utils.showLoading(context);
bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "",
password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false);
if (isConnected) {
if (Platform.isIOS) {
await closeWifiRequest();
await Future.delayed(Duration(seconds: 6));
if (Platform.isIOS) {
if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) {
isConnected = true;
} else {
await WiFiForIoTPlugin.forceWifiUsage(true);
isConnected = false;
}
}
if (isConnected) {
// if (Platform.isIOS) {
// await closeWifiRequest();
// await Future.delayed(Duration(seconds: 6));
// } else {
// await WiFiForIoTPlugin.forceWifiUsage(true);
// }
await WiFiForIoTPlugin.forceWifiUsage(true);
await Future.delayed(const Duration(seconds: 6));
try {
GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 3, nfcValue: "", isGpsRequired: isWifiLocationEnabled, lat: lat, long: lng);
bool status = await model.fetchAttendanceTracking(context);
Utils.hideLoading(context);
if (Platform.isAndroid) {
await closeWifiRequest();
}
// if (Platform.isAndroid) {
// await closeWifiRequest();
// }
await closeWifiRequest();
showMDialog(
context,
backgroundColor: Colors.transparent,
@ -239,12 +252,9 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
child: SuccessDialog(widget.isFromDashboard),
);
} catch (ex) {
print("performWifiAttendance: " + ex.toString());
await closeWifiRequest();
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {
Utils.confirmDialog(context, msg);
});
Utils.handleException(ex, context, null);
}
} else {
Utils.hideLoading(context);
@ -262,7 +272,7 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
Future<void> performQrCodeAttendance(DashboardProviderModel model, {String lat = "0", String lng = "0"}) async {
var qrCodeValue = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => QrScannerDialog(),
builder: (BuildContext context) => QrScannerDialog(),
),
);
if (qrCodeValue != null) {
@ -274,15 +284,13 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
showMDialog(
context,
backgroundColor: Colors.transparent,
isDismissable: false,
isDismissable: true,
child: SuccessDialog(widget.isFromDashboard),
);
} catch (ex) {
print(ex);
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {
Utils.confirmDialog(context, msg);
});
Utils.handleException(ex, context, null);
}
}
}
@ -296,9 +304,7 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
} catch (ex) {
print(ex);
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {
Utils.confirmDialog(context, msg);
});
Utils.handleException(ex, context, null);
}
}

@ -132,7 +132,7 @@ class ServicesHeaderShimmer extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
"Other".tr().toText10().toShimmer(),
LocaleKeys.otherCharges.tr().toText10().toShimmer(),
6.height,
LocaleKeys.services.tr().toText12(isBold: true).toShimmer(),
],
@ -273,7 +273,7 @@ class ChatHomeShimmer extends StatelessWidget {
children: <Widget>[
Container(
width: double.infinity,
height: 8.0,
height: 20.0,
color: Colors.white,
),
const Padding(
@ -281,7 +281,7 @@ class ChatHomeShimmer extends StatelessWidget {
),
Container(
width: double.infinity,
height: 8.0,
height: 15.0,
color: Colors.white,
),
const Padding(
@ -289,7 +289,7 @@ class ChatHomeShimmer extends StatelessWidget {
),
Container(
width: 40.0,
height: 8.0,
height: 10.0,
color: Colors.white,
),
],

@ -16,7 +16,7 @@ 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: 1.0.0+1
version: 3.2.0+300020
environment:
sdk: ">=2.16.0 <3.0.0"
@ -40,7 +40,7 @@ dependencies:
provider: ^6.0.1
easy_localization: ^3.0.0
http: ^0.13.4
permission_handler: ^9.2.0
permission_handler: ^10.2.0
flutter_svg: any
sizer: ^2.0.15
local_auth: ^1.1.9
@ -49,7 +49,7 @@ dependencies:
flutter_calendar_carousel: ^2.1.0
pie_chart: ^5.1.0
shared_preferences: ^2.0.12
firebase_messaging: ^11.2.8
firebase_messaging: ^13.0.4
shimmer: ^2.0.0
logger: ^1.1.0
flutter_countdown_timer: ^4.1.0
@ -67,7 +67,7 @@ dependencies:
month_year_picker: ^0.2.0+1
month_picker_dialog_2: 0.5.5
open_file: ^3.2.1
wifi_iot: ^0.3.16
wifi_iot: ^0.3.18
flutter_html: ^3.0.0-alpha.6
# flutter_barcode_scanner: ^2.0.0
qr_code_scanner: ^1.0.0
@ -92,11 +92,11 @@ dependencies:
swipe_to: ^1.0.2
flutter_webrtc: ^0.9.16
camera: ^0.10.0+4
#flutter_local_notifications: any
#Chat Voice Message Recoding & Play
# record: ^4.4.3
audio_waveforms: ^0.1.5+1
# animated_text_kit: ^4.2.2
rxdart: ^0.27.7
#Encryption
flutter_des: ^2.1.0
@ -106,6 +106,11 @@ dependencies:
safe_device: ^1.1.2
flutter_layout_grid: ^2.0.1
dependency_overrides:
firebase_core_platform_interface: 4.5.1
dev_dependencies:
flutter_test:
sdk: flutter
@ -138,6 +143,7 @@ flutter:
- assets/icons/
- assets/lottie/
- assets/audio/
- assets/json/
- assets/images/
- assets/images/worklist/
- assets/images/services_icons/

Loading…
Cancel
Save