From d4a795dda15dab34e79764929d6d556af9c773da Mon Sep 17 00:00:00 2001 From: Sultan khan <> Date: Tue, 19 Dec 2023 09:45:59 +0300 Subject: [PATCH 1/8] half day leave bug fixed --- .../leave_balance/calculate_absence_duration_model.dart | 4 ++-- lib/ui/leave_balance/add_leave_balance_screen.dart | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/models/leave_balance/calculate_absence_duration_model.dart b/lib/models/leave_balance/calculate_absence_duration_model.dart index 0f0a48b..cf32a0e 100644 --- a/lib/models/leave_balance/calculate_absence_duration_model.dart +++ b/lib/models/leave_balance/calculate_absence_duration_model.dart @@ -1,6 +1,6 @@ class CalculateAbsenceDuration { - num? pABSENCEDAYS; - num? pABSENCEHOURS; + double? pABSENCEDAYS; + double? pABSENCEHOURS; String? pRETURNMSG; String? pRETURNSTATUS; diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index a16e81d..830ca85 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -40,7 +40,7 @@ class _AddLeaveBalanceScreenState extends State { GetAbsenceAttendanceTypesList? selectedAbsenceType; DateTime? startDateTime; DateTime? endDateTime; - int? totalDays; + double? totalDays; String comment = ""; ReplacementList? selectedReplacementEmployee; String? selectedEmp; @@ -90,7 +90,7 @@ class _AddLeaveBalanceScreenState extends State { Utils.showLoading(context); CalculateAbsenceDuration duration = await LeaveBalanceApiClient() .calculateAbsenceDuration(selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, Utils.getMonthNamedFormat(startDateTime!), Utils.getMonthNamedFormat(endDateTime!), -999, empID: selectedEmp); - totalDays = duration.pABSENCEDAYS?.toInt(); + totalDays = duration.pABSENCEDAYS?.toDouble(); Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -232,7 +232,7 @@ class _AddLeaveBalanceScreenState extends State { isInputTypeNum: true, isEnable: false, onChange: (input) { - totalDays = int.parse(input); + totalDays = double.tryParse(input); }, ), 12.height, From 753d3de3c2045e4807a75c238b97d9244217c20c Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Sun, 24 Dec 2023 11:44:23 +0300 Subject: [PATCH 2/8] Join MarathonProviderFix --- lib/classes/consts.dart | 12 ++++++++---- lib/ui/marathon/marathon_provider.dart | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 6ce549f..654ee42 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -3,8 +3,8 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver - static String baseUrl = "https://hmgwebservices.com"; // Live server + static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver + // 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/"; @@ -36,7 +36,10 @@ class ApiConsts { static String chatUserImages = chatServerBaseUrl + "empservice/api/employee/"; //Brain Marathon Constants - static String marathonBaseUrl = "https://marathoon.com/service/api/"; + static String marathonBaseUrlLive = "https://marathoon.com/service/api/"; + static String marathonBaseUrlUAT = "https://marathoon.com/uatservice/api/"; + // static String marathonBaseUrl = marathonBaseUrlLive; + static String marathonBaseUrl = marathonBaseUrlUAT; static String marathonBaseUrlServices = "https://marathoon.com/service/"; static String marathonParticipantLoginUrl = marathonBaseUrl + "auth/participantlogin"; static String marathonProjectGetUrl = marathonBaseUrl + "Project/Project_Get"; @@ -49,7 +52,6 @@ class ApiConsts { static String marathonGetMarathonersCount = marathonBaseUrl + "Participant/GetRemainingParticipants"; //DummyCards for the UI - static CardContent dummyQuestion = const CardContent(); static int tabletMinLength = 500; } @@ -67,3 +69,5 @@ class SharedPrefsConsts { static String mohemmWifiPassword = "mohemmWifiPassword"; static String editItemForSale = "editItemForSale"; } + + diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index 0b1a783..544aad3 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -373,7 +373,7 @@ class MarathonProvider extends ChangeNotifier { void updateCardData() { if (currentQuestionNumber > 0) { - swiperController.swipeLeft(); + // swiperController.swipeLeft(); } selectedOptionIndex = null; currentQuestionNumber++; From 5723b64234717c11a33581245b216a94b82faa88 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Tue, 26 Dec 2023 10:52:26 +0300 Subject: [PATCH 3/8] Join MarathonProviderFix --- assets/json/demo_upcoming_marathon | 5 ++-- lib/app_state/app_state.dart | 2 +- lib/classes/decorations_helper.dart | 1 - lib/models/marathon/marathon_model.dart | 5 ++++ lib/ui/marathon/marathon_provider.dart | 29 +++++++++++++++------- lib/ui/marathon/widgets/question_card.dart | 2 +- 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/assets/json/demo_upcoming_marathon b/assets/json/demo_upcoming_marathon index 2fdabf0..f08cb22 100644 --- a/assets/json/demo_upcoming_marathon +++ b/assets/json/demo_upcoming_marathon @@ -16,7 +16,7 @@ "projects": { "id": "b1cd3fa3-bb27-422e-a4c1-08dac09254df", "nameEn": "Cloud Solutions", - "nameAr": "333شركة حلول السحابة للاتصالات وتقنية المعلومات", + "nameAr": "شركة حلول السحابة للاتصالات وتقنية المعلومات", "projectCode": "CS" }, "sponsors": [ @@ -42,5 +42,6 @@ "totalQuestions": 10, "cancelReason": null, "marathonBufferTime": 30, - "currentTime": "2022-12-28T08:03:24.3671803Z" + "currentTime": "2022-12-28T08:03:24.3671803Z", + "displayCorrectAnswer": true } diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 2cfc751..1039b20 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -90,7 +90,7 @@ class AppState { String get getHuaweiPushToken => _huaweiPushToken; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.3, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.4, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/classes/decorations_helper.dart b/lib/classes/decorations_helper.dart index b313673..fd6d4f7 100644 --- a/lib/classes/decorations_helper.dart +++ b/lib/classes/decorations_helper.dart @@ -30,7 +30,6 @@ class MyDecorations { return getContainersDecoration(MyColors.greenColor); case QuestionsOptionStatus.wrong: return getContainersDecoration(MyColors.redColor); - case QuestionsOptionStatus.selected: return getContainersDecoration(MyColors.yellowColorII); case QuestionsOptionStatus.unSelected: diff --git a/lib/models/marathon/marathon_model.dart b/lib/models/marathon/marathon_model.dart index d86ffc7..934b73b 100644 --- a/lib/models/marathon/marathon_model.dart +++ b/lib/models/marathon/marathon_model.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + class MarathonDetailModel { String? id; String? titleEn; @@ -17,6 +19,7 @@ class MarathonDetailModel { List? questions; int? totalQuestions; int? marathonBufferTime; + bool? displayCorrectAnswer; MarathonDetailModel({ id, @@ -37,6 +40,7 @@ class MarathonDetailModel { questions, totalQuestions, marathonBufferTime, + displayCorrectAnswer, }); MarathonDetailModel.fromJson(Map json) { @@ -68,6 +72,7 @@ class MarathonDetailModel { } totalQuestions = json["totalQuestions"]; marathonBufferTime = json["marathonBufferTime"]; + displayCorrectAnswer = json["displayCorrectAnswer"]; } Map toJson() { diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index 544aad3..ed241af 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer'; import 'package:appinio_swiper/appinio_swiper.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -414,13 +415,16 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); } - void updateCurrentQuestionOptionStatus(QuestionsOptionStatus status, int index) { + void updateCurrentQuestionOptionStatus({required QuestionsOptionStatus status, required int selectedOptIndex, required int correctOptionIndex}) { for (int i = 0; i < currentQuestion.questionOptions!.length; i++) { currentQuestion.questionOptions![i].optionStatus = QuestionsOptionStatus.unSelected; } - currentQuestion.questionOptions![index].optionStatus = status; - selectedOptionId = currentQuestion.questionOptions![index].id; - selectedOptionIndex = index; + if (status == QuestionsOptionStatus.wrong) { + currentQuestion.questionOptions![correctOptionIndex].optionStatus = QuestionsOptionStatus.correct; // if person's answer is wrong we have to show him the actual right answer + } + currentQuestion.questionOptions![selectedOptIndex].optionStatus = status; + selectedOptionId = currentQuestion.questionOptions![selectedOptIndex].id; + selectedOptionIndex = selectedOptIndex; notifyListeners(); } @@ -435,22 +439,30 @@ class MarathonProvider extends ChangeNotifier { } void getCorrectAnswerAndUpdateAnswerColor() { + log("correctOptionIndex"); + callCountThreshold = 1; + int correctOptionIndex = -1; + if (demoMarathonDetailModel.displayCorrectAnswer ?? false) { + correctOptionIndex = currentQuestion.questionOptions!.indexWhere((QuestionOptions element) => element.isCorrectOption ?? false); + log("correctOptionIndex: $correctOptionIndex"); + } + if (selectedOptionIndex != null) { scheduleMicrotask(() async { if (AppState().getIsDemoMarathon) { if (currentQuestion.questionOptions![selectedOptionIndex!].isCorrectOption!) { - updateCurrentQuestionOptionStatus(QuestionsOptionStatus.correct, selectedOptionIndex!); + updateCurrentQuestionOptionStatus(status: QuestionsOptionStatus.correct, selectedOptIndex: selectedOptionIndex!, correctOptionIndex: correctOptionIndex); } else { - updateCurrentQuestionOptionStatus(QuestionsOptionStatus.wrong, selectedOptionIndex!); + updateCurrentQuestionOptionStatus(status: QuestionsOptionStatus.wrong, selectedOptIndex: selectedOptionIndex!, correctOptionIndex: correctOptionIndex); } } else { await callSubmitOptionApi().then((bool value) async { updateIsUserOutOfGame = !value; if (value) { - updateCurrentQuestionOptionStatus(QuestionsOptionStatus.correct, selectedOptionIndex!); + updateCurrentQuestionOptionStatus(status: QuestionsOptionStatus.correct, selectedOptIndex: selectedOptionIndex!, correctOptionIndex: correctOptionIndex); } else { - updateCurrentQuestionOptionStatus(QuestionsOptionStatus.wrong, selectedOptionIndex!); + updateCurrentQuestionOptionStatus(status: QuestionsOptionStatus.wrong, selectedOptIndex: selectedOptionIndex!, correctOptionIndex: correctOptionIndex); } }); } @@ -551,7 +563,6 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); isPrivilegedWithMarathon = checkIfPrivilegedForMarathon(); demoMarathonDetailModel = await DemoMarathonRepo().getDemoMarathonDetails(); - if (isPrivilegedWithMarathon) { marathonDetailModel = await MarathonApiClient().getMarathonDetails(); updateTotalSecondsToWaitForMarathon = marathonDetailModel.marathonBufferTime ?? 30; diff --git a/lib/ui/marathon/widgets/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index 8aa76bd..0965c9d 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -133,7 +133,7 @@ class AnswerContent extends StatelessWidget { if (provider.totalCurrentQuestionTime - provider.currentGapTime <= 0) { null; } else { - provider.updateCurrentQuestionOptionStatus(QuestionsOptionStatus.selected, index); + provider.updateCurrentQuestionOptionStatus(status: QuestionsOptionStatus.selected, selectedOptIndex: index, correctOptionIndex: -1); // } }, ); From c86d9f467829e764f963aea7181c159b134e4025 Mon Sep 17 00:00:00 2001 From: Sultan khan <> Date: Tue, 2 Jan 2024 10:35:43 +0300 Subject: [PATCH 4/8] termination work-list fixed --- lib/api/worklist/worklist_api_client.dart | 17 ++++++++ lib/app_state/app_state.dart | 2 +- lib/models/generic_response_model.dart | 19 +++++++-- .../termination_notification_body.dart | 18 ++++++++ lib/ui/work_list/worklist_detail_screen.dart | 27 ++++++++++++ .../worklist_fragments/info_fragments.dart | 42 ++++++++++++++++++- 6 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 lib/models/termination/termination_notification_body.dart diff --git a/lib/api/worklist/worklist_api_client.dart b/lib/api/worklist/worklist_api_client.dart index 29805ec..611bcf4 100644 --- a/lib/api/worklist/worklist_api_client.dart +++ b/lib/api/worklist/worklist_api_client.dart @@ -24,6 +24,7 @@ import 'package:mohem_flutter_app/models/get_user_item_type_list.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/itg_request_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart'; +import 'package:mohem_flutter_app/models/termination/termination_notification_body.dart'; import 'package:mohem_flutter_app/models/update_user_item_type_list.dart'; import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; @@ -550,6 +551,22 @@ class WorkListApiClient { }, url, postParams); } + Future?> getTerminationNotificationBodyList(int? notificationId) async { + String url = "${ApiConsts.erpRest}GET_TERM_NOTIFICATION_BODY"; + Map postParams = { + "P_NOTIFICATION_ID": notificationId, + "P_PAGE_LIMIT": 100, + "P_PAGE_NUM": 1, + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getTermNotificationBodyList; + }, url, postParams); + } + + + Future?> getFavoriteReplacementWithoutImage() async { String url = "${ApiConsts.erpRest}Mohemm_GetFavoriteReplacementsWithoutImage"; Map postParams = {}; diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 2cfc751..51469c2 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -90,7 +90,7 @@ class AppState { String get getHuaweiPushToken => _huaweiPushToken; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.3, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.7, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 5188b2c..893b5b9 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -92,6 +92,7 @@ import 'package:mohem_flutter_app/models/submit_term_transaction_list_model.dart import 'package:mohem_flutter_app/models/subordinates_on_leaves_model.dart'; import 'package:mohem_flutter_app/models/termination/get_term_cols_structure_list_model.dart'; import 'package:mohem_flutter_app/models/termination/get_term_dff_structure_list_model.dart'; +import 'package:mohem_flutter_app/models/termination/termination_notification_body.dart'; import 'package:mohem_flutter_app/models/update_item_type_success_list.dart'; import 'package:mohem_flutter_app/models/update_user_item_type_list.dart'; import 'package:mohem_flutter_app/models/vacation_rule/create_vacation_rule_list_model.dart'; @@ -223,7 +224,6 @@ class GenericResponseModel { List? getOrganizationsSalariesList; List? getPaymentInformationList; List? getPayslipList; - // List? getPendingReqDetailsList; // List? getPendingReqFunctionsList; List? getPerformanceAppraisalList; @@ -254,7 +254,7 @@ class GenericResponseModel { List? getSwipesList; List? getTermColsStructureList; List? getTermDffStructureList; - List? getTermNotificationBodyList; + List? getTermNotificationBodyList; List? getTimeCardSummaryList; List? getTicketsByEmployeeList; List? getTicketDetailsByEmployee; @@ -680,6 +680,7 @@ class GenericResponseModel { successMsg = json['SuccessMsg']; successMsgN = json['SuccessMsgN']; vidaUpdatedResponse = json['VidaUpdatedResponse']; + if (json['AddAttSuccessList'] != null) { addAttSuccessList = []; json['AddAttSuccessList'].forEach((v) { @@ -693,6 +694,14 @@ class GenericResponseModel { businessCardPrivilege = json['BusinessCardPrivilege']; calculateAbsenceDuration = json['CalculateAbsenceDuration'] != null ? new CalculateAbsenceDuration.fromJson(json['CalculateAbsenceDuration']) : null; cancelHRTransactionLIst = json['CancelHRTransactionLIst'] != null ? new CancelHRTransactionLIst.fromJson(json['CancelHRTransactionLIst']) : null; + + if (json['GetTermNotificationBodyList'] != null) { + getTermNotificationBodyList = []; + json['GetTermNotificationBodyList'].forEach((v) { + getTermNotificationBodyList!.add(TerminationNotificationBody.fromJson(v)); + }); + } + chatEmployeeLoginList = json['Chat_EmployeeLoginList']; companyBadge = json['CompanyBadge']; companyImage = json['CompanyImage']; @@ -1090,7 +1099,7 @@ class GenericResponseModel { }); } - getTermNotificationBodyList = json['GetTermNotificationBodyList']; + if (json['GetTimeCardSummaryList'] != null) { getTimeCardSummaryList = []; @@ -1612,6 +1621,9 @@ class GenericResponseModel { data['GetNotificationReassignModeList'] = getNotificationReassignModeList!.map((v) => v.toJson()).toList(); } + if(getTermNotificationBodyList !=null){ + data['GetTermNotificationBodyList'] = getTermNotificationBodyList!.map((v) => v.toJson()).toList(); + } data['GetObjectValuesList'] = this.getObjectValuesList; data['GetOpenMissingSwipesList'] = this.getOpenMissingSwipesList; data['GetOpenNotificationsList'] = this.getOpenNotificationsList; @@ -1688,7 +1700,6 @@ class GenericResponseModel { data['GetTermDffStructureList'] = this.getTermDffStructureList!.map((v) => v.toJson()).toList(); } - data['GetTermNotificationBodyList'] = this.getTermNotificationBodyList; if (this.getTimeCardSummaryList != null) { data['GetTimeCardSummaryList'] = this.getTimeCardSummaryList!.map((v) => v.toJson()).toList(); } diff --git a/lib/models/termination/termination_notification_body.dart b/lib/models/termination/termination_notification_body.dart new file mode 100644 index 0000000..2c2c709 --- /dev/null +++ b/lib/models/termination/termination_notification_body.dart @@ -0,0 +1,18 @@ +class TerminationNotificationBody { + String? sEGMENTPROMPT; + String? sEGMENTVALUEDSP; + + TerminationNotificationBody({this.sEGMENTPROMPT, this.sEGMENTVALUEDSP}); + + TerminationNotificationBody.fromJson(Map json) { + sEGMENTPROMPT = json['SEGMENT_PROMPT']; + sEGMENTVALUEDSP = json['SEGMENT_VALUE_DSP']; + } + + Map toJson() { + Map data = new Map(); + data['SEGMENT_PROMPT'] = this.sEGMENTPROMPT; + data['SEGMENT_VALUE_DSP'] = this.sEGMENTVALUEDSP; + return data; + } +} diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 0a4f8cc..c80f1b4 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -44,6 +44,8 @@ import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dialogs/accept_reject_input_dialog.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; +import 'package:mohem_flutter_app/models/termination/termination_notification_body.dart'; + class WorkListDetailScreen extends StatefulWidget { WorkListDetailScreen({Key? key}) : super(key: key); @@ -80,6 +82,8 @@ class _WorkListDetailScreenState extends State { List? getAbsenceCollectionNotificationBodyList = []; GetContactNotificationBodyList? getContactNotificationBodyList; List? getAddressNotificationBodyList = []; + List? getTerminationNotificationBodyList = []; + GenericResponseModel? getBasicNTFBody; GenericResponseModel? getICBody; @@ -121,6 +125,7 @@ class _WorkListDetailScreenState extends State { getItemCreationNtfBody?.itemCreationHeader!.clear(); getPhonesNotificationBodyList!.clear(); getBasicDetNtfBodyList!.clear(); + getTerminationNotificationBodyList!.clear(); getAbsenceCollectionNotificationBodyList!.clear(); getContactNotificationBodyList = null; getAddressNotificationBodyList!.clear(); @@ -147,6 +152,8 @@ class _WorkListDetailScreenState extends State { getContactNotificationBody(); } else if (workListData!.rEQUESTTYPE == "ADDRESS") { getAddressNotificationBody(); + } else if(workListData!.rEQUESTTYPE =='TERMINATION'){ + getTerminationNotificationBody(); } } if (workListData!.iTEMTYPE == "STAMP") { @@ -257,6 +264,7 @@ class _WorkListDetailScreenState extends State { getAbsenceCollectionNotificationBodyList: getAbsenceCollectionNotificationBodyList, getContactNotificationBodyList: getContactNotificationBodyList, getPrNotificationBodyList: getPrNotificationBody, + getTerminationNotificationBodyList:getTerminationNotificationBodyList ), (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") ? DetailFragment(workListData, memberInformationListModel) @@ -854,6 +862,25 @@ class _WorkListDetailScreenState extends State { Utils.handleException(ex, context, null); } } + void getTerminationNotificationBody() async { + try { + if (apiCallCount == 0) + apiCallCount++; + getTerminationNotificationBodyList = await WorkListApiClient().getTerminationNotificationBodyList(workListData!.nOTIFICATIONID); + Utils.hideLoading(context); + apiCallCount--; + if (apiCallCount == 0) { + + setState(() {}); + } + } catch (ex) { + apiCallCount--; + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + void getStampNotificationBody() async { try { diff --git a/lib/ui/work_list/worklist_fragments/info_fragments.dart b/lib/ui/work_list/worklist_fragments/info_fragments.dart index 5edb6f1..7e1cd1c 100644 --- a/lib/ui/work_list/worklist_fragments/info_fragments.dart +++ b/lib/ui/work_list/worklist_fragments/info_fragments.dart @@ -20,6 +20,8 @@ import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_bod import 'package:mohem_flutter_app/models/worklist_response_model.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; +import 'package:mohem_flutter_app/models/termination/termination_notification_body.dart'; + class InfoFragment extends StatelessWidget { WorkListResponseModel? workListData; List poHeaderList; @@ -33,7 +35,7 @@ class InfoFragment extends StatelessWidget { GetContactNotificationBodyList? getContactNotificationBodyList; GetPrNotificationBodyList? getPrNotificationBodyList; List? getAddressNotificationBodyList = []; - + List? getTerminationNotificationBodyList =[]; InfoFragment( {this.workListData, this.poHeaderList = const [], @@ -46,7 +48,9 @@ class InfoFragment extends StatelessWidget { this.getAbsenceCollectionNotificationBodyList, this.getContactNotificationBodyList, this.getPrNotificationBodyList, - this.getAddressNotificationBodyList}); + this.getAddressNotificationBodyList, + this.getTerminationNotificationBodyList + }); double itemHeight = 0; double itemWidth = 0; @@ -93,6 +97,7 @@ class InfoFragment extends StatelessWidget { if (getAbsenceCollectionNotificationBodyList?.isNotEmpty ?? false) getAbsenceCollectionNotificationBodyListWidget(getAbsenceCollectionNotificationBodyList ?? []), if (getContactNotificationBodyList != null) getContactNotificationBodyListWidget(getContactNotificationBodyList ?? GetContactNotificationBodyList()).objectContainerView(), if (getAddressNotificationBodyList?.isNotEmpty ?? false) getAddressNotificationBodyListWidget(getAddressNotificationBodyList!), + if (getTerminationNotificationBodyList?.isNotEmpty ?? false) getTerminationNotificationBodyListWidget(getTerminationNotificationBodyList!), ]; return Container( width: double.infinity, @@ -499,6 +504,39 @@ class InfoFragment extends StatelessWidget { ).objectContainerView(); } + + Widget getTerminationNotificationBodyListWidget(List getterminationNotificationBodyList) { + bool isOdd = false; + try { + if (getterminationNotificationBodyList.length % 2 != 0) { + isOdd = true; + getterminationNotificationBodyList.add(TerminationNotificationBody(sEGMENTPROMPT: "--", sEGMENTVALUEDSP: "--")); + } + } catch (e) {} + + return GridView.builder( + itemCount: getterminationNotificationBodyList!.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) => ItemDetailViewGridItem( + index, + getterminationNotificationBodyList[index].sEGMENTPROMPT, + getterminationNotificationBodyList[index].sEGMENTVALUEDSP, + isNeedToShowEmptyDivider: (getterminationNotificationBodyList.length == index + 1) + ? isOdd + ? true + : false + : false, + ), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: (itemWidth / itemHeight), + ), + ).objectContainerView(); + } + + + List getPRHeaderValues() { List pRHeaders = []; getPrNotificationBodyList!.pRHeader!.forEach((element) { From a411b8e978aebd195001f211d9fd9e5b8a73139f Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 3 Jan 2024 14:37:52 +0300 Subject: [PATCH 5/8] File picker permission issue fixed --- lib/api/chat/chat_api_client.dart | 2 ++ lib/app_state/app_state.dart | 2 +- lib/widgets/image_picker.dart | 56 +++++++++++++++++++++---------- pubspec.yaml | 6 ++-- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index d077026..daafa92 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -29,6 +29,7 @@ class ChatApiClient { Future getUserLoginToken() async { user.UserAutoLoginModel userLoginResponse = user.UserAutoLoginModel(); + String? deviceToken = AppState().getIsHuawei ? AppState().getHuaweiPushToken : AppState().getDeviceToken; Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatLoginTokenUrl}externaluserlogin", { @@ -38,6 +39,7 @@ class ChatApiClient { "platform": Platform.isIOS ? "ios" : "android", "deviceToken": AppState().getIsHuawei ? AppState().getHuaweiPushToken : AppState().getDeviceToken, "isHuaweiDevice": AppState().getIsHuawei, + "voipToken": "", }, ); diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 2cfc751..1039b20 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -90,7 +90,7 @@ class AppState { String get getHuaweiPushToken => _huaweiPushToken; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.3, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 5.4, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index ef04f84..19b1e00 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -8,6 +8,8 @@ import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/attachment_options.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; +import 'package:permission_handler/permission_handler.dart'; class ImageOptions { static void showImageOptionsNew(BuildContext context, bool showFilesOption, Function(String, File) image) { @@ -43,24 +45,42 @@ 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', - ], - ); - List files = result!.paths.map((path) => File(path!)).toList(); - image(result.files.first.path.toString(), files.first); + Permission.storage.isGranted.then((isGranted) { + if (!isGranted) { + Permission.manageExternalStorage.request().then((granted) async { + if (granted == PermissionStatus.granted) { + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: [ + 'jpg', + 'jpeg ', + 'pdf', + 'txt', + 'docx', + 'doc', + 'pptx', + 'xlsx', + 'png', + 'rar', + 'zip', + ], + ); + List files = result!.paths.map((path) => File(path!)).toList(); + image(result.files.first.path.toString(), files.first); + } else { + showDialog( + context: context, + builder: (BuildContext cxt) => ConfirmDialog( + message: "You need to give storage permission to upload files.", + onTap: () { + Navigator.pop(context); + }, + ), + ); + } + }); + } + }); }, ), ); diff --git a/pubspec.yaml b/pubspec.yaml index e3b15bd..82ae41b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html #version: 3.3.01+300040 -version: 3.7.7+1 +version: 3.3.6+300046 environment: sdk: ">=2.16.0 <3.0.0" @@ -60,7 +60,7 @@ dependencies: # android_id: ^0.1.3+1 platform_device_id: ^1.0.1 image_picker: ^0.8.5+3 - file_picker: ^4.6.1 + file_picker: 5.2.5 geolocator: ^9.0.2 month_year_picker: ^0.2.0+1 month_picker_dialog_2: 0.5.5 @@ -124,6 +124,8 @@ dependencies: #todo its for temporary purpose, later will remove this. dotted_border: ^2.0.0+3 +# saf: ^1.0.3+4 + dependency_overrides: firebase_core_platform_interface: 4.5.1 From c104de86ba4c6b21bdf71bb949f58ddc8bd0ef6f Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 7 Jan 2024 16:17:57 +0300 Subject: [PATCH 6/8] Updates --- android/app/src/main/AndroidManifest.xml | 10 ++++++++++ ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 3f5e424..ea79d76 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -8,6 +8,16 @@ + + + + + + + + diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 073c15f..e734dc5 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -376,7 +376,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.7.2; + MARKETING_VERSION = 3.7.8; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.mohemm; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -514,7 +514,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.7.2; + MARKETING_VERSION = 3.7.8; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.mohemm; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -544,7 +544,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.7.2; + MARKETING_VERSION = 3.7.8; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.mohemm; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; From fc3c1c057aec46a5a213adf01eafe7a5b724611c Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 11 Jan 2024 16:41:10 +0300 Subject: [PATCH 7/8] Attachments handled in transactions list mowadhafi --- lib/api/mowadhafhi/mowadhafhi_api_client.dart | 15 ++++ lib/classes/consts.dart | 4 +- .../mowadhafhi/get_ticket_transactions.dart | 40 +++++++-- .../get_transaction_attachment_model.dart | 52 ++++++++++++ .../screens/mowadhafhi/request_details.dart | 83 +++++++++++++++++-- .../view_transaction_attachment.dart | 34 ++++++++ .../worklist_fragments/actions_fragment.dart | 12 ++- 7 files changed, 219 insertions(+), 21 deletions(-) create mode 100644 lib/models/mowadhafhi/get_transaction_attachment_model.dart create mode 100644 lib/ui/screens/mowadhafhi/view_transaction_attachment.dart diff --git a/lib/api/mowadhafhi/mowadhafhi_api_client.dart b/lib/api/mowadhafhi/mowadhafhi_api_client.dart index e5ecc4b..d724c67 100644 --- a/lib/api/mowadhafhi/mowadhafhi_api_client.dart +++ b/lib/api/mowadhafhi/mowadhafhi_api_client.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -10,6 +12,7 @@ import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_details.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_types.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_tickets_list.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_transaction_attachment_model.dart'; class MowadhafhiApiClient { static final MowadhafhiApiClient _instance = MowadhafhiApiClient._internal(); @@ -51,6 +54,18 @@ class MowadhafhiApiClient { }, url, postParams); } + Future getTransactionAttachments(int? attachmentID) async { + String url = "${ApiConsts.cocRest}Mohemm_ITG_GetTicketAttachment"; + Map postParams = {"EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER, "ItgAttachmentId": attachmentID}; + + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + var jsonDecodedData = jsonDecode(responseData.mohemmITGResponseItem!); + return GetTransactionAttachmentModel.fromJson(jsonDecodedData); + }, url, postParams); + } + Future> getTicketTypes() async { String url = "${ApiConsts.cocRest}Mohemm_ITG_GetTicketTypes"; Map postParams = {"EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER}; diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 437839b..bffc7ad 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -3,8 +3,8 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver - static String baseUrl = "https://hmgwebservices.com"; // Live server + static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver + // 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/"; diff --git a/lib/models/mowadhafhi/get_ticket_transactions.dart b/lib/models/mowadhafhi/get_ticket_transactions.dart index be793ca..3cb0ce1 100644 --- a/lib/models/mowadhafhi/get_ticket_transactions.dart +++ b/lib/models/mowadhafhi/get_ticket_transactions.dart @@ -1,24 +1,24 @@ class GetTicketTransactions { String? actionBy; String? actionDate; + List? attachments; String? comments; String? statusDisplayText; String? statusName; String? ticketId; int? ticketTransactionId; - GetTicketTransactions( - {this.actionBy, - this.actionDate, - this.comments, - this.statusDisplayText, - this.statusName, - this.ticketId, - this.ticketTransactionId}); + GetTicketTransactions({this.actionBy, this.actionDate, this.attachments, this.comments, this.statusDisplayText, this.statusName, this.ticketId, this.ticketTransactionId}); GetTicketTransactions.fromJson(Map json) { actionBy = json['actionBy']; actionDate = json['actionDate']; + if (json['attachments'] != null) { + attachments = []; + json['attachments'].forEach((v) { + attachments!.add(new Attachments.fromJson(v)); + }); + } comments = json['comments']; statusDisplayText = json['statusDisplayText']; statusName = json['statusName']; @@ -27,9 +27,12 @@ class GetTicketTransactions { } Map toJson() { - Map data = new Map(); + Map data = Map(); data['actionBy'] = this.actionBy; data['actionDate'] = this.actionDate; + if (this.attachments != null) { + data['attachments'] = this.attachments!.map((v) => v.toJson()).toList(); + } data['comments'] = this.comments; data['statusDisplayText'] = this.statusDisplayText; data['statusName'] = this.statusName; @@ -38,3 +41,22 @@ class GetTicketTransactions { return data; } } + +class Attachments { + int? attachmentId; + String? fileName; + + Attachments({this.attachmentId, this.fileName}); + + Attachments.fromJson(Map json) { + attachmentId = json['attachmentId']; + fileName = json['fileName']; + } + + Map toJson() { + Map data = Map(); + data['attachmentId'] = this.attachmentId; + data['fileName'] = this.fileName; + return data; + } +} diff --git a/lib/models/mowadhafhi/get_transaction_attachment_model.dart b/lib/models/mowadhafhi/get_transaction_attachment_model.dart new file mode 100644 index 0000000..1234946 --- /dev/null +++ b/lib/models/mowadhafhi/get_transaction_attachment_model.dart @@ -0,0 +1,52 @@ +class GetTransactionAttachmentModel { + int? attachmentId; + String? fileName; + String? contentType; + dynamic attachFileStream; + String? base64String; + dynamic isActive; + dynamic referenceItemId; + dynamic content; + dynamic filePath; + int? languageId; + + GetTransactionAttachmentModel( + {this.attachmentId, + this.fileName, + this.contentType, + this.attachFileStream, + this.base64String, + this.isActive, + this.referenceItemId, + this.content, + this.filePath, + this.languageId}); + + GetTransactionAttachmentModel.fromJson(Map json) { + attachmentId = json['attachmentId']; + fileName = json['fileName']; + contentType = json['contentType']; + attachFileStream = json['attachFileStream']; + base64String = json['base64String']; + isActive = json['isActive']; + referenceItemId = json['referenceItemId']; + content = json['content']; + filePath = json['filePath']; + languageId = json['languageId']; + } + + Map toJson() { + Map data = Map(); + data['attachmentId'] = this.attachmentId; + data['fileName'] = this.fileName; + data['contentType'] = this.contentType; + data['attachFileStream'] = this.attachFileStream; + data['base64String'] = this.base64String; + data['isActive'] = this.isActive; + data['referenceItemId'] = this.referenceItemId; + data['content'] = this.content; + data['filePath'] = this.filePath; + data['languageId'] = this.languageId; + return data; + } +} diff --git a/lib/ui/screens/mowadhafhi/request_details.dart b/lib/ui/screens/mowadhafhi/request_details.dart index aa22bdd..0dcaa13 100644 --- a/lib/ui/screens/mowadhafhi/request_details.dart +++ b/lib/ui/screens/mowadhafhi/request_details.dart @@ -1,3 +1,8 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:io' as Io; +import 'dart:typed_data'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/mowadhafhi/mowadhafhi_api_client.dart'; @@ -6,9 +11,13 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_details.dart'; import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart'; +import 'package:mohem_flutter_app/models/mowadhafhi/get_transaction_attachment_model.dart'; +import 'package:mohem_flutter_app/ui/screens/mowadhafhi/view_transaction_attachment.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:path_provider/path_provider.dart'; class MowadhafhiRequestDetails extends StatefulWidget { const MowadhafhiRequestDetails({Key? key}) : super(key: key); @@ -21,6 +30,9 @@ class _RequestDetailsState extends State { String? itgTicketID; List getTicketsByEmployeeList = []; List getTicketTransactionsList = []; + GetTransactionAttachmentModel? getTransactionAttachmentModel; + + late File imageFile; @override void initState() { @@ -43,7 +55,7 @@ class _RequestDetailsState extends State { backgroundColor: Colors.white, appBar: AppBarWidget( context, - title: LocaleKeys.mowadhafhiRequest.tr(), + title: LocaleKeys.mowadhafhiRequest.tr(), ), body: SingleChildScrollView( child: getTicketsByEmployeeList.length != 0 @@ -76,16 +88,16 @@ class _RequestDetailsState extends State { ], ), 8.height, - LocaleKeys.ticketReference.tr().toText12(color: MyColors.grey98Color), + LocaleKeys.ticketReference.tr().toText12(color: MyColors.grey98Color), getTicketsByEmployeeList![0].ticketReferenceNo!.toText14(color: MyColors.grey57Color), 8.height, - LocaleKeys.section.tr().toText12(color: MyColors.grey98Color), + LocaleKeys.section.tr().toText12(color: MyColors.grey98Color), getTicketsByEmployeeList![0].sectionName!.toText14(color: MyColors.grey57Color), 8.height, - LocaleKeys.topic.tr().toText12(color: MyColors.grey98Color), + LocaleKeys.topic.tr().toText12(color: MyColors.grey98Color), getTicketsByEmployeeList![0].topicName!.toText14(color: MyColors.grey57Color), 8.height, - LocaleKeys.description.tr().toText12(color: MyColors.grey98Color), + LocaleKeys.description.tr().toText12(color: MyColors.grey98Color), getTicketsByEmployeeList![0].description!.toText14(color: MyColors.grey57Color), ], ), @@ -128,15 +140,31 @@ class _RequestDetailsState extends State { Row( children: [ LocaleKeys.actionBy.tr().toText14(color: MyColors.grey57Color), + ": ".toText14(), getTicketTransactionsList![index].actionBy!.toText14(color: MyColors.grey57Color), ], ), + Row( + children: [ + LocaleKeys.actions.tr().toText14(color: MyColors.grey57Color), + ": ".toText14(), + getTicketTransactionsList![index].statusDisplayText!.toText14(color: MyColors.grey57Color), + ], + ), getTicketTransactionsList![index].comments!.toText14(color: MyColors.grey98Color), 12.height, + if (getTicketTransactionsList[index].attachments != null) + InkWell( + onTap: () { + print(getTicketTransactionsList[index].attachments![0].attachmentId); + getTransactionAttachment(getTicketTransactionsList[index].attachments![0].attachmentId!); + }, + child: LocaleKeys.attachments.tr().toText14(color: MyColors.gradiantEndColor, isUnderLine: true), + ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - getTicketTransactionsList![0].actionDate!.split(" ")[0].toText12(color: MyColors.grey70Color), + getTicketTransactionsList![index].actionDate!.split(" ")[0].toText12(color: MyColors.grey70Color), ], ), ], @@ -212,4 +240,47 @@ class _RequestDetailsState extends State { Utils.handleException(ex, context, null); } } + + void getTransactionAttachment(int attachmentID) async { + try { + Utils.showLoading(context); + getTransactionAttachmentModel = await MowadhafhiApiClient().getTransactionAttachments(attachmentID); + debugPrint(getTransactionAttachmentModel?.fileName); + Utils.hideLoading(context); + setState(() {}); + handleTransactionAttachment(); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + void handleTransactionAttachment() async { + String ext = ''; + String? rFile = getTransactionAttachmentModel!.base64String; + String? rFileExt = getTransactionAttachmentModel!.fileName; + + ext = "." + rFileExt!.split(".").last.toLowerCase(); + + if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif" || ext == ".tiff") { + try { + Uint8List decodedBytes = base64Decode(rFile!.split("base64,").last); + Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 + imageFile = Io.File("${appDocumentsDirectory.path}/addImage$ext"); + imageFile.writeAsBytesSync(decodedBytes); + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => ViewTransactionAttachment( + imageFile: imageFile, + ), + ), + ); + } catch (e) { + logger.d(e); + } + } else { + Utils.showErrorDialog(context: context, onOkTapped: () {}, message: "Unable to view attachment"); + } + } } diff --git a/lib/ui/screens/mowadhafhi/view_transaction_attachment.dart b/lib/ui/screens/mowadhafhi/view_transaction_attachment.dart new file mode 100644 index 0000000..e6ef8bc --- /dev/null +++ b/lib/ui/screens/mowadhafhi/view_transaction_attachment.dart @@ -0,0 +1,34 @@ +import 'dart:io'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; + +class ViewTransactionAttachment extends StatelessWidget { + final File imageFile; + + const ViewTransactionAttachment({Key? key, required this.imageFile}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget( + context, + title: LocaleKeys.mowadhafhiRequest.tr(), + ), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.file(imageFile), + 50.height, + ], + ), + ), + ); + } +} diff --git a/lib/ui/work_list/worklist_fragments/actions_fragment.dart b/lib/ui/work_list/worklist_fragments/actions_fragment.dart index 1d88129..10d027a 100644 --- a/lib/ui/work_list/worklist_fragments/actions_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/actions_fragment.dart @@ -167,10 +167,14 @@ class ActionsFragment extends StatelessWidget { Duration duration = DateTime.now().difference(dateTimeFrom); return "Action duration: " + DateUtil.formatDuration(duration); } else { - DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index].nOTIFICATIONDATE!); - DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index + 1].nOTIFICATIONDATE!); - Duration duration = dateTimeTo.difference(dateTimeFrom); - return "Action duration: " + DateUtil.formatDuration(duration); + if (actionHistoryList[index + 1].nOTIFICATIONDATE!.isEmpty) { + return ""; + } else { + DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index].nOTIFICATIONDATE!); + DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index + 1].nOTIFICATIONDATE!); + Duration duration = dateTimeTo.difference(dateTimeFrom); + return "Action duration: " + DateUtil.formatDuration(duration); + } } } From 0728cc3dd4fd12f5c10768a2ff8625f82b3ff7fe Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 14 Jan 2024 11:03:27 +0300 Subject: [PATCH 8/8] Updated Mowadhafi Attachment Handling --- android/app/src/main/AndroidManifest.xml | 12 ++++++ android/app/src/main/res/xml/filepaths.xml | 5 +++ .../screens/mowadhafhi/request_details.dart | 40 +++++++++---------- 3 files changed, 35 insertions(+), 22 deletions(-) create mode 100644 android/app/src/main/res/xml/filepaths.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ea79d76..15b0c54 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ @@ -34,6 +35,17 @@ android:extractNativeLibs="true" android:networkSecurityConfig="@xml/network_security_config" android:roundIcon="@mipmap/ic_launcher_round"> + + + + + + + \ No newline at end of file diff --git a/lib/ui/screens/mowadhafhi/request_details.dart b/lib/ui/screens/mowadhafhi/request_details.dart index 0dcaa13..b2371ab 100644 --- a/lib/ui/screens/mowadhafhi/request_details.dart +++ b/lib/ui/screens/mowadhafhi/request_details.dart @@ -17,6 +17,7 @@ import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart import 'package:mohem_flutter_app/models/mowadhafhi/get_transaction_attachment_model.dart'; import 'package:mohem_flutter_app/ui/screens/mowadhafhi/view_transaction_attachment.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:open_file/open_file.dart'; import 'package:path_provider/path_provider.dart'; class MowadhafhiRequestDetails extends StatefulWidget { @@ -245,9 +246,7 @@ class _RequestDetailsState extends State { try { Utils.showLoading(context); getTransactionAttachmentModel = await MowadhafhiApiClient().getTransactionAttachments(attachmentID); - debugPrint(getTransactionAttachmentModel?.fileName); Utils.hideLoading(context); - setState(() {}); handleTransactionAttachment(); } catch (ex) { Utils.hideLoading(context); @@ -255,32 +254,29 @@ class _RequestDetailsState extends State { } } + Future _createFileFromString(String encodedStr, String ext) async { + Uint8List bytes = base64.decode(encodedStr); + String dir = (await getApplicationDocumentsDirectory()).path; + File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); + await file.writeAsBytes(bytes); + return file.path; + } + void handleTransactionAttachment() async { String ext = ''; String? rFile = getTransactionAttachmentModel!.base64String; String? rFileExt = getTransactionAttachmentModel!.fileName; - ext = "." + rFileExt!.split(".").last.toLowerCase(); + ext = rFileExt!.split(".").last.toLowerCase(); - if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif" || ext == ".tiff") { - try { - Uint8List decodedBytes = base64Decode(rFile!.split("base64,").last); - Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 - imageFile = Io.File("${appDocumentsDirectory.path}/addImage$ext"); - imageFile.writeAsBytesSync(decodedBytes); - Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => ViewTransactionAttachment( - imageFile: imageFile, - ), - ), - ); - } catch (e) { - logger.d(e); - } - } else { - Utils.showErrorDialog(context: context, onOkTapped: () {}, message: "Unable to view attachment"); + try { + String path = await _createFileFromString(rFile!.split("base64,").last ?? "", ext ?? ""); + debugPrint(path); + + print(" file here: ${File(path).existsSync()}"); + await OpenFile.open(path); + } catch (ex) { + Utils.showToast("Cannot open file."); } } }