Merge branch 'development_haroon' into 'master'

Development haroon

See merge request Cloud_Solution/hmg-mohemm-flutter-app!3
development_haroon
haroon amjad 2 years ago
commit 373dd3a6d7

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

@ -0,0 +1 @@
{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

@ -52,19 +52,13 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.cloudsolutions.alhabibmohemm"
minSdkVersion 21
minSdkVersion 28
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
signingConfigs {
debug {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']

@ -21,6 +21,7 @@
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="Al Habib Mohemm"
android:extractNativeLibs="true"
android:networkSecurityConfig="@xml/network_security_config">
<activity
android:name=".MainActivity"

@ -43,6 +43,7 @@
"newString": "جديد",
"setTheNewPassword": "قم بتعيين كلمة المرور الجديدة",
"typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه",
"typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه",
"confirmPassword": "تأكيد كلمة المرور",
"update": "تحديث",
"title": "عنوان",
@ -404,7 +405,8 @@
"stamp": "ختم",
"addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله",
"feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم",
"rateUI": ".1 كيف تريد تقييم التطبيق",
"rateUI": "كيف تريد أن تقيم",
"rateUI2": "ما مدى رضائك عن هذا التطبيق",
"submitSurvey": "ارسال الاستبيان",
"typeHere": "اكتب هنا",
"infoDetail": "تفاصيل المعلومات",
@ -424,7 +426,7 @@
"typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه",
"currentPassword": "كلمة المرور الحاليه",
"concurrentReports": "التقارير المتزامنه",
"EnterNewAddressMoved" : "أدخل عنوان جديد إذا كنت قد انتقلت",
"EnterNewAddressMoved": "أدخل عنوان جديد إذا كنت قد انتقلت",
"CorrectAddress": "تصحيح أو تعديل هذا العنوان",
"SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.",
"profile": {
@ -480,7 +482,7 @@
"gameTime": "وقت اللعب:",
"joinMarathon": "انضم إلى ماراثون",
"joinDemoMarathon": "انضم إلى الماراثون التجريبي",
"demo":"تجريبي",
"demo": "تجريبي",
"minutes": "الدقائق",
"seconds": "ثواني",
"note": "ملحوظة:",
@ -517,12 +519,16 @@
"startingIn": "يبدأ في",
"youAreOutOfContest": "أنت خارج المسابقة.",
"winners": "الفائزين!!!",
"expireAfter":"تنتهي بعد",
"oneWeek":"أسبوع 1",
"twoWeek":"2 أسبوع",
"expireAfter": "تنتهي بعد",
"oneWeek": "أسبوع 1",
"twoWeek": "2 أسبوع",
"noUpcoming": "لا يوجد قادم",
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية",
"noWinner": "حزين! لم يفز أحد اليوم.",
"myTeam" : "فريقي",
"youCanPlayDemo": "لكن يمكنك لعب العرض"
"myTeam": "فريقي",
"youCanPlayDemo": "لكن يمكنك لعب العرض",
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI",
"itgForms": "نماذج (ITG)",
"resetAdPassword": "إعادة تعيين كلمة مرور AD"
}

@ -43,6 +43,7 @@
"newString": "New",
"setTheNewPassword": "Set the new password",
"typeYourNewPasswordBelow": "Type your new password below",
"typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below",
"confirmPassword": "Confirm Password",
"update": "Update",
"title": "Title",
@ -404,7 +405,8 @@
"stamp": "Stamp",
"addFavoriteList": "Do you want to add {name} in your favorite list",
"feedbackUserExperience": "This is to get the feedback about the user experience",
"rateUI": "1. How would you rate this UI?",
"rateUI": "How would you like to rate",
"rateUI2": "How do you satisfied with this application",
"submitSurvey": "Submit Survey",
"typeHere": "Type here",
"infoDetail": "Info Detail",
@ -424,7 +426,7 @@
"typeCurrentPasswordBelow": "Type Your Current password below",
"currentPassword": "Current password",
"concurrentReports": "Concurrent Reports",
"EnterNewAddressMoved" : "Enter a new address if you have moved",
"EnterNewAddressMoved": "Enter a new address if you have moved",
"CorrectAddress": "Correct or amend this address",
"SelectChangeWantToMake": "Select the type of change you want to make",
"profile": {
@ -469,7 +471,7 @@
"gameTime": "Game Time:",
"joinMarathon": "Join Marathon",
"joinDemoMarathon": "Join Demo Marathon",
"demo":"Demo",
"demo": "Demo",
"minutes": "Minutes",
"seconds": "Seconds",
"note": "Note:",
@ -517,12 +519,16 @@
"startingIn": "Starting in",
"youAreOutOfContest": "You are out of the contest.",
"winners": "WINNERS!!!",
"expireAfter":"Expires After",
"oneWeek":"1 Week",
"twoWeek":"2 Week",
"expireAfter": "Expires After",
"oneWeek": "1 Week",
"twoWeek": "2 Week",
"noUpcoming": "There is no upcoming",
"fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.",
"noWinner": "Sad! No one won today.",
"myTeam" : "My Team",
"youCanPlayDemo": "But you can play demo"
"myTeam": "My Team",
"youCanPlayDemo": "But you can play demo",
"connectHmgWifi": "Connect HMG WIFI",
"connectedHmgWifi": "Connected HMG WIFI",
"itgForms": "ITG Forms",
"resetAdPassword": "Reset AD Password"
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 60 KiB

@ -251,7 +251,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
};
C4CFBC4C5CAC00182015ACD5 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
@ -369,12 +369,12 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Al Habib Mohemm";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.6;
MARKETING_VERSION = 3.6.3;
PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.alhabibmohemm;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -507,12 +507,12 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Al Habib Mohemm";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.6;
MARKETING_VERSION = 3.6.3;
PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.alhabibmohemm;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -537,12 +537,12 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Al Habib Mohemm";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.6;
MARKETING_VERSION = 3.6.3;
PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.alhabibmohemm;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

@ -31,7 +31,8 @@ class ChatApiClient {
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
"isMobile": true,
"deviceToken": AppState().getDeviceToken,
"deviceToken":AppState().getIsHuawei ? AppState().getHuaweiPushToken : AppState().getDeviceToken,
"isHuaweiDevice": AppState().getIsHuawei,
},
);

@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/models/dashboard/list_menu.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/itg/itg_main_response.dart';
import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:platform_device_id/platform_device_id.dart';
import 'package:uuid/uuid.dart';
class DashboardApiClient {
@ -111,7 +112,8 @@ class DashboardApiClient {
// Generate a v4 (random) id
Map<String, dynamic> postParams = {
"UID": uuid.v4(), //Mobile Id
"UID": await PlatformDeviceId.getDeviceId, //uuid.v4(), //Mobile Id
// "UID": uuid.v4(), //Mobile Id
"Latitude": lat,
"Longitude": long,
"QRValue": QRValue,
@ -199,17 +201,18 @@ class DashboardApiClient {
}, url, postParams);
}
// Future setAdvertisementViewed(String masterID, int advertisementId) async {
// String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed";
//
// Map<String, dynamic> postParams = {
// "ItgNotificationMasterId": masterID,
// "ItgAdvertisement": {"advertisementId": advertisementId, "acknowledgment": true} //Mobile Id
// };
// postParams.addAll(AppState().postParamsJson);
// return await ApiClient().postJsonForObject((json) {
// // ItgMainRes responseData = ItgMainRes.fromJson(json);
// return json;
// }, url, postParams);
// }
Future setAdvertisementViewed(String masterID, int advertisementId) async {
String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed";
Map<String, dynamic> postParams = {
"ItgNotificationMasterId": masterID,
"EmployeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"ItgAdvertisement": {"advertisementId": advertisementId, "acknowledgment": true} //Mobile Id
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
// ItgMainRes responseData = ItgMainRes.fromJson(json);
return json;
}, url, postParams);
}
}

@ -85,7 +85,7 @@ class ItemsForSaleApiClient {
"employeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER,
"MobileNo": AppState().memberInformationList?.eMPLOYEEMOBILENUMBER,
"itemSaleID": itemSaleID.toString(),
"Channel": "31",
"Channel": "33",
"isActive": "false",
"Token": AppState().postParamsObject?.tokenID
};

@ -145,4 +145,15 @@ class LoginApiClient {
return responseData;
}, url, postParams);
}
Future<GenericResponseModel> changePasswordFromActiveDirectorySession(String password, String email) async {
String url = "${ApiConsts.authenticationRest}SetPassword";
Map<String, dynamic> postParams = {"EmailAddress": email, "Password": password, "generalid": "Cs2020@2016\$2958"};
postParams.addAll(AppState().postParamsJson);
postParams["LogInTokenID"] = "@acT!V3D!r3Ct0rY"; // hard code token for active directory
return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData;
}, url, postParams);
}
}

@ -34,6 +34,20 @@ class MarathonApiClient {
);
}
Future<int> getMarathonersCount({required String marathonId}) async {
Response response = await ApiClient().getJsonForResponse(
ApiConsts.marathonGetMarathonersCount + '?marathonId=$marathonId',
token: AppState().getMarathonToken == null || AppState().getMarathonToken == "" ? await getMarathonToken() : AppState().getMarathonToken,
);
var json = jsonDecode(response.body);
logger.i("json in getMarathonersCount: $json");
MarathonGenericModel marathonGenericModel = MarathonGenericModel.fromJson(json);
return marathonGenericModel.data as int;
}
Future<String> getProjectId() async {
return await ApiClient().postJsonForObject(
(json) {
@ -47,7 +61,7 @@ class MarathonApiClient {
}
Future<MarathonDetailModel> getMarathonDetails() async {
String payrollString = AppState().postParamsObject?.payrollCodeStr.toString() ?? "CS";
String payrollString = AppState().postParamsObject?.payrollCodeStr.toString() ?? "HMG";
Response response = await ApiClient().getJsonForResponse(
ApiConsts.marathonUpcomingUrl + payrollString,
@ -73,8 +87,8 @@ class MarathonApiClient {
Future<int?> joinMarathonAsParticipant() async {
Map<String, String> jsonObject = <String, String>{
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "",
"employeeNameAr": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
"employeeNameEn": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
"employeeNameAr": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
"employeeNameEn": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
"marathonId": AppState().getMarathonProjectId!,
};

@ -166,7 +166,7 @@ class ProfileApiClient {
],
"P_CONTACT_RELATIONSHIP_ID": contactRelationId,
"P_ACTION": actionType,
"PayrollCodeStr": AppState().postParamsObject?.payrollCodeStr,
"PayrollCodeStr": "HMG",
"LegislationCodeStr": "SA",
};
postParams.addAll(AppState().postParamsJson);

@ -14,6 +14,8 @@ import 'package:mohem_flutter_app/models/get_mo_notification_body_list_model.dar
import 'package:mohem_flutter_app/models/get_notification_buttons_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
import 'package:mohem_flutter_app/models/get_stamp_ms_notification_body_list_model.dart';
@ -46,7 +48,7 @@ class WorkListApiClient {
Map<String, dynamic> postParams = {
"P_NOTIFICATION_TYPE": pNotificationType,
"P_PAGE_NUM": pPageNum,
"P_PAGE_LIMIT": 25,
"P_PAGE_LIMIT": 20,
"P_ITEM_TYPE": pItemType,
"P_SEARCH_FROM_USER": pSearchUser,
"P_SEARCH_ITEM_TYPE_DSP_NAME": pSearchItemType,
@ -90,6 +92,16 @@ class WorkListApiClient {
}, url, postParams);
}
Future<List<GetAttachementList>> getPRAttachments(String pOLineID) async {
String url = "${ApiConsts.erpRest}GET_PR_ATTACHMENTS";
Map<String, dynamic> postParams = {"P_PO_LINE_ID": pOLineID};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData.getPRAttachmentList ?? [];
}, url, postParams);
}
Future<List<GetRFCEmployeeList>> getRFCEmployeeeList(int pNotificationID) async {
String url = "${ApiConsts.erpRest}GET_RFC_EMPLOYEE_LIST";
Map<String, dynamic> postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_PAGE_NUM": 1, "P_PAGE_LIMIT": 10};
@ -114,6 +126,20 @@ class WorkListApiClient {
}, url, postParams);
}
Future<List<GetPRActionHistoryList>> getActionHistoryForPR(String pOLineID) async {
String url = "${ApiConsts.erpRest}GET_PR_ACTION_HISTORY";
Map<String, dynamic> postParams = {
"P_PO_LINE_ID": pOLineID,
"P_PAGE_LIMIT": 100,
"P_PAGE_NUM": 1,
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData.getPRActionHistoryList?.reversed.toList() ?? [];
}, url, postParams);
}
Future<List<GetNotificationButtonsList>> getNotificationButtons(int pNotificationID) async {
String url = "${ApiConsts.erpRest}GET_NOTIFICATION_BUTTONS";
Map<String, dynamic> postParams = {"P_NOTIFICATION_ID": pNotificationID};
@ -413,7 +439,7 @@ class WorkListApiClient {
"EmployeeNumber": employeeNumber,
"Comments": "",
"AdditionalFields": null,
"NewUserEMPId":newUserEMPId
"NewUserEMPId": newUserEMPId
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
@ -589,7 +615,8 @@ class WorkListApiClient {
}, url, postParams);
}
Future<GenericResponseModel> submitComment({String? comment, String? email, String? userId, int? notificationId, required String apiMode, int? approverIndex = null}) async {
Future<GenericResponseModel> submitComment(
{String? comment, String? email, String? userId, int? notificationId, required String apiMode, int? approverIndex = null, List<Map<String, dynamic>>? attributeData = const []}) async {
String url = "${ApiConsts.erpRest}NOTIFICATION_ACTIONS";
Map<String, dynamic> postParams = {
"P_COMMENTS": comment,
@ -598,7 +625,7 @@ class WorkListApiClient {
"P_FORWARD_TO_USER_NAME": userId,
"P_NOTIFICATION_ID": notificationId,
"P_APPROVER_INDEX": approverIndex,
"RespondAttributeList": []
"RespondAttributeList": attributeData
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
@ -626,4 +653,18 @@ class WorkListApiClient {
return responseData.updateUserItemTypesList;
}, url, postParams);
}
Future<GetPRInformationList?> getPRDetailsForPO(String poLineID) async {
String url = "${ApiConsts.erpRest}GET_PR_INFORMATION";
Map<String, dynamic> postParams = {
"P_PO_LINE_ID": poLineID,
"P_PAGE_LIMIT": 100,
"P_PAGE_NUM": 1,
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData.getPRInformationList;
}, url, postParams);
}
}

@ -45,6 +45,8 @@ class AppState {
String? get getForgetPasswordTokenID => forgetPasswordTokenID;
bool isConnectedToHMG = false;
//Wifi info
String? _mohemmWifiSSID;
@ -88,7 +90,7 @@ class AppState {
String get getHuaweiPushToken => _huaweiPushToken;
final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 33, versionID: 4.2, mobileType: Platform.isAndroid ? "android" : "ios");
final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 33, versionID: 4.8, mobileType: Platform.isAndroid ? "android" : "ios");
void setPostParamsInitConfig() {
isAuthenticated = false;

@ -3,11 +3,12 @@ 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/";
static String authenticationRest = baseUrlServices + "Authentication.svc/REST/";
static String erpRest = baseUrlServices + "ERP.svc/REST/";
static String swpRest = baseUrlServices + "SWP.svc/REST/";
static String user = baseUrlServices + "api/User/";
@ -37,6 +38,7 @@ class ApiConsts {
static String marathonSubmitAnswerUrl = marathonBaseUrl + "question/submit";
static String marathonQualifiersUrl = marathonBaseUrl + "winner/getWinner/";
static String marathonSelectedWinner = marathonBaseUrl + "winner/getSelectedWinner/";
static String marathonGetMarathonersCount = marathonBaseUrl + "Participant/GetRemainingParticipants";
//DummyCards for the UI
static CardContent dummyQuestion = const CardContent();

@ -9,4 +9,5 @@ class MyLottieConsts {
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";
static const String audioPlaybackLottie = "assets/lottie/audio_playback.json";
}

@ -0,0 +1,21 @@
import 'package:flutter/foundation.dart';
import 'package:just_audio/just_audio.dart';
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',
);
}
}

@ -4,7 +4,8 @@ import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
// import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
import 'package:huawei_push/huawei_push.dart' as huawei_push;
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
@ -19,7 +20,7 @@ class AppNotifications {
factory AppNotifications() => _instance;
late HmsApiAvailability hmsApiAvailability;
// late HmsApiAvailability hmsApiAvailability;
String _huaweiToken = '';
@ -40,9 +41,9 @@ class AppNotifications {
}
void init(String? firebaseToken) async {
if (Platform.isAndroid) {
hmsApiAvailability = HmsApiAvailability();
}
// if (Platform.isAndroid) {
// hmsApiAvailability = HmsApiAvailability();
// }
await requestPermissions();
AppState().setDeviceToken = firebaseToken;
@ -68,22 +69,22 @@ class AppNotifications {
});
if (Platform.isAndroid) {
await hmsApiAvailability.isHMSAvailable().then((value) async {
if (value == 0) {
huawei_push.Push.enableLogger();
var result = await huawei_push.Push.setAutoInitEnabled(true);
huawei_push.Push.onNotificationOpenedApp.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
huawei_push.Push.onMessageReceivedStream.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
}
}).catchError((err) {
print(err);
});
// await hmsApiAvailability.isHMSAvailable().then((value) async {
if (!(await Utils.isGoogleServicesAvailable())) {
huawei_push.Push.enableLogger();
var result = await huawei_push.Push.setAutoInitEnabled(true);
huawei_push.Push.onNotificationOpenedApp.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
huawei_push.Push.onMessageReceivedStream.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
}
// }).catchError((err) {
// print(err);
// });
}
}
@ -101,6 +102,7 @@ class AppNotifications {
}
void _onTokenError(Object error) {
print(error.toString());
print("TOKEN ERROOORRRRR!!!!:");
}
@ -117,8 +119,10 @@ class AppNotifications {
}
void _handleOpenApp(RemoteMessage message) {
Utils.saveStringFromPrefs("isAppOpendByChat", "true");
Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString());
if (message.data.isNotEmpty && message.data["type"] == 'chat') {
Utils.saveStringFromPrefs("isAppOpendByChat", "true");
Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString());
}
}
}
@ -132,4 +136,7 @@ Future<dynamic> backgroundMessageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
Utils.saveStringFromPrefs("isAppOpendByChat", "false");
Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString());
if (message.data.isNotEmpty && message.data["type"] == 'call') {
// ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message);
}
}

@ -7,6 +7,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_api_availability/google_api_availability.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/config/routes.dart';
@ -390,4 +391,14 @@ class Utils {
print(err);
});
}
//HUAWEI DECISION MAKING
static Future<bool> isGoogleServicesAvailable() async {
GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability();
String status = availability.toString().split('.').last;
if (status == "success") {
return true;
}
return false;
}
}

@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart';
import 'package:mohem_flutter_app/ui/chat/chat_home.dart';
import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart';
import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart';
import 'package:mohem_flutter_app/ui/landing/today_attendance_screen2.dart';
@ -177,6 +178,7 @@ class AppRoutes {
static const String subordinateLeave = "/subordinateLeave";
static const String changePassword = "/changePassword";
static const String changeItgAdPasswordScreen = "/changeItgAdPasswordScreen";
//Chat
static const String chat = "/chat";
@ -289,7 +291,7 @@ class AppRoutes {
subordinateLeave: (BuildContext context) => SubordinateLeave(),
changePassword: (BuildContext context) => ChangePasswordScreen(),
changeItgAdPasswordScreen: (BuildContext context) => ChangeItgAdPasswordScreen(),
//Chat
chat: (BuildContext context) => ChatHome(),
chatDetailed: (BuildContext context) => ChatDetailScreen(),

@ -22,6 +22,17 @@ extension TrimString on String {
}
}
String displayLocalizedContent({required bool isPhoneLangArabic, required int selectedLanguage, required String englishContent, required String arabicContent}) {
if (selectedLanguage == 1) {
return englishContent;
} else if (selectedLanguage == 2) {
return arabicContent;
} else if (selectedLanguage == 3) {
return isPhoneLangArabic ? arabicContent : englishContent;
}
return englishContent;
}
extension EmailValidator on String {
Widget get toWidget => Text(this);
@ -111,9 +122,10 @@ extension EmailValidator on String {
decoration: isUnderLine ? TextDecoration.underline : null),
);
Widget toText16({Color? color, bool isUnderLine = false, bool isBold = false, int? maxlines, double? height}) => Text(
Widget toText16({Color? color, bool isUnderLine = false, bool isBold = false, int? maxlines, double? height, bool isCentered = false}) => Text(
this,
maxLines: maxlines,
textAlign: isCentered ? TextAlign.center : null,
style: TextStyle(
color: color ?? MyColors.darkTextColor,
fontSize: 16,

@ -59,6 +59,7 @@ class CodegenLoader extends AssetLoader{
"newString": "جديد",
"setTheNewPassword": "قم بتعيين كلمة المرور الجديدة",
"typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه",
"typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه",
"confirmPassword": "تأكيد كلمة المرور",
"update": "تحديث",
"title": "عنوان",
@ -420,7 +421,8 @@ class CodegenLoader extends AssetLoader{
"stamp": "ختم",
"addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله",
"feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم",
"rateUI": ".1 كيف تريد تقييم التطبيق",
"rateUI": "كيف تريد أن تقيم",
"rateUI2": "ما مدى رضائك عن هذا التطبيق",
"submitSurvey": "ارسال الاستبيان",
"typeHere": "اكتب هنا",
"infoDetail": "تفاصيل المعلومات",
@ -540,7 +542,11 @@ class CodegenLoader extends AssetLoader{
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية",
"noWinner": "حزين! لم يفز أحد اليوم.",
"myTeam": "فريقي",
"youCanPlayDemo": "لكن يمكنك لعب العرض"
"youCanPlayDemo": "لكن يمكنك لعب العرض",
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI",
"itgForms": "نماذج (ITG)",
"resetAdPassword": "إعادة تعيين كلمة مرور AD"
};
static const Map<String,dynamic> en_US = {
"mohemm": "Mohemm",
@ -587,6 +593,7 @@ static const Map<String,dynamic> en_US = {
"newString": "New",
"setTheNewPassword": "Set the new password",
"typeYourNewPasswordBelow": "Type your new password below",
"typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below",
"confirmPassword": "Confirm Password",
"update": "Update",
"title": "Title",
@ -948,7 +955,8 @@ static const Map<String,dynamic> en_US = {
"stamp": "Stamp",
"addFavoriteList": "Do you want to add {name} in your favorite list",
"feedbackUserExperience": "This is to get the feedback about the user experience",
"rateUI": "1. How would you rate this UI?",
"rateUI": "How would you like to rate",
"rateUI2": "How do you satisfied with this application",
"submitSurvey": "Submit Survey",
"typeHere": "Type here",
"infoDetail": "Info Detail",
@ -1068,7 +1076,11 @@ static const Map<String,dynamic> en_US = {
"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"
"youCanPlayDemo": "But you can play demo",
"connectHmgWifi": "Connect HMG WIFI",
"connectedHmgWifi": "Connected HMG WIFI",
"itgForms": "ITG Forms",
"resetAdPassword": "Reset AD Password"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -44,6 +44,7 @@ abstract class LocaleKeys {
static const newString = 'newString';
static const setTheNewPassword = 'setTheNewPassword';
static const typeYourNewPasswordBelow = 'typeYourNewPasswordBelow';
static const typeYourNewActiveDirectoryPasswordBelow = 'typeYourNewActiveDirectoryPasswordBelow';
static const confirmPassword = 'confirmPassword';
static const update = 'update';
static const title = 'title';
@ -406,6 +407,7 @@ abstract class LocaleKeys {
static const addFavoriteList = 'addFavoriteList';
static const feedbackUserExperience = 'feedbackUserExperience';
static const rateUI = 'rateUI';
static const rateUI2 = 'rateUI2';
static const submitSurvey = 'submitSurvey';
static const typeHere = 'typeHere';
static const infoDetail = 'infoDetail';
@ -511,5 +513,9 @@ abstract class LocaleKeys {
static const noWinner = 'noWinner';
static const myTeam = 'myTeam';
static const youCanPlayDemo = 'youCanPlayDemo';
static const connectHmgWifi = 'connectHmgWifi';
static const connectedHmgWifi = 'connectedHmgWifi';
static const itgForms = 'itgForms';
static const resetAdPassword = 'resetAdPassword';
}

@ -13,10 +13,10 @@ import 'package:firebase_core_web/firebase_core_web.dart';
import 'package:firebase_messaging_web/firebase_messaging_web.dart';
import 'package:fluttertoast/fluttertoast_web.dart';
import 'package:geolocator_web/geolocator_web.dart';
import 'package:google_maps_flutter_web/google_maps_flutter_web.dart';
// import 'package:google_maps_flutter_web/google_maps_flutter_web.dart';
import 'package:image_picker_for_web/image_picker_for_web.dart';
import 'package:just_audio_web/just_audio_web.dart';
import 'package:record_web/record_web.dart';
// import 'package:record_web/record_web.dart';
import 'package:shared_preferences_web/shared_preferences_web.dart';
import 'package:url_launcher_web/url_launcher_web.dart';
import 'package:video_player_web/video_player_web.dart';
@ -32,10 +32,10 @@ void registerPlugins(Registrar registrar) {
FirebaseMessagingWeb.registerWith(registrar);
FluttertoastWebPlugin.registerWith(registrar);
GeolocatorPlugin.registerWith(registrar);
GoogleMapsPlugin.registerWith(registrar);
// GoogleMapsPlugin.registerWith(registrar);
ImagePickerPlugin.registerWith(registrar);
JustAudioPlugin.registerWith(registrar);
RecordPluginWeb.registerWith(registrar);
// RecordPluginWeb.registerWith(registrar);
SharedPreferencesPlugin.registerWith(registrar);
UrlLauncherPlugin.registerWith(registrar);
VideoPlayerPlugin.registerWith(registrar);

@ -28,6 +28,8 @@ import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart';
import 'package:mohem_flutter_app/models/get_notification_buttons_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
import 'package:mohem_flutter_app/models/get_schedule_shifts_details_list_model.dart';
@ -169,9 +171,11 @@ class GenericResponseModel {
List<GetAbsenceTransactionList>? getAbsenceTransactionList;
List<GetAccrualBalancesList>? getAccrualBalancesList;
List<GetActionHistoryList>? getActionHistoryList;
List<GetPRActionHistoryList>? getPRActionHistoryList;
List<GetAddressDffStructureList>? getAddressDffStructureList;
List<GetApprovesList>? getApprovesList;
List<GetAttachementList>? getAttachementList;
List<GetAttachementList>? getPRAttachmentList;
GetAttendanceTracking? getAttendanceTrackingList;
List<GetBasicDetColsStructureList>? getBasicDetColsStructureList;
List<GetBasicDetDffStructureList>? getBasicDetDffStructureList;
@ -226,6 +230,7 @@ class GenericResponseModel {
List<GetPoItemHistoryList>? getPoItemHistoryList;
GetPoNotificationBodyList? getPoNotificationBodyList;
GetPrNotificationBodyList? getPrNotificationBodyList;
GetPRInformationList? getPRInformationList;
List<GetQuotationAnalysisList>? getQuotationAnalysisList;
List<GetRFCEmployeeList>? getRFCEmployeeListList;
List<String>? getRespondAttributeValueList;
@ -434,10 +439,12 @@ class GenericResponseModel {
this.getAbsenceTransactionList,
this.getAccrualBalancesList,
this.getActionHistoryList,
this.getPRActionHistoryList,
this.getAddressDffStructureList,
this.getAddressNotificationBodyList,
this.getApprovesList,
this.getAttachementList,
this.getPRAttachmentList,
this.getAttendanceTrackingList,
this.getBasicDetColsStructureList,
this.getBasicDetDffStructureList,
@ -490,6 +497,7 @@ class GenericResponseModel {
this.getPoItemHistoryList,
this.getPoNotificationBodyList,
this.getPrNotificationBodyList,
this.getPRInformationList,
this.getQuotationAnalysisList,
this.getRFCEmployeeListList,
this.getRespondAttributeValueList,
@ -748,6 +756,13 @@ class GenericResponseModel {
});
}
if (json['PR_Action_History_List'] != null) {
getPRActionHistoryList = <GetPRActionHistoryList>[];
json['PR_Action_History_List'].forEach((v) {
getPRActionHistoryList!.add(GetPRActionHistoryList.fromJson(v));
});
}
if (json['GetAddressDffStructureList'] != null) {
getAddressDffStructureList = <GetAddressDffStructureList>[];
json['GetAddressDffStructureList'].forEach((v) {
@ -769,6 +784,14 @@ class GenericResponseModel {
getAttachementList!.add(GetAttachementList.fromJson(v));
});
}
if (json['PR_Attachments_List'] != null) {
getPRAttachmentList = <GetAttachementList>[];
json['PR_Attachments_List'].forEach((v) {
getPRAttachmentList!.add(GetAttachementList.fromJson(v));
});
}
getAttendanceTrackingList = json["GetAttendanceTrackingList"] == null ? null : GetAttendanceTracking.fromMap(json["GetAttendanceTrackingList"]);
if (json['GetBasicDetColsStructureList'] != null) {
getBasicDetColsStructureList = <GetBasicDetColsStructureList>[];
@ -979,6 +1002,7 @@ class GenericResponseModel {
}
getPoNotificationBodyList = json['GetPoNotificationBodyList'] != null ? GetPoNotificationBodyList.fromJson(json['GetPoNotificationBodyList']) : null;
getPrNotificationBodyList = json['GetPrNotificationBodyList'] != null ? GetPrNotificationBodyList.fromJson(json['GetPrNotificationBodyList']) : null;
getPRInformationList = json['PR_Information_List'] != null ? GetPRInformationList.fromJson(json['PR_Information_List']) : null;
if (json['GetQuotationAnalysisList'] != null) {
getQuotationAnalysisList = <GetQuotationAnalysisList>[];
json['GetQuotationAnalysisList'].forEach((v) {
@ -1602,6 +1626,10 @@ class GenericResponseModel {
data['GetPrNotificationBodyList'] = this.getPrNotificationBodyList!.toJson();
}
if (this.getPRInformationList != null) {
data['PR_Information_List'] = this.getPRInformationList!.toJson();
}
if (this.getQuotationAnalysisList != null) {
data['GetQuotationAnalysisList'] = this.getQuotationAnalysisList!.map((v) => v.toJson()).toList();
}

@ -158,6 +158,7 @@ class POLines {
String? nEEDBYDATE;
int? nOOFROWS;
int? pOHEADERID;
int? pOLINEID;
String? pROMISEDDATE;
String? pRNUM;
num? qUANTITY;
@ -181,6 +182,7 @@ class POLines {
this.nEEDBYDATE,
this.nOOFROWS,
this.pOHEADERID,
this.pOLINEID,
this.pROMISEDDATE,
this.pRNUM,
this.qUANTITY,
@ -204,6 +206,7 @@ class POLines {
nEEDBYDATE = json['NEED_BY_DATE'];
nOOFROWS = json['NO_OF_ROWS'];
pOHEADERID = json['PO_HEADER_ID'];
pOLINEID = json['PO_LINE_ID'];
pROMISEDDATE = json['PROMISED_DATE'];
pRNUM = json['PR_NUM'];
qUANTITY = json['QUANTITY'];
@ -229,6 +232,7 @@ class POLines {
data['NEED_BY_DATE'] = this.nEEDBYDATE;
data['NO_OF_ROWS'] = this.nOOFROWS;
data['PO_HEADER_ID'] = this.pOHEADERID;
data['PO_LINE_ID'] = this.pOLINEID;
data['PROMISED_DATE'] = this.pROMISEDDATE;
data['PR_NUM'] = this.pRNUM;
data['QUANTITY'] = this.qUANTITY;

@ -0,0 +1,68 @@
class GetPRActionHistoryList {
String? aCTION;
String? aCTIONCODE;
String? aPPROVALDATE;
String? eMAILADDRESS;
String? eMPLOYEEIMAGE;
int? fROMROWNUM;
String? nAME;
String? nOTE;
int? nOOFROWS;
String? pOSITIONTITLE;
int? rOWNUM;
int? sEQUENCE;
int? tOROWNUM;
Null? uSERNAME;
GetPRActionHistoryList(
{this.aCTION,
this.aCTIONCODE,
this.aPPROVALDATE,
this.eMAILADDRESS,
this.eMPLOYEEIMAGE,
this.fROMROWNUM,
this.nAME,
this.nOTE,
this.nOOFROWS,
this.pOSITIONTITLE,
this.rOWNUM,
this.sEQUENCE,
this.tOROWNUM,
this.uSERNAME});
GetPRActionHistoryList.fromJson(Map<String, dynamic> json) {
aCTION = json['ACTION'];
aCTIONCODE = json['ACTION_CODE'];
aPPROVALDATE = json['APPROVAL_DATE'];
eMAILADDRESS = json['EMAIL_ADDRESS'];
eMPLOYEEIMAGE = json['EMPLOYEE_IMAGE'];
fROMROWNUM = json['FROM_ROW_NUM'];
nAME = json['NAME'];
nOTE = json['NOTE'];
nOOFROWS = json['NO_OF_ROWS'];
pOSITIONTITLE = json['POSITION_TITLE'];
rOWNUM = json['ROW_NUM'];
sEQUENCE = json['SEQUENCE'];
tOROWNUM = json['TO_ROW_NUM'];
uSERNAME = json['USER_NAME'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['ACTION'] = this.aCTION;
data['ACTION_CODE'] = this.aCTIONCODE;
data['APPROVAL_DATE'] = this.aPPROVALDATE;
data['EMAIL_ADDRESS'] = this.eMAILADDRESS;
data['EMPLOYEE_IMAGE'] = this.eMPLOYEEIMAGE;
data['FROM_ROW_NUM'] = this.fROMROWNUM;
data['NAME'] = this.nAME;
data['NOTE'] = this.nOTE;
data['NO_OF_ROWS'] = this.nOOFROWS;
data['POSITION_TITLE'] = this.pOSITIONTITLE;
data['ROW_NUM'] = this.rOWNUM;
data['SEQUENCE'] = this.sEQUENCE;
data['TO_ROW_NUM'] = this.tOROWNUM;
data['USER_NAME'] = this.uSERNAME;
return data;
}
}

@ -0,0 +1,125 @@
class GetPRInformationList {
List<PRHeader>? pRHeader;
List<PRLines>? pRLines;
String? pCURRENCYCODE;
GetPRInformationList({this.pRHeader, this.pRLines, this.pCURRENCYCODE});
GetPRInformationList.fromJson(Map<String, dynamic> json) {
if (json['PRHeader'] != null) {
pRHeader = <PRHeader>[];
json['PRHeader'].forEach((v) {
pRHeader!.add(new PRHeader.fromJson(v));
});
}
if (json['PRLines'] != null) {
pRLines = <PRLines>[];
json['PRLines'].forEach((v) {
pRLines!.add(new PRLines.fromJson(v));
});
}
pCURRENCYCODE = json['P_CURRENCY_CODE'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
if (this.pRHeader != null) {
data['PRHeader'] = this.pRHeader!.map((v) => v.toJson()).toList();
}
if (this.pRLines != null) {
data['PRLines'] = this.pRLines!.map((v) => v.toJson()).toList();
}
data['P_CURRENCY_CODE'] = this.pCURRENCYCODE;
return data;
}
}
class PRHeader {
String? dESCRIPTION;
String? pRNUMBER;
String? rEQUISITIONTOTAL;
String? tAXTOTAL;
PRHeader({this.dESCRIPTION, this.pRNUMBER, this.rEQUISITIONTOTAL, this.tAXTOTAL});
PRHeader.fromJson(Map<String, dynamic> json) {
dESCRIPTION = json['DESCRIPTION'];
pRNUMBER = json['PR_NUMBER'];
rEQUISITIONTOTAL = json['REQUISITION_TOTAL'];
tAXTOTAL = json['TAX_TOTAL'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['DESCRIPTION'] = this.dESCRIPTION;
data['PR_NUMBER'] = this.pRNUMBER;
data['REQUISITION_TOTAL'] = this.rEQUISITIONTOTAL;
data['TAX_TOTAL'] = this.tAXTOTAL;
return data;
}
}
class PRLines {
String? cOSTCENTER;
String? dESCRIPTION;
int? fROMROWNUM;
int? iTEMAMU;
String? iTEMCODE;
int? lINEAMOUNT;
int? lINENUM;
int? nOOFROWS;
int? qUANTITY;
int? rOWNUM;
int? tOROWNUM;
int? uNITPRICE;
String? uOM;
PRLines(
{this.cOSTCENTER,
this.dESCRIPTION,
this.fROMROWNUM,
this.iTEMAMU,
this.iTEMCODE,
this.lINEAMOUNT,
this.lINENUM,
this.nOOFROWS,
this.qUANTITY,
this.rOWNUM,
this.tOROWNUM,
this.uNITPRICE,
this.uOM});
PRLines.fromJson(Map<String, dynamic> json) {
cOSTCENTER = json['COST_CENTER'];
dESCRIPTION = json['DESCRIPTION'];
fROMROWNUM = json['FROM_ROW_NUM'];
iTEMAMU = json['ITEM_AMU'];
iTEMCODE = json['ITEM_CODE'];
lINEAMOUNT = json['LINE_AMOUNT'];
lINENUM = json['LINE_NUM'];
nOOFROWS = json['NO_OF_ROWS'];
qUANTITY = json['QUANTITY'];
rOWNUM = json['ROW_NUM'];
tOROWNUM = json['TO_ROW_NUM'];
uNITPRICE = json['UNIT_PRICE'];
uOM = json['UOM'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['COST_CENTER'] = this.cOSTCENTER;
data['DESCRIPTION'] = this.dESCRIPTION;
data['FROM_ROW_NUM'] = this.fROMROWNUM;
data['ITEM_AMU'] = this.iTEMAMU;
data['ITEM_CODE'] = this.iTEMCODE;
data['LINE_AMOUNT'] = this.lINEAMOUNT;
data['LINE_NUM'] = this.lINENUM;
data['NO_OF_ROWS'] = this.nOOFROWS;
data['QUANTITY'] = this.qUANTITY;
data['ROW_NUM'] = this.rOWNUM;
data['TO_ROW_NUM'] = this.tOROWNUM;
data['UNIT_PRICE'] = this.uNITPRICE;
data['UOM'] = this.uOM;
return data;
}
}

@ -5,6 +5,7 @@
import 'dart:convert';
import 'package:mohem_flutter_app/models/itg/advertisement.dart';
import 'package:mohem_flutter_app/models/itg/survey_model.dart';
MohemmItgResponseItem mohemmItgResponseItemFromJson(String str) => MohemmItgResponseItem.fromJson(json.decode(str));
@ -103,7 +104,7 @@ class ItgResponseData {
final bool? isDeleted;
final bool? showDelete;
final Advertisement? advertisement;
final dynamic survey;
final SurveyModel? survey;
final dynamic isActive;
final dynamic pageSize;
final dynamic pageNo;
@ -126,7 +127,7 @@ class ItgResponseData {
isDeleted: json["isDeleted"] == null ? null : json["isDeleted"],
showDelete: json["showDelete"] == null ? null : json["showDelete"],
advertisement: json["advertisement"] == null ? null : Advertisement.fromJson(json["advertisement"]),
survey: json["survey"],
survey: json["survey"] == null ? null : SurveyModel.fromJson(json["survey"]),
isActive: json["isActive"],
pageSize: json["pageSize"],
pageNo: json["pageNo"],

@ -0,0 +1,148 @@
class SurveyModel {
int? surveyId;
String? referenceNo;
String? title;
String? description;
List<Questions>? questions;
bool? isActive;
Null? pageSize;
Null? pageNo;
Null? languageId;
SurveyModel({this.surveyId, this.referenceNo, this.title, this.description, this.questions, this.isActive, this.pageSize, this.pageNo, this.languageId});
SurveyModel.fromJson(Map<String, dynamic> json) {
surveyId = json['surveyId'];
referenceNo = json['referenceNo'];
title = json['title'];
description = json['description'];
if (json['questions'] != null) {
questions = <Questions>[];
json['questions'].forEach((v) {
questions!.add(new Questions.fromJson(v));
});
}
isActive = json['isActive'];
pageSize = json['pageSize'];
pageNo = json['pageNo'];
languageId = json['languageId'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['surveyId'] = this.surveyId;
data['referenceNo'] = this.referenceNo;
data['title'] = this.title;
data['description'] = this.description;
if (this.questions != null) {
data['questions'] = this.questions!.map((v) => v.toJson()).toList();
}
data['isActive'] = this.isActive;
data['pageSize'] = this.pageSize;
data['pageNo'] = this.pageNo;
data['languageId'] = this.languageId;
return data;
}
}
class Questions {
int? questionId;
String? title;
bool? isRequired;
String? type;
int? sequenceNo;
Null? surveyId;
List<Options>? options;
Null? rspPercentage;
Null? isActive;
Null? pageSize;
Null? pageNo;
Null? languageId;
Questions({this.questionId, this.title, this.isRequired, this.type, this.sequenceNo, this.surveyId, this.options, this.rspPercentage, this.isActive, this.pageSize, this.pageNo, this.languageId});
Questions.fromJson(Map<String, dynamic> json) {
questionId = json['questionId'];
title = json['title'];
isRequired = json['isRequired'];
type = json['type'];
sequenceNo = json['sequenceNo'];
surveyId = json['surveyId'];
if (json['options'] != null) {
options = <Options>[];
json['options'].forEach((v) {
options!.add(new Options.fromJson(v));
});
}
rspPercentage = json['rspPercentage'];
isActive = json['isActive'];
pageSize = json['pageSize'];
pageNo = json['pageNo'];
languageId = json['languageId'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['questionId'] = this.questionId;
data['title'] = this.title;
data['isRequired'] = this.isRequired;
data['type'] = this.type;
data['sequenceNo'] = this.sequenceNo;
data['surveyId'] = this.surveyId;
if (this.options != null) {
data['options'] = this.options!.map((v) => v.toJson()).toList();
}
data['rspPercentage'] = this.rspPercentage;
data['isActive'] = this.isActive;
data['pageSize'] = this.pageSize;
data['pageNo'] = this.pageNo;
data['languageId'] = this.languageId;
return data;
}
}
class Options {
int? optionId;
String? title;
bool? isCommentsRequired;
int? sequenceNo;
int? questionId;
Null? rspPercentage;
Null? count;
Null? isActive;
Null? pageSize;
Null? pageNo;
Null? languageId;
Options({this.optionId, this.title, this.isCommentsRequired, this.sequenceNo, this.questionId, this.rspPercentage, this.count, this.isActive, this.pageSize, this.pageNo, this.languageId});
Options.fromJson(Map<String, dynamic> json) {
optionId = json['optionId'];
title = json['title'];
isCommentsRequired = json['isCommentsRequired'];
sequenceNo = json['sequenceNo'];
questionId = json['questionId'];
rspPercentage = json['rspPercentage'];
count = json['count'];
isActive = json['isActive'];
pageSize = json['pageSize'];
pageNo = json['pageNo'];
languageId = json['languageId'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['optionId'] = this.optionId;
data['title'] = this.title;
data['isCommentsRequired'] = this.isCommentsRequired;
data['sequenceNo'] = this.sequenceNo;
data['questionId'] = this.questionId;
data['rspPercentage'] = this.rspPercentage;
data['count'] = this.count;
data['isActive'] = this.isActive;
data['pageSize'] = this.pageSize;
data['pageNo'] = this.pageNo;
data['languageId'] = this.languageId;
return data;
}
}

@ -66,7 +66,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
if (attendanceTracking?.pSwipeIn != null) {
isTimeRemainingInSeconds = calculateSeconds(attendanceTracking!.pRemainingHours ?? "00:00:00");
int totalShiftTimeInSeconds = calculateSeconds(attendanceTracking!.pScheduledHours ?? "00:00:00");
if(isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) {
if (isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) {
progress = 0;
} else {
progress = (isTimeRemainingInSeconds / totalShiftTimeInSeconds);
@ -245,7 +245,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
}
void getCategoryOffersListAPI(BuildContext context) async {
void getCategoryOffersListAPI(BuildContext context) async {
try {
// Utils.showLoading(context);
getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 10);
@ -262,7 +262,25 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List<Menus> menus = [];
for (int i = 0; i < getMenuEntriesList.length; i++) {
if (getMenuEntriesList[i].parentMenuName!.isEmpty) {
menus.add(Menus(getMenuEntriesList[i], getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList()));
GetMenuEntriesList abc = GetMenuEntriesList(requestType: "itg_forms", prompt: LocaleKeys.itgForms.tr());
List<GetMenuEntriesList> list = getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList();
if (getMenuEntriesList[i].menuName == "MBL_E_PROFESSIONALS_01") {
// hard coding this check to add change password for Active Directory
GetMenuEntriesList activeDirectoryEntry = GetMenuEntriesList(
requestType: "RESET_ITG_AD_PASSWORD",
prompt: LocaleKeys.resetAdPassword.tr(),
parentMenuName: 'ITG_FORMS',
menuName: LocaleKeys.itgForms.tr(),
menuEntryType: "FUNCTION", //Reset AD Password
);
getMenuEntriesList.add(activeDirectoryEntry);
list.add(GetMenuEntriesList(requestType: "ITG_FORMS", prompt: LocaleKeys.itgForms.tr(), menuName: 'ITG_FORMS'));
}
menus.add(Menus(getMenuEntriesList[i], list));
}
}
return menus;
@ -272,6 +290,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification();
return res;
}
void notify() {
notifyListeners();
}

@ -0,0 +1,46 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:wifi_iot/wifi_iot.dart';
class HmgConnectionProvider extends ChangeNotifier {
bool isConnectedToHMG = false;
Future<bool> checkHmgNetworkConnectivity() async {
if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) {
isConnectedToHMG = true;
} else {
isConnectedToHMG = false;
}
AppState().isConnectedToHMG = isConnectedToHMG;
return isConnectedToHMG;
}
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);
await Future.delayed(const Duration(seconds: 2));
isConnectedToHMG=true;
}
} catch (e) {
isConnectedToHMG = false;
AppState().isConnectedToHMG = isConnectedToHMG;
print("----------------o----");
print(e);
}
}
Future<bool> closeWifiRequest() async {
if (Platform.isAndroid) {
await WiFiForIoTPlugin.forceWifiUsage(false);
}
isConnectedToHMG = false;
AppState().isConnectedToHMG = isConnectedToHMG;
return await WiFiForIoTPlugin.disconnect();
}
}

@ -8,6 +8,7 @@ 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';
import 'package:mohem_flutter_app/classes/my_custom_stream.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
@ -429,7 +430,7 @@ class ChatBubble extends StatelessWidget {
Widget getPlayer({required AudioPlayer player, required SingleUserChatModel modelData}) {
return StreamBuilder<PlayerState>(
stream: player!.playerStateStream,
stream: player.playerStateStream,
builder: (BuildContext context, AsyncSnapshot<PlayerState> snapshot) {
PlayerState? playerState = snapshot.data;
ProcessingState? processingState = playerState?.processingState;
@ -442,7 +443,7 @@ class ChatBubble extends StatelessWidget {
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return Icon(
return const Icon(
Icons.play_arrow,
size: 30,
color: MyColors.lightGreenColor,
@ -470,22 +471,3 @@ class ChatBubble extends StatelessWidget {
);
}
}
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',
);
}
}

@ -14,7 +14,7 @@ class BusinessCardDialog extends StatelessWidget {
child: Container(
// width: MediaQuery.of(context).size.height / 2,
color: Colors.white,
margin: EdgeInsets.all(12),
margin: EdgeInsets.all(21),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@ -34,7 +34,7 @@ class BusinessCardDialog extends StatelessWidget {
width: 120,
height: 120,
),
// 12.height,
12.height,
(AppState().memberInformationList!.eMPLOYEENAME ?? "").toText20(isBold: true),
],
),

@ -16,7 +16,6 @@ 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/offers_and_discounts/get_offers_list.dart';
import 'package:mohem_flutter_app/models/privilege_list_model.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
@ -98,7 +97,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
cProvider.getUserAutoLoginToken().whenComplete(() async {
if (!cProvider.disbaleChatForThisUser) {
String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat");
if (isAppOpendByChat != null && isAppOpendByChat == "true") {
if (isAppOpendByChat != "null" && isAppOpendByChat == "true") {
Utils.showLoading(context);
cProvider.buildHubConnection();
Future.delayed(const Duration(seconds: 2), () async {
@ -128,11 +127,21 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
if (chatHubConnection.state == HubConnectionState.Connected) {
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.chat);
String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat");
if (isAppOpendByChat != "null" || isAppOpendByChat == "true") {
Utils.saveStringFromPrefs("isAppOpendByChat", "false");
Utils.saveStringFromPrefs("notificationData", "null");
}
}
}
void _onRefresh(bool isFromInit) async {
data.initProvider();
// data.getITGNotification().then((value) {
// print("--------------------detail_1-----------------");
// print(value!.result!.data!.notificationMasterId);
// print(value.result!.data!.notificationTitle);
// });
data.fetchListMenu();
data.fetchAttendanceTracking(context);
data.fetchWorkListCounter(context);
@ -141,54 +150,55 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
data.fetchMenuEntries();
data.getCategoryOffersListAPI(context);
marathonProvider.getMarathonDetailsFromApi();
if (!cProvider.disbaleChatForThisUser && !isFromInit && checkIfPrivilegedForChat()) checkHubCon();
if (isFromInit) {
checkERMChannel();
}
if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon();
_refreshController.refreshCompleted();
}
void checkERMChannel() {
data.getITGNotification().then((val) {
if (val!.result!.data != null) {
print("-------------------- Survey ----------------------------");
if (val.result!.data!.notificationType == "Survey") {
DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then(
(value) {
if (value!.mohemmItgResponseItem!.statusCode == 200) {
if (value.mohemmItgResponseItem!.result!.data != null) {
// Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data);
Navigator.pushNamed(context, AppRoutes.survey, arguments: value.mohemmItgResponseItem!.result!.data);
// Navigator.pushNamed(context, AppRoutes.advertisement, arguments: {
// "masterId": val.result!.data!.notificationMasterId,
// "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement,
// });
}
}
},
);
} else {
print("------------------------------------------- Ads --------------------");
DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then(
(value) {
if (value!.mohemmItgResponseItem!.statusCode == 200) {
if (value.mohemmItgResponseItem!.result!.data != null) {
Navigator.pushNamed(context, AppRoutes.advertisement, arguments: {
"masterId": val.result!.data!.notificationMasterId,
"advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement,
});
}
}
},
);
}
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldState,
// appBar: AppBar(
// actions: [
// IconButton(
// onPressed: () {
// data.getITGNotification().then((val) {
// if (val!.result!.data != null) {
// print("-------------------- Survey ----------------------------");
// if (val.result!.data!.notificationType == "Survey") {
// Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data);
// } else {
// print("------------------------------------------- Ads --------------------");
// DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then(
// (value) {
// if (value!.mohemmItgResponseItem!.statusCode == 200) {
// if (value.mohemmItgResponseItem!.result!.data != null) {
// Navigator.pushNamed(context, AppRoutes.advertisement, arguments: {
// "masterId": val.result!.data!.notificationMasterId,
// "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement,
// });
//
// // Navigator.push(
// // context,
// // MaterialPageRoute(
// // builder: (BuildContext context) => ITGAdsScreen(
// // addMasterId: val.result!.data!.notificationMasterId!,
// // advertisement: value.mohemmItgResponseItem!.result!.data!.advertisement!,
// // ),
// // ),
// // );
// }
// }
// },
// );
// }
// }
// });
// },
// icon: Icon(Icons.add))
// ],
// ),
body: Column(
children: [
Row(
@ -249,7 +259,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color),
(AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true),
16.height,
@ -447,7 +457,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!,
transitionOnUserGestures: true,
child: Image.network(
data.getOffersList[index].logo!,
data.getOffersList[index].logo ?? "",
fit: BoxFit.contain,
),
),
@ -634,7 +644,6 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
}
}
});
Navigator.pushNamed(context, AppRoutes.offersAndDiscountsDetails, arguments: getOffersDetailList);
}
}

@ -0,0 +1,166 @@
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/login_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/input_widget.dart';
class ChangeItgAdPasswordScreen extends StatefulWidget {
ChangeItgAdPasswordScreen({Key? key}) : super(key: key);
@override
_ChangeItgAdPasswordScreenState createState() {
return _ChangeItgAdPasswordScreenState();
}
}
class _ChangeItgAdPasswordScreenState extends State<ChangeItgAdPasswordScreen> {
TextEditingController password = TextEditingController();
TextEditingController confirmPassword = TextEditingController();
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
void setNewPassword() async {
Utils.showLoading(context);
try {
GenericResponseModel response = await LoginApiClient().changePasswordFromActiveDirectorySession(password.text, AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!);
Utils.hideLoading(context);
if ((response.messageStatus ?? 0) == 1) {
Utils.showToast(LocaleKeys.passwordChangedSuccessfully.tr());
Navigator.pop(context);
}
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {
Utils.confirmDialog(context, msg);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
onPressed: () => Navigator.pop(context),
),
),
body: Column(
children: [
ListView(
padding: const EdgeInsets.all(21),
children: [
LocaleKeys.changePassword.tr().toText24(isBold: true),
LocaleKeys.typeYourNewActiveDirectoryPasswordBelow.tr().toText16(),
16.height,
InputWidget(
LocaleKeys.password.tr(),
"**********",
password,
onChange: (value) {
setState(() {});
},
),
12.height,
InputWidget(
LocaleKeys.confirmPassword.tr(),
"**********",
confirmPassword,
isTextIsPassword: true,
onChange: (value) {
setState(() {});
},
),
16.height,
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.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.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text),
],
).expanded,
DefaultButton(LocaleKeys.changePassword.tr(), (!isPasswordCompliant(password.text, 8)) ? null : setNewPassword).insideContainer
],
),
);
}
bool checkRegEx(String pattern) {
return RegExp(pattern).hasMatch(password.text);
}
String recentPassword = "";
bool isPasswordCompliant(String? password, int minLength) {
if (password == null || password.isEmpty) {
return false;
}
// 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 hasMinLength = password.length >= minLength;
bool isMatched = password == confirmPassword.text;
return hasDigits && hasLowercase && hasMinLength && isMatched && checkRepeatedChars(password);
}
bool checkRepeatedChars(String password) {
bool isNonRepeatedLetters = true;
if (password.length > 2) {
for (int i = 0; i < password.length; i++) {
String char = password[i];
try {
if (char == password[i + 1]) {
isNonRepeatedLetters = false;
break;
}
} catch (ex) {}
}
}
return isNonRepeatedLetters;
}
Widget passwordConstraintsUI(String description, bool check) {
return Row(
children: [
4.width,
SizedBox(
width: 12,
height: 12,
child: Checkbox(fillColor: MaterialStateProperty.all(MyColors.gradiantEndColor), shape: const CircleBorder(), value: check, onChanged: null),
),
8.width,
description.toText14()
],
);
}
}

@ -2,10 +2,17 @@ import 'dart:convert';
import 'dart:io' as Io;
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:flutter_countdown_timer/index.dart';
import 'package:lottie/lottie.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/lottie_consts.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/itg/advertisement.dart' as ads;
import 'package:path_provider/path_provider.dart';
@ -24,11 +31,13 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
bool skip = false;
bool isVideo = false;
bool isImage = false;
bool isAudio = false;
String ext = '';
late File imageFile;
ads.Advertisement? advertisementData;
dynamic data;
String? masterID;
int videoDuration = 0;
void checkFileType() async {
String? rFile = advertisementData!.viewAttachFileColl!.first.base64String;
@ -38,11 +47,13 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
await processImage(rFile!);
isImage = true;
} else {
if (ext == ".aac") {
isAudio = true;
}
isVideo = true;
_futureController = createVideoPlayer(rFile!);
}
setState(() {});
initTimer();
}
Future processImage(String encodedBytes) async {
@ -76,26 +87,29 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
void initTimer() {
Future.delayed(const Duration(seconds: 5), () {
skip = true;
setState(() {});
// setState(() {});
});
}
@override
void dispose() {
_controller.dispose();
if (_controller != null) _controller.dispose();
// player.stop();
// player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
data = ModalRoute.of(context)!.settings.arguments;
if (advertisementData == null) advertisementData = data["advertisement"] as ads.Advertisement;
if (masterID == null) masterID = data["masterId"];
advertisementData ??= data["advertisement"] as ads.Advertisement;
masterID ??= data["masterId"];
if (advertisementData != null) {
checkFileType();
videoDuration = advertisementData?.durationInSeconds ?? 0;
}
// double height = MediaQuery.of(context).size.height * .25;
return Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: [
if (isVideo)
@ -104,11 +118,52 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
builder: (BuildContext context, AsyncSnapshot<Object?> snapshot) {
if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) {
_controller = snapshot.data as VideoPlayerController;
return Positioned.fill(
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
),
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: isAudio
? Lottie.asset(MyLottieConsts.audioPlaybackLottie)
: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
),
),
30.height,
CountdownTimer(
endTime: DateTime.now().millisecondsSinceEpoch + 1000 * videoDuration,
onEnd: null,
endWidget: "00:00:00".toText14(color: Colors.white, isBold: true),
textStyle: const TextStyle(color: Colors.white, fontSize: 16, letterSpacing: -0.48, fontWeight: FontWeight.bold),
),
50.height,
Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor))
.onPress(() {
try {
DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!).then((value) {
logger.d(value);
Navigator.pop(context);
});
} catch (ex) {
logger.wtf(ex);
Utils.handleException(ex, context, null);
}
}),
// DefaultButton(LocaleKeys.home.tr(), () async {
// DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!).then((value) {
// logger.d(value);
// });
// }).paddingOnly(left: 50, right: 50)
// ElevatedButton(
// onPressed: () async {
// // DashboardApiClient().setAdvertisementViewed(widget.addMasterId, widget.advertisement!.advertisementId!).then((value) {
// // logger.d(value);
// // });
// },
// child: const Text("Go To Dashboard"),
// )
],
);
} else {
return const Center(
@ -117,16 +172,28 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
}
},
),
if (isImage) Image.file(imageFile),
if (skip)
ElevatedButton(
onPressed: () async {
// DashboardApiClient().setAdvertisementViewed(widget.addMasterId, widget.advertisement!.advertisementId!).then((value) {
// logger.d(value);
// });
},
child: const Text("Go To Dashboard"),
)
if (isImage)
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.file(imageFile),
50.height,
Container(padding: const EdgeInsets.all(16), decoration: Utils.containerRadius(MyColors.white, 10), child: const Icon(Icons.thumb_up, color: MyColors.gradiantEndColor)).onPress(
() {
try {
DashboardApiClient().setAdvertisementViewed(masterID!, advertisementData!.advertisementId!).then((value) {
logger.d(value);
Navigator.pop(context);
});
} catch (ex) {
logger.wtf(ex);
Utils.handleException(ex, context, null);
}
},
),
],
),
],
),
);

@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
@ -7,15 +5,14 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/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/itg/itg_main_response.dart';
import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:mohem_flutter_app/models/itg/survey_model.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
class SurveyScreen extends StatefulWidget {
const SurveyScreen({Key? key}) : super(key: key);
@ -27,78 +24,50 @@ class SurveyScreen extends StatefulWidget {
class _SurveyScreenState extends State<SurveyScreen> {
String reviewText = "";
double starRating = 1;
int _selectedIndex = 5;
int _selectedIndex = 0;
ItgResponseData? itgResponseData;
List<String> answeredQuestions = [];
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(
(_) => initAnswersList(),
);
super.initState();
}
@override
Widget build(BuildContext context) {
if (itgResponseData == null) itgResponseData = ModalRoute.of(context)!.settings.arguments as ItgResponseData;
itgResponseData ??= ModalRoute.of(context)!.settings.arguments as ItgResponseData;
return Scaffold(
backgroundColor: MyColors.backgroundColor,
body: Column(
children: [
Expanded(
child: ListView(
scrollDirection: Axis.vertical,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
124.height,
LocaleKeys.feedbackUserExperience.tr().toText19(),
27.height,
LocaleKeys.rateUI.tr().toText16(),
22.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
RatingBar.builder(
initialRating: 3,
minRating: starRating,
direction: Axis.horizontal,
allowHalfRating: false,
itemCount: 5,
itemPadding: EdgeInsets.symmetric(horizontal: 8),
itemBuilder: (context, _) => Icon(
Icons.star,
color: Colors.amber,
),
onRatingUpdate: (rating) {
starRating = rating;
},
)
],
).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true),
39.height,
LocaleKeys.rateUI.tr().toText16(),
10.height,
GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7),
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.only(top: 0),
shrinkWrap: true,
children: [
optionUI("poor.svg", 1),
optionUI("bad.svg", 2),
optionUI("normal.svg", 3),
optionUI("good.svg", 4),
optionUI("xcellent.svg", 5),
],
),
27.height,
DynamicTextFieldWidget(
LocaleKeys.description.tr(),
LocaleKeys.typeHere.tr(),
lines: 3,
onChange: (v) {
reviewText = v;
},
),
150.height
],
).paddingOnly(left: 21, right: 21),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
32.height,
itgResponseData?.survey?.title?.toText24() ?? const Text(""),
8.height,
itgResponseData?.survey?.description?.toText16() ?? const Text(""),
ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: itgResponseData?.survey?.questions?.length,
itemBuilder: (cxt, index) {
return answeredQuestions.isNotEmpty ? getSurveyWidget(itgResponseData?.survey?.questions![index], index) : Container();
},
),
],
).paddingOnly(left: 21, right: 21),
),
],
)),
DefaultButton(
@ -111,7 +80,7 @@ class _SurveyScreenState extends State<SurveyScreen> {
));
}
Widget optionUI(String icon, int index) {
Widget optionUI(String icon, int? index, int answerIndex) {
return (_selectedIndex == index
? SvgPicture.asset(
'assets/images/' + icon,
@ -126,33 +95,129 @@ class _SurveyScreenState extends State<SurveyScreen> {
disablePadding: true,
))
.onPress(() {
_selectedIndex = index;
_selectedIndex = index!;
answeredQuestions[answerIndex] = _selectedIndex.toString();
setState(() {});
});
}
void initAnswersList() {
answeredQuestions.clear();
itgResponseData?.survey?.questions?.forEach((element) {
if (element.type != "Stars") {
if(element.type == "Faces") {
_selectedIndex = element.options![0].optionId!;
}
answeredQuestions.add(element.options![0].optionId.toString());
} else {
answeredQuestions.add("4");
}
});
setState(() {});
}
Widget getSurveyWidget(Questions? question, int parentIndex) {
if (question?.type == "Expressions") {
// Expressions = radio buttons
return Column(
children: [
24.height,
question?.title?.toText18() ?? const Text(""),
16.height,
GridView.builder(
padding: EdgeInsets.zero,
itemCount: question?.options?.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return radioOption(question?.options?[index].title ?? "", question?.options?[index].optionId.toString() ?? "", answeredQuestions[parentIndex], parentIndex);
},
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: (4.0),
),
).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true),
],
);
} else if (question?.type == "Stars") {
// Stars = star rating
return Column(
mainAxisSize: MainAxisSize.min,
children: [
24.height,
question?.title?.toText18() ?? Text(""),
16.height,
RatingBar.builder(
initialRating: 3,
minRating: starRating,
direction: Axis.horizontal,
allowHalfRating: false,
itemCount: 5,
itemPadding: const EdgeInsets.symmetric(horizontal: 8),
itemBuilder: (context, _) => const Icon(
Icons.star,
color: Colors.amber,
),
onRatingUpdate: (rating) {
starRating = rating;
answeredQuestions[parentIndex] = rating.toInt().toString();
},
).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true),
],
);
} else if (question?.type == "Faces") {
// Faces = face rating
return Column(
mainAxisSize: MainAxisSize.min,
children: [
24.height,
question?.title?.toText18() ?? Text("asdasdasdasd"),
16.height,
GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7),
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.only(top: 0),
shrinkWrap: true,
children: [
optionUI("poor.svg", question?.options?[0].optionId, parentIndex),
optionUI("bad.svg", question?.options?[1].optionId, parentIndex),
optionUI("normal.svg", question?.options?[2].optionId, parentIndex),
optionUI("good.svg", question?.options?[3].optionId, parentIndex),
optionUI("xcellent.svg", question?.options?[4].optionId, parentIndex),
],
),
],
);
} else {
return Container();
}
return Container();
}
void performAPI() async {
Utils.showLoading(context);
List<Map<String, dynamic>> itgAnswersList = [];
int index = 0;
try {
ItgMainRes? res= await DashboardApiClient().submitItgForm(
comment: reviewText,
masterId: itgResponseData!.notificationMasterId ?? "",
itgList: [
{"questionId": "1", "optionId": null, "starRating": starRating},
{"questionId": "2", "optionId": "4", "starRating": _selectedIndex}
],
serviceId: itgResponseData!.serviceId ?? 0);
Utils.hideLoading(context);
answeredQuestions.forEach((element) {
itgAnswersList.add({
"questionId": itgResponseData?.survey?.questions![index].questionId,
"optionId": itgResponseData?.survey?.questions![index].type != "Stars" ? answeredQuestions[index] : null,
"starRating": itgResponseData?.survey?.questions![index].type == "Stars" ? answeredQuestions[index] : null
});
index++;
});
ItgMainRes? res = await DashboardApiClient()
.submitItgForm(comment: reviewText, masterId: itgResponseData!.notificationMasterId ?? "", itgList: itgAnswersList, serviceId: itgResponseData!.survey!.surveyId ?? 0);
Utils.hideLoading(context);
if(res!.mohemmItgResponseItem!.statusCode==200){
if (res!.mohemmItgResponseItem!.statusCode == 200) {
Utils.showToast("Survey has been submitted successfully");
Navigator.pop(context);
}else{
} else {
Utils.showToast(res.mohemmItgResponseItem!.message.toString());
}
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {
@ -160,4 +225,41 @@ class _SurveyScreenState extends State<SurveyScreen> {
});
}
}
Widget radioOption(String title, String value, String groupValue, int answerIndex) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(color: MyColors.borderColor, width: 1),
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
),
padding: const EdgeInsets.all(4),
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: value == answeredQuestions[answerIndex] ? MyColors.greenColor : Colors.transparent,
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
),
),
),
6.width,
title.toText12(color: MyColors.grey57Color),
12.width
],
).onPress(() {
answeredQuestions[answerIndex] = value;
setState(() {});
});
}
}

@ -5,11 +5,11 @@ import 'package:easy_localization/src/public_ext.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
// import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
import 'package:mohem_flutter_app/api/login_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
@ -27,7 +27,9 @@ import 'package:mohem_flutter_app/models/member_information_list_model.dart';
import 'package:mohem_flutter_app/models/member_login_list_model.dart';
import 'package:mohem_flutter_app/models/privilege_list_model.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/button/hmg_connectivity_button.dart';
import 'package:mohem_flutter_app/widgets/input_widget.dart';
// import 'package:safe_device/safe_device.dart';
import 'package:wifi_iot/wifi_iot.dart';
@ -58,12 +60,12 @@ class _LoginScreenState extends State<LoginScreen> {
bool isOnExternalStorage = false;
bool isDevelopmentModeEnable = false;
late HmsApiAvailability hmsApiAvailability;
// late HmsApiAvailability hmsApiAvailability;
@override
void initState() {
super.initState();
hmsApiAvailability = HmsApiAvailability();
// hmsApiAvailability = HmsApiAvailability();
// checkFirebaseToken();
// if (kReleaseMode) {
// checkDeviceSafety();
@ -99,39 +101,32 @@ class _LoginScreenState extends State<LoginScreen> {
Utils.showLoading(context);
if (Platform.isAndroid) {
try {
await hmsApiAvailability.isHMSAvailable().then((value) async {
if (value == 0) {
AppState().setIsHuawei = true;
AppNotifications().initHuaweiPush(checkLoginInfo);
} else {
await Firebase.initializeApp();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().init(firebaseToken);
checkLoginInfo();
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
});
} catch (ex) {
Utils.hideLoading(context);
checkLoginInfo();
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
if (!(await Utils.isGoogleServicesAvailable())) {
print("HUAWEI APPPP GALLERYYYY!!!!");
AppState().setIsHuawei = true;
AppNotifications().initHuaweiPush(checkLoginInfo);
} else {
print("GOOGLE PLAY STOREEEE!!!!");
await Firebase.initializeApp();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().init(firebaseToken);
checkLoginInfo();
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
// });
} catch (ex) {}
} else {
await Firebase.initializeApp();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().init(firebaseToken);
checkLoginInfo();
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
}
@ -226,7 +221,9 @@ class _LoginScreenState extends State<LoginScreen> {
children: [
Row(
children: [
Expanded(child: SizedBox()),
// Expanded(
// child:SizedBox(child: HmgConnectivityButton(),),
// ),
Row(
children: [
LocaleKeys.english.tr().toText14(color: AppState().isArabic(context) ? null : MyColors.textMixColor).onPress(() {

@ -17,7 +17,18 @@ class MarathonIntroScreen extends StatelessWidget {
Widget build(BuildContext context) {
MarathonProvider provider = context.watch<MarathonProvider>();
return Scaffold(
appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()),
appBar: AppBarWidget(
context,
title: LocaleKeys.brainMarathon.tr(),
onHomeTapped: () {
Navigator.pop(context);
context.setLocale(provider.savedLocale);
},
onBackTapped: () {
Navigator.pop(context);
context.setLocale(provider.savedLocale);
},
),
body: Column(
children: <Widget>[
ListView(

@ -1,7 +1,7 @@
import 'dart:async';
import 'dart:developer';
import 'package:appinio_swiper/appinio_swiper.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/marathon/demo_marathon_repo.dart';
@ -32,7 +32,7 @@ class MarathonProvider extends ChangeNotifier {
int? selectedOptionIndex;
String? selectedOptionId;
int? totalQualifiers;
Locale savedLocale = const Locale("en", "US");
String? gapTimeImage;
String? gapTimeText;
int? gapTimeType;
@ -135,7 +135,6 @@ class MarathonProvider extends ChangeNotifier {
late VideoPlayerController videoController;
Future<void> initializeVideoPlayer() async {
log("VIDEO PLAYER INITIALIZED!!!");
videoController = VideoPlayerController.network(ApiConsts.marathonBaseUrlServices + marathonDetailModel.sponsors!.first.video!);
await videoController.initialize();
await videoController.play();
@ -220,7 +219,7 @@ class MarathonProvider extends ChangeNotifier {
oneSec,
(Timer timer) async {
// This 1 is just to show the color of answer tile for 1 and then update card status
if (totalCurrentQuestionTime - currentGapTime == 1) {
if (totalCurrentQuestionTime - currentGapTime == 0) {
if (callCountThreshold == 0) {
getCorrectAnswerAndUpdateAnswerColor();
}
@ -280,8 +279,8 @@ class MarathonProvider extends ChangeNotifier {
oneSec,
(Timer timer) async {
if (totalSecondsToWaitForWinner == 1) {
await callGetSelectedWinnersApi().whenComplete(() => updateQuestionCardStatus(QuestionCardStatus.winnerFound));
timer.cancel();
await callGetSelectedWinnersApi().whenComplete(() => updateQuestionCardStatus(QuestionCardStatus.winnerFound));
return;
} else if (totalSecondsToWaitForWinner == 15) {
totalSecondsToWaitForWinner--;
@ -297,6 +296,18 @@ class MarathonProvider extends ChangeNotifier {
//************************************************ FUNCTIONS **********************************************************
void updateLanguageAsPerMarathon(BuildContext context, MarathonDetailModel detailModel) {
savedLocale = context.locale;
if (detailModel.selectedLanguage == 1) {
context.setLocale(const Locale("en", "US"));
} else if (detailModel.selectedLanguage == 2) {
context.setLocale(const Locale("ar", "SA"));
} else if (detailModel.selectedLanguage == 3) {
} else {
context.setLocale(const Locale("en", "US"));
}
}
Future<bool> callSubmitOptionApi() async {
return await MarathonApiClient().submitSelectedOption(marathonId: marathonDetailModel.id!, questionId: currentQuestion.id, selectedAnswerId: selectedOptionId);
}
@ -342,11 +353,15 @@ class MarathonProvider extends ChangeNotifier {
gapTimeImage = currentQuestion.gapImage;
gapTimeText = currentQuestion.gapText;
gapTimeType = currentQuestion.gapType;
startTimerForQuestion();
updateCardData();
if (Utils.isLoading) {
Utils.hideLoading(AppRoutes.navigatorKey.currentContext!);
}
startTimerForQuestion();
updateCardData();
if (!AppState().getIsDemoMarathon) {
totalMarathoners = await MarathonApiClient().getMarathonersCount(marathonId: marathonDetailModel.id!);
}
Navigator.pushReplacementNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.marathonScreen);
} else {
currentQuestion = AppState().getIsDemoMarathon
@ -512,6 +527,7 @@ class MarathonProvider extends ChangeNotifier {
answerStatusesList[i] = QuestionCardStatus.question;
}
}
AppRoutes.navigatorKey.currentContext!.setLocale(savedLocale);
notifyListeners();
}

@ -78,7 +78,12 @@ class MarathonScreen extends StatelessWidget {
16.height,
Column(
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.demoMarathonDetailModel.selectedLanguage!,
arabicContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr!,
englishContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!,
).toText22(
color: MyColors.grey3AColor,
isCentered: true,
),
@ -92,7 +97,12 @@ class MarathonScreen extends StatelessWidget {
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(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.demoMarathonDetailModel.selectedLanguage!,
englishContent: provider.demoMarathonDetailModel.sponsors!.first.nameEn!,
arabicContent: provider.demoMarathonDetailModel.sponsors!.first.nameAr!,
).toText14(
color: MyColors.darkTextColor,
isBold: true,
),
@ -160,7 +170,12 @@ class MarathonScreen extends StatelessWidget {
provider.iAmWinner
? Column(
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage ?? 0,
arabicContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
englishContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
).toText24(
color: MyColors.grey3AColor,
isCentered: true,
),
@ -170,10 +185,15 @@ class MarathonScreen extends StatelessWidget {
)
: const SizedBox(),
if (provider.selectedWinners != null) ...<Widget>[
provider.selectedWinners!.length == 1
provider.selectedWinners!.length == 1 && !provider.iAmWinner
? Column(
children: <Widget>[
(AppState().isArabic(context) ? provider.selectedWinners![0].nameEn : provider.selectedWinners![0].nameEn)!.toText24(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage ?? 0,
arabicContent: provider.selectedWinners![0].nameAr ?? "",
englishContent: provider.selectedWinners![0].nameEn ?? "",
).toText24(
color: MyColors.grey3AColor,
isCentered: true,
),
@ -191,10 +211,15 @@ class MarathonScreen extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(AppState().isArabic(context) ? provider.selectedWinners![index].nameEn : provider.selectedWinners![index].nameEn)!.toText16(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage ?? 0,
arabicContent: provider.selectedWinners![index].nameAr ?? "",
englishContent: provider.selectedWinners![index].nameEn ?? "",
).toText16(
color: MyColors.grey3AColor,
),
provider.selectedWinners!.first.employeeId!.toText16(color: MyColors.grey57Color),
provider.selectedWinners![index].employeeId!.toText16(color: MyColors.grey57Color),
],
);
},
@ -206,7 +231,12 @@ class MarathonScreen extends StatelessWidget {
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(
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage!,
arabicContent: provider.marathonDetailModel.sponsors!.first.nameAr ?? "",
englishContent: provider.marathonDetailModel.sponsors!.first.nameEn ?? "",
).toText14(
color: MyColors.darkTextColor,
isBold: true,
),
@ -231,7 +261,7 @@ class MarathonScreen extends StatelessWidget {
);
}
Widget getNameContainer(BuildContext context) {
Widget getNameContainer(BuildContext context, MarathonProvider provider) {
return Container(
height: 50,
padding: const EdgeInsets.symmetric(horizontal: 20),
@ -243,8 +273,12 @@ class MarathonScreen extends StatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!)
.toText17(isBold: true, color: MyColors.white),
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: (!AppState().getIsDemoMarathon ? provider.marathonDetailModel.selectedLanguage : provider.demoMarathonDetailModel.selectedLanguage) ?? 0,
arabicContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
englishContent: AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
).toText17(isBold: true, color: MyColors.white),
AppState().memberInformationList!.eMPLOYEENUMBER!.toText17(isBold: true, color: MyColors.white),
],
),
@ -310,7 +344,7 @@ class MarathonScreen extends StatelessWidget {
MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21),
],
if (provider.questionCardStatus == QuestionCardStatus.findingWinner && !provider.isUserOutOfGame) ...<Widget>[
getNameContainer(context),
getNameContainer(context, provider),
],
QuestionCardBuilder(
onQuestion: (BuildContext context) => const QuestionCard(),

@ -434,7 +434,12 @@ class MarathonBanner extends StatelessWidget {
),
Flexible(
child: Text(
(AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "").trimString(isTablet ? 25 : 15),
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: provider.marathonDetailModel.selectedLanguage ?? 0,
englishContent: provider.marathonDetailModel.titleEn ?? "",
arabicContent: provider.marathonDetailModel.titleAr ?? "",
),
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontStyle: FontStyle.italic,
@ -525,10 +530,7 @@ class MarathonBanner extends StatelessWidget {
],
).onPress(() async {
int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes;
if (remainingTimeInMinutes > 5 && provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) {
log("IF CALLED!!!");
log("Remaining Time: $remainingTimeInMinutes");
Utils.showLoading(context);
try {
await provider.initializeVideoPlayer().then((_) {
@ -537,20 +539,16 @@ class MarathonBanner extends StatelessWidget {
Navigator.pushNamed(context, AppRoutes.marathonSponsorVideoScreen);
});
} catch (e) {
// if (kDebugMode) {
if (kDebugMode) {
log("Error in VideoPlayer: ${e.toString()}");
// }
}
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen).then((value) {
print("Back to home!!!");
});
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen);
}
} else {
log("ELSE CALLED!!!");
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen).then((value) {
print("Back to home!!!");
});
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen);
}
provider.updateLanguageAsPerMarathon(context, provider.isUpComingMarathon ? provider.marathonDetailModel : provider.demoMarathonDetailModel);
}),
)
: getNoUpcomingMarathonWidget(context);

@ -39,11 +39,23 @@ class MarathonDetailsCard extends StatelessWidget {
),
7.height,
LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey77Color),
"${AppState().isArabic(context) ? marathonDetailModel.titleAr : marathonDetailModel.titleEn}".toText20(color: MyColors.textMixColor, isBold: true),
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: marathonDetailModel.selectedLanguage ?? 0,
englishContent: marathonDetailModel.titleEn ?? "",
arabicContent: marathonDetailModel.titleAr ?? "",
).toText20(color: MyColors.textMixColor, isBold: true),
Row(
children: <Widget>[
Flexible(
child: "${AppState().isArabic(context) ? marathonDetailModel.descAr : marathonDetailModel.descEn}".toText14(color: MyColors.grey77Color),
child: displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: marathonDetailModel.selectedLanguage ?? 0,
englishContent: marathonDetailModel.descEn ?? "",
arabicContent: marathonDetailModel.descAr ?? "",
).toText14(
color: MyColors.grey77Color,
),
)
],
),
@ -57,18 +69,22 @@ class MarathonDetailsCard extends StatelessWidget {
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);
}),
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: displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: marathonDetailModel.selectedLanguage ?? 0,
englishContent: prizes.marathonPrizeEn ?? "",
arabicContent: prizes.marathonPrizeAr ?? "",
).toText16(color: MyColors.greenColor, isBold: true).paddingOnly(left: 5, right: 5),
).paddingOnly(left: 5);
},
),
),
)
],
@ -77,7 +93,12 @@ class MarathonDetailsCard extends StatelessWidget {
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),
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: marathonDetailModel.selectedLanguage ?? 0,
englishContent: marathonDetailModel.sponsors?.first.nameEn ?? "",
arabicContent: marathonDetailModel.sponsors?.first.nameAr ?? "",
).toText16(color: MyColors.darkTextColor, isBold: true),
],
),
10.height,

@ -3,8 +3,6 @@ import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/classes/colors.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:provider/provider.dart';
class MarathonHeader extends StatelessWidget {
const MarathonHeader({Key? key}) : super(key: key);

@ -85,7 +85,12 @@ class CardContent extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 15),
child: Text(
AppState().isArabic(context) ? "${provider.currentQuestion.titleAr}" ?? "" : provider.currentQuestion.titleEn ?? "",
displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: (AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.selectedLanguage : provider.marathonDetailModel.selectedLanguage) ?? 0,
englishContent: provider.currentQuestion.titleEn ?? "",
arabicContent: provider.currentQuestion.titleAr ?? "",
),
style: const TextStyle(
color: MyColors.white,
fontSize: 16,
@ -125,7 +130,7 @@ class AnswerContent extends StatelessWidget {
return AnswerTileForText(
index: index,
onAnswerTapped: () {
if (provider.totalCurrentQuestionTime - provider.currentGapTime <= 1) {
if (provider.totalCurrentQuestionTime - provider.currentGapTime <= 0) {
null;
} else {
provider.updateCurrentQuestionOptionStatus(QuestionsOptionStatus.selected, index);
@ -170,9 +175,12 @@ class AnswerTileForText extends StatelessWidget {
alignment: Alignment.centerLeft,
decoration: MyDecorations.getAnswersContainerColor(provider.currentQuestion.questionOptions![index].optionStatus!),
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: 13, bottom: 13),
child: displayLocalizedContent(
isPhoneLangArabic: AppState().isArabic(context),
selectedLanguage: (AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.selectedLanguage : provider.marathonDetailModel.selectedLanguage) ?? 0,
englishContent: provider.currentQuestion.questionOptions![index].titleEn ?? "",
arabicContent: provider.currentQuestion.questionOptions![index].titleAr ?? "",
).toText16(color: provider.isUserOutOfGame ? MyColors.darkTextColor : getAnswerTextColor(provider.currentQuestion.questionOptions![index].optionStatus!)).paddingOnly(top: 13, bottom: 13),
),
),
);

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
@ -71,27 +72,31 @@ class _RequestSubmitScreenState extends State<RequestSubmitScreen> {
}
}
Future<List<Map<String, dynamic>>> addAttachments() async {
List<Map<String, dynamic>> list = [];
if (attachmentFiles.isNotEmpty) {
attachmentFiles.asMap().forEach((index, value) {
String type = attachmentFiles[index].path.split('.').last;
String name = attachmentFiles[index].path.split('/').last;
List<int> fileContent = value.readAsBytesSync();
String encodedFile = base64Encode(fileContent);
list.add(AttachmentModel(
attachmentID: index,
pFILECONTENTTYPE: type,
pFILENAME: name,
pFILEDATA: encodedFile,
pTRANSACTIONID: params!.transactionId,
).toJson());
});
}
return list;
}
void submitRequest() async {
try {
Utils.showLoading(context);
List<Map<String, dynamic>> list = [];
if (attachmentFiles.isNotEmpty) {
attachments.asMap().forEach((index, value) async {
String type = attachmentFiles[index].path.split('.').last;
String name = attachmentFiles[index].path.split('/').last;
// List<int> fileContent = await value.readAsBytes();
// String encodedFile = base64Encode(fileContent);
list.add(AttachmentModel(
attachmentID: index,
pFILECONTENTTYPE: type,
pFILENAME: name,
pFILEDATA: value,
pTRANSACTIONID: params!.transactionId,
).toJson());
});
}
List<Map<String, dynamic>> list = await addAttachments();
await MyAttendanceApiClient().addAttachment(list);
if (params!.approvalFlag == 'phone_numbers') {
await ProfileApiClient().startPhoneApprovalProcess(
"SUBMIT",

@ -57,6 +57,9 @@ class ServicesMenuListScreen extends StatelessWidget {
} else if (servicesMenuData.list[index].requestType == "ABSENCE") {
Navigator.pushNamed(context, AppRoutes.leaveBalance, arguments: servicesMenuData.selectedEmp);
return;
} else if (servicesMenuData.list[index].requestType == "RESET_ITG_AD_PASSWORD") {
Navigator.pushNamed(context, AppRoutes.changeItgAdPasswordScreen);
return;
}
if (servicesMenuData.list[index].requestType == "EIT") {
Navigator.pushNamed(context, AppRoutes.dynamicScreen,

@ -18,7 +18,7 @@ import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/select_cat
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/button/simple_button.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
import 'package:mohem_flutter_app/widgets/image_picker.dart';
import 'package:mohem_flutter_app/widgets/image_picker.dart' as imagePicker;
import 'package:mohem_flutter_app/widgets/radio/show_radio.dart';
class AddItemDetailsFragment extends StatefulWidget {
@ -200,14 +200,22 @@ class _AddItemDetailsFragmentState extends State<AddItemDetailsFragment> {
children: [
title.toText16().expanded,
6.width,
SimpleButton(LocaleKeys.add.tr(), () {
ImageOptions.showImageOptionsNew(context, false, (String image, File file) {
setState(() {
images.add(image);
Navigator.of(context).pop();
});
});
}, fontSize: 14),
SimpleButton(
LocaleKeys.add.tr(),
() {
if (images.length < 3) {
imagePicker.ImageOptions.showImageOptionsNew(context, false, (String image, File file) {
setState(() {
images.add(image);
Navigator.of(context).pop();
});
});
} else {
Utils.showToast("The maximum no. of images allowed is 3.");
}
},
fontSize: 14,
),
],
),
if (images.isNotEmpty) 12.height,

@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
@ -98,9 +96,7 @@ class _ItemsForSaleFragmentState extends State<ItemsForSaleFragment> {
currentCategoryID == getSaleCategoriesList[index].categoryID ? const Icon(Icons.check_circle_rounded, color: MyColors.greenColor, size: 16.0) : Container(),
],
).expanded,
AppState().isArabic(context)
?getSaleCategoriesList[index].titleAr!.toText10()
:getSaleCategoriesList[index].title!.toText10()
AppState().isArabic(context) ? getSaleCategoriesList[index].titleAr!.toText10() : getSaleCategoriesList[index].title!.toText10()
],
).paddingOnly(left: 10, right: 10, bottom: 10, top: 12).expanded.objectContainerView(disablePadding: true),
),
@ -163,8 +159,8 @@ class _ItemsForSaleFragmentState extends State<ItemsForSaleFragment> {
aspectRatio: 148 / 127,
child: ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.memory(
base64Decode(getItemsForSaleList.itemAttachments![0].content!),
child: Image.network(
getItemsForSaleList.itemAttachments![0].filePath!,
fit: BoxFit.cover,
),
),

@ -189,7 +189,7 @@ class _MyPostedAdsFragmentState extends State<MyPostedAdsFragment> {
request.fields['RegionID'] = employeePostedAds.regionID.toString();
request.fields['Itg_EndDate'] = employeePostedAds.endDate.toString();
request.fields['endDate'] = employeePostedAds.endDate.toString();
request.fields['Channel'] = "31";
request.fields['Channel'] = "33";
request.fields['ItgIsActive'] = "false";
request.fields['LogInToken'] = loginTokenID!;
request.fields['Token'] = tokenID!;

@ -1,5 +1,4 @@
import 'dart:convert';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
@ -24,6 +23,7 @@ class ItemForSaleDetailPage extends StatefulWidget {
class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
late GetItemsForSaleList getItemsForSaleList;
int _current = 0;
@override
Widget build(BuildContext context) {
@ -46,15 +46,32 @@ class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
transitionOnUserGestures: true,
child: AspectRatio(
aspectRatio: 322 / 261,
child: ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.memory(
base64Decode(getItemsForSaleList.itemAttachments![0].content!),
fit: BoxFit.cover,
),
child: CarouselSlider(
items: getItemImages(),
options: CarouselOptions(
enableInfiniteScroll: false,
onPageChanged: (index, reason) {
setState(() {
_current = index;
});
}),
),
),
).paddingAll(8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: getItemImages().asMap().entries.map((entry) {
return Container(
width: 8.0,
height: 8.0,
margin: const EdgeInsets.symmetric(horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: (Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black).withOpacity(_current == entry.key ? 0.9 : 0.4),
),
);
}).toList(),
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@ -88,22 +105,34 @@ class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
).expanded,
Row(
children: [
DefaultButton("Email", () async {
Uri emailLaunchUri = Uri(
scheme: 'mailto',
path: getItemsForSaleList.emailAddress,
);
launchUrl(emailLaunchUri);
}, iconData: Icons.email_sharp, isTextExpanded: false)
DefaultButton(
"Email",
getItemsForSaleList.status == 'Approved'
? () async {
Uri emailLaunchUri = Uri(
scheme: 'mailto',
path: getItemsForSaleList.emailAddress,
);
launchUrl(emailLaunchUri);
}
: null,
iconData: Icons.email_sharp,
isTextExpanded: false)
.expanded,
8.width,
DefaultButton("Call", () async {
Uri callLaunchUri = Uri(
scheme: 'tel',
path: getItemsForSaleList.mobileNumber,
);
launchUrl(callLaunchUri);
}, iconData: Icons.call_sharp, isTextExpanded: false)
DefaultButton(
"Call",
getItemsForSaleList.status == 'Approved'
? () async {
Uri callLaunchUri = Uri(
scheme: 'tel',
path: getItemsForSaleList.mobileNumber,
);
launchUrl(callLaunchUri);
}
: null,
iconData: Icons.call_sharp,
isTextExpanded: false)
.expanded,
],
).insideContainer,
@ -111,4 +140,25 @@ class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
),
);
}
List<Widget> getItemImages() {
int index = 0;
List<Widget> itemImages = [];
getItemsForSaleList.itemAttachments!.forEach((element) {
itemImages.add(
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.network(
getItemsForSaleList.itemAttachments![index].filePath!,
fit: BoxFit.cover,
),
),
),
);
index++;
});
return itemImages;
}
}

@ -1,15 +1,29 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.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/date_uitl.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_attachement_list_model.dart';
import 'package:mohem_flutter_app/models/get_mo_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
class ItemHistoryScreenParams {
String? title;
@ -18,8 +32,12 @@ class ItemHistoryScreenParams {
int? pItemId;
int? pPoHeaderId;
int? pOrgId;
bool isPRInfo;
GetPRInformationList? getPRInformationList;
String pOLineID;
ItemHistoryScreenParams({@required this.title, this.isItemHistory = true, this.isMO = true, this.pItemId, this.pPoHeaderId, this.pOrgId});
ItemHistoryScreenParams(
{@required this.title, this.isItemHistory = true, this.isMO = true, this.isPRInfo = false, this.getPRInformationList, this.pItemId, this.pPoHeaderId, this.pOrgId, this.pOLineID = ""});
}
class ItemHistoryScreen extends StatefulWidget {
@ -37,6 +55,9 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
List<GetMoItemHistoryList> moItemHistoryList = [];
List<GetPoItemHistoryList> poItemHistoryList = [];
List<GetQuotationAnalysisList> quotationAnalysisList = [];
List<GetPRActionHistoryList> actionHistoryList = [];
List<GetAttachementList> getAttachmentList = [];
int tabIndex = 0;
@override
void initState() {
@ -46,12 +67,43 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
@override
void dispose() {
super.dispose();
actionHistoryList.clear();
}
void loadData() {
if (_screenParams == null) {
_screenParams = ModalRoute.of(context)!.settings.arguments as ItemHistoryScreenParams;
getDataFromApi();
if (!_screenParams!.isPRInfo) {
getDataFromApi();
}
}
}
void getActionsDataFromApi() async {
if (actionHistoryList.isEmpty) {
try {
Utils.showLoading(context);
actionHistoryList = await WorkListApiClient().getActionHistoryForPR(_screenParams!.pOLineID);
Utils.hideLoading(context);
setState(() {});
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
}
void getAttachmentsDataFromApi() async {
if (getAttachmentList.isEmpty) {
try {
Utils.showLoading(context);
getAttachmentList = await WorkListApiClient().getPRAttachments(_screenParams!.pOLineID!);
Utils.hideLoading(context);
setState(() {});
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
}
@ -83,18 +135,259 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
appBar: AppBarWidget(context, title: _screenParams?.title ?? ""),
backgroundColor: Colors.white,
body: ListView(
padding: const EdgeInsets.all(21),
padding: _screenParams!.isPRInfo ? const EdgeInsets.all(0) : const EdgeInsets.all(21),
physics: const BouncingScrollPhysics(),
children: [
if (_screenParams!.isPRInfo) prLinesDataView(),
if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData(),
if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData(),
if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData(),
if (moItemHistoryList.isEmpty && poItemHistoryList.isEmpty && quotationAnalysisList.isEmpty) Utils.getNoDataWidget(context),
if (moItemHistoryList.isEmpty && poItemHistoryList.isEmpty && quotationAnalysisList.isEmpty && !_screenParams!.isPRInfo) Utils.getNoDataWidget(context),
],
),
);
}
Widget prLinesDataView() {
return Column(
children: [
Container(
padding: const EdgeInsets.only(left: 21, right: 21, top: 16, bottom: 16),
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
gradient: LinearGradient(
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
),
),
child: Row(
children: [
myTab(LocaleKeys.info.tr(), 0),
myTab(LocaleKeys.actions.tr(), 1),
myTab(LocaleKeys.attachments.tr(), 2),
],
),
),
if (tabIndex == 0) _screenParams!.getPRInformationList!.pRHeader![0].dESCRIPTION!.toText14().paddingOnly(top: 20, right: 21, left: 21),
if (tabIndex == 0)
ListView.separated(
padding: const EdgeInsets.all(21),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (cxt, index) => Column(
children: [
ItemDetailGrid(
ItemDetailViewCol("Cost Center", _screenParams!.getPRInformationList!.pRLines![index].cOSTCENTER ?? ""),
ItemDetailViewCol("Code", _screenParams!.getPRInformationList!.pRLines![index].iTEMCODE ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("Unit", _screenParams!.getPRInformationList!.pRLines![index].uOM ?? ""),
ItemDetailViewCol("Price (SAR)", _screenParams!.getPRInformationList!.pRLines![index].uNITPRICE.toString() ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("Amount (SAR)", _screenParams!.getPRInformationList!.pRLines![index].lINEAMOUNT.toString() ?? ""),
ItemDetailViewCol("Quantity", _screenParams!.getPRInformationList!.pRLines![index].qUANTITY.toString() ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("AMU (Last 3 months)", _screenParams!.getPRInformationList!.pRLines![index].iTEMAMU.toString() ?? ""),
ItemDetailViewCol("PR Number", _screenParams!.getPRInformationList!.pRHeader![0].pRNUMBER!.toString() ?? ""),
isItLast: true,
),
],
).objectContainerView(),
separatorBuilder: (cxt, index) => 12.height,
itemCount: _screenParams!.getPRInformationList!.pRLines!.length),
if (tabIndex == 1) getPRActionsHistory(), //"ACTIONS".toText14().paddingOnly(top: 20, right: 21, left: 21),
if (tabIndex == 2) getPRAttachments(),
],
);
}
String determineFileIcon(String fileContentType) {
String icon = "";
switch (fileContentType) {
case "pdf":
icon = "assets/images/pdf.svg";
break;
case "xls":
icon = "assets/images/xls.svg";
break;
case "xlsx":
icon = "assets/images/xls.svg";
break;
case "png":
icon = "assets/images/png.svg";
break;
case "jpg":
icon = "assets/images/jpg.svg";
break;
case "jpeg":
icon = "assets/images/jpg.svg";
break;
}
return icon;
}
Future<String> _createFileFromString(String encodedStr, String ext) async {
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getApplicationDocumentsDirectory()).path;
File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
await file.writeAsBytes(bytes);
return file.path;
}
Widget getPRAttachments() {
return ListView.separated(
itemCount: getAttachmentList.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Row(
children: [
SvgPicture.asset(determineFileIcon(getAttachmentList[index].fILECONTENTTYPE ?? "")),
12.width,
(getAttachmentList[index].fILENAME ?? "").toText16().expanded,
],
).objectContainerView().onPress(() async {
try {
String path = await _createFileFromString(getAttachmentList[index].fILEDATA ?? "", getAttachmentList[index].fILECONTENTTYPE ?? "");
OpenFile.open(path);
} catch (ex) {
Utils.showToast("Cannot open file.");
}
});
},
separatorBuilder: (BuildContext context, int index) => 12.height,
).paddingAll(21);
}
Widget getPRActionsHistory() {
return SingleChildScrollView(
child: ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: actionHistoryList.length,
padding: EdgeInsets.all(21),
itemBuilder: (context, index) {
return showItem(context, actionHistoryList[index], index);
},
separatorBuilder: (BuildContext context, int index) {
return 12.height;
},
),
);
}
Widget showItem(BuildContext context, GetPRActionHistoryList actionHistory, int index) {
return Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: const Color(0xff000000).withOpacity(.05),
blurRadius: 26,
offset: const Offset(0, -3),
),
],
),
clipBehavior: Clip.antiAlias,
child: Stack(
clipBehavior: Clip.antiAlias,
children: [
Positioned(
left: -20,
top: -10,
child: Transform.rotate(
angle: 15,
child: Container(
width: 50,
height: 30,
color: getStatusColor(actionHistory.aCTIONCODE!),
),
),
),
Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
actionHistory.eMPLOYEEIMAGE != null
? CircularAvatar(url: actionHistory.eMPLOYEEIMAGE ?? "", isImageBase64: true, height: 34, width: 34)
: CircularAvatar(url: "https://cdn4.iconfinder.com/data/icons/professions-2-2/151/89-512.png", isImageBase64: false, height: 34, width: 34),
9.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
actionHistory.nAME!.toText16(),
if ((actionHistory.nOTE ?? "").isNotEmpty)
SelectableText(
actionHistory.nOTE!,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: MyColors.grey57Color,
letterSpacing: -0.72,
),
),
// "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color),
4.height,
Row(
children: [
actionHistory.aCTION!.toText10(color: getStatusColor(actionHistory.aCTIONCODE!)),
8.width,
if (actionHistory.aPPROVALDATE!.isNotEmpty)
DateUtil.formatDateToDate(DateUtil.convertSimpleStringDateToDateddMMyyyy(actionHistory.aPPROVALDATE!), false).toText12(color: MyColors.lightTextColor),
],
),
10.height,
// getActionDuration(index).toText11(maxLine: 1, color: const Color(0xff1FA269))
],
),
)
],
).paddingOnly(top: 19, left: 16, right: 16, bottom: 12),
],
),
],
),
);
}
Color getStatusColor(String code) {
if (code == "SUBMIT") {
return const Color(0xff2E303A);
} else if (code == "REJECTED") {
return MyColors.redColor;
} else if (code == "REJECT") {
return MyColors.redColor;
} else if (code == "PENDING") {
return MyColors.orange;
} else if (code == "APPROVED" || code == "APPROVE" || code == "ANSWER_INFO") {
return const Color(0xff1FA269);
} else if (code == "REQUEST_INFO" || code == "FORWARD") {
return const Color(0xff2E303A);
} else if (code != "SUBMIT" && code != "REJECT" && code != "PENDING") {
return MyColors.orange;
} else {
return const Color(0xff2E303A);
}
}
Widget getActionHistory() {
return Container();
}
Widget loadMoItemHistoryData() {
return ListView.separated(
shrinkWrap: true,
@ -231,4 +524,34 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
separatorBuilder: (cxt, index) => 12.height,
itemCount: quotationAnalysisList.length);
}
Widget myTab(String title, int index) {
bool isSelected = (index == tabIndex);
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
title.toText12(color: isSelected ? Colors.white : Colors.white.withOpacity(.74), isCenter: true),
4.height,
Container(
height: 8,
width: 8,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isSelected ? Colors.white : Colors.transparent,
),
)
],
).onPress(() {
setState(() {
if (index == 1) {
getActionsDataFromApi();
}
if (index == 2) {
getAttachmentsDataFromApi();
}
tabIndex = index;
});
}).expanded;
}
}

@ -13,6 +13,7 @@ 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/get_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/wf_history_model.dart';
import 'package:mohem_flutter_app/models/notification_get_respond_attributes_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/ui/work_list/sheets/search_options_sheet.dart';
@ -29,8 +30,10 @@ class DelegateSheet extends StatefulWidget {
List<GetActionHistoryList>? actionHistoryList;
List<WFHistory>? wFHistory;
VoidCallback callBackFunc;
List<NotificationGetRespondAttributesList> getNotificationRespondAttributes;
DelegateSheet({required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, this.wFHistory, required this.callBackFunc});
DelegateSheet(
{required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, this.wFHistory, required this.callBackFunc, this.getNotificationRespondAttributes = const []});
@override
State<DelegateSheet> createState() => _DelegateSheetState();
@ -415,6 +418,7 @@ class _DelegateSheetState extends State<DelegateSheet> {
actionHistoryList: actionHistory,
notificationID: widget.notificationID,
isITGRequest: widget.wFHistory != null,
getNotificationRespondAttributes: widget.getNotificationRespondAttributes,
));
},
child: Row(
@ -489,6 +493,7 @@ class _DelegateSheetState extends State<DelegateSheet> {
favoriteReplacements: actionHistory,
notificationID: widget.notificationID,
isITGRequest: widget.wFHistory != null,
getNotificationRespondAttributes: widget.getNotificationRespondAttributes,
));
},
child: Row(
@ -555,6 +560,7 @@ class _DelegateSheetState extends State<DelegateSheet> {
replacementList: actionHistory,
notificationID: widget.notificationID,
isITGRequest: widget.wFHistory != null,
getNotificationRespondAttributes: widget.getNotificationRespondAttributes,
));
},
child: Row(

@ -6,14 +6,15 @@ import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/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/get_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/member_information_list_model.dart';
import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart';
import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart';
import 'package:mohem_flutter_app/models/worklist/replacement_list_model.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/dialogs/accept_reject_input_dialog.dart';
import 'package:mohem_flutter_app/widgets/input_widget.dart';
class SelectedItemSheet extends StatelessWidget {
@ -23,10 +24,18 @@ class SelectedItemSheet extends StatelessWidget {
GetFavoriteReplacements? favoriteReplacements;
ReplacementList? replacementList;
MemberInformationListModel? memberInformationListModel;
List<NotificationGetRespondAttributesList> getNotificationRespondAttributes;
bool isITGRequest;
SelectedItemSheet(this.title, {required this.apiMode, this.notificationID, this.actionHistoryList, this.favoriteReplacements, this.replacementList, this.isITGRequest = false});
SelectedItemSheet(this.title,
{required this.apiMode,
this.notificationID,
this.actionHistoryList,
this.favoriteReplacements,
this.replacementList,
this.isITGRequest = false,
this.getNotificationRespondAttributes = const []});
TextEditingController username = TextEditingController();
String comment = "";
@ -103,7 +112,7 @@ class SelectedItemSheet extends StatelessWidget {
email = replacementList!.emailAddress;
userId = replacementList!.userName;
}
isITGRequest ? performITGNetworkCall(context, email: email ?? "", userId: userId ?? "") : performNetworkCall(context, email: email ?? "", userId: userId ?? "");
isITGRequest ? performITGNetworkCall(context, email: email ?? "", userId: userId ?? "") : askForConfirmation(context, email: email ?? "", userId: userId ?? "");
} else {
Utils.showToast("Please enter comments");
}
@ -121,6 +130,45 @@ class SelectedItemSheet extends StatelessWidget {
);
}
void askForConfirmation(BuildContext context, {String? email, String? userId}) {
NotificationGetRespondAttributesList? notificationNoteInput;
NotificationGetRespondAttributesList? forwardToUser;
List<NotificationGetRespondAttributesList> filtered = getNotificationRespondAttributes.where((element) => element.attributeName == "NOTE" || element.attributeName == "WF_NOTE").toList();
if (filtered.isNotEmpty) {
notificationNoteInput = filtered.first;
}
filtered = getNotificationRespondAttributes.where((element) => element.attributeName == "FORWARD_TO_USERNAME_RESPONSE").toList();
if (filtered.isNotEmpty) {
forwardToUser = filtered.first;
}
if (notificationNoteInput == null) {
performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: []);
} else {
showDialog(
context: context,
builder: (cxt) => AcceptRejectInputDialog(
message: title != null ? null : LocaleKeys.requestedItems.tr(),
// title: title,
notificationGetRespond: notificationNoteInput,
actionMode: apiMode,
onTap: (note) {
performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: [
if ((apiMode == "FORWARD" || apiMode == "APPROVE_AND_FORWARD") && forwardToUser != null)
{"ATTRIBUTE_NAME": "FORWARD_TO_USERNAME_RESPONSE", "ATTRIBUTE_TEXT_VALUE": actionHistoryList?.uSERNAME},
if (notificationNoteInput != null)
{
"ATTRIBUTE_NAME": notificationNoteInput.attributeName,
if (notificationNoteInput.attributeType == "number") "ATTRIBUTE_NUMBER_VALUE": note else if (notificationNoteInput.attributeType == "VARCHAR2") "ATTRIBUTE_TEXT_VALUE": note
}
]);
},
),
);
}
}
void getUserInformation(BuildContext context) async {
String? empID = "";
if (actionHistoryList != null) empID = actionHistoryList!.uSERNAME;
@ -137,10 +185,17 @@ class SelectedItemSheet extends StatelessWidget {
}
}
Future<void> performNetworkCall(BuildContext context, {String? email, String? userId}) async {
Future<void> performNetworkCall(BuildContext context, {String? email, String? userId, List<Map<String, dynamic>>? attributeData = const []}) async {
Utils.showLoading(context);
try {
await WorkListApiClient().submitComment(comment: comment, email: email, userId: userId, notificationId: notificationID, apiMode: apiMode, approverIndex: actionHistoryList != null ? actionHistoryList!.sEQUENCE : null);
await WorkListApiClient().submitComment(
comment: comment,
email: email,
userId: userId,
notificationId: notificationID,
apiMode: apiMode,
approverIndex: actionHistoryList != null ? actionHistoryList!.sEQUENCE : null,
attributeData: attributeData);
Utils.hideLoading(context);
// Navigator.pop(context);
// Navigator.pop(context);

@ -93,10 +93,12 @@ class _WorkListScreenState extends State<WorkListScreen> {
final ScrollController _controller = ScrollController();
int pNotificationType = 1;
ScrollController? _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController()..addListener(_scrollListener);
providerData = Provider.of<DashboardProviderModel>(context, listen: false);
calculateCounter();
if (workListItemIndex != null) getWorkList();
@ -154,7 +156,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
ItgFormsModel? itgFormsModel;
int? itgRequestTypeIndex;
Future<void> getWorkList({bool showLoading = true}) async {
Future<void> getWorkList({bool showLoading = true, bool isCallingFromRefresh = false}) async {
try {
if (showLoading) Utils.showLoading(context);
if (workListItemTypes[workListItemIndex!].key == "ITG") {
@ -173,7 +175,12 @@ class _WorkListScreenState extends State<WorkListScreen> {
}
} else {
itgRequestTypeIndex = null;
workList = await WorkListApiClient().getWorkList(pageNumber, workListItemTypes[workListItemIndex!].key, pNotificationType.toString());
List<WorkListResponseModel>? _list = await WorkListApiClient().getWorkList(pageNumber, workListItemTypes[workListItemIndex!].key, pNotificationType.toString());
if (workList != null && _list != null && !isCallingFromRefresh) {
workList!.addAll(_list);
} else {
workList = _list;
}
AppState().setWorkList = workList;
}
if (showLoading) Utils.hideLoading(context);
@ -188,9 +195,10 @@ class _WorkListScreenState extends State<WorkListScreen> {
try {
_refreshController.refreshCompleted();
Utils.showLoading(context);
pageNumber = 1;
List dataOnRefresh = await Future.wait([
providerData.fetchWorkListCounter(context, showLoading: false),
getWorkList(showLoading: false),
getWorkList(showLoading: false, isCallingFromRefresh: true),
]);
calculateCounter();
Utils.hideLoading(context);
@ -203,9 +211,19 @@ class _WorkListScreenState extends State<WorkListScreen> {
@override
void dispose() {
_scrollController?.dispose();
super.dispose();
}
void _scrollListener() {
if (_scrollController!.position.pixels == _scrollController!.position.maxScrollExtent) {
pageNumber = pageNumber + 1;
if (itgRequestTypeIndex == null && workListItemTypes[workListItemIndex!].value != workList!.length) {
getWorkList();
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -236,6 +254,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
}
if (workListItemIndex != index && !workListItemTypes[index].disable) {
workListItemIndex = index;
pageNumber = 1;
if (workListItemTypes[index].value == 0) {
workList = [];
itgRequestTypeIndex = null;
@ -273,6 +292,7 @@ class _WorkListScreenState extends State<WorkListScreen> {
),
controller: _refreshController,
onRefresh: _onRefresh,
scrollController: _scrollController,
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: itgRequestTypeIndex != null
@ -354,7 +374,6 @@ class _WorkListScreenState extends State<WorkListScreen> {
setState(() {});
}
}
} else {
verifyWorkListCounter();
if (mounted) setState(() {});

@ -148,9 +148,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
} else if (workListData!.rEQUESTTYPE == "ADDRESS") {
getAddressNotificationBody();
}
// getBasicNTFBody = await WorkListApiClient().getBasicDetNTFBody(workListData!.nOTIFICATIONID!, -999);
// getAbsenceCollectionNotifications = await WorkListApiClient().getAbsenceNotificationBody(workListData!.nOTIFICATIONID!, -999);
// subordinatesLeavesModel = await WorkListApiClient().getSubordinatesLeaves("", "");
}
if (workListData!.iTEMTYPE == "STAMP") {
getStampNotificationBody();
@ -449,7 +446,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
}
void handleFabAction(GetNotificationButtonsList notificationButton) {
print("notificationButton:${notificationButton.bUTTONACTION}");
switch (notificationButton.bUTTONACTION) {
case "DELEGATE":
showMyBottomSheet(context,
@ -526,6 +522,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
notificationID: workListData!.nOTIFICATIONID,
actionHistoryList: actionHistoryList,
callBackFunc: reloadWorkList,
getNotificationRespondAttributes: getNotificationRespondAttributes,
));
break;
case "FORWARD":
@ -537,8 +534,12 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
notificationID: workListData!.nOTIFICATIONID,
actionHistoryList: actionHistoryList,
callBackFunc: reloadWorkList,
getNotificationRespondAttributes: getNotificationRespondAttributes,
));
break;
case "DEL":
performAction(notificationButton.bUTTONACTION!);
break;
case "REJECT":
performAction(notificationButton.bUTTONACTION!);
break;
@ -565,6 +566,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
actionHistoryList: actionHistoryList.last,
notificationID: workListData!.nOTIFICATIONID,
isITGRequest: false,
getNotificationRespondAttributes: getNotificationRespondAttributes,
));
setState(() {});
} catch (ex) {
@ -656,7 +658,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
}
void performAction(String actionMode, {String? title}) {
print(actionMode);
showDialog(
context: context,
builder: (cxt) => AcceptRejectInputDialog(
@ -1003,19 +1004,11 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try {
isActionHistoryLoaded = false;
actionHistoryList.clear();
// if (apiCallCount == 0) Utils.showLoading(context);
// apiCallCount++;
actionHistoryList = await WorkListApiClient().getActionHistory(workListData!.nOTIFICATIONID!);
// apiCallCount--;
// if (apiCallCount == 0) {
// Utils.hideLoading(context);
setState(() {
isActionHistoryLoaded = true;
});
// }
} catch (ex) {
// apiCallCount--;
// Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
@ -1024,88 +1017,15 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try {
isAttachmentLoaded = false;
getAttachmentList.clear();
// if (apiCallCount == 0) Utils.showLoading(context);
// apiCallCount++;
getAttachmentList = await WorkListApiClient().getAttachments(workListData!.nOTIFICATIONID!);
// apiCallCount--;
// if (apiCallCount == 0) {
// Utils.hideLoading(context);
setState(() {
isAttachmentLoaded = true;
});
// }
} catch (ex) {
// apiCallCount--;
// Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
// Widget showUpdateContinueSheet(List<GetEitCollectionNotificationBodyList> list) {
// double itemHeight = 0;
// double itemWidth = 0;
// var size = MediaQuery.of(context).size;
// itemHeight = (size.height - kToolbarHeight - 24) / 9;
// itemWidth = size.width / 2;
// return Column(
// children: [
// if ((workListData?.sUBJECT ?? "").isNotEmpty) workListData!.sUBJECT!.toText14().paddingOnly(top: 10, right: 21, left: 21, bottom: 21),
// ListView.separated(
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
// itemBuilder: (cxt, index) {
// List<CollectionNotificationEit> dataList = list.isEmpty ? [] : (list[index].collectionNotification ?? []);
// dataList = dataList.where((o) => o.displayFlag == "Y").toList();
// bool isOdd = false;
// if (dataList.length % 2 != 0) {
// isOdd = true;
// dataList.add(new CollectionNotificationEit());
// }
// return GridView.builder(
// itemCount: dataList.length,
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
// itemBuilder: (context, index) => ItemDetailViewGridItem(
// index,
// dataList[index].segmentPrompt,
// dataList[index].segmentValueDsp,
// isNeedToShowEmptyDivider: (dataList.length == index + 1)
// ? isOdd
// ? true
// : false
// : false,
// ),
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 2,
// childAspectRatio: (itemWidth / itemHeight),
// ),
// ).objectContainerView();
// },
// separatorBuilder: (cxt, index) => 12.height,
// itemCount: list.length,
// ),
// Padding(
// padding: const EdgeInsets.only(right: 21, left: 21, bottom: 21),
// child: Row(
// children: [
// DefaultButton(
// LocaleKeys.edit.tr(),
// () => performEditAction(),
// colors: const [Color(0xffE47A7E), Color(0xffDE6D71)],
// ).expanded,
// 8.width,
// DefaultButton(
// LocaleKeys.next.tr(),
// () => performNextAction(),
// colors: const [Color(0xff28C884), Color(0xff1BB271)],
// ).expanded,
// ],
// ),
// ),
// ],
// );
// }
Widget showLoadingAnimation() {
return Lottie.asset(
'assets/lottie/loading.json',

@ -82,7 +82,20 @@ class ActionsFragment extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
actionHistory.nAME!.toText16(),
if ((actionHistory.nOTE ?? "").isNotEmpty) "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color),
if ((actionHistory.nOTE ?? "").isNotEmpty)
SelectableText(
actionHistory.nOTE!,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: MyColors.grey57Color,
letterSpacing: -0.72,
),
),
// if ((actionHistory.nOTE ?? "").isNotEmpty) "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color),
4.height,
Row(
children: [

@ -22,7 +22,6 @@ class AttachmentsFragment extends StatelessWidget {
return ListView.separated(
itemCount: getAttachmentList.length,
itemBuilder: (context, index) {
return Row(
children: [
SvgPicture.asset(determineFileIcon(getAttachmentList[index].fILECONTENTTYPE ?? "")),

@ -1,7 +1,9 @@
import 'package:easy_localization/src/public_ext.dart';
import 'package:expandable/expandable.dart';
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';
@ -10,7 +12,8 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_item_creation_ntf_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_mo_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart' as get_pr_notification_body_list_model;
import 'package:mohem_flutter_app/ui/work_list/item_history_screen.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart';
@ -19,14 +22,14 @@ class RequestFragment extends StatelessWidget {
final List<GetMoNotificationBodyList> moNotificationBodyList;
final List<ItemCreationLines> itemCreationLines;
final List<POLines> poLinesList;
final List<PRLines> prLinesList;
final List<get_pr_notification_body_list_model.PRLines> prLinesList;
RequestFragment({
Key? key,
this.moNotificationBodyList = const <GetMoNotificationBodyList>[],
this.itemCreationLines = const <ItemCreationLines>[],
this.poLinesList = const <POLines>[],
this.prLinesList = const <PRLines>[],
this.prLinesList = const <get_pr_notification_body_list_model.PRLines>[],
}) : super(key: key);
@override
@ -37,7 +40,7 @@ class RequestFragment extends StatelessWidget {
padding: const EdgeInsets.all(21),
children: [
if (moNotificationBodyList.isNotEmpty) moNotificationDataView(),
if (poLinesList.isNotEmpty) poLinesDataView(),
if (poLinesList.isNotEmpty) poLinesDataView(context),
if (itemCreationLines.isNotEmpty) itemCreationLinesView(),
if (prLinesList.isNotEmpty) prLinesDataView(),
],
@ -45,7 +48,7 @@ class RequestFragment extends StatelessWidget {
);
}
Widget poLinesDataView() {
Widget poLinesDataView(BuildContext context) {
return ExpandableNotifier(
child: ListView.separated(
shrinkWrap: true,
@ -87,22 +90,38 @@ class RequestFragment extends StatelessWidget {
12.height,
Row(
children: [
DefaultButton(LocaleKeys.itemHistory.tr(), () {
Navigator.pushNamed(
cxt,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(title: LocaleKeys.itemHistory.tr(), isMO: false, pItemId: poLinesList[index].iTEMID),
);
}).expanded,
DefaultButton(
LocaleKeys.itemHistory.tr(),
() {
Navigator.pushNamed(
cxt,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(title: LocaleKeys.itemHistory.tr(), isMO: false, pItemId: poLinesList[index].iTEMID),
);
},
fontSize: 13,
).expanded,
12.width,
DefaultButton(LocaleKeys.quotationAnalysis.tr(), () {
Navigator.pushNamed(
cxt,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(
isItemHistory: false, isMO: false, title: LocaleKeys.quotationAnalysis.tr(), pItemId: poLinesList[index].iTEMID, pPoHeaderId: poLinesList[index].pOHEADERID),
);
}).expanded,
DefaultButton(
LocaleKeys.quotationAnalysis.tr(),
() {
Navigator.pushNamed(
cxt,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(
isItemHistory: false, isMO: false, title: LocaleKeys.quotationAnalysis.tr(), pItemId: poLinesList[index].iTEMID, pPoHeaderId: poLinesList[index].pOHEADERID),
);
},
fontSize: 13,
).expanded,
12.width,
DefaultButton(
"PR Details",
() {
getPRDetails(context, poLinesList[index].pOLINEID.toString());
},
fontSize: 13,
).expanded,
],
)
],
@ -263,4 +282,23 @@ class RequestFragment extends StatelessWidget {
separatorBuilder: (cxt, index) => 12.height,
itemCount: itemCreationLines.length);
}
void getPRDetails(BuildContext context, String poLineID) async {
try {
Utils.showLoading(context);
GetPRInformationList? getPRInformationList = GetPRInformationList();
getPRInformationList = await WorkListApiClient().getPRDetailsForPO(poLineID);
Utils.hideLoading(context);
Navigator.pushNamed(
context,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(
isItemHistory: false, isMO: false, isPRInfo: true, getPRInformationList: getPRInformationList, title: "PR Details", pItemId: 0, pPoHeaderId: 0, pOLineID: poLineID),
);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
}

@ -1,18 +1,20 @@
/* ZiK */
import 'dart:async';
import 'package:flutter/cupertino.dart';
typedef ChildProvider<E> = Widget Function(BuildContext context, E? data);
class Updater<T> extends StatelessWidget{
class Updater<T> extends StatelessWidget {
final ChildProvider<T> childProvider;
StreamController<T?>? sink;
T? initialData;
List<T?> _history = [];
Stream<T?>? _stream;
Updater({T? initialData, required this.childProvider}){
Updater({T? initialData, required this.childProvider}) {
this.sink = StreamController<T?>();
this.initialData = initialData;
_stream = this.sink?.stream;
@ -23,17 +25,17 @@ class Updater<T> extends StatelessWidget{
return StreamBuilder<T?>(
initialData: this.initialData,
stream: _stream,
builder: (ctx, snapshot){
return childProvider(context, snapshot.data);
});
builder: (ctx, snapshot) {
return childProvider(context, snapshot.data);
});
}
void pushData(T? data) {
_history.add(data);
sink?.sink.add(data);
}
List<T?> getDataHistory() => _history;
T? getLatestData() => _history.last;
}
T? getLatestData() => _history.last;
}

@ -1,13 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:provider/provider.dart';
AppBar AppBarWidget(BuildContext context,
{required String title,

@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -26,7 +24,6 @@ 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;
@ -243,11 +240,11 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
children: [
Stack(
children: <Widget>[
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
SvgPicture.asset(
"assets/images/user.svg",
height: 48,
width: 48,
),
Positioned(
right: 5,
bottom: 1,
@ -307,13 +304,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
).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) {
provider.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: provider.chatUsersList![index].id!, fromSearch: true).then((value) {
setState(() {});
});
} else if (provider.chatUsersList![index].isFav == true) {
@ -326,13 +317,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
setState(() {});
});
} else {
provider
.favoriteUser(
userID: AppState().chatDetails!.response!.id!,
targetUserID: provider.chatUsersList![index].id!,
fromSearch: true
)
.then((value) {
provider.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: provider.chatUsersList![index].id!, fromSearch: true).then((value) {
setState(() {});
});
}

@ -5,8 +5,7 @@ import 'package:mohem_flutter_app/classes/colors.dart';
extension WithContainer on Widget {
Widget get insideContainer => Container(
color: Colors.white,
padding:
const EdgeInsets.only(top: 16, bottom: 16, right: 21, left: 21),
padding: const EdgeInsets.only(top: 16, bottom: 16, right: 21, left: 21),
child: this,
);
}
@ -76,8 +75,7 @@ class DefaultButton extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (iconData != null) Icon(iconData, color: textColor),
if (svgIcon != null)
SvgPicture.asset(svgIcon ?? "", color: textColor),
if (svgIcon != null) SvgPicture.asset(svgIcon ?? "", color: textColor),
if (!isTextExpanded)
Padding(
padding: EdgeInsets.only(

@ -0,0 +1,50 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/provider/hmg_connection_provider.dart';
import 'package:provider/provider.dart';
class HmgConnectivityButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
Provider.of<HmgConnectionProvider>(context, listen: false).checkHmgNetworkConnectivity();
return Consumer<HmgConnectionProvider>(
builder: (_, HmgConnectionProvider foo, __) {
return Container(
height: 45,
padding: const EdgeInsets.only(left: 12, right: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(200.0),
gradient: const LinearGradient(
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: <Color>[
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
),
),
child: InkWell(
onTap: (){
},
child: Row(
children: [
const Icon(
Icons.wifi,
color: Colors.white,
),
12.width,
LocaleKeys.connectHmgWifi.tr().toText18(color: Colors.white),
],
),
),
);
},
);
}
}

@ -7,7 +7,6 @@ import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:provider/provider.dart';
AppBar ChatAppBarWidget(BuildContext context,

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
void showMDialog(context, {Widget? child,Color? backgroundColor,bool isDismissable=true}) async {
void showMDialog(context, {Widget? child, Color? backgroundColor, bool isDismissable = true}) async {
return showDialog(
context: context,
barrierDismissible: isDismissable,

@ -55,20 +55,23 @@ class DynamicTextFieldWidget extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
labelText,
style: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: Color(0xff2B353E),
letterSpacing: -0.44,
if (labelText.isNotEmpty)
Text(
labelText,
style: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: Color(0xff2B353E),
letterSpacing: -0.44,
),
),
),
TextField(
enabled: isEnable,
scrollPadding: EdgeInsets.zero,
readOnly: isReadOnly,
keyboardType: (isInputTypeNum) ? (isInputTypeNumSigned ? const TextInputType.numberWithOptions(signed: true, decimal: true) : TextInputType.numberWithOptions(signed: true, decimal: true)) : TextInputType.text,
keyboardType: (isInputTypeNum)
? (isInputTypeNumSigned ? const TextInputType.numberWithOptions(signed: true, decimal: true) : TextInputType.numberWithOptions(signed: true, decimal: true))
: TextInputType.text,
textInputAction: TextInputAction.done,
//controller: controller,
maxLines: lines,

@ -45,7 +45,19 @@ class ImageOptions {
onFilesTap: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'jpeg ', 'pdf', 'txt', 'docx', 'doc', 'pptx', 'xlsx', 'png', 'rar', 'zip',],
allowedExtensions: [
'jpg',
'jpeg ',
'pdf',
'txt',
'docx',
'doc',
'pptx',
'xlsx',
'png',
'rar',
'zip',
],
);
List<File> files = result!.paths.map((path) => File(path!)).toList();
image(result.files.first.path.toString(), files.first);
@ -54,67 +66,68 @@ class ImageOptions {
);
}
static void showImageOptions(BuildContext context, Function(String, File) image) {
showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (BuildContext bc) {
return _BottomSheet(
children: <Widget>[
_BottomSheetItem(
title: "Select File Source",
onTap: () {},
icon: Icons.file_present,
color: MyColors.black,
),
_BottomSheetItem(
title: "Gallery",
icon: Icons.image,
onTap: () async {
if (Platform.isAndroid) {
galleryImageAndroid(image);
} else {
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 10))?.path ?? "");
String fileName = _image.path;
var bytes = File(fileName).readAsBytesSync();
String base64Encode = base64.encode(bytes);
if (base64Encode != null) {
image(base64Encode, _image);
}
}
},
),
_BottomSheetItem(
title: "Camera",
icon: Icons.camera_alt,
onTap: () async {
if (Platform.isAndroid) {
cameraImageAndroid(image);
} else {
File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 10))?.path ?? "");
String fileName = _image.path;
var bytes = File(fileName).readAsBytesSync();
String base64Encode = base64.encode(bytes);
if (base64Encode != null) {
image(base64Encode, _image);
}
}
},
),
_BottomSheetItem(
title: "Cancel",
onTap: () {},
icon: Icons.cancel,
color: MyColors.redColor,
)
],
);
});
}
// static void showImageOptions(BuildContext context, Function(String, File) image) {
// showModalBottomSheet(
// backgroundColor: Colors.transparent,
// context: context,
// builder: (BuildContext bc) {
// return _BottomSheet(
// children: <Widget>[
// _BottomSheetItem(
// title: "Select File Source",
// onTap: () {},
// icon: Icons.file_present,
// color: MyColors.black,
// ),
// _BottomSheetItem(
// title: "Gallery",
// icon: Icons.image,
// onTap: () async {
// if (Platform.isAndroid) {
// galleryImageAndroid(image);
// } else {
// File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.gallery, imageQuality: 10))?.path ?? "");
// String fileName = _image.path;
// var bytes = File(fileName).readAsBytesSync();
// String base64Encode = base64.encode(bytes);
// if (base64Encode != null) {
// image(base64Encode, _image);
// }
// }
// },
// ),
// _BottomSheetItem(
// title: "Camera",
// icon: Icons.camera_alt,
// onTap: () async {
// if (Platform.isAndroid) {
// cameraImageAndroid(image);
// } else {
// File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 10))?.path ?? "");
// String fileName = _image.path;
// var bytes = File(fileName).readAsBytesSync();
// String base64Encode = base64.encode(bytes);
// if (base64Encode != null) {
// image(base64Encode, _image);
// }
// }
// },
// ),
// _BottomSheetItem(
// title: "Cancel",
// onTap: () {},
// icon: Icons.cancel,
// color: MyColors.redColor,
// )
// ],
// );
// });
// }
}
void galleryImageAndroid(Function(String, File) image) async {
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);

@ -44,15 +44,18 @@ class Location {
AppPermissions.location((granted) {
if (granted) {
Geolocator.getLastKnownPosition(forceAndroidLocationManager: true).then((value) {
if (value == null) {
Geolocator.getCurrentPosition().then((value) {
done(value);
});
} else {
done(value);
}
Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium, timeLimit: const Duration(seconds: 5)).then((value) {
done(value);
});
// Geolocator.getLastKnownPosition(forceAndroidLocationManager: true).then((value) {
// if (value == null) {
// Geolocator.getCurrentPosition().then((value) {
// done(value);
// });
// } else {
// done(value);
// }
// });
} else {
// AppPermissions
}

@ -4,6 +4,10 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:geolocator/geolocator.dart';
import 'package:huawei_location/location/fused_location_provider_client.dart';
import 'package:huawei_location/location/location_request.dart';
import 'package:huawei_location/location/location_settings_request.dart';
import 'package:huawei_location/permission/permission_handler.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';
@ -21,6 +25,8 @@ import 'package:mohem_flutter_app/widgets/location/Location.dart';
import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart';
import 'package:mohem_flutter_app/widgets/qr_scanner_dialog.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:platform_device_id/platform_device_id.dart';
import 'package:wifi_iot/wifi_iot.dart';
class MarkAttendanceWidget extends StatefulWidget {
@ -39,6 +45,8 @@ class MarkAttendanceWidget extends StatefulWidget {
class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
bool isNfcEnabled = false, isNfcLocationEnabled = false, isQrEnabled = false, isQrLocationEnabled = false, isWifiEnabled = false, isWifiLocationEnabled = false;
int _locationUpdateCbId = 0;
@override
void initState() {
super.initState();
@ -46,6 +54,8 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
}
void checkAttendanceAvailability() async {
String? deviceID = await PlatformDeviceId.getDeviceId;
print("Platform Device ID: $deviceID");
bool isAvailable = await NfcManager.instance.isAvailable();
setState(() {
AppState().privilegeListModel!.forEach((PrivilegeListModel element) {
@ -66,6 +76,36 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
});
}
void checkHuaweiLocationPermission(String attendanceType) async {
PermissionHandler permissionHandler = PermissionHandler();
if (await permissionHandler.hasLocationPermission()) {
getHuaweiCurrentLocation(attendanceType);
} else {
bool has = await requestPermissions();
if (has) {
getHuaweiCurrentLocation(attendanceType);
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to give location permission to mark attendance",
onTap: () {
Navigator.pop(context);
},
),
);
}
}
}
Future<bool> requestPermissions() async {
var result = await [
Permission.location,
].request();
return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted);
}
@override
void dispose() {
super.dispose();
@ -94,46 +134,57 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
children: <Widget>[
// if (isNfcEnabled)
attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () {
if (isNfcLocationEnabled) {
Location.getCurrentLocation((Position position, bool isMocked) {
if (isMocked) {
markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
} else {
performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
}
}, context);
} else {
performNfcAttendance(widget.model);
}
}),
if (isWifiEnabled)
attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () {
if (isWifiLocationEnabled) {
// if (isNfcLocationEnabled) {
if (AppState().getIsHuawei) {
checkHuaweiLocationPermission("NFC");
} else {
Location.getCurrentLocation((Position position, bool isMocked) {
if (isMocked) {
markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
} else {
performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
}
}, context);
} else {
performWifiAttendance(widget.model);
}
// connectWifi();
// } else {
// performNfcAttendance(widget.model);
// }
}),
if (isWifiEnabled)
attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () {
// if (isWifiLocationEnabled) {
if (AppState().getIsHuawei) {
checkHuaweiLocationPermission("WIFI");
} else {
Location.getCurrentLocation((Position position, bool isMocked) {
if (isMocked) {
markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
} else {
performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
}
}, context);
}
// } else {
// performWifiAttendance(widget.model);
// }
}),
if (isQrEnabled)
attendanceMethod("QR", "assets/images/ic_qr.svg", isQrEnabled, () async {
if (isQrLocationEnabled) {
Location.getCurrentLocation((Position position, bool isMocked) {
if (isMocked) {
markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
} else {
performQrCodeAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
}
}, context);
} else {
performQrCodeAttendance(widget.model);
}
// if (isQrLocationEnabled) {
if (AppState().getIsHuawei) {
checkHuaweiLocationPermission("QR");
} else {
Location.getCurrentLocation((Position position, bool isMocked) {
if (isMocked) {
markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
} else {
performQrCodeAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
}
}, context);
}
// } else {
// performQrCodeAttendance(widget.model);
// }
// performQrCodeAttendance(model);
}),
],
@ -143,6 +194,55 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
);
}
void getHuaweiCurrentLocation(String attendanceType) {
try {
FusedLocationProviderClient locationService = FusedLocationProviderClient();
LocationRequest locationRequest = LocationRequest();
locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
locationRequest.interval = 1000;
List<LocationRequest> locationRequestList = <LocationRequest>[locationRequest];
LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList);
locationService.checkLocationSettings(locationSettingsRequest).then((settings) async {
await locationService.getLastLocation().then((value) {
if (value.latitude == null || value.longitude == null) {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "Unable to get your location, Please check your location settings & try again.",
onTap: () {
Navigator.pop(context);
},
),
);
} else {
if (attendanceType == "QR") {
performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
}
if (attendanceType == "WIFI") {
performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
}
if (attendanceType == "NFC") {
performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
}
}
}).catchError((error) {
print("HUAWEI LOCATION getLastLocation ERROR!!!!!");
print(error);
});
}).catchError((error) {
print("HUAWEI LOCATION checkLocationSettings ERROR!!!!!");
print(error);
if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") {
// Location service not enabled.
}
});
} catch (error) {
print("HUAWEI LOCATION ERROR!!!!!");
print(error);
}
}
Future<void> performNfcAttendance(DashboardProviderModel model, {String lat = "0", String lng = "0"}) async {
if (Platform.isIOS) {
Utils.readNFc(onRead: (String nfcId) async {
@ -252,12 +352,26 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
bool status = await model.fetchAttendanceTracking(context);
Utils.hideLoading(context);
await closeWifiRequest();
showMDialog(
context,
backgroundColor: Colors.transparent,
isDismissable: false,
child: SuccessDialog(widget.isFromDashboard),
);
if (g?.messageStatus == 2) {
showDialog(
barrierDismissible: true,
context: context,
builder: (cxt) => ConfirmDialog(
message: g?.errorEndUserMessage ?? "",
onTap: () {
Navigator.pop(context);
},
onCloseTap: () {},
),
);
} else {
showMDialog(
context,
backgroundColor: Colors.transparent,
isDismissable: false,
child: SuccessDialog(widget.isFromDashboard),
);
}
} catch (ex) {
await closeWifiRequest();
Utils.hideLoading(context);
@ -292,12 +406,26 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 1, isGpsRequired: isQrLocationEnabled, lat: lat, long: lng, QRValue: qrCodeValue);
bool status = await model.fetchAttendanceTracking(context);
Utils.hideLoading(context);
showMDialog(
context,
backgroundColor: Colors.transparent,
isDismissable: true,
child: SuccessDialog(widget.isFromDashboard),
);
if (g?.messageStatus == 2) {
showDialog(
barrierDismissible: true,
context: context,
builder: (cxt) => ConfirmDialog(
message: g?.errorEndUserMessage ?? "",
onTap: () {
Navigator.pop(context);
},
onCloseTap: () {},
),
);
} else {
showMDialog(
context,
backgroundColor: Colors.transparent,
isDismissable: true,
child: SuccessDialog(widget.isFromDashboard),
);
}
} catch (ex) {
print(ex);
Utils.hideLoading(context);

@ -108,7 +108,7 @@ class OTPWidgetState extends State<OTPWidget> with SingleTickerProviderStateMixi
}
}
void calculateStrList() {
void calculateStrList() {
if (strList.length > widget.maxLength) {
strList.length = widget.maxLength;
}

@ -1,9 +1,8 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
class QrScannerDialog extends StatefulWidget {
@override
@ -68,6 +67,8 @@ class _QrScannerDialogState extends State<QrScannerDialog> {
}
});
});
controller.pauseCamera();
controller.resumeCamera();
}
@override

@ -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: 4.2.0+4000002
version: 3.6.4+1
environment:
sdk: ">=2.16.0 <3.0.0"
@ -54,7 +54,10 @@ dependencies:
logger: ^1.1.0
flutter_countdown_timer: ^4.1.0
nfc_manager: ^3.2.0
uuid: ^3.0.6
# uuid: ^3.0.6
# device_info_plus: ^4.0.0
# android_id: ^0.1.3+1
platform_device_id: ^1.0.1
image_picker: ^0.8.5+3
file_picker: ^4.6.1
geolocator: ^9.0.2
@ -64,7 +67,7 @@ dependencies:
wifi_iot: ^0.3.18
flutter_html: ^3.0.0-alpha.6
# flutter_barcode_scanner: ^2.0.0
qr_code_scanner: ^1.0.0
qr_code_scanner: ^1.0.1
# qr_flutter: ^4.0.0
url_launcher: ^6.0.15
share: 2.0.4
@ -86,7 +89,7 @@ dependencies:
swipe_to: ^1.0.2
flutter_webrtc: ^0.9.16
camera: ^0.10.3
flutter_local_notifications: any
flutter_local_notifications: ^10.0.0
#firebase_analytics: any
#Chat Voice Message Recoding & Play
@ -102,12 +105,18 @@ dependencies:
flutter_layout_grid: ^2.0.1
#Huawei Dependencies
huawei_hmsavailability: ^6.6.0+300
# huawei_hmsavailability: ^6.6.0+300
huawei_location: 6.0.0+302
huawei_push: ^6.7.0+300
firebase_crashlytics: ^2.9.0
#Items for sale Image Carousel Slider
carousel_slider: ^4.2.1
#Huawei Specified
google_api_availability: ^3.0.1
dependency_overrides:
firebase_core_platform_interface: 4.5.1

Loading…
Cancel
Save