From 0cca8ec935c39c6201e5e73142755a43b74125c6 Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Wed, 2 Nov 2022 15:01:10 +0300 Subject: [PATCH 01/82] fix issues --- assets/langs/en-US.json | 2 +- lib/models/generic_response_model.dart | 2 +- lib/ui/misc/request_submit_screen.dart | 15 ++++---- .../dynamic_screens/dynamic_input_screen.dart | 10 +++--- lib/ui/my_team/employee_details.dart | 36 ++++++++++++------- lib/ui/profile/add_update_family_member.dart | 21 +++++------ lib/ui/profile/contact_details.dart | 7 +++- 7 files changed, 53 insertions(+), 40 deletions(-) diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 503302b..c15ada7 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -296,7 +296,7 @@ "relatedTopic": "Related Topic", "selectTopic": "Select Topic", "supportingDocument": "Supporting Document", - "mowadhafhiRequest": "Mowadhafhi Request", + "mowadhafhiRequest": "Mowadhafi Request", "ticketReference": "Ticket Reference", "section": "Section", "topic": "Topic", diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 753d2c2..2c8e98f 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -1291,7 +1291,7 @@ class GenericResponseModel { startEitApprovalProcess = json['StartEitApprovalProcess'] != null ? StartEitApprovalProcess.fromJson(json['StartEitApprovalProcess']) : null; startHrApprovalProcessList = json['StartHrApprovalProcessList']; - startPhonesApprovalProcessList = json['StartPhonesApprovalProcessList'] != null ? StartPhoneApprovalProcess.fromJson(json['startPhonesApprovalProcessList']) : null; + startPhonesApprovalProcessList = json['StartPhonesApprovalProcessList'] != null ? StartPhoneApprovalProcess.fromJson(json['StartPhonesApprovalProcessList']) : null; startSitApprovalProcess = json['StartSitApprovalProcess']; startTermApprovalProcessList = json['StartTermApprovalProcessList'] != null ? StartTermApprovalProcessList.fromJson(json['StartTermApprovalProcessList']) : null; diff --git a/lib/ui/misc/request_submit_screen.dart b/lib/ui/misc/request_submit_screen.dart index 8ca9a0c..7869443 100644 --- a/lib/ui/misc/request_submit_screen.dart +++ b/lib/ui/misc/request_submit_screen.dart @@ -68,7 +68,7 @@ class _RequestSubmitScreenState extends State { } void submitRequest() async { - try { + // try { Utils.showLoading(context); List> list = []; if (attachmentFiles.isNotEmpty) { @@ -97,7 +97,7 @@ class _RequestSubmitScreenState extends State { ); } else if (params!.approvalFlag == 'address') { await ProfileApiClient().startAddressApprovalProcess( - "SUBMIT", + LocaleKeys.submit.tr(), comments.text, params!.pItemId, params!.transactionId, @@ -111,7 +111,7 @@ class _RequestSubmitScreenState extends State { ); } else if (params!.approvalFlag == 'basicDetails') { await ProfileApiClient().startBasicDetailsApprovalProcess( - "SUBMIT", + LocaleKeys.submit.tr(), comments.text, params!.pItemId, params!.transactionId, @@ -131,6 +131,7 @@ class _RequestSubmitScreenState extends State { ); }else if (params!.approvalFlag == 'endEmployment') { await TerminationDffApiClient().startTermApprovalProcess( + // "SUBMIT", LocaleKeys.submit.tr(), comments.text, params!.pItemId, @@ -142,10 +143,10 @@ class _RequestSubmitScreenState extends State { Utils.showToast(LocaleKeys.yourRequestHasBeenSubmittedForApprovals.tr(), longDuration: true); Navigator.of(context).popUntil((route) => route.settings.name == AppRoutes.dashboard); Navigator.pushNamed(context, AppRoutes.workList); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - } + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // } } @override diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 0a6c9d4..c1b8a43 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -136,7 +136,7 @@ class _DynamicInputScreenState extends State { } Future getDefaultValues(GetEITDFFStructureList structureList) async { - try { + // try { Utils.showLoading(context); for (int i = 0; i < (structureList.cHILDSEGMENTSDVSplited?.length ?? 0); i++) { String segmentId = structureList.cHILDSEGMENTSDVSplited![i]; @@ -163,10 +163,10 @@ class _DynamicInputScreenState extends State { await Future.delayed(const Duration(seconds: 1)); Utils.hideLoading(context); setState(() {}); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - } + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // } } // List> calGetValueSetValuesIonicLogic(GetEITDFFStructureList structureElement) { diff --git a/lib/ui/my_team/employee_details.dart b/lib/ui/my_team/employee_details.dart index d0e167d..9fc0070 100644 --- a/lib/ui/my_team/employee_details.dart +++ b/lib/ui/my_team/employee_details.dart @@ -256,19 +256,29 @@ class _EmployeeDetailsState extends State { child: Column( children: [ Text(LocaleKeys.addFavoriteList).tr(namedArgs: {'name': '${getEmployeeSubordinates!.eMPLOYEENAME}'}), - Image.memory( - Utils.getPostBytes( - getEmployeeSubordinates!.eMPLOYEEIMAGE ?? "", - ), - errorBuilder: (BuildContext context, error, stackTrace) { - return SvgPicture.asset( - "assets/images/user.svg", height: 50, width: 50, - ); - }, - width: 50, - height: 50, - fit: BoxFit.cover, - ).circle(50).paddingOnly(top: 21), + getEmployeeSubordinates!.eMPLOYEEIMAGE == null + ? SvgPicture.asset( + "assets/images/user.svg", + height: 68, + width: 68,) + : CircleAvatar( + radius: 68, + backgroundImage: MemoryImage(Utils.dataFromBase64String(getEmployeeSubordinates!.eMPLOYEEIMAGE!)), + backgroundColor: Colors.black, + ), + // Image.memory( + // Utils.getPostBytes( + // getEmployeeSubordinates!.eMPLOYEEIMAGE ?? "", + // ), + // errorBuilder: (BuildContext context, error, stackTrace) { + // return SvgPicture.asset( + // "assets/images/user.svg", height: 50, width: 50, + // ); + // }, + // width: 50, + // height: 50, + // fit: BoxFit.cover, + // ).circle(50).paddingOnly(top: 21), ], ), ), diff --git a/lib/ui/profile/add_update_family_member.dart b/lib/ui/profile/add_update_family_member.dart index 61b6639..e6b0b3e 100644 --- a/lib/ui/profile/add_update_family_member.dart +++ b/lib/ui/profile/add_update_family_member.dart @@ -223,9 +223,8 @@ class _AddUpdateFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - //date = DateFormat('yyyy/MM/dd').format(dateValue); - date = "2022-10-23T09:17:38.653+03:00"; - // date = (DateFormat('yyyy-MM-dd').format(dateValue)+"T"+ dateTime.toString() + dateTime1.toString()); + date = (DateFormat('yyyy-MM-dd').format(dateValue)); + // date = (DateFormat('yyyy-MM-dd').format(dateValue)+"T"+ dateTime.toString() + dateTime1.toString()); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; print(dateTime); print(dateTime1); @@ -288,9 +287,8 @@ class _AddUpdateFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - date = "2022-10-23T09:17:38.653+03:00"; - // date = (DateFormat('yyyy-MM-dd').format(dateValue) +"T"+ dateTime.toString() + dateTime1.toString()); - // date = DateFormat('yyyy/MM/dd').format(dateValue); + // date = (DateFormat('yyyy-MM-dd').format(dateValue) +"T"+ dateTime.toString() + dateTime1.toString()); + date = (DateFormat('yyyy-MM-dd').format(dateValue)); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; setState(() {}); }, @@ -349,9 +347,8 @@ class _AddUpdateFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - date = "2022-10-23T09:17:38.653+03:00"; - // date = (DateFormat('yyyy-MM-dd').format(dateValue)+"T"+ dateTime.toString() + dateTime1.toString()); - // date = DateFormat('yyyy/MM/dd').format(dateValue); + // date = (DateFormat('yyyy-MM-dd').format(dateValue)+"T"+ dateTime.toString() + dateTime1.toString()); + date = (DateFormat('yyyy-MM-dd').format(dateValue)); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; setState(() {}); }, @@ -407,7 +404,7 @@ class _AddUpdateFamilyMemberState extends State { numberVal = null; } else { dateVal = null; - vatcherVal = e!.getContactDetailsList!.sEGMENTVALUEDSP; + vatcherVal = e!.getContactDetailsList!.vARCHAR2VALUE; numberVal = null; } return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: vatcherVal.toString()).toJson(); @@ -427,7 +424,7 @@ class _AddUpdateFamilyMemberState extends State { } else { dateVal = null; numberVal = null; - vatcherVal = e!.getContactDetailsList!.sEGMENTVALUEDSP; + vatcherVal = e!.getContactDetailsList!.vARCHAR2VALUE; } return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: vatcherVal.toString()).toJson(); }).toList(); @@ -441,7 +438,7 @@ class _AddUpdateFamilyMemberState extends State { if (e!.dATATYPE == 'VARCHAR2') { dateVal = null; numberVal = null; - vatcherVal = e.getContactDetailsList?.sEGMENTVALUEDSP ?? ""; + vatcherVal = e.getContactDetailsList?.vARCHAR2VALUE ?? ""; } else if (e.dATATYPE == 'DATE') { dateVal = e.getContactDetailsList!.sEGMENTVALUEDSP.toString(); print("dateVal:${dateVal ?? ""}"); diff --git a/lib/ui/profile/contact_details.dart b/lib/ui/profile/contact_details.dart index 9a6f25e..95c867a 100644 --- a/lib/ui/profile/contact_details.dart +++ b/lib/ui/profile/contact_details.dart @@ -129,7 +129,12 @@ class _ContactDetailsState extends State { separatorBuilder: (cxt, index) => 12.height, itemCount: getEmployeeAddressList.length), if (menuEntriesAddress.updateButton == 'Y') - Positioned( + AppState().isArabic(context)? Positioned( + top: 1, + left: 1, + child: const Icon(Icons.edit_location_alt_outlined, size: 20).onPress(addUpdateAddress), + ) + :Positioned( top: 1, right: 1, child: const Icon(Icons.edit_location_alt_outlined, size: 20).onPress(addUpdateAddress), From 7cc110b9a1092a5d23809b4106e32b711b55a372 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 2 Nov 2022 15:03:01 +0300 Subject: [PATCH 02/82] JIRA fixes --- assets/langs/en-US.json | 4 +-- assets/lottie/loading.json | 2 +- lib/classes/consts.dart | 4 +-- lib/generated/codegen_loader.g.dart | 4 +-- .../add_leave_balance_screen.dart | 33 ++++++++++++------- lib/ui/login/login_screen.dart | 4 +-- .../dynamic_screens/dynamic_input_screen.dart | 2 +- .../dynamic_input_address_screen.dart | 4 +-- lib/ui/profile/widgets/profile_panel.dart | 20 ++++++----- lib/ui/work_list/itg_detail_screen.dart | 11 +++++-- lib/ui/work_list/sheets/delegate_sheet.dart | 15 ++++++--- .../sheets/selected_itg_item_sheet.dart | 4 +-- lib/ui/work_list/worklist_detail_screen.dart | 16 +++++---- .../dialogs/accept_reject_input_dialog.dart | 9 +++-- lib/widgets/item_detail_view_widget.dart | 8 +++-- 15 files changed, 88 insertions(+), 52 deletions(-) diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 503302b..a589a82 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -284,7 +284,7 @@ "add": "Add", "edit": "Edit", "myProfile": "My Profile", - "mowadhafhi": "Mowadhafhi", + "mowadhafhi": "Mowadhafi", "searchAnnouncements": "Search Announcements", "announcements": "Announcements", "swipeRequest": "Swipe Request", @@ -296,7 +296,7 @@ "relatedTopic": "Related Topic", "selectTopic": "Select Topic", "supportingDocument": "Supporting Document", - "mowadhafhiRequest": "Mowadhafhi Request", + "mowadhafhiRequest": "Mowadhafi Request", "ticketReference": "Ticket Reference", "section": "Section", "topic": "Topic", diff --git a/assets/lottie/loading.json b/assets/lottie/loading.json index 8190459..ea7bff3 100644 --- a/assets/lottie/loading.json +++ b/assets/lottie/loading.json @@ -1 +1 @@ -{"v":"5.8.1","fr":30,"ip":0,"op":60,"w":300,"h":300,"nm":"loading_6","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[360]}],"ix":10},"p":{"a":0,"k":[150.00000000000003,150.00000000000003,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[30.000000000000004,30.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.12941176470588237,0.7411764705882353,0.7764705882352941,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":60,"s":[99]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[1]},{"t":50,"s":[100]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[3]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":30,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150.00000000000003,150.00000000000003,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[30.000000000000004,30.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.7450980392156863,0.9254901960784314,0.9372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]} \ No newline at end of file +{"v":"5.8.1","fr":30,"ip":0,"op":60,"w":100,"h":100,"nm":"loading_6","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[360]}],"ix":10},"p":{"a":0,"k":[50.00000000000002,50.00000000000002,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10.000000000000004,10.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.12941176470588237,0.7411764705882353,0.7764705882352941,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":60,"s":[99]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[1]},{"t":50,"s":[100]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[3]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":30,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50.00000000000002,50.00000000000002,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10.000000000000004,10.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.7450980392156863,0.9254901960784314,0.9372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index e82c30a..eea2481 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 6b702f8..8754d9b 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -797,7 +797,7 @@ static const Map en_US = { "add": "Add", "edit": "Edit", "myProfile": "My Profile", - "mowadhafhi": "Mowadhafhi", + "mowadhafhi": "Mowadhafi", "searchAnnouncements": "Search Announcements", "announcements": "Announcements", "swipeRequest": "Swipe Request", @@ -809,7 +809,7 @@ static const Map en_US = { "relatedTopic": "Related Topic", "selectTopic": "Select Topic", "supportingDocument": "Supporting Document", - "mowadhafhiRequest": "Mowadhafhi Request", + "mowadhafhiRequest": "Mowadhafi Request", "ticketReference": "Ticket Reference", "section": "Section", "topic": "Topic", diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index 864a507..85337aa 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -92,7 +92,7 @@ class _AddLeaveBalanceScreenState extends State { } void validateAbsenceTransaction() async { - // try { + try { Utils.showLoading(context); Map dffDataMap = {}; for (int i = 1; i <= 20; i++) { @@ -100,7 +100,8 @@ class _AddLeaveBalanceScreenState extends State { for (int dffIndex = 0; dffIndex < getabsenceDffStructureList.length; dffIndex++) { if ("ATTRIBUTE$i" == getabsenceDffStructureList[dffIndex].aPPLICATIONCOLUMNNAME) { if (getabsenceDffStructureList[dffIndex].fORMATTYPE == "X") { - dffDataMap["P_ATTRIBUTE$i"] = getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME != null ? Utils.formatDate(getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME!) : ""; + dffDataMap["P_ATTRIBUTE$i"] = + getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME != null ? Utils.formatDate(getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME!) : ""; } else { dffDataMap["P_ATTRIBUTE$i"] = getabsenceDffStructureList[dffIndex].eSERVICESDV?.pIDCOLUMNNAME; } @@ -108,9 +109,17 @@ class _AddLeaveBalanceScreenState extends State { } } } - await LeaveBalanceApiClient().validateAbsenceTransaction(selectedAbsenceType!.dESCFLEXCONTEXTCODE!, "HR_LOA_SS", selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, - selectedReplacementEmployee != null ? selectedReplacementEmployee!.userName! : "", DateUtil.getFormattedDate(startDateTime!, "MM/dd/yyyy"), DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), -999, dffDataMap, - comments: comment); + await LeaveBalanceApiClient() + .validateAbsenceTransaction( + selectedAbsenceType!.dESCFLEXCONTEXTCODE!, + "HR_LOA_SS", + selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, + selectedReplacementEmployee != null ? selectedReplacementEmployee!.userName! : "", + DateUtil.getFormattedDate(startDateTime!, "MM/dd/yyyy"), + DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), + -999, + dffDataMap, + comments: comment); SumbitAbsenceTransactionList submit = await LeaveBalanceApiClient().submitAbsenceTransaction( selectedAbsenceType!.dESCFLEXCONTEXTCODE!, @@ -126,13 +135,13 @@ class _AddLeaveBalanceScreenState extends State { Utils.hideLoading(context); await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submit.pTRANSACTIONID!, "", "add_leave_balance")); - // Utils.showLoading(context); + Utils.showLoading(context); await LeaveBalanceApiClient().cancelHrTransaction(submit.pTRANSACTIONID!); - // Utils.hideLoading(context); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + Utils.hideLoading(context); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } @override @@ -221,7 +230,7 @@ class _AddLeaveBalanceScreenState extends State { onTap: () { showMyBottomSheet( context, - callBackFunc: (){}, + callBackFunc: () {}, child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 0c4e268..20fa8bc 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -145,8 +145,8 @@ class _LoginScreenState extends State { // username.text = "15153"; // Tamer User // password.text = "Abcd@12345"; - username.text = "210038"; // Hashim User - password.text = "123"; + // username.text = "206535"; // Hashim User + // password.text = "Namira786"; } if (isAppOpenBySystem!) checkFirebaseToken(); } diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 0a6c9d4..519bb6c 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -448,7 +448,7 @@ class _DynamicInputScreenState extends State { return DynamicTextFieldWidget( (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), model.eSERVICESDV?.pIDCOLUMNNAME ?? "", - isReadOnly: model.rEADONLY == "Y", + // isReadOnly: model.rEADONLY == "Y", isInputTypeNum: true, onChange: (text) { model.fieldAnswer = text; diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart index cc8e861..6933a28 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart @@ -269,13 +269,13 @@ class _DynamicInputScreenState extends State { if (tempVar.isNotEmpty) { DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('dd/MMM/yyy').format(date); + tempVar = DateFormat('dd-MMM-yyy').format(date); if (e.aPPLICATIONCOLUMNNAME == null) { effectiveDate = tempVar; } } } else if (e.eSERVICESVS?.isNotEmpty ?? false) { - tempVar = e.getEmployeeAddressList!.vARCHAR2VALUE!; + e.getEmployeeAddressList!.vARCHAR2VALUE != null ? tempVar = e.getEmployeeAddressList!.vARCHAR2VALUE! : tempVar = ""; if (e.aPPLICATIONCOLUMNNAME == null) { countryCode = tempVar; } diff --git a/lib/ui/profile/widgets/profile_panel.dart b/lib/ui/profile/widgets/profile_panel.dart index 5018171..440fbb3 100644 --- a/lib/ui/profile/widgets/profile_panel.dart +++ b/lib/ui/profile/widgets/profile_panel.dart @@ -44,12 +44,16 @@ class ProfilePanel extends StatelessWidget { Widget profileImage() => memberInformationList.eMPLOYEEIMAGE == null ? SvgPicture.asset( - "assets/images/user.svg", - height: 68, - width: 68,) - : CircleAvatar( - radius: 68, - backgroundImage: MemoryImage(Utils.dataFromBase64String(memberInformationList.eMPLOYEEIMAGE!)), - backgroundColor: Colors.black, - ); + "assets/images/user.svg", + height: 68, + width: 68, + ) + : ClipOval( + child: Image.memory( + Utils.dataFromBase64String(memberInformationList.eMPLOYEEIMAGE!), + width: 75, + height: 75, + fit: BoxFit.fill, + ), + ); } diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index 0f45648..84bd9bd 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -66,7 +66,9 @@ class _ItgDetailScreenState extends State { isRejectAvailable = itgRequest!.allowedActions!.any((element) => element.action == "Reject"); } Utils.hideLoading(context); - setState(() {}); + setState(() { + controller.jumpToPage(0); + }); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); @@ -264,12 +266,12 @@ class _ItgDetailScreenState extends State { switch (action.action) { case "Delegate": showMyBottomSheet(context, callBackFunc: reloadITG, - child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [])); + child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [], callBackFunc: reloadITG,)); break; case "RequestInformation": showMyBottomSheet(context, callBackFunc: reloadITG, - child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [])); + child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [], callBackFunc: reloadITG,)); break; case "RFC": @@ -279,6 +281,9 @@ class _ItgDetailScreenState extends State { // do something else break; } + setState(() { + showFabOptions = false; + }); } Widget myTab(String title, int index) { diff --git a/lib/ui/work_list/sheets/delegate_sheet.dart b/lib/ui/work_list/sheets/delegate_sheet.dart index 28a90e6..bd3b010 100644 --- a/lib/ui/work_list/sheets/delegate_sheet.dart +++ b/lib/ui/work_list/sheets/delegate_sheet.dart @@ -28,8 +28,9 @@ class DelegateSheet extends StatefulWidget { String title, apiMode; List? actionHistoryList; List? wFHistory; + VoidCallback callBackFunc; - DelegateSheet({required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, this.wFHistory}); + DelegateSheet({required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, this.wFHistory, required this.callBackFunc}); @override State createState() => _DelegateSheetState(); @@ -392,8 +393,9 @@ class _DelegateSheetState extends State { Widget showItem(GetActionHistoryList actionHistory) { return InkWell( onTap: () { + Navigator.pop(context); showMyBottomSheet(context, - callBackFunc: (){}, + callBackFunc: widget.callBackFunc, child: SelectedItemSheet( "Comment", apiMode: widget.apiMode, @@ -438,8 +440,9 @@ class _DelegateSheetState extends State { Widget showItgItem(WFHistory wfHistory) { return InkWell( onTap: () { + Navigator.pop(context); showMyBottomSheet(context, - callBackFunc: (){}, + callBackFunc: widget.callBackFunc, child: SelectedItgItemSheet( "Comment", apiMode: widget.apiMode, @@ -463,8 +466,9 @@ class _DelegateSheetState extends State { Widget showFavUserItem(GetFavoriteReplacements actionHistory) { return InkWell( onTap: () { + Navigator.pop(context); showMyBottomSheet(context, - callBackFunc: (){}, + callBackFunc: widget.callBackFunc, child: SelectedItemSheet( "Comment", apiMode: widget.apiMode, @@ -509,8 +513,9 @@ class _DelegateSheetState extends State { Widget showInputUserItem(ReplacementList actionHistory) { return InkWell( onTap: () { + Navigator.pop(context); showMyBottomSheet(context, - callBackFunc: (){}, + callBackFunc: widget.callBackFunc, child: SelectedItemSheet( LocaleKeys.comments.tr(), apiMode: widget.apiMode, diff --git a/lib/ui/work_list/sheets/selected_itg_item_sheet.dart b/lib/ui/work_list/sheets/selected_itg_item_sheet.dart index 7381d59..f44ca04 100644 --- a/lib/ui/work_list/sheets/selected_itg_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_itg_item_sheet.dart @@ -128,8 +128,8 @@ class SelectedItgItemSheet extends StatelessWidget { .informationITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); } Utils.hideLoading(context); - Navigator.pop(context); - Navigator.pop(context); + // Navigator.pop(context); + // Navigator.pop(context); Navigator.pop(context, "delegate_reload"); } catch (ex) { Utils.hideLoading(context); diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index ec02631..0e769e7 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -388,20 +388,20 @@ class _WorkListDetailScreenState extends State { case "DELEGATE": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "REQUEST_INFO": // do something else showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "TRANSFER_INFO": // do something else showMyBottomSheet(context, callBackFunc: reloadWorkList, child: - DelegateSheet(title: notificationButton.bUTTONLABEL!, apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + DelegateSheet(title: notificationButton.bUTTONLABEL!, apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "ANSWER_INFO": performAction(notificationButton.bUTTONACTION!, title: notificationButton.bUTTONLABEL); @@ -417,12 +417,12 @@ class _WorkListDetailScreenState extends State { case "APPROVE_AND_FORWARD": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: "Approve and Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: "Approve and Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "FORWARD": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "REJECT": performNetworkCall(context, email: "", userId: ""); @@ -431,6 +431,9 @@ class _WorkListDetailScreenState extends State { Navigator.pop(context); break; } + setState(() { + showFabOptions = false; + }); } Future performNetworkCall(BuildContext context, {String? email, String? userId}) async { @@ -516,7 +519,6 @@ class _WorkListDetailScreenState extends State { } void performAction(String actionMode, {String? title}) { - TextEditingController textEditingController = TextEditingController(); showDialog( context: context, builder: (cxt) => AcceptRejectInputDialog( @@ -823,6 +825,8 @@ class _WorkListDetailScreenState extends State { void getActionHistory() async { try { + isActionHistoryLoaded = false; + actionHistoryList.clear(); // if (apiCallCount == 0) Utils.showLoading(context); // apiCallCount++; actionHistoryList = await WorkListApiClient().getActionHistory(workListData!.nOTIFICATIONID!); diff --git a/lib/widgets/dialogs/accept_reject_input_dialog.dart b/lib/widgets/dialogs/accept_reject_input_dialog.dart index a0faf2c..db9c5d6 100644 --- a/lib/widgets/dialogs/accept_reject_input_dialog.dart +++ b/lib/widgets/dialogs/accept_reject_input_dialog.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.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/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; @@ -89,8 +90,12 @@ class AcceptRejectInputDialog extends StatelessWidget { DefaultButton( actionMode == "REJECTED" ? LocaleKeys.reject.tr() : LocaleKeys.ok.tr(), () { - Navigator.pop(context); - onTap(note); + if(note.isNotEmpty) { + Navigator.pop(context); + onTap(note); + } else { + Utils.showToast(LocaleKeys.pleaseEnterComments.tr()); + } }, colors: actionMode == "REJECTED" ? const [ diff --git a/lib/widgets/item_detail_view_widget.dart b/lib/widgets/item_detail_view_widget.dart index 05495e9..5148389 100644 --- a/lib/widgets/item_detail_view_widget.dart +++ b/lib/widgets/item_detail_view_widget.dart @@ -80,9 +80,13 @@ class ItemDetailViewGridItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Flexible(child: "$title:".toText12Auto(isBold: true, color: const Color(0xff2BB8A6))), + title != null ? Flexible(child: "$title:".toText12Auto(isBold: true, color: const Color(0xff2BB8A6))) : Container(), 4.width, - type!.toLowerCase() == "table" ? getStringFromJSON(value!) : Flexible(child: (value!.isEmpty ? "--" : value).toString().toText12Auto(color: MyColors.normalTextColor)), + type != null + ? type!.toLowerCase() == "table" + ? getStringFromJSON(value!) + : Flexible(child: (value!.isEmpty ? "--" : value).toString().toText12Auto(color: MyColors.normalTextColor)) + : Container(), ], ), ); From ea676e19ca319bb299b15e39406329f9e925ad2c Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 3 Nov 2022 14:39:33 +0300 Subject: [PATCH 03/82] JIRA Fixes --- assets/images/monthly_attendance.svg | 6 +++--- lib/ui/attendance/monthly_attendance_screen.dart | 1 - lib/ui/landing/widget/services_widget.dart | 4 ++-- lib/ui/my_team/view_attendance.dart | 1 - lib/ui/work_list/worklist_detail_screen.dart | 3 ++- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/assets/images/monthly_attendance.svg b/assets/images/monthly_attendance.svg index c84a9a1..b77ccc3 100644 --- a/assets/images/monthly_attendance.svg +++ b/assets/images/monthly_attendance.svg @@ -7,9 +7,9 @@ - - - + + + diff --git a/lib/ui/attendance/monthly_attendance_screen.dart b/lib/ui/attendance/monthly_attendance_screen.dart index 439a5f4..de35da0 100644 --- a/lib/ui/attendance/monthly_attendance_screen.dart +++ b/lib/ui/attendance/monthly_attendance_screen.dart @@ -287,7 +287,6 @@ class _MonthlyAttendanceScreenState extends State { cellBorderColor: Colors.white, selectionDecoration: BoxDecoration( border: Border.all(color: MyColors.white, width: 10), - borderRadius: const BorderRadius.all(Radius.circular(100)), shape: BoxShape.circle, ), dataSource: MeetingDataSource(_getDataSource()), diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index d822920..0b257c5 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -22,8 +22,8 @@ class ServicesWidget extends StatelessWidget { "assets/images/monthly_attendance.svg", "assets/images/monthly_attendance.svg", "assets/images/ticket_request.svg", - "assets/images/ticket_request.svg", - "assets/images/ticket_request.svg", + "assets/images/ticket_bal.svg", + "assets/images/vacation_rule.svg", "assets/images/ticket_request.svg", "assets/images/ticket_request.svg", "assets/images/ticket_request.svg" diff --git a/lib/ui/my_team/view_attendance.dart b/lib/ui/my_team/view_attendance.dart index c77b1b4..90414d1 100644 --- a/lib/ui/my_team/view_attendance.dart +++ b/lib/ui/my_team/view_attendance.dart @@ -283,7 +283,6 @@ class _ViewAttendanceState extends State { cellBorderColor: Colors.white, selectionDecoration: BoxDecoration( border: Border.all(color: MyColors.white, width: 10), - borderRadius: const BorderRadius.all(Radius.circular(100)), shape: BoxShape.circle, ), dataSource: MeetingDataSource(_getDataSource()), diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 0e769e7..de7c152 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -846,6 +846,8 @@ class _WorkListDetailScreenState extends State { void getAttachments() async { try { + isAttachmentLoaded = false; + getAttachmentList.clear(); // if (apiCallCount == 0) Utils.showLoading(context); // apiCallCount++; getAttachmentList = await WorkListApiClient().getAttachments(workListData!.nOTIFICATIONID!); @@ -868,7 +870,6 @@ class _WorkListDetailScreenState extends State { 'assets/lottie/loading.json', repeat: true, reverse: false, - fit: BoxFit.contain, ); } } From c0e7bc7c7da84d691b9e35c25bca4dce9f558b94 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 6 Nov 2022 11:23:56 +0300 Subject: [PATCH 04/82] Last Login fixes --- lib/ui/login/verify_last_login_screen.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ui/login/verify_last_login_screen.dart b/lib/ui/login/verify_last_login_screen.dart index 6e51e51..0b07b43 100644 --- a/lib/ui/login/verify_last_login_screen.dart +++ b/lib/ui/login/verify_last_login_screen.dart @@ -58,7 +58,8 @@ class _VerifyLastLoginScreenState extends State { @override Widget build(BuildContext context) { mobileLoginInfoListModel ??= ModalRoute.of(context)!.settings.arguments as GetMobileLoginInfoListModel; - String empName = AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; + // String empName = AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; + String empName = mobileLoginInfoListModel!.employeeName!; return Scaffold( appBar: AppBar( @@ -68,7 +69,7 @@ class _VerifyLastLoginScreenState extends State { ? LocaleKeys.viewBusinessCard.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { showMDialog(context, child: BusinessCardDialog()); }) - : null, + : Container(), actions: [ Center( child: LocaleKeys.employeeDigitalID.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { From 28a882a2f6455f9636ebc15a42c2a97b2c3cfedf Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 6 Nov 2022 17:44:15 +0300 Subject: [PATCH 05/82] Updates & Fixes --- lib/ui/landing/widget/missing_swipe.dart | 8 --- .../leave_balance/leave_balance_screen.dart | 27 ++++++--- .../dynamic_listview_screen.dart | 58 ++++++++++++++++--- lib/ui/work_list/worklist_detail_screen.dart | 3 +- .../dialogs/accept_reject_input_dialog.dart | 16 ++--- 5 files changed, 78 insertions(+), 34 deletions(-) diff --git a/lib/ui/landing/widget/missing_swipe.dart b/lib/ui/landing/widget/missing_swipe.dart index ebd011a..c5bc4fb 100644 --- a/lib/ui/landing/widget/missing_swipe.dart +++ b/lib/ui/landing/widget/missing_swipe.dart @@ -1,20 +1,12 @@ -import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/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/generated/locale_keys.g.dart'; -import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart'; -import 'package:mohem_flutter_app/models/dashboard/menus.dart'; import 'package:mohem_flutter_app/models/eit/get_eit_transaction_model.dart'; -import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/provider/eit_provider_model.dart'; -import 'package:mohem_flutter_app/ui/work_list/work_list_screen.dart'; import 'package:mohem_flutter_app/widgets/loading_dialog.dart'; -import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; class MissingSwipe extends StatelessWidget { diff --git a/lib/ui/leave_balance/leave_balance_screen.dart b/lib/ui/leave_balance/leave_balance_screen.dart index f3a1f91..548ca99 100644 --- a/lib/ui/leave_balance/leave_balance_screen.dart +++ b/lib/ui/leave_balance/leave_balance_screen.dart @@ -62,7 +62,7 @@ class _LeaveBalanceState extends State { physics: const BouncingScrollPhysics(), padding: const EdgeInsets.all(21), children: [ - BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true), + BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true), 12.height, absenceTransList == null ? const SizedBox() @@ -76,14 +76,23 @@ class _LeaveBalanceState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - ItemDetailView(LocaleKeys.startDateT.tr(), absenceTransList![index].sTARTDATE ?? ""), - ItemDetailView(LocaleKeys.endDateT.tr(), absenceTransList![index].eNDDATE ?? ""), - ItemDetailView(LocaleKeys.absenceType.tr(), absenceTransList![index].aBSENCETYPE ?? ""), - ItemDetailView(LocaleKeys.absenceCategory.tr(), absenceTransList![index].aBSENCECATEGORY ?? ""), - ItemDetailView(LocaleKeys.days.tr(), absenceTransList![index].aBSENCEDAYS?.toString() ?? ""), - ItemDetailView(LocaleKeys.hours.tr(), absenceTransList![index].aBSENCEHOURS?.toString() ?? ""), - ItemDetailView(LocaleKeys.approvalStatus.tr(), absenceTransList![index].aPPROVALSTATUS ?? ""), - ItemDetailView(LocaleKeys.absenceStatus.tr(), absenceTransList![index].aBSENCESTATUS ?? ""), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.startDateT.tr(), absenceTransList![index].sTARTDATE ?? ""), + ItemDetailViewCol(LocaleKeys.endDateT.tr(), absenceTransList![index].eNDDATE ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.absenceType.tr(), absenceTransList![index].aBSENCETYPE ?? ""), + ItemDetailViewCol(LocaleKeys.absenceCategory.tr(), absenceTransList![index].aBSENCECATEGORY ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.days.tr(), absenceTransList![index].aBSENCEDAYS?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.hours.tr(), absenceTransList![index].aBSENCEHOURS?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.approvalStatus.tr(), absenceTransList![index].aPPROVALSTATUS ?? ""), + ItemDetailViewCol(LocaleKeys.absenceStatus.tr(), absenceTransList![index].aBSENCESTATUS ?? ""), + isItLast: true, + ), ], ).objectContainerView(), separatorBuilder: (cxt, index) => 12.height, diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index 57b61d9..bdfb391 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -62,6 +62,17 @@ class _DynamicListViewScreenState extends State { late bool isTicketRequest; + List getEITWidgetsList(List? collectionTransaction) { + List itemsList = []; + + for (int t = 0; t < (collectionTransaction ?? []).length; t++) { + if (collectionTransaction![t].dISPLAYFLAG == "Y") { + itemsList.add(ItemDetailViewCol(collectionTransaction[t].sEGMENTPROMPT!, collectionTransaction[t].sEGMENTVALUEDSP ?? "")); + } + } + return itemsList; + } + @override Widget build(BuildContext context) { if (dynamicParams == null) { @@ -84,16 +95,45 @@ class _DynamicListViewScreenState extends State { shrinkWrap: true, itemBuilder: (cxt, int parentIndex) => getEITTransactionList![parentIndex].collectionTransaction!.isEmpty ? const SizedBox() - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - for (int t = 0; t < (getEITTransactionList![parentIndex].collectionTransaction ?? []).length; t++) - if (getEITTransactionList![parentIndex].collectionTransaction![t].dISPLAYFLAG == "Y") - ItemDetailView(getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTPROMPT!, - getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTVALUEDSP ?? ""), - ], + : GridView( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 1.9 / 0.75), + padding: const EdgeInsets.all(12.0), + shrinkWrap: true, + primary: false, + physics: const ScrollPhysics(), + children: getEITWidgetsList(getEITTransactionList![parentIndex].collectionTransaction), ).objectContainerView(), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisSize: MainAxisSize.min, + // children: [ + // for (int t = 0; t < (getEITTransactionList![parentIndex].collectionTransaction ?? []).length; t++) + // if (getEITTransactionList![parentIndex].collectionTransaction![t].dISPLAYFLAG == "Y") + // // ItemDetailView(getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTPROMPT!, + // // getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTVALUEDSP ?? ""), + // // GridView( + // // gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2), + // // padding: const EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 12), + // // shrinkWrap: true, + // // primary: false, + // // physics: const ScrollPhysics(), + // // children: getEITWidgetsList(getEITTransactionList![parentIndex].collectionTransaction), + // // ) + // // ItemDetailViewCol(getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTPROMPT!, + // // getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTVALUEDSP ?? ""), + // + // // GridView( + // // gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2), + // // padding: const EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 12), + // // shrinkWrap: true, + // // primary: false, + // // physics: const ScrollPhysics(), + // // children: getEITWidgetsList(getEITTransactionList![parentIndex].collectionTransaction), + // // ) + // // ItemDetailView(getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTPROMPT!, + // // getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTVALUEDSP ?? ""), + // ], + // ).objectContainerView(), separatorBuilder: (cxt, index) => 12.height, itemCount: getEITTransactionList!.length)), ], diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index de7c152..4dd9a04 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -425,7 +425,8 @@ class _WorkListDetailScreenState extends State { child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "REJECT": - performNetworkCall(context, email: "", userId: ""); + // performNetworkCall(context, email: "", userId: ""); + performAction(notificationButton.bUTTONACTION!); break; case "RETURNED": Navigator.pop(context); diff --git a/lib/widgets/dialogs/accept_reject_input_dialog.dart b/lib/widgets/dialogs/accept_reject_input_dialog.dart index db9c5d6..0008a1d 100644 --- a/lib/widgets/dialogs/accept_reject_input_dialog.dart +++ b/lib/widgets/dialogs/accept_reject_input_dialog.dart @@ -88,16 +88,18 @@ class AcceptRejectInputDialog extends StatelessWidget { ).expanded, 10.width, DefaultButton( - actionMode == "REJECTED" ? LocaleKeys.reject.tr() : LocaleKeys.ok.tr(), + (actionMode == "REJECTED" || actionMode == "REJECT") ? LocaleKeys.reject.tr() : LocaleKeys.ok.tr(), () { - if(note.isNotEmpty) { - Navigator.pop(context); - onTap(note); - } else { - Utils.showToast(LocaleKeys.pleaseEnterComments.tr()); + if (note.isEmpty) { + if (actionMode == "APPROVED" || actionMode == "APPROVE") { + Navigator.pop(context); + onTap(note); + } else { + Utils.showToast(LocaleKeys.pleaseEnterComments.tr()); + } } }, - colors: actionMode == "REJECTED" + colors: (actionMode == "REJECTED" || actionMode == "REJECT") ? const [ Color(0xffE47A7E), Color(0xffE47A7E), From b834c52b5fbbd695b5ab48501e478f089cec5963 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Mon, 7 Nov 2022 12:04:42 +0300 Subject: [PATCH 06/82] Updated Profile screen --- lib/ui/profile/profile_screen.dart | 76 +++++++++++++++++------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/lib/ui/profile/profile_screen.dart b/lib/ui/profile/profile_screen.dart index 0bf007e..0a78873 100644 --- a/lib/ui/profile/profile_screen.dart +++ b/lib/ui/profile/profile_screen.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'dart:ui'; import 'package:easy_localization/easy_localization.dart'; @@ -16,6 +17,7 @@ import 'package:mohem_flutter_app/models/get_employee_basic_details.model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/ui/profile/widgets/profile_panel.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; +import 'package:mohem_flutter_app/widgets/image_picker.dart'; class ProfileScreen extends StatefulWidget { const ProfileScreen({Key? key}) : super(key: key); @@ -28,6 +30,7 @@ class _ProfileScreenState extends State { late MemberInformationListModel memberInformationList; final ImagePicker _picker = ImagePicker(); List getEmployeeBasicDetailsList = []; + List images = []; @override void initState() { @@ -46,24 +49,25 @@ class _ProfileScreenState extends State { children: [ memberInformationList!.eMPLOYEEIMAGE != null ? Container( - height: 300, - margin: const EdgeInsets.only(top: 50), - decoration: BoxDecoration( - image: DecorationImage( - image: MemoryImage( - Utils.dataFromBase64String(memberInformationList.eMPLOYEEIMAGE!), + height: 300, + margin: const EdgeInsets.only(top: 50), + decoration: BoxDecoration( + image: DecorationImage( + image: MemoryImage( + Utils.dataFromBase64String(memberInformationList.eMPLOYEEIMAGE!), + ), + fit: BoxFit.cover), ), - fit: BoxFit.cover), - ), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), - child: Container( - color: Colors.white.withOpacity(0.0), - ), - ), - ): Container( - decoration: BoxDecoration(color: Colors.white.withOpacity(0.0)), - ), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), + child: Container( + color: Colors.white.withOpacity(0.0), + ), + ), + ) + : Container( + decoration: BoxDecoration(color: Colors.white.withOpacity(0.0)), + ), SingleChildScrollView( scrollDirection: Axis.vertical, child: Column( @@ -83,7 +87,14 @@ class _ProfileScreenState extends State { ), InkWell( onTap: () { - startImageSheet(); + // startImageSheet(); + ImageOptions.showImageOptionsNew(context, false, (String image, File file) { + setState(() { + // images.add(image); + Navigator.of(context).pop(); + openGallery(image); + }); + }); }, child: Container( padding: const EdgeInsets.only(left: 17, right: 17, top: 8, bottom: 8), @@ -112,7 +123,8 @@ class _ProfileScreenState extends State { } void startImageSheet() { - showMyBottomSheet(context, callBackFunc: (){}, + showMyBottomSheet(context, + callBackFunc: () {}, child: Column( children: [ Container( @@ -123,14 +135,14 @@ class _ProfileScreenState extends State { )), BottomSheetItem( onTap: () { - openGallery(false); + // openGallery(false); }, title: 'Open Gallery', icon: Icons.browse_gallery_outlined, ), BottomSheetItem( onTap: () { - openGallery(true); + // openGallery(true); }, title: 'Open Camera', icon: Icons.camera, @@ -139,19 +151,17 @@ class _ProfileScreenState extends State { )); } - void openGallery(bool isCamera) async { - XFile? image = await _picker.pickImage(source: isCamera ? ImageSource.camera : ImageSource.gallery); + void openGallery(String image) async { + // XFile? image = await _picker.pickImage(source: isCamera ? ImageSource.camera : ImageSource.gallery); - if (image != null) { - String img = base64.encode(await image!.readAsBytes()); - Utils.showLoading(context); - dynamic empImageUpdteResp = await ProfileApiClient().updateEmpImage(img); - Utils.hideLoading(context); - if (empImageUpdteResp['P_RETURN_STATUS'] == 'S') { - setState(() { - memberInformationList.eMPLOYEEIMAGE = img; - }); - } + // String img = base64.encode(await image!.readAsBytes()); + Utils.showLoading(context); + dynamic empImageUpdteResp = await ProfileApiClient().updateEmpImage(image); + Utils.hideLoading(context); + if (empImageUpdteResp['P_RETURN_STATUS'] == 'S') { + setState(() { + memberInformationList.eMPLOYEEIMAGE = image; + }); } } } From c83f0c11994aa5f93259d91431fbf06ac5c89230 Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Tue, 8 Nov 2022 08:13:05 +0300 Subject: [PATCH 07/82] fix issues --- lib/api/profile_api_client.dart | 2 +- lib/models/get_employee_address_model.dart | 2 +- lib/models/profile/get_address_dff_structure_list.dart | 6 +++--- .../dynamic_screens/dynamic_input_screen.dart | 10 +++++----- .../dynamic_screens/dynamic_input_address_screen.dart | 5 ++--- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/api/profile_api_client.dart b/lib/api/profile_api_client.dart index d7ceba0..210d179 100644 --- a/lib/api/profile_api_client.dart +++ b/lib/api/profile_api_client.dart @@ -293,7 +293,7 @@ class ProfileApiClient { "P_COUNTRY_CODE": countryCode, //"SA", "P_DESC_FLEX_CONTEXT_CODE": "SA", "P_FUNCTION_NAME": pFunctionName, - "P_ACTION": correctOrNew == 1 ? 'CORRECT' : 'NEW', + "P_ACTION": correctOrNew == 1 ? 'CORRECT' : 'CHANGE', "P_EFFECTIVE_DATE": effectiveDate, //"EITTransactionTBL": list, diff --git a/lib/models/get_employee_address_model.dart b/lib/models/get_employee_address_model.dart index 8531ced..71c5885 100644 --- a/lib/models/get_employee_address_model.dart +++ b/lib/models/get_employee_address_model.dart @@ -5,7 +5,7 @@ String? dATATYPE; String? dATEVALUE; String? dISPLAYFLAG; - Null? nUMBERVALUE; + dynamic? nUMBERVALUE; String? sEGMENTPROMPT; int? sEGMENTSEQNUM; String? sEGMENTVALUEDSP; diff --git a/lib/models/profile/get_address_dff_structure_list.dart b/lib/models/profile/get_address_dff_structure_list.dart index 786e683..61f6b5e 100644 --- a/lib/models/profile/get_address_dff_structure_list.dart +++ b/lib/models/profile/get_address_dff_structure_list.dart @@ -5,7 +5,7 @@ class GetAddressDffStructureList { String? aLPHANUMERICALLOWEDFLAG; String? aPPLICATIONCOLUMNNAME; String? cHILDSEGMENTSVS; - Null? cHILDSEGMENTSVSSplited; + dynamic? cHILDSEGMENTSVSSplited; String? dEFAULTTYPE; String? dEFAULTVALUE; String? dESCFLEXCONTEXTCODE; @@ -27,9 +27,9 @@ class GetAddressDffStructureList { String? nUMBERPRECISION; String? nUMERICMODEENABLEDFLAG; String? pARENTSEGMENTSDV; - List? pARENTSEGMENTSDVSplited; + List? pARENTSEGMENTSDVSplited; String? pARENTSEGMENTSVS; - List? pARENTSEGMENTSVSSplitedVS; + List? pARENTSEGMENTSVSSplitedVS; String? rEADONLY; String? rEQUIREDFLAG; String? sEGMENTNAME; diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index c1b8a43..0a6c9d4 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -136,7 +136,7 @@ class _DynamicInputScreenState extends State { } Future getDefaultValues(GetEITDFFStructureList structureList) async { - // try { + try { Utils.showLoading(context); for (int i = 0; i < (structureList.cHILDSEGMENTSDVSplited?.length ?? 0); i++) { String segmentId = structureList.cHILDSEGMENTSDVSplited![i]; @@ -163,10 +163,10 @@ class _DynamicInputScreenState extends State { await Future.delayed(const Duration(seconds: 1)); Utils.hideLoading(context); setState(() {}); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } // List> calGetValueSetValuesIonicLogic(GetEITDFFStructureList structureElement) { diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart index cc8e861..ecc2426 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart @@ -266,16 +266,15 @@ class _DynamicInputScreenState extends State { if (e.fORMATTYPE == "X") { // for date format type, date format is changed tempVar = e.eSERVICESDV?.pVALUECOLUMNNAME ?? ""; - if (tempVar.isNotEmpty) { DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('dd/MMM/yyy').format(date); + tempVar = DateFormat('dd-MMM-yyy').format(date); if (e.aPPLICATIONCOLUMNNAME == null) { effectiveDate = tempVar; } } } else if (e.eSERVICESVS?.isNotEmpty ?? false) { - tempVar = e.getEmployeeAddressList!.vARCHAR2VALUE!; + tempVar = e.getEmployeeAddressList!.vARCHAR2VALUE ?? ""; if (e.aPPLICATIONCOLUMNNAME == null) { countryCode = tempVar; } From 965edf9141730de2a70cc75be10930ab5e49f7fc Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Tue, 8 Nov 2022 10:20:08 +0300 Subject: [PATCH 08/82] fix issues --- .../profile/dynamic_screens/dynamic_input_address_screen.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart index 6933a28..ecc2426 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart @@ -266,7 +266,6 @@ class _DynamicInputScreenState extends State { if (e.fORMATTYPE == "X") { // for date format type, date format is changed tempVar = e.eSERVICESDV?.pVALUECOLUMNNAME ?? ""; - if (tempVar.isNotEmpty) { DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); tempVar = DateFormat('dd-MMM-yyy').format(date); @@ -275,7 +274,7 @@ class _DynamicInputScreenState extends State { } } } else if (e.eSERVICESVS?.isNotEmpty ?? false) { - e.getEmployeeAddressList!.vARCHAR2VALUE != null ? tempVar = e.getEmployeeAddressList!.vARCHAR2VALUE! : tempVar = ""; + tempVar = e.getEmployeeAddressList!.vARCHAR2VALUE ?? ""; if (e.aPPLICATIONCOLUMNNAME == null) { countryCode = tempVar; } From a0201efbfb084e6e800b39f6af0b6b7de6d0a5dc Mon Sep 17 00:00:00 2001 From: Sultan khan <> Date: Tue, 8 Nov 2022 10:24:05 +0300 Subject: [PATCH 09/82] dynamic screen updated --- .../dynamic_screens/dynamic_input_screen.dart | 259 ++++++++++-------- lib/ui/profile/add_update_family_member.dart | 171 ++++++------ lib/ui/screens/my_requests/new_request.dart | 4 +- 3 files changed, 242 insertions(+), 192 deletions(-) diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 1c97b28..01895a7 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -57,51 +57,51 @@ class _DynamicInputScreenState extends State { } void validateTransaction() async { - try { - Utils.showLoading(context); - List> values = getEitDffStructureList!.map((e) { - String tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; - if (e.fORMATTYPE == "X") { - // for date format type, date format is changed - tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; - if (tempVar.isNotEmpty) { - if (!tempVar.contains("/")) { - DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); - } + /// try { + Utils.showLoading(context); + List> values = getEitDffStructureList!.map((e) { + String tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; + if (e.fORMATTYPE == "X") { + // for date format type, date format is changed + tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; + if (tempVar.isNotEmpty) { + if (!tempVar.contains("/")) { + DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); + tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); } } - // else if (e.fORMATTYPE == "N") { - // // for date format type, date format is changed - // tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; - // print("------------------------sEGMENTNAME:${e.sEGMENTNAME}"); - // print("------------------------tempVar:$tempVar"); - // if (tempVar.isNotEmpty) { - // if (!tempVar.contains("/")) { - // DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - // tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); - // } - // } - // } - return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: tempVar.toString()).toJson(); - }).toList(); - - values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_ACTION", nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: "NEW_ROW").toJson()); - values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_EXTRA_INFO_ID", nUMBERVALUE: -1, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); - values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); - - genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); - SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); - Utils.hideLoading(context); - await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, - arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit')); - Utils.showLoading(context); - await LeaveBalanceApiClient().cancelHrTransaction(submitEITTransactionList.pTRANSACTIONID!); - Utils.hideLoading(context); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - } + } + // else if (e.fORMATTYPE == "N") { + // // for date format type, date format is changed + // tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; + // print("------------------------sEGMENTNAME:${e.sEGMENTNAME}"); + // print("------------------------tempVar:$tempVar"); + // if (tempVar.isNotEmpty) { + // if (!tempVar.contains("/")) { + // DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); + // tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); + // } + // } + // } + return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: tempVar.toString()).toJson(); + }).toList(); + + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_ACTION", nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: "NEW_ROW").toJson()); + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_EXTRA_INFO_ID", nUMBERVALUE: -1, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); + + genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); + SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); + Utils.hideLoading(context); + await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, + arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit')); + Utils.showLoading(context); + await LeaveBalanceApiClient().cancelHrTransaction(submitEITTransactionList.pTRANSACTIONID!); + Utils.hideLoading(context); + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // } } String dESCFLEXCONTEXTCODE = ""; @@ -119,6 +119,19 @@ class _DynamicInputScreenState extends State { sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) .toJson()) .toList(); + + // if (structureList.pARENTSEGMENTSVSSplitedVS!.isNotEmpty) { + // structureList.pARENTSEGMENTSVSSplitedVS!.forEach((element2) { + // filteredList = getEitDffStructureList?.where((element) => element.sEGMENTNAME == element2.name).toList() ?? []; + // values = filteredList + // .map((e) => GetSetValuesRequestModel( + // sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) + // .toJson()) + // .toList(); + // }); + // List filteredList2 = getEitDffStructureList?.where((element) => element.fLEXVALUESETNAME == structureList.fLEXVALUESETNAME).toList() ?? []; + // } + List eServicesResponseModel = await MyAttendanceApiClient().getValueSetValues(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); List abc = genericResponseModel?.getEITDFFStructureList ?? []; getEitDffStructureList = abc; @@ -158,6 +171,25 @@ class _DynamicInputScreenState extends State { ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, getSetList); int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); getEitDffStructureList![index].eSERVICESDV = defaultValue; + GetEITDFFStructureList defaultValueCheck = getEitDffStructureList!.where((GetEITDFFStructureList element) => element.sEGMENTNAME == segmentId).toList().first; + + if (defaultValueCheck.cHILDSEGMENTSDVSplited!.isNotEmpty && defaultValueCheck.rEADONLY == 'Y') { + getDefaultValues(defaultValueCheck); + Utils.hideLoading(context); + + // GetEITDFFStructureList? parent = getEitDffStructureList!.firstWhere((element) => element.sEGMENTNAME == segmentId); + // List> getSetList = getDefaultValuesIonicLogic(parent); + // ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, defaultValueCheck.dESCFLEXCONTEXTCODE!, defaultValueCheck.dESCFLEXNAME!, getSetList); + // int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); + // getEitDffStructureList![index].eSERVICESDV = defaultValue; + } else if (defaultValueCheck.cHILDSEGMENTSVSSplited!.isNotEmpty && defaultValueCheck.rEADONLY == 'Y') { + calGetValueSetValues(defaultValueCheck); + Utils.hideLoading(context); + } + } else if (values.isNotEmpty) { + ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); + int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); + getEitDffStructureList![index].eSERVICESDV = defaultValue; } } await Future.delayed(const Duration(seconds: 1)); @@ -180,79 +212,79 @@ class _DynamicInputScreenState extends State { // } List> getDefaultValuesIonicLogic(GetEITDFFStructureList structureElement) { - try { - List parentValue = structureElement.pARENTSEGMENTSVSSplitedVS ?? []; - List parentsList = structureElement.pARENTSEGMENTSDVSplited ?? []; - - List> dependenciesList = []; - String? parentVal; - bool isStandardDate = false; - bool isStandardTimeDate = false; - bool isStandardTime = false; - bool isHidden = false; - bool isReadOnlyList = false; - bool isSelectElement = false; - - // isStandardDate = this.isStandardDate(obj); - // isStandardTimeDate = this.isStandardDateTime(obj); - // isStandardTime = this.isStandardTime(obj); - if (structureElement.dISPLAYFLAG == "N") isHidden = true; - if (structureElement.vALIDATIONTYPE != "N" && structureElement.rEADONLY == "Y") { - isReadOnlyList = true; - } - if (structureElement.vALIDATIONTYPE != "N" && structureElement.rEADONLY == "N") { - isSelectElement = true; - } + //try { + List parentValue = structureElement.pARENTSEGMENTSVSSplitedVS ?? []; + List parentsList = structureElement.pARENTSEGMENTSDVSplited ?? []; + + List> dependenciesList = []; + String? parentVal; + bool isStandardDate = false; + bool isStandardTimeDate = false; + bool isStandardTime = false; + bool isHidden = false; + bool isReadOnlyList = false; + bool isSelectElement = false; + + // isStandardDate = this.isStandardDate(obj); + // isStandardTimeDate = this.isStandardDateTime(obj); + // isStandardTime = this.isStandardTime(obj); + if (structureElement.dISPLAYFLAG == "N") isHidden = true; + if (structureElement.vALIDATIONTYPE != "N" && structureElement.rEADONLY == "Y") { + isReadOnlyList = true; + } + if (structureElement.vALIDATIONTYPE != "N" && structureElement.rEADONLY == "N") { + isSelectElement = true; + } - if (parentValue.isNotEmpty && (structureElement.vALIDATIONTYPE == "D" || structureElement.vALIDATIONTYPE == "Y")) { - List parValue = getDependenciesParams(parentValue); + if (parentValue.isNotEmpty && (structureElement.vALIDATIONTYPE == "D" || structureElement.vALIDATIONTYPE == "Y")) { + List parValue = getDependenciesParams(parentValue); - if (parValue.isNotEmpty) { - parentVal = parValue.first.ID_COLUMN_NAME; - } + if (parValue.isNotEmpty) { + parentVal = parValue.first.ID_COLUMN_NAME; + } - if (parentVal == null) { - return []; - } + if (parentVal == null) { + return []; } - if (parentsList.isNotEmpty) { - if (parentValue.isNotEmpty) { - parentsList = parentsList + parentValue.map((e) => PARENTSEGMENTSDVSplited.fromJson(e.toJson())).toList(); - // parentsList.addAll(parentValue.map((e) => PARENTSEGMENTSDVSplited.fromJson(e.toJson()))); - // parentsList.concat(parentValue); - } - dependenciesList = getDependenciesParams(parentsList); + } + if (parentsList.isNotEmpty) { + if (parentValue.isNotEmpty) { + parentsList = parentsList + parentValue.map((e) => PARENTSEGMENTSDVSplited.fromJson(e.toJson())).toList(); + // parentsList.addAll(parentValue.map((e) => PARENTSEGMENTSDVSplited.fromJson(e.toJson()))); + // parentsList.concat(parentValue); } - return dependenciesList; - // for (int i = 0; i < (structureList.cHILDSEGMENTSDVSplited?.length ?? 0); i++) { - // String segmentId = structureList.cHILDSEGMENTSDVSplited![i]; - // print("segmentId:$segmentId"); - // print("segmentName:${structureList.sEGMENTNAME}"); - // GetEITDFFStructureList? parent = getEitDffStructureList!.firstWhere((element) => element.sEGMENTNAME == segmentId); - // List parentDvRequired = parent.pARENTSEGMENTSDVSplited ?? []; - // List parentVsRequired = parent.pARENTSEGMENTSVSSplitedVS ?? []; - // - // List filteredList = - // getEitDffStructureList!.where((outerElement) => parentDvRequired.any((element) => outerElement.sEGMENTNAME == element.name && element.isRequired == "REQUIRED")).toList(); - // - // List> values = filteredList - // .map((e) => GetSetValuesRequestModel( - // sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) - // .toJson()) - // .toList(); - // print("values:$values"); - // - // ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); - // int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); - // getEitDffStructureList![index].eSERVICESDV = defaultValue; - // } - // Utils.hideLoading(context); - // setState(() {}); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - return []; + dependenciesList = getDependenciesParams(parentsList); } + return dependenciesList; + // for (int i = 0; i < (structureList.cHILDSEGMENTSDVSplited?.length ?? 0); i++) { + // String segmentId = structureList.cHILDSEGMENTSDVSplited![i]; + // print("segmentId:$segmentId"); + // print("segmentName:${structureList.sEGMENTNAME}"); + // GetEITDFFStructureList? parent = getEitDffStructureList!.firstWhere((element) => element.sEGMENTNAME == segmentId); + // List parentDvRequired = parent.pARENTSEGMENTSDVSplited ?? []; + // List parentVsRequired = parent.pARENTSEGMENTSVSSplitedVS ?? []; + // + // List filteredList = + // getEitDffStructureList!.where((outerElement) => parentDvRequired.any((element) => outerElement.sEGMENTNAME == element.name && element.isRequired == "REQUIRED")).toList(); + // + // List> values = filteredList + // .map((e) => GetSetValuesRequestModel( + // sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) + // .toJson()) + // .toList(); + // print("values:$values"); + // + // ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); + // int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); + // getEitDffStructureList![index].eSERVICESDV = defaultValue; + // } + // Utils.hideLoading(context); + // setState(() {}); + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // return []; + // } } List> getDependenciesParams(parentsList) { @@ -260,7 +292,7 @@ class _DynamicInputScreenState extends State { for (int i = 0; i < parentsList.length; i++) { for (int j = 0; j < (getEitDffStructureList?.length ?? 0); j++) { - if (getEitDffStructureList![j].sEGMENTNAME == parentsList[i].opt1) { + if (getEitDffStructureList![j].sEGMENTNAME == parentsList[i]?.name) { if (getEitDffStructureList![j].dISPLAYFLAG != "N") { if (getEitDffStructureList![j].vALIDATIONTYPE == "N") { String? idColName; @@ -455,6 +487,11 @@ class _DynamicInputScreenState extends State { model.eSERVICESDV ??= ESERVICESDV(); model.eSERVICESDV!.pIDCOLUMNNAME = text; }, + onTap: () async { + if (model.cHILDSEGMENTSDVSplited?.isNotEmpty ?? false) { + await getDefaultValues(model); + } + }, ).paddingOnly(bottom: 12); } else if (model.fORMATTYPE == "X") { String displayText = model.eSERVICESDV?.pIDCOLUMNNAME ?? (getEitDffStructureList![index].fieldAnswer ?? ""); diff --git a/lib/ui/profile/add_update_family_member.dart b/lib/ui/profile/add_update_family_member.dart index 00ad7fc..528e38d 100644 --- a/lib/ui/profile/add_update_family_member.dart +++ b/lib/ui/profile/add_update_family_member.dart @@ -224,8 +224,8 @@ class _AddUpdateFamilyMemberState extends State { onTap: () async { DateTime dateValue = await _selectDate(context); //date = DateFormat('yyyy/MM/dd').format(dateValue); - date = "2022-10-23T09:17:38.653+03:00"; - // date = (DateFormat('yyyy-MM-dd').format(dateValue)+"T"+ dateTime.toString() + dateTime1.toString()); + //date = "2022-10-23T09:17:38.653+03:00"; + date = (DateFormat('yyyy-MM-dd').format(dateValue)); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; print(dateTime); print(dateTime1); @@ -288,7 +288,7 @@ class _AddUpdateFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - date = "2022-10-23T09:17:38.653+03:00"; + date = (DateFormat('yyyy-MM-dd').format(dateValue)); // date = (DateFormat('yyyy-MM-dd').format(dateValue) +"T"+ dateTime.toString() + dateTime1.toString()); // date = DateFormat('yyyy/MM/dd').format(dateValue); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; @@ -349,8 +349,8 @@ class _AddUpdateFamilyMemberState extends State { isEnable: false, onTap: () async { DateTime dateValue = await _selectDate(context); - date = "2022-10-23T09:17:38.653+03:00"; - // date = (DateFormat('yyyy-MM-dd').format(dateValue)+"T"+ dateTime.toString() + dateTime1.toString()); + // date = "2022-10-23T09:17:38.653+03:00"; + date = (DateFormat('yyyy-MM-dd').format(dateValue)); // date = DateFormat('yyyy/MM/dd').format(dateValue); model!.getContactDetailsList!.sEGMENTVALUEDSP = date; setState(() {}); @@ -392,80 +392,93 @@ class _AddUpdateFamilyMemberState extends State { } void submitUpdateForm() async { - // try { - List> values1 = getBasicDetDffStructureList!.map((e) { - String? dateVal = ''; - String? vatcherVal = ''; - int? numberVal; - if (e!.fORMATTYPE == 'N') { - dateVal = null; - vatcherVal = null; - numberVal = int.parse(e.getContactDetailsList!.sEGMENTVALUEDSP??"0"); - } else if (e.fORMATTYPE == 'X') { - dateVal = e!.getContactDetailsList!.sEGMENTVALUEDSP.toString(); - vatcherVal = null; - numberVal = null; - } else { - dateVal = null; - vatcherVal = e!.getContactDetailsList!.sEGMENTVALUEDSP; - numberVal = null; - } - return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: vatcherVal.toString()).toJson(); - }).toList(); - List> values2 = getContactDffStructureList!.map((e) { - String? dateVal = ''; - String? vatcherVal = ''; - int? numberVal; - if (e!.fORMATTYPE == 'N') { - dateVal = null; - vatcherVal = null; - numberVal = int.parse(e.getContactDetailsList!.sEGMENTVALUEDSP??"0"); - } else if (e.fORMATTYPE == 'X') { - dateVal = e!.getContactDetailsList!.sEGMENTVALUEDSP; - vatcherVal = null; - numberVal = null; - } else { - dateVal = null; - numberVal = null; - vatcherVal = e!.getContactDetailsList!.sEGMENTVALUEDSP; - } - return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: vatcherVal.toString()).toJson(); - }).toList(); - List> values3 = getContactColsStructureList!.map((e) { - // String tempVar = e!.getContactDetailsList!.sEGMENTVALUEDSP ?? ""; - String? dateVal = ''; - String? vatcherVal = ''; - int? numberVal; + print("submit"); + try { + List> values1 = getBasicDetDffStructureList!.map((e) { + String? dateVal = ''; + String? varChar = ''; + int? numberVal; + if (e!.fORMATTYPE == 'N') { + dateVal = null; + varChar = null; + numberVal = int.parse(e.getContactDetailsList!.sEGMENTVALUEDSP ?? "0"); + } else if (e.fORMATTYPE == 'X') { + dateVal = e!.getContactDetailsList!.sEGMENTVALUEDSP.toString(); + varChar = null; + numberVal = null; + } else if (e.eSERVICESVS!.isNotEmpty) { + dateVal = null; + varChar = e!.getContactDetailsList!.vARCHAR2VALUE; + numberVal = null; + } else { + dateVal = null; + varChar = e!.getContactDetailsList!.sEGMENTVALUEDSP; + numberVal = null; + } + return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: varChar).toJson(); + }).toList(); + List> values2 = getContactDffStructureList!.map((e) { + String? dateVal = ''; + String? varChar = ''; + int? numberVal; + if (e!.fORMATTYPE == 'N') { + dateVal = null; + varChar = null; + numberVal = int.parse(e.getContactDetailsList!.sEGMENTVALUEDSP ?? "0"); + } else if (e.fORMATTYPE == 'X') { + dateVal = e!.getContactDetailsList!.dATEVALUE; + varChar = null; + numberVal = null; + } else if (e.eSERVICESVS!.isNotEmpty) { + dateVal = null; + varChar = e!.getContactDetailsList!.vARCHAR2VALUE; + numberVal = null; + } else { + dateVal = null; + numberVal = null; + varChar = e!.getContactDetailsList!.sEGMENTVALUEDSP; + } + return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: varChar).toJson(); + }).toList(); + List> values3 = getContactColsStructureList!.map((e) { + // String tempVar = e!.getContactDetailsList!.sEGMENTVALUEDSP ?? ""; + String? dateVal = ''; + dynamic? varChar1 = ''; + int? numberVal; - print("e.dATATYPE:${e?.dATATYPE}"); - if (e!.dATATYPE == 'VARCHAR2') { - dateVal = null; - numberVal = null; - vatcherVal = e.getContactDetailsList?.sEGMENTVALUEDSP ?? ""; - } else if (e.dATATYPE == 'DATE') { - dateVal = e.getContactDetailsList!.sEGMENTVALUEDSP.toString(); - print("dateVal:${dateVal ?? ""}"); - vatcherVal = null; - numberVal = null; - } else if (e.dATATYPE == 'NUMBER') { - dateVal = null; - vatcherVal = null; - numberVal = int.parse(e.getContactDetailsList!.sEGMENTVALUEDSP??"0"); - } else {} - return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: vatcherVal).toJson(); - }).toList(); - List> valuesFinal = [...values1, ...values2, ...values3]; - Utils.showLoading(context); - submitContactTransactionList = await ProfileApiClient().submitContactTransactionAddAndUpdate(args['actionType'], args['relationID'] ?? null, valuesFinal); - var transactionId = submitContactTransactionList!.pTRANSACTIONID; - var itemKey = submitContactTransactionList!.pITEMKEY; - Utils.hideLoading(context); - Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, - arguments: RequestSubmitScreenParams(LocaleKeys.profile_familyDetails.tr(), transactionId!.toInt(), itemKey.toString(), 'family_member')); - setState(() {}); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + print("e.dATATYPE:${e?.dATATYPE}"); + if (e!.dATATYPE == 'VARCHAR2') { + dateVal = null; + numberVal = null; + if (e.objectValuesList != null && e.objectValuesList!.isNotEmpty) { + varChar1 = e.getContactDetailsList?.vARCHAR2VALUE ?? ""; + } else { + varChar1 = e.getContactDetailsList?.sEGMENTVALUEDSP ?? ""; + } + } else if (e.dATATYPE == 'DATE') { + dateVal = e.getContactDetailsList!.sEGMENTVALUEDSP.toString(); + varChar1 = null; + numberVal = null; + } else if (e.dATATYPE == 'NUMBER') { + dateVal = null; + varChar1 = null; + numberVal = int.parse(e.getContactDetailsList!.sEGMENTVALUEDSP ?? "0"); + } + return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: varChar1).toJson(); + }).toList(); + List> valuesFinal = [...values1, ...values2, ...values3]; + Utils.showLoading(context); + submitContactTransactionList = await ProfileApiClient().submitContactTransactionAddAndUpdate(args['actionType'], args['relationID'] ?? null, valuesFinal); + var transactionId = submitContactTransactionList!.pTRANSACTIONID; + var itemKey = submitContactTransactionList!.pITEMKEY; + Utils.hideLoading(context); + Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, + arguments: RequestSubmitScreenParams(LocaleKeys.profile_familyDetails.tr(), transactionId!.toInt(), itemKey.toString(), 'family_member')); + setState(() {}); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } } diff --git a/lib/ui/screens/my_requests/new_request.dart b/lib/ui/screens/my_requests/new_request.dart index b476ecc..851b82f 100644 --- a/lib/ui/screens/my_requests/new_request.dart +++ b/lib/ui/screens/my_requests/new_request.dart @@ -84,9 +84,9 @@ class _NewRequestState extends State { 1.divider, DefaultButton(LocaleKeys.submit.tr(), () { // todo need to add submit method + print("hi"); // openNewRequest(); - }) - .insideContainer, + }).insideContainer, ], ), ); From 26ddc0004846a0e36c6770bc27027cd1843aac3e Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 8 Nov 2022 11:09:45 +0300 Subject: [PATCH 10/82] Updates & fixes --- lib/api/worklist/worklist_api_client.dart | 10 ++++++ lib/ui/work_list/sheets/delegate_sheet.dart | 35 +++++++++++++++---- .../work_list/sheets/selected_item_sheet.dart | 29 +++++++++------ lib/ui/work_list/worklist_detail_screen.dart | 1 + .../dialogs/accept_reject_input_dialog.dart | 2 +- 5 files changed, 58 insertions(+), 19 deletions(-) diff --git a/lib/api/worklist/worklist_api_client.dart b/lib/api/worklist/worklist_api_client.dart index 1b00383..5ea1b72 100644 --- a/lib/api/worklist/worklist_api_client.dart +++ b/lib/api/worklist/worklist_api_client.dart @@ -481,6 +481,16 @@ class WorkListApiClient { }, url, postParams); } + Future?> getFavoriteReplacementWithImageNew(String selectedFavLetter) async { + String url = "${ApiConsts.erpRest}Mohemm_GetFavoriteReplacements_Images"; + Map postParams = {"ItgFilter": selectedFavLetter}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.mohemmGetFavoriteReplacementsList; + }, url, postParams); + } + Future changeFavoriteReplacements({required String email, required String employeName, required String image, required String userName, bool isFav = false}) async { String url = "${ApiConsts.erpRest}Mohemm_ChangeFavoriteReplacements"; Map postParamsObj = { diff --git a/lib/ui/work_list/sheets/delegate_sheet.dart b/lib/ui/work_list/sheets/delegate_sheet.dart index bd3b010..6d39fc8 100644 --- a/lib/ui/work_list/sheets/delegate_sheet.dart +++ b/lib/ui/work_list/sheets/delegate_sheet.dart @@ -91,6 +91,15 @@ class _DelegateSheetState extends State { favUsersList = await WorkListApiClient().getFavoriteReplacementWithImage(selectedFavLetter ?? ""); if (isNeedLoading) Utils.hideLoading(context); setState(() {}); + fetchFavUsersListNew(isNeedLoading: false); + return null; + } + + Future fetchFavUsersListNew({bool isNeedLoading = true}) async { + if (isNeedLoading) Utils.showLoading(context); + favUsersList = await WorkListApiClient().getFavoriteReplacementWithImageNew(selectedFavLetter ?? ""); + if (isNeedLoading) Utils.hideLoading(context); + setState(() {}); return null; } @@ -195,7 +204,7 @@ class _DelegateSheetState extends State { ).onPress(() { showMyBottomSheet( context, - callBackFunc: (){}, + callBackFunc: () {}, child: SearchOptionsSheet( selectedType, onSelection: (String value) { @@ -478,12 +487,24 @@ class _DelegateSheetState extends State { }, child: Row( children: [ - CircularAvatar( - url: actionHistory.employeeImage, - height: 30, - width: 30, - isImageBase64: (actionHistory.employeeImage != null || actionHistory.employeeImage!.isNotEmpty) ? true : false, - ), + actionHistory.employeeImage != "" + ? CircularAvatar( + url: actionHistory.employeeImage, + height: 40, + width: 40, + isImageBase64: (actionHistory.employeeImage != null || actionHistory.employeeImage!.isNotEmpty) ? true : false, + ) + : ClipRRect( + borderRadius: const BorderRadius.all( + Radius.circular(50), + ), + child: Image.network( + "https://play-lh.googleusercontent.com/NPo88ojmhah4HDiposucJmfQIop4z4xc8kqJK9ITO9o-yCab2zxIp7PPB_XPj2iUojo", + fit: BoxFit.cover, + height: 40, + width: 40, + ).toShimmer(), + ), 16.width, Expanded( child: (actionHistory.employeeDisplayName ?? "").toText12(), diff --git a/lib/ui/work_list/sheets/selected_item_sheet.dart b/lib/ui/work_list/sheets/selected_item_sheet.dart index e053218..355fee6 100644 --- a/lib/ui/work_list/sheets/selected_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_item_sheet.dart @@ -133,26 +133,33 @@ class SelectedItemSheet extends StatelessWidget { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: Color(0xffF7F7F7), + color: const Color(0xffF7F7F7), border: Border.all( - color: Color(0xffefefef), + color: const Color(0xffefefef), width: 1, ), ), - padding: EdgeInsets.only(top: 16, bottom: 16, left: 21, right: 21), + padding: const EdgeInsets.only(top: 16, bottom: 16, left: 21, right: 21), child: Row( children: [ - (actionHistoryList != null && actionHistoryList!.eMPLOYEEIMAGE != null) + (isFav != null && isFav) ? CircularAvatar( - height: 30, - width: 30, - url: actionHistoryList!.eMPLOYEEIMAGE, + height: 40, + width: 40, + url: favoriteReplacements != null ? favoriteReplacements!.employeeImage : actionHistoryList!.eMPLOYEEIMAGE, isImageBase64: true, ) - : CircularAvatar( - height: 30, - width: 30, - ), + : (actionHistoryList != null && actionHistoryList!.eMPLOYEEIMAGE != null) + ? CircularAvatar( + height: 40, + width: 40, + url: actionHistoryList!.eMPLOYEEIMAGE, + isImageBase64: true, + ) + : CircularAvatar( + height: 40, + width: 40, + ), 16.width, Expanded( child: (name ?? "").toText12(), diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 4dd9a04..1d5931d 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -520,6 +520,7 @@ class _WorkListDetailScreenState extends State { } void performAction(String actionMode, {String? title}) { + print(actionMode); showDialog( context: context, builder: (cxt) => AcceptRejectInputDialog( diff --git a/lib/widgets/dialogs/accept_reject_input_dialog.dart b/lib/widgets/dialogs/accept_reject_input_dialog.dart index 0008a1d..e335453 100644 --- a/lib/widgets/dialogs/accept_reject_input_dialog.dart +++ b/lib/widgets/dialogs/accept_reject_input_dialog.dart @@ -91,7 +91,7 @@ class AcceptRejectInputDialog extends StatelessWidget { (actionMode == "REJECTED" || actionMode == "REJECT") ? LocaleKeys.reject.tr() : LocaleKeys.ok.tr(), () { if (note.isEmpty) { - if (actionMode == "APPROVED" || actionMode == "APPROVE") { + if (actionMode != "REJECTED" || actionMode != "REJECT") { Navigator.pop(context); onTap(note); } else { From b9f9c31f01e5a14c5edfe7069292d40e009e57e7 Mon Sep 17 00:00:00 2001 From: Sultan khan <> Date: Wed, 9 Nov 2022 12:39:08 +0300 Subject: [PATCH 11/82] lynx access issue fixed --- .../dynamic_screens/dynamic_input_screen.dart | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 0e71b09..9aafdd8 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -110,16 +110,26 @@ class _DynamicInputScreenState extends State { Future calGetValueSetValues(GetEITDFFStructureList structureList) async { try { Utils.showLoading(context); + List> values = []; String segmentId = structureList.cHILDSEGMENTSVS!; + if (dESCFLEXCONTEXTCODE.isEmpty) dESCFLEXCONTEXTCODE = structureList.dESCFLEXCONTEXTCODE!; List filteredList = getEitDffStructureList?.where((element) => element.cHILDSEGMENTSVSSplited!.contains(segmentId)).toList() ?? []; - List> values = filteredList + + if (filteredList.isEmpty && structureList.cHILDSEGMENTSVSSplited!.isNotEmpty) { + segmentId = structureList.cHILDSEGMENTSVSSplited![0]; + filteredList = getEitDffStructureList?.where((element) => element.cHILDSEGMENTSVSSplited!.contains(segmentId)).toList() ?? []; + } + values = filteredList .map((e) => GetSetValuesRequestModel( sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) .toJson()) .toList(); + // if (parentValue.isNotEmpty && (structureList.vALIDATIONTYPE == "F")) { + // values = getDependenciesParams(parentValue); + // } // if (structureList.pARENTSEGMENTSVSSplitedVS!.isNotEmpty) { // structureList.pARENTSEGMENTSVSSplitedVS!.forEach((element2) { // filteredList = getEitDffStructureList?.where((element) => element.sEGMENTNAME == element2.name).toList() ?? []; @@ -135,7 +145,7 @@ class _DynamicInputScreenState extends State { List eServicesResponseModel = await MyAttendanceApiClient().getValueSetValues(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); List abc = genericResponseModel?.getEITDFFStructureList ?? []; getEitDffStructureList = abc; - int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == structureList.cHILDSEGMENTSVS); + int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); getEitDffStructureList![index].eSERVICESVS!.clear(); if (eServicesResponseModel.isNotEmpty) getEitDffStructureList![index].eSERVICESVS!.addAll(eServicesResponseModel); // getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; From 21d396b3bb968e2cb5eaa357edf3e948a7369e34 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 9 Nov 2022 14:37:17 +0300 Subject: [PATCH 12/82] Worklist updates --- lib/api/my_attendance_api_client.dart | 16 ++ lib/api/worklist/worklist_api_client.dart | 38 +++- lib/app_state/app_state.dart | 4 + lib/models/generic_response_model.dart | 18 +- lib/models/worklist/GetRFCEmployeeList.dart | 48 +++++ .../get_favorite_replacements_model.dart | 8 +- .../worklist/replacement_list_model.dart | 2 +- .../worklist/resubmit_eit_response_model.dart | 22 +++ .../dynamic_listview_screen.dart | 5 +- lib/ui/work_list/itg_detail_screen.dart | 126 ++++++++++++- .../approval_level_fragment.dart | 3 +- lib/ui/work_list/sheets/delegate_sheet.dart | 37 ++-- .../work_list/sheets/selected_item_sheet.dart | 94 ++++++++-- .../sheets/selected_itg_item_sheet.dart | 5 +- .../sheets/update_continue_sheet.dart | 131 +++++++++++++ lib/ui/work_list/worklist_detail_screen.dart | 175 ++++++++++++++++-- .../dialogs/accept_reject_input_dialog.dart | 5 +- pubspec.yaml | 1 + 18 files changed, 673 insertions(+), 65 deletions(-) create mode 100644 lib/models/worklist/GetRFCEmployeeList.dart create mode 100644 lib/models/worklist/resubmit_eit_response_model.dart create mode 100644 lib/ui/work_list/sheets/update_continue_sheet.dart diff --git a/lib/api/my_attendance_api_client.dart b/lib/api/my_attendance_api_client.dart index eb66a8b..72d9bcb 100644 --- a/lib/api/my_attendance_api_client.dart +++ b/lib/api/my_attendance_api_client.dart @@ -9,6 +9,7 @@ import 'package:mohem_flutter_app/models/get_eit_dff_structure_list_model.dart'; import 'package:mohem_flutter_app/models/get_eit_transaction_list_model.dart'; import 'package:mohem_flutter_app/models/start_eit_approval_process_model.dart'; import 'package:mohem_flutter_app/models/submit_eit_transaction_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/resubmit_eit_response_model.dart'; class MyAttendanceApiClient { static final MyAttendanceApiClient _instance = MyAttendanceApiClient._internal(); @@ -108,6 +109,21 @@ class MyAttendanceApiClient { }, url, postParams); } + Future reSubmitEitTransaction(String itemKey, var notifID, List> list) async { + String url = "${ApiConsts.erpRest}RESUBMIT_EIT_TRANSACTION"; + Map postParams = { + "P_NOTIFICATION_ID": notifID, + "P_ITEM_KEY": itemKey, + "P_EMAIL_ADDRESS": AppState().memberInformationList!.eMPLOYEEEMAILADDRESS, + "EITTransactionTBL": list + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.resubmitEITTransactionList!; //ESERVICESDV.fromJson(responseData.getDefaultValueList!.toJson()); + }, url, postParams); + } + Future> getApproversList(String pAmeTransactionType, int pTransactionId) async { String url = "${ApiConsts.erpRest}GET_APPROVERS_LIST"; Map postParams = { diff --git a/lib/api/worklist/worklist_api_client.dart b/lib/api/worklist/worklist_api_client.dart index 5ea1b72..d999d18 100644 --- a/lib/api/worklist/worklist_api_client.dart +++ b/lib/api/worklist/worklist_api_client.dart @@ -23,6 +23,7 @@ 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/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'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; @@ -88,6 +89,16 @@ class WorkListApiClient { }, url, postParams); } + Future> getRFCEmployeeeList(int pNotificationID) async { + String url = "${ApiConsts.erpRest}GET_RFC_EMPLOYEE_LIST"; + Map postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_PAGE_NUM": 1, "P_PAGE_LIMIT": 10}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getRFCEmployeeListList ?? []; + }, url, postParams); + } + Future> getActionHistory(int pNotificationID) async { String url = "${ApiConsts.erpRest}GET_ACTION_HISTORY"; Map postParams = { @@ -357,7 +368,7 @@ class WorkListApiClient { }, url, postParams); } - Future delegateITGRequest(String requestType, int taskId, int itemId, String employeeNumber,String newUserEMPId, String comments) async { + Future delegateITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGDelegateRequest"; Map postParams = { "RequestType": requestType, @@ -373,7 +384,26 @@ class WorkListApiClient { return responseData.itgRequest; }, url, postParams); } - Future informationITGRequest(String requestType, int taskId, int itemId, String employeeNumber,String newUserEMPId, String comments) async { + + // ANSWER = 'Services/COCWS.svc/REST/ITGAnswer'; + + Future answerITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { + String url = "${ApiConsts.cocRest}ITGAnswer"; + Map postParams = { + "RequestType": requestType, + "TaskID": taskId, + "ItemID": itemId, + "EmployeeNumber": employeeNumber, + "Comments": comments, + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, url, postParams); + } + + Future informationITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGRequestInformation"; Map postParams = { "RequestType": requestType, @@ -526,7 +556,7 @@ class WorkListApiClient { }, url, postParams); } - Future submitComment({String? comment, String? email, String? userId, int? notificationId, required String apiMode}) async { + Future submitComment({String? comment, String? email, String? userId, int? notificationId, required String apiMode, int? approverIndex = null}) async { String url = "${ApiConsts.erpRest}NOTIFICATION_ACTIONS"; Map postParams = { "P_COMMENTS": comment, @@ -534,7 +564,7 @@ class WorkListApiClient { "P_EMAIL_ADDRESS": email, "P_FORWARD_TO_USER_NAME": userId, "P_NOTIFICATION_ID": notificationId, - "P_APPROVER_INDEX": null, + "P_APPROVER_INDEX": approverIndex, "RespondAttributeList": [] }; postParams.addAll(AppState().postParamsJson); diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 44de36f..9e61872 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -125,4 +125,8 @@ class AppState { set setchatUserDetails(UserAutoLoginModel details) => chatDetails = details; UserAutoLoginModel? get getchatUserDetails => chatDetails; + + String? _base64ImageEmp = "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"; + + String? get getBase64ImageEmp => _base64ImageEmp; } diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 2c8e98f..bf8d166 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -99,12 +99,14 @@ import 'package:mohem_flutter_app/models/vacation_rule/respond_attributes_list_m import 'package:mohem_flutter_app/models/vacation_rule/vr_item_types_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/wf_look_up_list_model.dart'; import 'package:mohem_flutter_app/models/validate_eit_transaction_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/resubmit_eit_response_model.dart'; import 'package:mohem_flutter_app/models/worklist_response_model.dart'; import 'package:mohem_flutter_app/start_term_approval_process_list_model.dart'; @@ -224,7 +226,7 @@ class GenericResponseModel { GetPoNotificationBodyList? getPoNotificationBodyList; GetPrNotificationBodyList? getPrNotificationBodyList; List? getQuotationAnalysisList; - List? getRFCEmployeeListList; + List? getRFCEmployeeListList; List? getRespondAttributeValueList; List? getSITCollectionNotificationBodyList; List? getSITDFFStructureList; @@ -326,7 +328,7 @@ class GenericResponseModel { List? respondAttributesList; List? respondRolesList; String? resubmitAbsenceTransactionList; - String? resubmitEITTransactionList; + ResubmitEITRequestResponse? resubmitEITTransactionList; String? resubmitHrTransactionList; String? sFHGetPoNotificationBodyList; String? sFHGetPrNotificationBodyList; @@ -975,7 +977,7 @@ class GenericResponseModel { getQuotationAnalysisList!.add(GetQuotationAnalysisList.fromJson(v)); }); } - getRFCEmployeeListList = json['GetRFCEmployeeListList']; + getRespondAttributeValueList = json['GetRespondAttributeValueList']; getSITCollectionNotificationBodyList = json['GetSITCollectionNotificationBodyList']; getSITDFFStructureList = json['GetSITDFFStructureList']; @@ -986,6 +988,14 @@ class GenericResponseModel { getScheduleShiftsDetailsList!.add(GetScheduleShiftsDetailsList.fromJson(v)); }); } + + if (json['GetRFCEmployeeListList'] != null) { + getRFCEmployeeListList = []; + json['GetRFCEmployeeListList'].forEach((v) { + getRFCEmployeeListList!.add(GetRFCEmployeeList.fromJson(v)); + }); + } + getShiftTypesList = json['GetShiftTypesList']; if (json['GetStampMsNotificationBodyList'] != null) { @@ -1277,7 +1287,7 @@ class GenericResponseModel { }); } resubmitAbsenceTransactionList = json['ResubmitAbsenceTransactionList']; - resubmitEITTransactionList = json['ResubmitEITTransactionList']; + resubmitEITTransactionList = json['ResubmitEITTransactionList'] != null ? ResubmitEITRequestResponse.fromJson(json['ResubmitEITTransactionList']) : null; resubmitHrTransactionList = json['ResubmitHrTransactionList']; sFHGetPoNotificationBodyList = json['SFH_GetPoNotificationBodyList']; sFHGetPrNotificationBodyList = json['SFH_GetPrNotificationBodyList']; diff --git a/lib/models/worklist/GetRFCEmployeeList.dart b/lib/models/worklist/GetRFCEmployeeList.dart new file mode 100644 index 0000000..33881c7 --- /dev/null +++ b/lib/models/worklist/GetRFCEmployeeList.dart @@ -0,0 +1,48 @@ +class GetRFCEmployeeList { + String? aCTION; + String? eMPLOYEEDISPLAYNAME; + String? eMPLOYEEIMAGE; + int? fROMROWNUM; + int? nOOFROWS; + int? rOWNUM; + int? sEQ; + int? tOROWNUM; + String? uSERNAME; + + GetRFCEmployeeList( + {this.aCTION, + this.eMPLOYEEDISPLAYNAME, + this.eMPLOYEEIMAGE, + this.fROMROWNUM, + this.nOOFROWS, + this.rOWNUM, + this.sEQ, + this.tOROWNUM, + this.uSERNAME}); + + GetRFCEmployeeList.fromJson(Map json) { + aCTION = json['ACTION']; + eMPLOYEEDISPLAYNAME = json['EMPLOYEE_DISPLAY_NAME']; + eMPLOYEEIMAGE = json['EMPLOYEE_IMAGE']; + fROMROWNUM = json['FROM_ROW_NUM']; + nOOFROWS = json['NO_OF_ROWS']; + rOWNUM = json['ROW_NUM']; + sEQ = json['SEQ']; + tOROWNUM = json['TO_ROW_NUM']; + uSERNAME = json['USER_NAME']; + } + + Map toJson() { + Map data = new Map(); + data['ACTION'] = this.aCTION; + data['EMPLOYEE_DISPLAY_NAME'] = this.eMPLOYEEDISPLAYNAME; + data['EMPLOYEE_IMAGE'] = this.eMPLOYEEIMAGE; + data['FROM_ROW_NUM'] = this.fROMROWNUM; + data['NO_OF_ROWS'] = this.nOOFROWS; + data['ROW_NUM'] = this.rOWNUM; + data['SEQ'] = this.sEQ; + data['TO_ROW_NUM'] = this.tOROWNUM; + data['USER_NAME'] = this.uSERNAME; + return data; + } +} diff --git a/lib/models/worklist/get_favorite_replacements_model.dart b/lib/models/worklist/get_favorite_replacements_model.dart index b5cefad..feee917 100644 --- a/lib/models/worklist/get_favorite_replacements_model.dart +++ b/lib/models/worklist/get_favorite_replacements_model.dart @@ -16,10 +16,10 @@ class GetFavoriteReplacements { this.employeeImage, }); - final String? userName; - final String? employeeDisplayName; - final String? emailAddress; - final String? employeeImage; + String? userName; + String? employeeDisplayName; + String? emailAddress; + String? employeeImage; factory GetFavoriteReplacements.fromJson(Map json) => GetFavoriteReplacements( userName: json["USER_NAME"] == null ? null : json["USER_NAME"], diff --git a/lib/models/worklist/replacement_list_model.dart b/lib/models/worklist/replacement_list_model.dart index f77b991..864cbe1 100644 --- a/lib/models/worklist/replacement_list_model.dart +++ b/lib/models/worklist/replacement_list_model.dart @@ -23,7 +23,7 @@ class ReplacementList { final String? emailAddress; final String? employeeDisplayName; - final String? employeeImage; + String? employeeImage; final int? fromRowNum; bool? isFavorite; final int? noOfRows; diff --git a/lib/models/worklist/resubmit_eit_response_model.dart b/lib/models/worklist/resubmit_eit_response_model.dart new file mode 100644 index 0000000..1da90ba --- /dev/null +++ b/lib/models/worklist/resubmit_eit_response_model.dart @@ -0,0 +1,22 @@ +class ResubmitEITRequestResponse { + String? pRETURNMSG; + String? pRETURNSTATUS; + int? pTRANSACTIONID; + + ResubmitEITRequestResponse( + {this.pRETURNMSG, this.pRETURNSTATUS, this.pTRANSACTIONID}); + + ResubmitEITRequestResponse.fromJson(Map json) { + pRETURNMSG = json['P_RETURN_MSG']; + pRETURNSTATUS = json['P_RETURN_STATUS']; + pTRANSACTIONID = json['P_TRANSACTION_ID']; + } + + Map toJson() { + Map data = new Map(); + data['P_RETURN_MSG'] = this.pRETURNMSG; + data['P_RETURN_STATUS'] = this.pRETURNSTATUS; + data['P_TRANSACTION_ID'] = this.pTRANSACTIONID; + return data; + } +} diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index bdfb391..ec52304 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -6,6 +6,7 @@ import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/models/get_eit_transaction_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/balances_dashboard_widget.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; @@ -16,8 +17,10 @@ class DynamicListViewParams { String uRL; String requestID; String colsURL; + bool isUpdate; + List? collectionNotificationList; - DynamicListViewParams(this.title, this.dynamicId, {this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = '', this.colsURL = ''}); + DynamicListViewParams(this.title, this.dynamicId, {this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = '', this.colsURL = '', this.isUpdate = false, this.collectionNotificationList}); } class DynamicListViewScreen extends StatefulWidget { diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index 84bd9bd..b215435 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -127,7 +127,10 @@ class _ItgDetailScreenState extends State { }, children: [ RequestDetailFragment(fields: itgRequest?.fieldGoups?[1].fields ?? []), - ApprovalLevelfragment(wFHistory: itgRequest?.wFHistory ?? [], voidCallback: reloadITG,), + ApprovalLevelfragment( + wFHistory: itgRequest?.wFHistory ?? [], + voidCallback: reloadITG, + ), RequestDetailFragment(fields: itgRequest?.fieldGoups?[0].fields ?? []), ], ).expanded, @@ -256,24 +259,106 @@ class _ItgDetailScreenState extends State { if (allowedActionList[i].action! == "Reject" || allowedActionList[i].action! == "Approve" || allowedActionList[i].action! == "CLOSE") { continue; } - fabs.add(myFab(allowedActionList[i].action!, "", isIconAsset: false).paddingOnly(bottom: 12).onPress(() => handleFabAction(allowedActionList[i]))); + fabs.add(myFab(getFabActionTitle(allowedActionList[i].action!), getFabActionImages(allowedActionList[i].action!)).paddingOnly(bottom: 12).onPress(() => handleFabAction(allowedActionList[i]))); } return fabs; } + String getFabActionImages(String actionTitle) { + String returnActionImage = ""; + switch (actionTitle) { + case "Delegate": + returnActionImage = "assets/images/delegate.svg"; + break; + case "RequestInformation": + returnActionImage = "assets/images/request_info.svg"; + break; + case "ReportGenerated": + returnActionImage = "assets/images/request_info.svg"; + break; + case "DataCorrected": + returnActionImage = "assets/images/request_info.svg"; + break; + case "Doable": + returnActionImage = "assets/images/request_info.svg"; + break; + case "NotDoable": + returnActionImage = "assets/images/request_info.svg"; + break; + default: + returnActionImage = "assets/images/request_info.svg"; + break; + } + + return returnActionImage; + } + + String getFabActionTitle(String title) { + String returnTitle = ""; + switch (title) { + case "Delegate": + returnTitle = "Delegate"; + break; + case "RequestInformation": + returnTitle = "Request Information"; + break; + case "ReportGenerated": + returnTitle = "Report Generated"; + break; + case "DataCorrected": + returnTitle = "Data Corrected"; + break; + case "Doable": + returnTitle = "Doable"; + break; + case "NotDoable": + returnTitle = "Not Doable"; + break; + default: + returnTitle = title; + break; + } + return returnTitle; + } + void handleFabAction(AllowedActions action) { print(action.toJson()); switch (action.action) { case "Delegate": - showMyBottomSheet(context, callBackFunc: reloadITG, - child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [], callBackFunc: reloadITG,)); + showMyBottomSheet(context, + callBackFunc: reloadITG, + child: DelegateSheet( + title: LocaleKeys.delegate.tr(), + apiMode: action.action!, + notificationID: null, + actionHistoryList: null, + wFHistory: itgRequest?.wFHistory ?? [], + callBackFunc: reloadITG, + )); break; case "RequestInformation": - showMyBottomSheet(context, callBackFunc: reloadITG, - child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [], callBackFunc: reloadITG,)); - + showMyBottomSheet(context, + callBackFunc: reloadITG, + child: DelegateSheet( + title: LocaleKeys.request_info.tr(), + apiMode: action.action!, + notificationID: null, + actionHistoryList: null, + wFHistory: itgRequest?.wFHistory ?? [], + callBackFunc: reloadITG, + )); break; + case "Doable": + performAction("APPROVED"); + break; + case "NotDoable": + performAction("REJECTED"); + break; + case "Answer": + performAction("Answer"); + break; + case "RFC": // do something else break; @@ -356,6 +441,8 @@ class _ItgDetailScreenState extends State { onTap: (note) { if (actionMode == "APPROVED") { performApproveAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); + } else if (actionMode == "Answer") { + performAnswerAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); } else { performRejectAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); } @@ -364,6 +451,30 @@ class _ItgDetailScreenState extends State { ); } + void performAnswerAction(String requestType, int taskId, int itemId, String employeeNumber, String comments) async { + try { + Utils.showLoading(context); + ITGRequest? itgRequest = await WorkListApiClient().answerITGRequest(requestType, taskId, itemId, employeeNumber, "", comments); + Utils.hideLoading(context); + Utils.showToast(LocaleKeys.yourChangeHasBeenSavedSuccessfully.tr()); + // Navigator.pop(context, "delegate_reload"); + AppState().requestAllList!.removeAt(AppState().itgWorkListIndex!); + if (AppState().requestAllList!.isEmpty) { + Navigator.pop(context, "delegate_reload"); + } else { + if (AppState().requestAllList!.length <= AppState().itgWorkListIndex!) { + Navigator.pop(context, "delegate_reload"); + } else { + requestDetails = null; + getDataFromState(); + } + } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + void performRejectAction(String requestType, int taskId, int itemId, String employeeNumber, String comments) async { try { Utils.showLoading(context); @@ -425,5 +536,4 @@ class _ItgDetailScreenState extends State { } } } - } diff --git a/lib/ui/work_list/itg_fragments/approval_level_fragment.dart b/lib/ui/work_list/itg_fragments/approval_level_fragment.dart index eb478af..52915ab 100644 --- a/lib/ui/work_list/itg_fragments/approval_level_fragment.dart +++ b/lib/ui/work_list/itg_fragments/approval_level_fragment.dart @@ -138,7 +138,8 @@ class ApprovalLevelfragment extends StatelessWidget { } else if (code.toLowerCase() == "approved" || code.toLowerCase() == "auto-approve" || code.toLowerCase() == "auto-approved" || - code.toLowerCase() == "doable") { + code.toLowerCase() == "doable" || + code.toLowerCase() == "answer") { return MyColors.greenColor; } else if (code.toLowerCase() == "requested information" || code.toLowerCase() == "assign" || code.toLowerCase() == "reassign") { return MyColors.orange; diff --git a/lib/ui/work_list/sheets/delegate_sheet.dart b/lib/ui/work_list/sheets/delegate_sheet.dart index 6d39fc8..2a5f453 100644 --- a/lib/ui/work_list/sheets/delegate_sheet.dart +++ b/lib/ui/work_list/sheets/delegate_sheet.dart @@ -47,6 +47,8 @@ class _DelegateSheetState extends State { List? favUsersList; List? replacementList; + bool isImageLoaded = false; + @override void initState() { super.initState(); @@ -99,7 +101,9 @@ class _DelegateSheetState extends State { if (isNeedLoading) Utils.showLoading(context); favUsersList = await WorkListApiClient().getFavoriteReplacementWithImageNew(selectedFavLetter ?? ""); if (isNeedLoading) Utils.hideLoading(context); - setState(() {}); + setState(() { + isImageLoaded = true; + }); return null; } @@ -410,6 +414,7 @@ class _DelegateSheetState extends State { apiMode: widget.apiMode, actionHistoryList: actionHistory, notificationID: widget.notificationID, + isITGRequest: widget.wFHistory != null, )); }, child: Row( @@ -483,6 +488,7 @@ class _DelegateSheetState extends State { apiMode: widget.apiMode, favoriteReplacements: actionHistory, notificationID: widget.notificationID, + isITGRequest: widget.wFHistory != null, )); }, child: Row( @@ -494,17 +500,23 @@ class _DelegateSheetState extends State { width: 40, isImageBase64: (actionHistory.employeeImage != null || actionHistory.employeeImage!.isNotEmpty) ? true : false, ) - : ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(50), - ), - child: Image.network( - "https://play-lh.googleusercontent.com/NPo88ojmhah4HDiposucJmfQIop4z4xc8kqJK9ITO9o-yCab2zxIp7PPB_XPj2iUojo", - fit: BoxFit.cover, - height: 40, - width: 40, - ).toShimmer(), - ), + : isImageLoaded + ? CircularAvatar( + height: 40, + width: 40, + isImageBase64: false, + ) + : ClipRRect( + borderRadius: const BorderRadius.all( + Radius.circular(50), + ), + child: Image.network( + "https://play-lh.googleusercontent.com/NPo88ojmhah4HDiposucJmfQIop4z4xc8kqJK9ITO9o-yCab2zxIp7PPB_XPj2iUojo", + fit: BoxFit.cover, + height: 40, + width: 40, + ).toShimmer(), + ), 16.width, Expanded( child: (actionHistory.employeeDisplayName ?? "").toText12(), @@ -542,6 +554,7 @@ class _DelegateSheetState extends State { apiMode: widget.apiMode, replacementList: actionHistory, notificationID: widget.notificationID, + isITGRequest: widget.wFHistory != null, )); }, child: Row( diff --git a/lib/ui/work_list/sheets/selected_item_sheet.dart b/lib/ui/work_list/sheets/selected_item_sheet.dart index 355fee6..4f7f6b3 100644 --- a/lib/ui/work_list/sheets/selected_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_item_sheet.dart @@ -1,12 +1,15 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; 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/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'; @@ -19,8 +22,11 @@ class SelectedItemSheet extends StatelessWidget { GetActionHistoryList? actionHistoryList; GetFavoriteReplacements? favoriteReplacements; ReplacementList? replacementList; + MemberInformationListModel? memberInformationListModel; - SelectedItemSheet(this.title, {required this.apiMode, this.notificationID, this.actionHistoryList, this.favoriteReplacements, this.replacementList}); + bool isITGRequest; + + SelectedItemSheet(this.title, {required this.apiMode, this.notificationID, this.actionHistoryList, this.favoriteReplacements, this.replacementList, this.isITGRequest = false}); TextEditingController username = TextEditingController(); String comment = ""; @@ -41,9 +47,9 @@ class SelectedItemSheet extends StatelessWidget { children: [ title.toText24(isBold: true), 21.height, - if (actionHistoryList != null) showItem(actionHistoryList!.nAME, actionHistoryList!.isFavorite), - if (favoriteReplacements != null) showItem(favoriteReplacements!.employeeDisplayName, true), - if (replacementList != null) showItem(replacementList!.employeeDisplayName, replacementList!.isFavorite), + if (actionHistoryList != null) showItem(actionHistoryList!.nAME, context, actionHistoryList!.isFavorite), + if (favoriteReplacements != null) showItem(favoriteReplacements!.employeeDisplayName, context, true), + if (replacementList != null) showItem(replacementList!.employeeDisplayName, context, replacementList!.isFavorite), 14.height, InputWidget( "Enter a note", @@ -97,7 +103,7 @@ class SelectedItemSheet extends StatelessWidget { email = replacementList!.emailAddress; userId = replacementList!.userName; } - performNetworkCall(context, email: email ?? "", userId: userId ?? ""); + isITGRequest ? performITGNetworkCall(context, email: email ?? "", userId: userId ?? "") : performNetworkCall(context, email: email ?? "", userId: userId ?? ""); } else { Utils.showToast("Please enter comments"); } @@ -115,10 +121,26 @@ class SelectedItemSheet extends StatelessWidget { ); } + void getUserInformation(BuildContext context) async { + String? empID = ""; + if (actionHistoryList != null) empID = actionHistoryList!.uSERNAME; + if (favoriteReplacements != null) empID = favoriteReplacements!.userName; + if (replacementList != null) empID = replacementList!.userName; + try { + memberInformationListModel = await WorkListApiClient().getUserInformation(-999, empID!); + if (actionHistoryList != null) empID = actionHistoryList!.eMPLOYEEIMAGE = memberInformationListModel!.eMPLOYEEIMAGE ?? AppState().getBase64ImageEmp; + if (favoriteReplacements != null) empID = favoriteReplacements!.employeeImage = memberInformationListModel!.eMPLOYEEIMAGE ?? AppState().getBase64ImageEmp; + if (replacementList != null) empID = replacementList!.employeeImage = memberInformationListModel!.eMPLOYEEIMAGE ?? AppState().getBase64ImageEmp; + (context as Element).markNeedsBuild(); + } catch (ex) { + Utils.handleException(ex, context, null); + } + } + Future performNetworkCall(BuildContext context, {String? email, String? userId}) async { Utils.showLoading(context); try { - await WorkListApiClient().submitComment(comment: comment, email: email, userId: userId, notificationId: notificationID, apiMode: apiMode); + await WorkListApiClient().submitComment(comment: comment, email: email, userId: userId, notificationId: notificationID, apiMode: apiMode, approverIndex: actionHistoryList!.sEQUENCE); Utils.hideLoading(context); // Navigator.pop(context); // Navigator.pop(context); @@ -129,7 +151,44 @@ class SelectedItemSheet extends StatelessWidget { } } - Widget showItem(String? name, bool? isFav) { + Future performITGNetworkCall(BuildContext context, {String? email, String? userId}) async { + Utils.showLoading(context); + try { + var requestDetails = AppState().requestAllList![AppState().itgWorkListIndex!]; + if (apiMode == "Delegate") { + await WorkListApiClient().delegateITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", + isITGRequest ? favoriteReplacements!.userName! : actionHistoryList!.uSERNAME!, comment); + } else if (apiMode == "RequestInformation") { + await WorkListApiClient().informationITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", + isITGRequest ? favoriteReplacements!.userName! : actionHistoryList!.uSERNAME!, comment); + } else if (apiMode == "Answer") { + await WorkListApiClient().answerITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", + isITGRequest ? favoriteReplacements!.userName! : actionHistoryList!.uSERNAME!, comment); + } + Utils.hideLoading(context); + Navigator.pop(context, "delegate_reload"); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + Widget showItem(String? name, BuildContext context, bool? isFav) { + if (actionHistoryList != null) { + if (actionHistoryList!.eMPLOYEEIMAGE == null || actionHistoryList!.eMPLOYEEIMAGE == "") { + // getUserInformation(context); + } + } + if (favoriteReplacements != null) { + if (favoriteReplacements!.employeeImage == null || favoriteReplacements!.employeeImage == "") { + // getUserInformation(context); + } + } + if (replacementList != null) { + if (replacementList!.employeeImage == null || replacementList!.employeeImage == "") { + // getUserInformation(context); + } + } return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), @@ -142,13 +201,18 @@ class SelectedItemSheet extends StatelessWidget { padding: const EdgeInsets.only(top: 16, bottom: 16, left: 21, right: 21), child: Row( children: [ - (isFav != null && isFav) - ? CircularAvatar( - height: 40, - width: 40, - url: favoriteReplacements != null ? favoriteReplacements!.employeeImage : actionHistoryList!.eMPLOYEEIMAGE, - isImageBase64: true, - ) + (isFav != null && isFav && favoriteReplacements != null) + ? favoriteReplacements!.employeeImage != "" + ? CircularAvatar( + height: 40, + width: 40, + url: favoriteReplacements != null ? favoriteReplacements!.employeeImage : actionHistoryList!.eMPLOYEEIMAGE, + isImageBase64: true, + ) + : CircularAvatar( + height: 40, + width: 40, + ).toShimmer() : (actionHistoryList != null && actionHistoryList!.eMPLOYEEIMAGE != null) ? CircularAvatar( height: 40, @@ -159,7 +223,7 @@ class SelectedItemSheet extends StatelessWidget { : CircularAvatar( height: 40, width: 40, - ), + ).toShimmer(), 16.width, Expanded( child: (name ?? "").toText12(), diff --git a/lib/ui/work_list/sheets/selected_itg_item_sheet.dart b/lib/ui/work_list/sheets/selected_itg_item_sheet.dart index f44ca04..e836a07 100644 --- a/lib/ui/work_list/sheets/selected_itg_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_itg_item_sheet.dart @@ -126,10 +126,11 @@ class SelectedItgItemSheet extends StatelessWidget { } else if (apiMode == "RequestInformation") { await WorkListApiClient() .informationITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); + } else if (apiMode == "Answer") { + await WorkListApiClient() + .answerITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); } Utils.hideLoading(context); - // Navigator.pop(context); - // Navigator.pop(context); Navigator.pop(context, "delegate_reload"); } catch (ex) { Utils.hideLoading(context); diff --git a/lib/ui/work_list/sheets/update_continue_sheet.dart b/lib/ui/work_list/sheets/update_continue_sheet.dart new file mode 100644 index 0000000..169e12e --- /dev/null +++ b/lib/ui/work_list/sheets/update_continue_sheet.dart @@ -0,0 +1,131 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/my_attendance_api_client.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/worklist/hr/eit_otification_body_model.dart'; +import 'package:mohem_flutter_app/models/worklist/resubmit_eit_response_model.dart'; +import 'package:mohem_flutter_app/models/worklist_response_model.dart'; +import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart'; +import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; + +class UpdateContinueSheet extends StatefulWidget { + WorkListResponseModel? workListData; + List? getEitCollectionNotificationBodyList; + DynamicListViewParams? dynamicParams; + + UpdateContinueSheet({this.workListData, this.getEitCollectionNotificationBodyList, this.dynamicParams, Key? key}) : super(key: key); + + @override + State createState() => _UpdateContinueSheetState(); +} + +class _UpdateContinueSheetState extends State { + double itemHeight = 0; + double itemWidth = 0; + + @override + Widget build(BuildContext context) { + var size = MediaQuery.of(context).size; + itemHeight = (size.height - kToolbarHeight - 24) / 9; + itemWidth = size.width / 2; + return Column( + children: [ + if ((widget.workListData?.sUBJECT ?? "").isNotEmpty) widget.workListData!.sUBJECT!.toText14().paddingOnly(top: 10, right: 21, left: 21, bottom: 21), + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (cxt, index) { + List dataList = widget.getEitCollectionNotificationBodyList!.isEmpty ? [] : (widget.getEitCollectionNotificationBodyList![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: widget.getEitCollectionNotificationBodyList!.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, + ], + ), + ), + ], + ); + } + + void performNextAction() async { + //Resubmit EIT Transaction + try { + Utils.showLoading(context); + List> values = []; + for (GetEitCollectionNotificationBodyList element in widget.getEitCollectionNotificationBodyList!) { + for (CollectionNotificationEit collectionElement in element.collectionNotification!) { + values.add({ + "TRANSACTION_NUMBER": collectionElement.transactionNumber, + "NAME": collectionElement.applicationColumnName, + "VARCHAR2_VALUE": collectionElement.varchar2Value, + "NUMBER_VALUE": collectionElement.numberValue, + "DATE_VALUE": collectionElement.dateValue, + }); + } + } + ResubmitEITRequestResponse resubmitEITRequestResponse = await MyAttendanceApiClient().reSubmitEitTransaction(widget.workListData!.iTEMKEY!, widget.workListData!.nOTIFICATIONID, values); + Utils.hideLoading(context); + await Navigator.pushNamed( + context, + AppRoutes.requestSubmitScreen, + arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), resubmitEITRequestResponse.pTRANSACTIONID!, widget.workListData!.iTEMKEY!, 'eit'), + ); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + void performEditAction() { + //Open EIT Edit Screen + + Navigator.pushNamed(context, AppRoutes.addDynamicInput, arguments: widget.dynamicParams); + } +} diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 1d5931d..262ec4f 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -23,12 +23,16 @@ import 'package:mohem_flutter_app/models/get_stamp_ms_notification_body_list_mod import 'package:mohem_flutter_app/models/get_stamp_ns_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist_response_model.dart'; +import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/ui/work_list/sheets/delegate_sheet.dart'; +import 'package:mohem_flutter_app/ui/work_list/sheets/selected_item_sheet.dart'; +import 'package:mohem_flutter_app/ui/work_list/sheets/update_continue_sheet.dart'; import 'package:mohem_flutter_app/ui/work_list/worklist_fragments/actions_fragment.dart'; import 'package:mohem_flutter_app/ui/work_list/worklist_fragments/attachments_fragment.dart'; import 'package:mohem_flutter_app/ui/work_list/worklist_fragments/detail_fragment.dart'; @@ -65,6 +69,8 @@ class _WorkListDetailScreenState extends State { List getNotificationRespondAttributes = []; NotificationGetRespondAttributesList? notificationNoteInput; + List getRFCEmployeeList = []; + //HR Details Screen Requests List? getEitCollectionNotificationBodyList = []; List? getPhonesNotificationBodyList = []; @@ -375,57 +381,115 @@ class _WorkListDetailScreenState extends State { } fabs.add(myFab( notificationButtonsList[i].bUTTONLABEL!, - notificationButtonsList[i].bUTTONACTION == "DELEGATE" ? "assets/images/delegate.svg" : notificationButtonsList[i].bUTTONICON ?? "", - isIconAsset: notificationButtonsList[i].bUTTONACTION == "DELEGATE" ? true : false, + getActionImage(notificationButtonsList[i].bUTTONACTION!), + isIconAsset: true, ).paddingOnly(bottom: 12).onPress(() => handleFabAction(notificationButtonsList[i]))); } return fabs; } + String getActionImage(String action) { + String returnActionImage = ""; + + switch (action) { + case "DELEGATE": + returnActionImage = "assets/images/delegate.svg"; + break; + case "REQUEST_INFO": + returnActionImage = "assets/images/request_info.svg"; + break; + case "RFC": + returnActionImage = "assets/images/worklist/return.svg"; + break; + case "UPDATE_ACTION": + returnActionImage = "assets/images/worklist/update_action.svg"; + break; + } + + return returnActionImage; + } + void handleFabAction(GetNotificationButtonsList notificationButton) { print("notificationButton:${notificationButton.bUTTONACTION}"); switch (notificationButton.bUTTONACTION) { case "DELEGATE": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); + child: DelegateSheet( + title: LocaleKeys.delegate.tr(), + apiMode: notificationButton.bUTTONACTION!, + notificationID: workListData!.nOTIFICATIONID, + actionHistoryList: actionHistoryList, + callBackFunc: reloadWorkList, + )); break; case "REQUEST_INFO": // do something else showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); + child: DelegateSheet( + title: LocaleKeys.request_info.tr(), + apiMode: "REQUEST_INFO", + notificationID: workListData!.nOTIFICATIONID, + actionHistoryList: actionHistoryList, + callBackFunc: reloadWorkList, + )); break; case "TRANSFER_INFO": // do something else showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: - DelegateSheet(title: notificationButton.bUTTONLABEL!, apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); + child: DelegateSheet( + title: notificationButton.bUTTONLABEL!, + apiMode: notificationButton.bUTTONACTION!, + notificationID: workListData!.nOTIFICATIONID, + actionHistoryList: actionHistoryList, + callBackFunc: reloadWorkList, + )); break; case "ANSWER_INFO": performAction(notificationButton.bUTTONACTION!, title: notificationButton.bUTTONLABEL); break; case "RFC": - // do something else + getRFCEmployeeListFunc(); break; case "APPROVE": performAction(notificationButton.bUTTONACTION!); break; case "UPDATE_ACTION": - // do something else + showMyBottomSheet( + context, + callBackFunc: reloadWorkList, + child: UpdateContinueSheet( + workListData: workListData, + getEitCollectionNotificationBodyList: getEitCollectionNotificationBodyList, + dynamicParams: DynamicListViewParams(workListData!.sUBJECT!, workListData!.fUNCTIONNAME!, + isUpdate: true, collectionNotificationList: getEitCollectionNotificationBodyList![0].collectionNotification)), + ); + break; case "APPROVE_AND_FORWARD": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: "Approve and Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); + child: DelegateSheet( + title: "Approve and Forward", + apiMode: notificationButton.bUTTONACTION!, + notificationID: workListData!.nOTIFICATIONID, + actionHistoryList: actionHistoryList, + callBackFunc: reloadWorkList, + )); break; case "FORWARD": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); + child: DelegateSheet( + title: "Forward", + apiMode: notificationButton.bUTTONACTION!, + notificationID: workListData!.nOTIFICATIONID, + actionHistoryList: actionHistoryList, + callBackFunc: reloadWorkList, + )); break; case "REJECT": - // performNetworkCall(context, email: "", userId: ""); performAction(notificationButton.bUTTONACTION!); break; case "RETURNED": @@ -437,6 +501,28 @@ class _WorkListDetailScreenState extends State { }); } + void getRFCEmployeeListFunc() async { + try { + Utils.showLoading(context); + getRFCEmployeeList = await WorkListApiClient().getRFCEmployeeeList(workListData!.nOTIFICATIONID!); + Utils.hideLoading(context); + actionHistoryList.last.sEQUENCE = getRFCEmployeeList[0].sEQ; + showMyBottomSheet(context, + callBackFunc: reloadWorkList, + child: SelectedItemSheet( + "Comment", + apiMode: "RFC", + actionHistoryList: actionHistoryList.last, + notificationID: workListData!.nOTIFICATIONID, + isITGRequest: false, + )); + setState(() {}); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + Future performNetworkCall(BuildContext context, {String? email, String? userId}) async { showDialog( context: context, @@ -543,7 +629,7 @@ class _WorkListDetailScreenState extends State { } ], }; - if (actionMode == "APPROVED" || actionMode == "APPROVE" || actionMode == "CLOSE") { + if (actionMode == "APPROVED" || actionMode == "APPROVE" || actionMode == "CLOSE" || actionMode == "ANSWER_INFO" || actionMode == "RFC") { performNotificationAction(payload); } else if (note.isNotEmpty && (actionMode != "APPROVED" || actionMode != "APPROVE")) { performNotificationAction(payload); @@ -867,6 +953,71 @@ class _WorkListDetailScreenState extends State { } } + // Widget showUpdateContinueSheet(List 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 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', diff --git a/lib/widgets/dialogs/accept_reject_input_dialog.dart b/lib/widgets/dialogs/accept_reject_input_dialog.dart index e335453..ac5db05 100644 --- a/lib/widgets/dialogs/accept_reject_input_dialog.dart +++ b/lib/widgets/dialogs/accept_reject_input_dialog.dart @@ -91,12 +91,15 @@ class AcceptRejectInputDialog extends StatelessWidget { (actionMode == "REJECTED" || actionMode == "REJECT") ? LocaleKeys.reject.tr() : LocaleKeys.ok.tr(), () { if (note.isEmpty) { - if (actionMode != "REJECTED" || actionMode != "REJECT") { + if ((actionMode != "REJECTED" && actionMode != "REJECT") && actionMode != "ANSWER_INFO" && actionMode != "RFC") { Navigator.pop(context); onTap(note); } else { Utils.showToast(LocaleKeys.pleaseEnterComments.tr()); } + } else { + Navigator.pop(context); + onTap(note); } }, colors: (actionMode == "REJECTED" || actionMode == "REJECT") diff --git a/pubspec.yaml b/pubspec.yaml index 16c5737..40fd3bc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -127,6 +127,7 @@ flutter: - assets/lottie/ - assets/audio/ - assets/images/ + - assets/images/worklist/ - assets/images/login/ - assets/icons/chat/ - assets/images/logos/ From 89812c0f726a9772b3cacd45117e9c6e885ced94 Mon Sep 17 00:00:00 2001 From: Sultan khan <> Date: Wed, 9 Nov 2022 17:10:12 +0300 Subject: [PATCH 13/82] Worklist changes --- .../dynamic_screens/dynamic_input_screen.dart | 100 ++++++++++-------- .../dynamic_input_address_screen.dart | 2 +- .../sheets/update_continue_sheet.dart | 32 +++--- 3 files changed, 78 insertions(+), 56 deletions(-) diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 9aafdd8..c0fbc2b 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -48,6 +48,17 @@ class _DynamicInputScreenState extends State { descFlexConTextTitle = genericResponseModel!.pDESCFLEXCONTEXTNAME ?? ""; getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; //getEitDffStructureList = getEitDffStructureList!.where((element) => element.dISPLAYFLAG != "N").toList(); + if (dynamicParams!.collectionNotificationList != null && dynamicParams!.collectionNotificationList!.isNotEmpty) { + getEitDffStructureList!.forEach((element) { + dynamicParams!.collectionNotificationList!.forEach((element2) { + if (element.sEGMENTNAME == element2.segmentName) { + element.fieldAnswer = element2.varchar2Value; + element.eSERVICESDV ??= ESERVICESDV(); + element.eSERVICESDV!.pIDCOLUMNNAME = element2.varchar2Value; + } + }); + }); + } Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -57,51 +68,56 @@ class _DynamicInputScreenState extends State { } void validateTransaction() async { - /// try { - Utils.showLoading(context); - List> values = getEitDffStructureList!.map((e) { - String tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; - if (e.fORMATTYPE == "X") { - // for date format type, date format is changed - tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; - if (tempVar.isNotEmpty) { - if (!tempVar.contains("/")) { - DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); + try { + Utils.showLoading(context); + List> values = getEitDffStructureList!.map((e) { + String tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; + if (e.fORMATTYPE == "X") { + // for date format type, date format is changed + tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; + if (tempVar.isNotEmpty) { + if (!tempVar.contains("/")) { + DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); + tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); + } } } + // else if (e.fORMATTYPE == "N") { + // // for date format type, date format is changed + // tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; + // print("------------------------sEGMENTNAME:${e.sEGMENTNAME}"); + // print("------------------------tempVar:$tempVar"); + // if (tempVar.isNotEmpty) { + // if (!tempVar.contains("/")) { + // DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); + // tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); + // } + // } + // } + return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: tempVar.toString()).toJson(); + }).toList(); + + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_ACTION", nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: "NEW_ROW").toJson()); + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_EXTRA_INFO_ID", nUMBERVALUE: -1, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); + values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); + + genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); + if (dynamicParams!.collectionNotificationList != null && dynamicParams!.collectionNotificationList!.isNotEmpty) { + Utils.hideLoading(context); + Navigator.pop(context, values); + return; } - // else if (e.fORMATTYPE == "N") { - // // for date format type, date format is changed - // tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; - // print("------------------------sEGMENTNAME:${e.sEGMENTNAME}"); - // print("------------------------tempVar:$tempVar"); - // if (tempVar.isNotEmpty) { - // if (!tempVar.contains("/")) { - // DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - // tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date); - // } - // } - // } - return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: tempVar.toString()).toJson(); - }).toList(); - - values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_ACTION", nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: "NEW_ROW").toJson()); - values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_EXTRA_INFO_ID", nUMBERVALUE: -1, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); - values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); - - genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); - SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); - Utils.hideLoading(context); - await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, - arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit')); - Utils.showLoading(context); - await LeaveBalanceApiClient().cancelHrTransaction(submitEITTransactionList.pTRANSACTIONID!); - Utils.hideLoading(context); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); + Utils.hideLoading(context); + await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, + arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit')); + Utils.showLoading(context); + await LeaveBalanceApiClient().cancelHrTransaction(submitEITTransactionList.pTRANSACTIONID!); + Utils.hideLoading(context); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } String dESCFLEXCONTEXTCODE = ""; diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart index ecc2426..226eae9 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart @@ -88,7 +88,7 @@ class _DynamicInputScreenState extends State { getAddressDffStructureList! .insert(1, GetAddressDffStructureList(fORMATTYPE: 'C', sEGMENTPROMPT: LocaleKeys.profile_country.tr(), eSERVICESVS: eSerivceList, getEmployeeAddressList: GetEmployeeAddressList())); } - print(getAddressDffStructureList); + // genericResponseModel = await ProfileApiClient().getColStructure(dynamicParams!.dynamicId, 'GET_BASIC_DET_COLS_STRUCTURE', dynamicParams!.requestID); // getBasicDetColsStructureList = genericResponseModel?.getBasicDetColsStructureList ?? []; // getBasicDetColsStructureList?.forEach((element) { diff --git a/lib/ui/work_list/sheets/update_continue_sheet.dart b/lib/ui/work_list/sheets/update_continue_sheet.dart index 169e12e..1e4e5f3 100644 --- a/lib/ui/work_list/sheets/update_continue_sheet.dart +++ b/lib/ui/work_list/sheets/update_continue_sheet.dart @@ -29,7 +29,7 @@ class UpdateContinueSheet extends StatefulWidget { class _UpdateContinueSheetState extends State { double itemHeight = 0; double itemWidth = 0; - + List> validatedValues = []; @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; @@ -99,17 +99,22 @@ class _UpdateContinueSheetState extends State { try { Utils.showLoading(context); List> values = []; - for (GetEitCollectionNotificationBodyList element in widget.getEitCollectionNotificationBodyList!) { - for (CollectionNotificationEit collectionElement in element.collectionNotification!) { - values.add({ - "TRANSACTION_NUMBER": collectionElement.transactionNumber, - "NAME": collectionElement.applicationColumnName, - "VARCHAR2_VALUE": collectionElement.varchar2Value, - "NUMBER_VALUE": collectionElement.numberValue, - "DATE_VALUE": collectionElement.dateValue, - }); + if (validatedValues!.isNotEmpty) { + values = validatedValues; + } else { + for (GetEitCollectionNotificationBodyList element in widget.getEitCollectionNotificationBodyList!) { + for (CollectionNotificationEit collectionElement in element.collectionNotification!) { + values.add({ + "TRANSACTION_NUMBER": collectionElement.transactionNumber, + "NAME": collectionElement.applicationColumnName, + "VARCHAR2_VALUE": collectionElement.varchar2Value, + "NUMBER_VALUE": collectionElement.numberValue, + "DATE_VALUE": collectionElement.dateValue, + }); + } } } + ResubmitEITRequestResponse resubmitEITRequestResponse = await MyAttendanceApiClient().reSubmitEitTransaction(widget.workListData!.iTEMKEY!, widget.workListData!.nOTIFICATIONID, values); Utils.hideLoading(context); await Navigator.pushNamed( @@ -124,8 +129,9 @@ class _UpdateContinueSheetState extends State { } void performEditAction() { - //Open EIT Edit Screen - - Navigator.pushNamed(context, AppRoutes.addDynamicInput, arguments: widget.dynamicParams); + // ignore: avoid_annotating_with_dynamic + Navigator.pushNamed(context, AppRoutes.addDynamicInput, arguments: widget.dynamicParams).then((dynamic value) { + validatedValues = value; + }); } } From 3be279d57197c11c54237d8965a3b61435f2b52e Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 9 Nov 2022 18:00:26 +0300 Subject: [PATCH 14/82] Worklist images added --- lib/ui/work_list/itg_detail_screen.dart | 18 +++++++----------- lib/ui/work_list/worklist_detail_screen.dart | 9 +++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index b215435..0a29a72 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -274,16 +274,19 @@ class _ItgDetailScreenState extends State { returnActionImage = "assets/images/request_info.svg"; break; case "ReportGenerated": - returnActionImage = "assets/images/request_info.svg"; + returnActionImage = "assets/images/worklist/report_generated.svg"; break; case "DataCorrected": - returnActionImage = "assets/images/request_info.svg"; + returnActionImage = "assets/images/worklist/report_generated.svg"; break; case "Doable": - returnActionImage = "assets/images/request_info.svg"; + returnActionImage = "assets/images/worklist/doable.svg"; break; case "NotDoable": - returnActionImage = "assets/images/request_info.svg"; + returnActionImage = "assets/images/worklist/not_doable.svg"; + break; + case "Answer": + returnActionImage = "assets/images/worklist/answer_hr.svg"; break; default: returnActionImage = "assets/images/request_info.svg"; @@ -358,13 +361,6 @@ class _ItgDetailScreenState extends State { case "Answer": performAction("Answer"); break; - - case "RFC": - // do something else - break; - case "UPDATE_ACTION": - // do something else - break; } setState(() { showFabOptions = false; diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 262ec4f..3c05204 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -404,6 +404,15 @@ class _WorkListDetailScreenState extends State { case "UPDATE_ACTION": returnActionImage = "assets/images/worklist/update_action.svg"; break; + case "APPROVE_AND_FORWARD": + returnActionImage = "assets/images/worklist/approve_and_forward.svg"; + break; + case "FORWARD": + returnActionImage = "assets/images/worklist/forward.svg"; + break; + default: + returnActionImage = "assets/images/request_info.svg"; + break; } return returnActionImage; From 22ac89e74435f182da5fe6f1d5c1174db4e54520 Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Thu, 10 Nov 2022 09:45:29 +0300 Subject: [PATCH 15/82] fix issues --- lib/classes/consts.dart | 4 +- lib/models/generic_response_model.dart | 2 +- .../attendance/add_vacation_rule_screen.dart | 2 +- .../dynamic_screens/dynamic_input_screen.dart | 37 ++++++++++--------- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index eea2481..6276213 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 2c8e98f..cf799fd 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -1273,7 +1273,7 @@ class GenericResponseModel { if (json['RespondRolesList'] != null) { respondRolesList = []; json['RespondRolesList'].forEach((v) { - respondRolesList!.add(v); + // respondRolesList!.add(v); }); } resubmitAbsenceTransactionList = json['ResubmitAbsenceTransactionList']; diff --git a/lib/ui/attendance/add_vacation_rule_screen.dart b/lib/ui/attendance/add_vacation_rule_screen.dart index a698adc..caa1ee3 100644 --- a/lib/ui/attendance/add_vacation_rule_screen.dart +++ b/lib/ui/attendance/add_vacation_rule_screen.dart @@ -98,7 +98,7 @@ class _AddVacationRuleScreenState extends State { } void callCombineApis() async { - try { + try { Utils.showLoading(context); List results = await Future.wait([ VacationRuleApiClient().getNotificationReassignMode(), diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 519bb6c..f71e6f1 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -57,7 +57,7 @@ class _DynamicInputScreenState extends State { } void validateTransaction() async { - try { + // try { Utils.showLoading(context); List> values = getEitDffStructureList!.map((e) { String tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; @@ -98,10 +98,10 @@ class _DynamicInputScreenState extends State { Utils.showLoading(context); await LeaveBalanceApiClient().cancelHrTransaction(submitEITTransactionList.pTRANSACTIONID!); Utils.hideLoading(context); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - } + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // } } String dESCFLEXCONTEXTCODE = ""; @@ -136,7 +136,7 @@ class _DynamicInputScreenState extends State { } Future getDefaultValues(GetEITDFFStructureList structureList) async { - try { + // try { Utils.showLoading(context); for (int i = 0; i < (structureList.cHILDSEGMENTSDVSplited?.length ?? 0); i++) { String segmentId = structureList.cHILDSEGMENTSDVSplited![i]; @@ -163,10 +163,10 @@ class _DynamicInputScreenState extends State { await Future.delayed(const Duration(seconds: 1)); Utils.hideLoading(context); setState(() {}); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - } + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // } } // List> calGetValueSetValuesIonicLogic(GetEITDFFStructureList structureElement) { @@ -180,7 +180,7 @@ class _DynamicInputScreenState extends State { // } List> getDefaultValuesIonicLogic(GetEITDFFStructureList structureElement) { - try { + // try { List parentValue = structureElement.pARENTSEGMENTSVSSplitedVS ?? []; List parentsList = structureElement.pARENTSEGMENTSDVSplited ?? []; @@ -248,11 +248,11 @@ class _DynamicInputScreenState extends State { // } // Utils.hideLoading(context); // setState(() {}); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - return []; - } + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // return []; + // } } List> getDependenciesParams(parentsList) { @@ -340,7 +340,7 @@ class _DynamicInputScreenState extends State { String? text = data?.pVALUECOLUMNNAME; String? val = data?.pIDCOLUMNNAME; - if ((val ?? "").isEmpty && parentsList[i].IsRequired == "REQUIRED") { + if ((val ?? "").isEmpty && parentsList[i].isRequired == "REQUIRED") { //alert(parentsList[i].Name +" Is required"); return []; } else {} @@ -362,7 +362,8 @@ class _DynamicInputScreenState extends State { String? text = data?.pVALUECOLUMNNAME; String? val = data?.pIDCOLUMNNAME; - if ((val ?? "").isEmpty && parentsList[i].IsRequired == "REQUIRED") { + /// + if ((val ?? "").isEmpty && parentsList[i].isRequired == "REQUIRED") { //alert(parentsList[i].Name +" Is required"); return []; } else {} From 4d0d3a980eeab4acacd10a2d97059e9b2dc83cd6 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 10 Nov 2022 10:44:15 +0300 Subject: [PATCH 16/82] Item history updated --- lib/ui/work_list/item_history_screen.dart | 48 ++++++++++++++++------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/lib/ui/work_list/item_history_screen.dart b/lib/ui/work_list/item_history_screen.dart index 6cf80ca..782e34d 100644 --- a/lib/ui/work_list/item_history_screen.dart +++ b/lib/ui/work_list/item_history_screen.dart @@ -131,21 +131,39 @@ class _ItemHistoryScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - ItemDetailView(LocaleKeys.operatingUnit.tr(), poItemHistoryList[index].oUNAME ?? ""), - ItemDetailView(LocaleKeys.poNumber.tr(), poItemHistoryList[index].pONUMBER ?? ""), - ItemDetailView(LocaleKeys.revision.tr(), poItemHistoryList[index].rEVISIONNUM?.toString() ?? ""), - ItemDetailView(LocaleKeys.creationDate.tr(), poItemHistoryList[index].cREATIONDATE ?? ""), - ItemDetailView(LocaleKeys.supplier.tr(), poItemHistoryList[index].sUPPLIER ?? ""), - ItemDetailView(LocaleKeys.buyer.tr(), poItemHistoryList[index].bUYER ?? ""), - ItemDetailView(LocaleKeys.uom.tr(), poItemHistoryList[index].uOM ?? ""), - ItemDetailView(LocaleKeys.quantityOrdered.tr(), poItemHistoryList[index].qUANTITYORDERED?.toString() ?? ""), - ItemDetailView(LocaleKeys.quantityReceived.tr(), poItemHistoryList[index].qUANTITYRECEIVED?.toString() ?? ""), - ItemDetailView(LocaleKeys.bonusQuantity.tr(), poItemHistoryList[index].bONUSQUANTITY?.toString() ?? ""), - ItemDetailView(LocaleKeys.purchasePrice.tr(), poItemHistoryList[index].pURCHASEPRICE?.toString() ?? ""), - ItemDetailView(LocaleKeys.discountPer.tr(), poItemHistoryList[index].dISCOUNTPERCENTAGE?.toString() ?? ""), - ItemDetailView(LocaleKeys.balanceQuantity.tr(), poItemHistoryList[index].bALANCEQUANTITY?.toString() ?? ""), - ItemDetailView(LocaleKeys.netPrice.tr(), poItemHistoryList[index].nETPRICE?.toString() ?? ""), - ItemDetailView(LocaleKeys.closureStatus.tr(), poItemHistoryList[index].cLOSEDCODE ?? ""), + // ItemDetailGrid( + // ItemDetailViewCol(LocaleKeys.from.tr(), workListData!.fROMUSER ?? ""), + // ItemDetailViewCol(LocaleKeys.to.tr(), workListData!.tOUSER ?? ""), + // ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.operatingUnit.tr(), poItemHistoryList[index].oUNAME ?? ""), + ItemDetailViewCol(LocaleKeys.poNumber.tr(), poItemHistoryList[index].pONUMBER ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.revision.tr(), poItemHistoryList[index].rEVISIONNUM?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.creationDate.tr(), poItemHistoryList[index].cREATIONDATE ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.supplier.tr(), poItemHistoryList[index].sUPPLIER ?? ""), + ItemDetailViewCol(LocaleKeys.buyer.tr(), poItemHistoryList[index].bUYER ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.uom.tr(), poItemHistoryList[index].uOM ?? ""), + ItemDetailViewCol(LocaleKeys.quantityOrdered.tr(), poItemHistoryList[index].qUANTITYORDERED?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.quantityReceived.tr(), poItemHistoryList[index].qUANTITYRECEIVED?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.bonusQuantity.tr(), poItemHistoryList[index].bONUSQUANTITY?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.purchasePrice.tr(), poItemHistoryList[index].pURCHASEPRICE?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.discountPer.tr(), poItemHistoryList[index].dISCOUNTPERCENTAGE?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.balanceQuantity.tr(), poItemHistoryList[index].bALANCEQUANTITY?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.netPrice.tr(), poItemHistoryList[index].nETPRICE?.toString() ?? ""), + ), + ItemDetailGrid(ItemDetailViewCol(LocaleKeys.closureStatus.tr(), poItemHistoryList[index].cLOSEDCODE ?? ""), Container(), isItLast: true,) ], ).objectContainerView(), separatorBuilder: (cxt, index) => 12.height, From c22556d9b6afae97cf514ce7c63ac4674baa7484 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 10 Nov 2022 15:43:28 +0300 Subject: [PATCH 17/82] fixes --- lib/classes/consts.dart | 4 +- lib/main.dart | 6 ++ lib/ui/dialogs/success_dialog.dart | 2 +- lib/ui/landing/dashboard_screen.dart | 4 +- lib/ui/landing/widget/services_widget.dart | 90 ++++++++++++++++++- .../fragments/add_details_fragment.dart | 6 +- .../fragments/item_review_fragment.dart | 2 + pubspec.yaml | 1 + 8 files changed, 107 insertions(+), 8 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 6276213..eea2481 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/main.dart b/lib/main.dart index adca4aa..a2ae0ae 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -92,6 +92,12 @@ class MyApp extends StatelessWidget { MonthYearPickerLocalizations.delegate, ); return MaterialApp( + builder: (BuildContext context, Widget? child) { + return MediaQuery( + data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), + child: child!, + ); + }, theme: AppTheme.getTheme( EasyLocalization.of(context)?.locale.languageCode == "ar", ), diff --git a/lib/ui/dialogs/success_dialog.dart b/lib/ui/dialogs/success_dialog.dart index 5150110..a5df64f 100644 --- a/lib/ui/dialogs/success_dialog.dart +++ b/lib/ui/dialogs/success_dialog.dart @@ -53,8 +53,8 @@ class _SuccessDialogState extends State with TickerProviderStateM repeat: false, reverse: false, controller: _controller, + frameRate: FrameRate(60.0), onLoaded: (LottieComposition v) async { - print("calling_lottie " + v.seconds.toString()); await playSuccessSound(); _controller ..duration = v.duration diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index d342072..b49b98b 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -256,7 +256,7 @@ class _DashboardScreenState extends State { margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0), width: 45, height: 45, - padding: const EdgeInsets.only(left: 14, right: 14), + padding: const EdgeInsets.only(left: 10, right: 10), decoration: BoxDecoration( color: Color(0xff259EA4), borderRadius: BorderRadius.only( @@ -296,7 +296,7 @@ class _DashboardScreenState extends State { ), ], ).paddingOnly(left: 21, right: 21, top: 7), - MarathonBanner().paddingAll(20), + const MarathonBanner().paddingAll(20), ServicesWidget(), // 8.height, Container( diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 0b257c5..ae24dde 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -39,7 +39,7 @@ class ServicesWidget extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, - children: [ + children: [ data.homeMenus![parentIndex].menuEntry.prompt!.toSectionHeading().paddingOnly(left: 21, right: 21), SizedBox( height: 105 + 26, @@ -69,7 +69,7 @@ class ServicesWidget extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SvgPicture.asset(iconT[index]), + SvgPicture.asset(AppState().isArabic(context) ? getMenuIconAr(data.homeMenus![parentIndex].menuEntiesList[index].prompt!) : getMenuIconEn(data.homeMenus![parentIndex].menuEntiesList[index].prompt!)), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -102,6 +102,92 @@ class ServicesWidget extends StatelessWidget { ); } + String getMenuIconAr(String name) { + String returnImage = ""; + switch (name) { + case "الحضور الشهري": + returnImage = "assets/images/services_icons/monthly_attendance.svg"; + break; + case "كشف الراتب": + returnImage = "assets/images/services_icons/payslips.svg"; + break; + case "تغيير معلومات البنك": + returnImage = "assets/images/services_icons/change_bank_details.svg"; + break; + case "طلب بدل السكن مقدما": + returnImage = "assets/images/services_icons/housing_allowance.svg"; + break; + case "شهادات تعريف الموظف": + returnImage = "assets/images/services_icons/employee_certificates.svg"; + break; + case "البيانات الشخصية": + returnImage = "assets/images/personal-info.svg"; + break; + case "الحضور": + returnImage = "assets/images/services_icons/my_attendance.svg"; + break; + case "طلبات أخرى": + returnImage = "assets/images/services_icons/other_requests.svg"; + break; + case "الإجازات": + returnImage = "assets/images/services_icons/my_leaves.svg"; + break; + case "طلب تذكرة": + returnImage = "assets/images/services_icons/ticket_bal.svg"; + break; + case "قاعدة الاجازات": + returnImage = "assets/images/services_icons/vacation_rule.svg"; + break; + default: + returnImage = "assets/images/monthly_attendance.svg"; + break; + } + return returnImage; + } + + String getMenuIconEn(String name) { + String returnImage = ""; + switch (name) { + case "Monthly Attendance": + returnImage = "assets/images/services_icons/monthly_attendance.svg"; + break; + case "Payslip": + returnImage = "assets/images/services_icons/payslips.svg"; + break; + case "Change Bank Details": + returnImage = "assets/images/services_icons/change_bank_details.svg"; + break; + case "Housing Advance": + returnImage = "assets/images/services_icons/housing_allowance.svg"; + break; + case "Employee Certificate": + returnImage = "assets/images/services_icons/employee_certificates.svg"; + break; + case "Personal Information": + returnImage = "assets/images/personal-info.svg"; + break; + case "My Attendance": + returnImage = "assets/images/services_icons/my_attendance.svg"; + break; + case "Other Requests": + returnImage = "assets/images/services_icons/other_requests.svg"; + break; + case "My Leave": + returnImage = "assets/images/services_icons/my_leaves.svg"; + break; + case "Ticket Request": + returnImage = "assets/images/services_icons/ticket_bal.svg"; + break; + case "Vacation Rule": + returnImage = "assets/images/services_icons/vacation_rule.svg"; + break; + default: + returnImage = "assets/images/monthly_attendance.svg"; + break; + } + return returnImage; + } + void handleOnPress(context, GetMenuEntriesList menuEntry) { var pro = Provider.of(context, listen: false); if (menuEntry.requestType == "MONTHLY_ATTENDANCE") { diff --git a/lib/ui/screens/items_for_sale/fragments/add_details_fragment.dart b/lib/ui/screens/items_for_sale/fragments/add_details_fragment.dart index b2791ec..f0f2c62 100644 --- a/lib/ui/screens/items_for_sale/fragments/add_details_fragment.dart +++ b/lib/ui/screens/items_for_sale/fragments/add_details_fragment.dart @@ -25,8 +25,9 @@ class AddItemDetailsFragment extends StatefulWidget { final Function changePageViewIndex; final GetSaleCategoriesList selectedSaleCategory; static late ItemReviewModel itemReviewModel; + static late bool isUpdate; - const AddItemDetailsFragment({Key? key, required this.changePageViewIndex, required this.selectedSaleCategory}) : super(key: key); + AddItemDetailsFragment({Key? key, required this.changePageViewIndex, required this.selectedSaleCategory}) : super(key: key); @override State createState() => _AddItemDetailsFragmentState(); @@ -246,6 +247,7 @@ class _AddItemDetailsFragmentState extends State { String details = await Utils.getStringFromPrefs(SharedPrefsConsts.editItemForSale); if(details.isNotEmpty) { var body = json.decode(details); + AddItemDetailsFragment.isUpdate = true; GetRegionsList selectedRegionAd = GetRegionsList(); @@ -268,6 +270,8 @@ class _AddItemDetailsFragmentState extends State { AddItemDetailsFragment.itemReviewModel = itemReviewModel; SelectCategoryFragment.selectedSaleCategory = selectedSaleCategoryAd; + } else { + AddItemDetailsFragment.isUpdate = false; } } diff --git a/lib/ui/screens/items_for_sale/fragments/item_review_fragment.dart b/lib/ui/screens/items_for_sale/fragments/item_review_fragment.dart index 0b02658..190460e 100644 --- a/lib/ui/screens/items_for_sale/fragments/item_review_fragment.dart +++ b/lib/ui/screens/items_for_sale/fragments/item_review_fragment.dart @@ -26,11 +26,13 @@ class ItemReviewFragment extends StatefulWidget { class _ItemReviewFragmentState extends State { ItemReviewModel? itemReviewModel; + late bool isUpdate; @override void initState() { itemReviewModel = AddItemDetailsFragment.itemReviewModel; itemReviewModel!.selectedSaleCategory = SelectCategoryFragment.selectedSaleCategory; + isUpdate = AddItemDetailsFragment.isUpdate; super.initState(); } diff --git a/pubspec.yaml b/pubspec.yaml index bba295d..9fb50ac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -128,6 +128,7 @@ flutter: - assets/audio/ - assets/images/ - assets/images/worklist/ + - assets/images/services_icons/ - assets/images/login/ - assets/icons/chat/ - assets/images/logos/ From 8ba3dcf43bf1f35b6e734811bc3790919e0a6862 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 10 Nov 2022 16:00:55 +0300 Subject: [PATCH 18/82] Chat Fixes & Favorite Api Implementation --- assets/icons/chat/doc.svg | 54 ++ assets/icons/chat/ppt.svg | 51 ++ assets/icons/chat/txt.svg | 51 ++ assets/icons/chat/xls.svg | 53 ++ assets/icons/chat/zip.svg | 51 ++ lib/api/chat/chat_provider_model.dart | 461 +++++++++++++++--- lib/classes/colors.dart | 1 + lib/classes/consts.dart | 9 +- lib/extensions/string_extensions.dart | 2 +- ...t => get_single_user_chat_list_model.dart} | 77 ++- ...e_user_favotire_unfavorite_chat_model.dart | 53 ++ lib/ui/chat/chat_bubble.dart | 85 ++-- lib/ui/chat/chat_detailed_screen.dart | 306 +++++++++--- lib/ui/chat/chat_home.dart | 121 +++-- .../search_employee_bottom_sheet.dart | 88 +++- lib/widgets/image_picker.dart | 9 +- pubspec.yaml | 4 + 17 files changed, 1251 insertions(+), 225 deletions(-) create mode 100644 assets/icons/chat/doc.svg create mode 100644 assets/icons/chat/ppt.svg create mode 100644 assets/icons/chat/txt.svg create mode 100644 assets/icons/chat/xls.svg create mode 100644 assets/icons/chat/zip.svg rename lib/models/chat/{get_single_user_chat_list_Model.dart => get_single_user_chat_list_model.dart} (58%) create mode 100644 lib/models/chat/make_user_favotire_unfavorite_chat_model.dart diff --git a/assets/icons/chat/doc.svg b/assets/icons/chat/doc.svg new file mode 100644 index 0000000..1f678df --- /dev/null +++ b/assets/icons/chat/doc.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/chat/ppt.svg b/assets/icons/chat/ppt.svg new file mode 100644 index 0000000..5134010 --- /dev/null +++ b/assets/icons/chat/ppt.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/chat/txt.svg b/assets/icons/chat/txt.svg new file mode 100644 index 0000000..bbaf693 --- /dev/null +++ b/assets/icons/chat/txt.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/chat/xls.svg b/assets/icons/chat/xls.svg new file mode 100644 index 0000000..325f974 --- /dev/null +++ b/assets/icons/chat/xls.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/chat/zip.svg b/assets/icons/chat/zip.svg new file mode 100644 index 0000000..9aaaf6b --- /dev/null +++ b/assets/icons/chat/zip.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index bcb748c..b3f37ab 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -1,8 +1,9 @@ import 'dart:convert'; - +import 'dart:io'; +import 'dart:math'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:http/http.dart'; import 'package:logging/logging.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; @@ -10,11 +11,14 @@ import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; -import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_Model.dart'; +import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as login; -import 'package:shared_preferences/shared_preferences.dart'; +import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; +import 'package:mohem_flutter_app/widgets/image_picker.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:signalr_netcore/signalr_client.dart'; import 'package:logger/logger.dart' as L; +import 'package:uuid/uuid.dart'; class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List userChatHistory = []; @@ -22,8 +26,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { late HubConnection hubConnection; L.Logger logger = L.Logger(); TextEditingController message = TextEditingController(); - ScrollController scrollController = ScrollController(); bool isLoading = true; + bool isChatScreenActive = false; + late File selectedFile; + bool isFileSelected = false; + String sFileType = ""; + bool isMsgReply = false; + List repliedMsg = []; + int paginationVal = 0; Future getUserAutoLoginToken() async { String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString(); @@ -40,9 +50,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { token: AppState().chatDetails!.response!.token, ); return searchUserJsonModel(response.body); - logger.d(response.body); - isLoading = false; - notifyListeners(); } List searchUserJsonModel(String str) => List.from(json.decode(str).map((x) => ChatUser.fromJson(x))); @@ -52,25 +59,52 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}", token: AppState().chatDetails!.response!.token, ); + + logger.d(AppState().chatDetails!.response!.token); ChatUserModel recentChat = userToList(response.body); + + Response favRes = await ApiClient().getJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}", + token: AppState().chatDetails!.response!.token, + ); + print("============================== Fav Response ====================================="); + ChatUserModel favUsersList = userToList(favRes.body); + for (var user in recentChat.response!) { + for (var favUser in favUsersList.response!) { + logger.d(favUser.isFav); + if (user.id == favUser.id) { + user.isFav = favUser.isFav; + } + } + } + pChatHistory = recentChat.response; searchedChats = pChatHistory; isLoading = false; notifyListeners(); } - void getSingleUserChatHistory({required String senderUID, required int receiverUID, required String pagination}) async { + void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore}) async { isLoading = true; + if (!loadMore) paginationVal = 0; + logger.d(paginationVal); + isChatScreenActive = true; Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$pagination", + "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", token: AppState().chatDetails!.response!.token, ); - logger.d(response.statusCode); - print(response.body); + + logger.d(response.body); if (response.statusCode == 204) { - userChatHistory = []; + if (!loadMore) userChatHistory = []; + Utils.showToast("No More Data To Load"); } else { - userChatHistory = getSingleUserChatModel(response.body); + if (loadMore) { + List temp = getSingleUserChatModel(response.body); + userChatHistory.insertAll(0, temp); + } else { + userChatHistory = getSingleUserChatModel(response.body); + } } isLoading = false; notifyListeners(); @@ -80,6 +114,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ChatUserModel userToList(String str) => ChatUserModel.fromJson(json.decode(str)); + Future uploadAttachments(String userId, File file) async { + dynamic result; + dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}')); + request.fields.addAll({'userId': userId, 'fileSource': '1'}); + request.files.add(await MultipartFile.fromPath('files', file.path)); + request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'}); + try { + StreamedResponse response = await request.send(); + if (response.statusCode == 200) { + result = jsonDecode(await response.stream.bytesToString()); + } else { + result = []; + } + } catch (e) {} + return result; + } + Future buildHubConnection() async { HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); hubConnection = await HubConnectionBuilder() @@ -113,7 +164,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection.on("OnUserTypingAsync", onUserTyping); // hubConnection.on("OnUserCountAsync", userCountAsync); // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); - // hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); + hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); } else { hubConnection.on("OnUpdateUserStatusAsync", changeStatus); @@ -219,7 +270,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } userChatHistory.add(data.first); notifyListeners(); - scrollDown(); + logger.d(isChatScreenActive); + // if (isChatScreenActive) scrollDown(); } void onUserTyping(List? parameters) { @@ -228,7 +280,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUser user in searchedChats!) { if (user.id == parameters![1] && parameters[0] == true) { user.isTyping = parameters[0] as bool?; - Future.delayed( const Duration(seconds: 2), () { @@ -241,12 +292,122 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - void sendChatMessage(String chatMessage, int targetUserId, String targetUserName) async { - if (chatMessage == null || chatMessage.isEmpty) { - return; + int getFileType(String value) { + switch (value) { + case ".pdf": + return 1; + case ".png": + return 3; + case ".txt": + return 5; + case ".jpg": + return 12; + case ".jpeg": + return 4; + case ".xls": + return 7; + case ".xlsx": + return 7; + case ".doc": + return 6; + case ".docx": + return 6; + case ".ppt": + return 8; + case ".pptx": + return 8; + case ".zip": + return 2; + case ".rar": + return 2; + default: + return 0; } + } - var contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); + String getFileTypeDescription(String value) { + switch (value) { + case ".pdf": + return "application/pdf"; + case ".png": + return "image/png"; + case ".txt": + return "text/plain"; + case ".jpg": + return "image/jpg"; + case ".jpeg": + return "image/jpeg"; + case ".ppt": + return "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + case ".pptx": + return "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + case ".doc": + return "application/vnd.openxmlformats-officedocument.wordprocessingm"; + case ".docx": + return "application/vnd.openxmlformats-officedocument.wordprocessingm"; + case ".xls": + return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + case ".xlsx": + return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + case ".zip": + return "application/octet-stream"; + case ".rar": + return "application/octet-stream"; + default: + return ""; + } + } + + // void scrollDown() { + // scrollController.animateTo( + // scrollController.position.maxScrollExtent + 100, + // curve: Curves.easeOut, + // duration: const Duration(milliseconds: 300), + // ); + // notifyListeners(); + // } + + Future sendChatToServer( + {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { + Uuid uuid = const Uuid(); + SingleUserChatModel data = SingleUserChatModel( + chatEventId: chatEventId, + chatSource: 1, + contant: message.text, + contantNo: uuid.v4(), + conversationId: uuid.v4(), + createdDate: DateTime.now(), + currentUserId: AppState().chatDetails!.response!.id, + currentUserName: AppState().chatDetails!.response!.userName, + targetUserId: targetUserId, + targetUserName: targetUserName, + isReplied: false, + fileTypeId: fileTypeId, + userChatReplyResponse: isReply ? UserChatReplyResponse.fromJson(repliedMsg.first.toJson()) : null, + fileTypeResponse: isAttachment + ? FileTypeResponse( + fileTypeId: fileTypeId, + fileTypeName: getFileType(getFileExtension(selectedFile.path).toString()), + fileKind: getFileExtension(selectedFile.path), + fileName: selectedFile.path.split("/").last, + fileTypeDescription: getFileTypeDescription(getFileExtension(selectedFile.path).toString()), + ) + : null, + ); + String chatData = + '{"contant":"${message.text}","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}'; + await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); + userChatHistory.add(data); + isFileSelected = false; + isMsgReply = false; + sFileType = ""; + message.clear(); + notifyListeners(); + // scrollDown(); + } + + void sendChatMessage(int targetUserId, String targetUserName) async { + dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); if (contain.isEmpty) { searchedChats!.add( ChatUser( @@ -254,51 +415,233 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { userName: targetUserName, ), ); + notifyListeners(); + } + if (!isFileSelected && !isMsgReply) { + logger.d("Normal Text Message"); + if (message.text == null || message.text.isEmpty) { + return; + } + sendChatToServer(chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: false, chatReplyId: null, isReply: false); + } + if (isFileSelected && !isMsgReply) { + logger.d("Normal Attachment Message"); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); + String? ext = getFileExtension(selectedFile.path); + sendChatToServer(chatEventId: 2, fileTypeId: getFileType(ext.toString()), targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: true, chatReplyId: null, isReply: false); + } + if (!isFileSelected && isMsgReply) { + logger.d("Normal Text Message With Reply"); + if (message.text == null || message.text.isEmpty) { + return; + } + sendChatToServer( + chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, chatReplyId: repliedMsg.first.userChatHistoryId, isAttachment: false, isReply: true); +//chatReplyId + } + if (isFileSelected && isMsgReply) { + logger.d("Attachment Message With Reply"); + logger.d(repliedMsg.first.userChatHistoryId); + dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); + String? ext = getFileExtension(selectedFile.path); + sendChatToServer( + chatEventId: 2, + fileTypeId: getFileType(ext.toString()), + targetUserId: targetUserId, + targetUserName: targetUserName, + isAttachment: true, + chatReplyId: repliedMsg.first.userChatHistoryId, + isReply: true); } - String chatData = - '{"contant":"$chatMessage","contantNo":"8a129295-36d7-7185-5d34-cc4eec7bcba4","chatEventId":1,"fileTypeId":null,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"conversationId":"715f8b13-96ee-cd36-cb07-5a982a219982"}'; - await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); - userChatHistory.add( - SingleUserChatModel( - chatEventId: 1, - chatSource: 1, - contant: chatMessage, - contantNo: "8a129295-36d7-7185-5d34-cc4eec7bcba4", - conversationId: "715f8b13-96ee-cd36-cb07-5a982a219982", - createdDate: DateTime.now(), - currentUserId: AppState().chatDetails!.response!.id, - currentUserName: AppState().chatDetails!.response!.userName, - targetUserId: targetUserId, - targetUserName: targetUserName, - ), - ); - message.clear(); + // dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); + // if (contain.isEmpty) { + // searchedChats!.add( + // ChatUser( + // id: targetUserId, + // userName: targetUserName, + // ), + // ); + // notifyListeners(); + // } + // Uuid uuid = const Uuid(); + // dynamic fileID = fileUploadResponse.isEmpty ? null : getFileType(chatMessage); + // SingleUserChatModel data = SingleUserChatModel( + // chatEventId: fileUploadResponse.isEmpty ? 1 : 2, + // chatSource: 1, + // contant: chatMessage, + // contantNo: uuid.v4(), + // conversationId: uuid.v4(), + // createdDate: DateTime.now(), + // currentUserId: AppState().chatDetails!.response!.id, + // currentUserName: AppState().chatDetails!.response!.userName, + // targetUserId: targetUserId, + // targetUserName: targetUserName, + // fileTypeId: fileID, + // isReplied: false, + // // fileTypeResponse: FileTypeResponse( + // // fileTypeId: 0, + // // fileTypeDescription: fileUploadResponse.isEmpty ? null : fileUploadResponse.first["filePath"], + // // fileName: fileUploadResponse.isEmpty ? null : fileUploadResponse.first["filePath"], + // // fileKind: "image", + // // fileTypeName: fileUploadResponse.isEmpty ? null : fileUploadResponse.first["filePath"].toString().split(".").last), + // ); + // + // String chatData = + // '{"contant":"$chatMessage","contantNo":"${uuid.v4()}","chatEventId":${fileUploadResponse.isEmpty ? 1 : 2},"fileTypeId": $fileID,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"conversationId":"${uuid.v4()}"}'; + // await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); + // userChatHistory.add(data); + // message.clear(); + // notifyListeners(); + // scrollDown(); + } + + void scrollListener() { + if (userChatHistory.length < paginationVal) { + print("Get New Data"); + } + } + + void selectImageToUpload(BuildContext context) { + ImageOptions.showImageOptionsNew(context, true, (String image, File file) async { + if (checkFileSize(file.path)) { + selectedFile = file; + isFileSelected = true; + sFileType = getFileExtension(file.path)!; + message.text = file.path.split("/").last; + Navigator.of(context).pop(); + } else { + Utils.showToast("Max 1 mb size is allowed to upload"); + } + //Utils.showLoading(context); + notifyListeners(); + //Utils.hideLoading(context); + // Utils.showLoading(context); + // await m.uploadAttachments(AppState().chatDetails!.response!.id.toString(), file).then((value) { + // if (value == null) { + // m.logger.d("Returned EMPTY"); + // } else { + // m.sendChatMessage(value.isEmpty ? m.message.text : value.first["filePath"], userDetails["targetUser"].id, userDetails["targetUser"].userName, value); + // } + // }); + // Utils.hideLoading(context); + }); + } + + void removeAttachment() { + isFileSelected = false; + sFileType = ""; + message.text = ''; notifyListeners(); - scrollDown(); } - void scrollDown() { - scrollController.animateTo( - scrollController.position.maxScrollExtent + 100, - curve: Curves.easeOut, - duration: const Duration(milliseconds: 300), - ); + String? getFileExtension(String fileName) { + try { + return "." + fileName.split('.').last; + } catch (e) { + return null; + } + } + + bool checkFileSize(String path) { + int fileSizeLimit = 1024; + File f = File(path); + double fileSizeInKB = f.lengthSync() / 1024; + double fileSizeInMB = fileSizeInKB / 1024; + if (fileSizeInKB > fileSizeLimit) { + return false; + } else { + return true; + } + } + + String getType(String type) { + switch (type) { + case ".pdf": + return "assets/images/pdf.svg"; + case ".png": + return "assets/images/png.svg"; + case ".txt": + return "assets/icons/chat/txt.svg"; + case ".jpg": + return "assets/images/jpg.svg"; + case ".jpeg": + return "assets/images/jpg.svg"; + case ".xls": + return "assets/icons/chat/xls.svg"; + case ".xlsx": + return "assets/icons/chat/xls.svg"; + case ".doc": + return "assets/icons/chat/doc.svg"; + case ".docx": + return "assets/icons/chat/doc.svg"; + case ".ppt": + return "assets/icons/chat/ppt.svg"; + case ".pptx": + return "assets/icons/chat/ppt.svg"; + case ".zip": + return "assets/icons/chat/zip.svg"; + case ".rar": + return "assets/icons/chat/zip.svg"; + default: + return "assets/images/thumb.svg"; + } + } + + void chatReply(SingleUserChatModel data) { + repliedMsg = []; + data.isReplied = true; + isMsgReply = true; + repliedMsg.add(data); + notifyListeners(); + } + + void closeMe() { + repliedMsg = []; + isMsgReply = false; + notifyListeners(); + } + + String dateFormte(DateTime data) { + DateFormat f = new DateFormat('hh:mm a dd MMM yyyy'); + f.format(data); + return f.format(data); + } + + Future favoriteUser({required int userID, required int targetUserID}) async { + Response response = + await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token); + fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); + if (favoriteChatUser.response != null) { + for (var user in searchedChats!) { + if (user.id == favoriteChatUser.response!.targetUserId!) { + user.isFav = favoriteChatUser.response!.isFav; + } + } + } notifyListeners(); } -// void _scrollListener() { -// if (scrollController.position.extentAfter.toInt() <= 0 && canCallApi) { -// if (userChatHistory.length < _ayatTangheemTypeMapped.totalItemsCount) { -// currentPageNo++; -// if (widget.tangheemQuery == null) { -// getTangheemData(); -// } else { -// getTangheemDataByKeyword(); -// } -// } -// canCallApi = false; -// } -// } + Future unFavoriteUser({required int userID, required int targetUserID}) async { + Response response = await ApiClient() + .postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/deleteFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token); + fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); + if (favoriteChatUser.response != null) { + for (var user in searchedChats!) { + if (user.id == favoriteChatUser.response!.targetUserId!) { + user.isFav = favoriteChatUser.response!.isFav; + } + } + } + notifyListeners(); + } + void clearSelections() { + isChatScreenActive = false; + paginationVal = 0; + message.text = ''; + isFileSelected = false; + repliedMsg = []; + sFileType = ""; + } } diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart index e670bbc..5e390c7 100644 --- a/lib/classes/colors.dart +++ b/lib/classes/colors.dart @@ -58,4 +58,5 @@ class MyColors { static const Color greyC4Color = Color(0xffC4C4C4); static const Color grey35Color = Color(0xff535353); static const Color grey9DColor = Color(0xff9D9D9D); + static const Color grey71Color = Color(0xff717171); } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index e82c30a..c98d136 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; @@ -16,7 +16,12 @@ class ApiConsts { static String chatSearchMember = "user/getUserWithStatusAndFavAsync/"; static String chatRecentUrl = "UserChatHistory/getchathistorybyuserid"; //For a Mem static String chatSingleUserHistoryUrl = "UserChatHistory/GetUserChatHistory"; + static String chatMediaImageUploadUrl = "shared/upload"; + static String chatFavoriteUsers = "FavUser/getFavUserById/"; + //https://apiderichat.hmg.com/api/FavUser/getFavUserById/42062 +//https://apiderichat.hmg.com/api/shared/upload // 42062 is CurrentUserID and 36745 is targetUserID and 0 is For Pagination + // static String chatSearchMember = "https://apiderichat.hmg.com/api/user/getUserWithStatusAndFavAsync/aamir.muhammad/36239"; } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 37f41ae..9af8f2b 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -18,7 +18,7 @@ extension EmailValidator on String { Widget toText10({Color? color, bool isBold = false, int? maxlines, FontStyle? fontStyle}) => Text( this, - //maxLines: maxlines, + maxLines: maxlines, style: TextStyle(fontSize: 10, fontStyle: fontStyle ?? FontStyle.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4), ); diff --git a/lib/models/chat/get_single_user_chat_list_Model.dart b/lib/models/chat/get_single_user_chat_list_model.dart similarity index 58% rename from lib/models/chat/get_single_user_chat_list_Model.dart rename to lib/models/chat/get_single_user_chat_list_model.dart index 0e3cb22..6a35f0e 100644 --- a/lib/models/chat/get_single_user_chat_list_Model.dart +++ b/lib/models/chat/get_single_user_chat_list_model.dart @@ -1,3 +1,9 @@ +import 'dart:convert'; + +List singleUserChatModelFromJson(String str) => List.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); + +String singleUserChatModelToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + class SingleUserChatModel { SingleUserChatModel({ this.userChatHistoryId, @@ -19,6 +25,7 @@ class SingleUserChatModel { this.conversationId, this.fileTypeResponse, this.userChatReplyResponse, + this.isReplied, }); int? userChatHistoryId; @@ -29,17 +36,18 @@ class SingleUserChatModel { String? currentUserName; int? targetUserId; String? targetUserName; - dynamic encryptedTargetUserId; - dynamic encryptedTargetUserName; + String? encryptedTargetUserId; + String? encryptedTargetUserName; int? chatEventId; - dynamic fileTypeId; + dynamic? fileTypeId; bool? isSeen; bool? isDelivered; DateTime? createdDate; int? chatSource; String? conversationId; FileTypeResponse? fileTypeResponse; - dynamic userChatReplyResponse; + UserChatReplyResponse? userChatReplyResponse; + bool? isReplied; factory SingleUserChatModel.fromJson(Map json) => SingleUserChatModel( userChatHistoryId: json["userChatHistoryId"] == null ? null : json["userChatHistoryId"], @@ -50,8 +58,8 @@ class SingleUserChatModel { currentUserName: json["currentUserName"] == null ? null : json["currentUserName"], targetUserId: json["targetUserId"] == null ? null : json["targetUserId"], targetUserName: json["targetUserName"] == null ? null : json["targetUserName"], - encryptedTargetUserId: json["encryptedTargetUserId"], - encryptedTargetUserName: json["encryptedTargetUserName"], + encryptedTargetUserId: json["encryptedTargetUserId"] == null ? null : json["encryptedTargetUserId"], + encryptedTargetUserName: json["encryptedTargetUserName"] == null ? null : json["encryptedTargetUserName"], chatEventId: json["chatEventId"] == null ? null : json["chatEventId"], fileTypeId: json["fileTypeId"], isSeen: json["isSeen"] == null ? null : json["isSeen"], @@ -60,7 +68,8 @@ class SingleUserChatModel { chatSource: json["chatSource"] == null ? null : json["chatSource"], conversationId: json["conversationId"] == null ? null : json["conversationId"], fileTypeResponse: json["fileTypeResponse"] == null ? null : FileTypeResponse.fromJson(json["fileTypeResponse"]), - userChatReplyResponse: json["userChatReplyResponse"], + userChatReplyResponse: json["userChatReplyResponse"] == null ? null : UserChatReplyResponse.fromJson(json["userChatReplyResponse"]), + isReplied: false, ); Map toJson() => { @@ -72,8 +81,8 @@ class SingleUserChatModel { "currentUserName": currentUserName == null ? null : currentUserName, "targetUserId": targetUserId == null ? null : targetUserId, "targetUserName": targetUserName == null ? null : targetUserName, - "encryptedTargetUserId": encryptedTargetUserId, - "encryptedTargetUserName": encryptedTargetUserName, + "encryptedTargetUserId": encryptedTargetUserId == null ? null : encryptedTargetUserId, + "encryptedTargetUserName": encryptedTargetUserName == null ? null : encryptedTargetUserName, "chatEventId": chatEventId == null ? null : chatEventId, "fileTypeId": fileTypeId, "isSeen": isSeen == null ? null : isSeen, @@ -82,7 +91,7 @@ class SingleUserChatModel { "chatSource": chatSource == null ? null : chatSource, "conversationId": conversationId == null ? null : conversationId, "fileTypeResponse": fileTypeResponse == null ? null : fileTypeResponse!.toJson(), - "userChatReplyResponse": userChatReplyResponse, + "userChatReplyResponse": userChatReplyResponse == null ? null : userChatReplyResponse!.toJson(), }; } @@ -117,3 +126,51 @@ class FileTypeResponse { "fileName": fileName, }; } + +class UserChatReplyResponse { + UserChatReplyResponse({ + this.userChatHistoryId, + this.chatEventId, + this.contant, + this.contantNo, + this.fileTypeId, + this.createdDate, + this.targetUserId, + this.targetUserName, + this.fileTypeResponse, + }); + + int? userChatHistoryId; + int? chatEventId; + String? contant; + String? contantNo; + dynamic? fileTypeId; + DateTime? createdDate; + int? targetUserId; + String? targetUserName; + FileTypeResponse? fileTypeResponse; + + factory UserChatReplyResponse.fromJson(Map json) => UserChatReplyResponse( + userChatHistoryId: json["userChatHistoryId"] == null ? null : json["userChatHistoryId"], + chatEventId: json["chatEventId"] == null ? null : json["chatEventId"], + contant: json["contant"] == null ? null : json["contant"], + contantNo: json["contantNo"] == null ? null : json["contantNo"], + fileTypeId: json["fileTypeId"], + createdDate: json["createdDate"] == null ? null : DateTime.parse(json["createdDate"]), + targetUserId: json["targetUserId"] == null ? null : json["targetUserId"], + targetUserName: json["targetUserName"] == null ? null : json["targetUserName"], + fileTypeResponse: json["fileTypeResponse"] == null ? null : FileTypeResponse.fromJson(json["fileTypeResponse"]), + ); + + Map toJson() => { + "userChatHistoryId": userChatHistoryId == null ? null : userChatHistoryId, + "chatEventId": chatEventId == null ? null : chatEventId, + "contant": contant == null ? null : contant, + "contantNo": contantNo == null ? null : contantNo, + "fileTypeId": fileTypeId, + "createdDate": createdDate == null ? null : createdDate!.toIso8601String(), + "targetUserId": targetUserId == null ? null : targetUserId, + "targetUserName": targetUserName == null ? null : targetUserName, + "fileTypeResponse": fileTypeResponse == null ? null : fileTypeResponse!.toJson(), + }; +} diff --git a/lib/models/chat/make_user_favotire_unfavorite_chat_model.dart b/lib/models/chat/make_user_favotire_unfavorite_chat_model.dart new file mode 100644 index 0000000..64eb6b1 --- /dev/null +++ b/lib/models/chat/make_user_favotire_unfavorite_chat_model.dart @@ -0,0 +1,53 @@ +// To parse this JSON data, do +// +// final favoriteChatUser = favoriteChatUserFromJson(jsonString); + +import 'dart:convert'; + +class FavoriteChatUser { + FavoriteChatUser({ + this.response, + this.errorResponses, + }); + + Response? response; + dynamic? errorResponses; + + factory FavoriteChatUser.fromRawJson(String str) => FavoriteChatUser.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory FavoriteChatUser.fromJson(Map json) => FavoriteChatUser( + response: json["response"] == null ? null : Response.fromJson(json["response"]), + errorResponses: json["errorResponses"], + ); + + Map toJson() => { + "response": response == null ? null : response!.toJson(), + "errorResponses": errorResponses, + }; +} + +class Response { + Response({ + this.targetUserId, + this.isFav, + }); + + int? targetUserId; + bool? isFav; + + factory Response.fromRawJson(String str) => Response.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Response.fromJson(Map json) => Response( + targetUserId: json["targetUserId"] == null ? null : json["targetUserId"], + isFav: json["isFav"] == null ? null : json["isFav"], + ); + + Map toJson() => { + "targetUserId": targetUserId == null ? null : targetUserId, + "isFav": isFav == null ? null : isFav, + }; +} diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 74d2e2b..1e8aec4 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -2,82 +2,105 @@ import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:sizer/sizer.dart'; class ChatBubble extends StatelessWidget { const ChatBubble( {Key? key, required this.text, + required this.replyText, required this.isCurrentUser, required this.isSeen, required this.isDelivered, - required this.dateTime}) + required this.dateTime, + required this.isReplied, + required this.userName}) : super(key: key); final String text; + final String replyText; final bool isCurrentUser; final bool isSeen; final bool isDelivered; final String dateTime; + final bool isReplied; + final String userName; @override Widget build(BuildContext context) { return Padding( - // asymmetric padding - padding: EdgeInsets.fromLTRB( - isCurrentUser ? 64.0 : 16.0, - 4, - isCurrentUser ? 16.0 : 64.0, - 4, - ), + // padding: EdgeInsets.zero, + padding: EdgeInsets.only(left: isCurrentUser ? 110 : 20, right: isCurrentUser ? 20 : 110, bottom: 9), + child: Align( - // align the child within the container alignment: isCurrentUser ? Alignment.centerRight : Alignment.centerLeft, child: DecoratedBox( - // chat bubble decoration decoration: BoxDecoration( color: Colors.white, gradient: isCurrentUser ? null - : LinearGradient( + : const LinearGradient( transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, - colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ]), + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), borderRadius: BorderRadius.circular(10), ), child: Padding( - padding: const EdgeInsets.all(12), + padding: EdgeInsets.only(top: isReplied ? 8 : 5, right:8, left: 8, bottom: 5), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - text.toText12( - color: - isCurrentUser ? MyColors.grey57Color : MyColors.white), - 8.height, + if (isReplied) + ClipRRect( + borderRadius: BorderRadius.circular(5.0), + child: Container( + decoration: BoxDecoration( + border: Border( + left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), + ), + color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30), + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5), + replyText + .toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4) + .paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + ], + ), + ), + ], + ), + ), + ), + if (isReplied) 8.height, + text.toText12(color: isCurrentUser ? MyColors.grey57Color : MyColors.white), + Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - dateTime.toText12( - color: isCurrentUser - ? MyColors.grey41Color.withOpacity(.5) - : Colors.white.withOpacity(0.7)), + dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : Colors.white.withOpacity(0.7)), if (isCurrentUser) 5.width, if (isCurrentUser) Icon( - isDelivered - ? Icons.done_all - : Icons.done_all, - color: isSeen - ? MyColors.textMixColor - : MyColors.grey9DColor, + isDelivered ? Icons.done_all : Icons.done_all, + color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor, size: 14, - ) + ), ], ), + ], ), ), diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 5f2fa97..d2d3598 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,4 +1,6 @@ import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -6,27 +8,53 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/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/ui/chat/chat_bubble.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/image_picker.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import 'package:sizer/sizer.dart'; +import 'package:swipe_to/swipe_to.dart'; class ChatDetailScreen extends StatelessWidget { + ChatDetailScreen({Key? key}) : super(key: key); dynamic userDetails; late ChatProviderModel data; + ScrollController scrollController = ScrollController(); + RefreshController _refreshController = RefreshController(initialRefresh: false); - ChatDetailScreen({Key? key}) : super(key: key); + void onRefresh() async { + print("Refresh Triggered"); + await Future.delayed(Duration(milliseconds: 1000)); + if (userDetails != null) { + data.paginationVal = data.paginationVal + 10; + data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true); + } + _refreshController.refreshCompleted(); + } @override Widget build(BuildContext context) { - userDetails = ModalRoute - .of(context)! - .settings - .arguments; + userDetails = ModalRoute.of(context)!.settings.arguments; data = Provider.of(context, listen: false); - data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, pagination: "0"); - Timer(const Duration(seconds: 1), () => data.scrollDown()); + if (userDetails != null) data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: false); + // + // if (userDetails != null) { + // scrollController.addListener(() { + // if (scrollController.position.minScrollExtent == scrollController.offset) { + // data.paginationVal++; + // data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true); + // } + // }); + // } + return Scaffold( backgroundColor: const Color(0xFFF8F8F8), appBar: AppBarWidget(context, title: userDetails["targetUser"].userName, showHomeButton: false, image: userDetails["targetUser"].image), @@ -35,73 +63,217 @@ class ChatDetailScreen extends StatelessWidget { return (m.isLoading ? ChatHomeShimmer() : Column( - children: [ - Expanded( - child: ListView.builder( - controller: m.scrollController, - shrinkWrap: true, - itemCount: m.userChatHistory.length, - padding: const EdgeInsets.symmetric(vertical: 10), - itemBuilder: (BuildContext context, int i) { - i == 0 ? m.logger.d(m.userChatHistory.length) : ""; - return ChatBubble( - text: m.userChatHistory[i].contant.toString(), - isSeen: m.userChatHistory[i].isSeen == true ? true : false, - isCurrentUser: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id ? true : false, - isDelivered: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id && m.userChatHistory[i].isDelivered == true ? true : false, - dateTime: m.userChatHistory[i].createdDate.toString(), - ); - }, - ), - ), - Card( - margin: EdgeInsets.zero, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: TextField( - controller: m.message, - decoration: InputDecoration( - hintText: LocaleKeys.typeheretoreply.tr(), - hintStyle: const TextStyle(color: MyColors.grey98Color), - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), - suffixIcon: SizedBox( - width: 100, - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - IconButton( - icon: const Icon( - Icons.attach_file_rounded, - size: 27, - color: MyColors.lightGreenColor, + children: [ + Expanded( + flex: 2, + child: SmartRefresher( + enablePullDown: true, + enablePullUp: false, + header: const MaterialClassicHeader( + color: MyColors.gradiantEndColor, + ), + controller: _refreshController, + onRefresh: onRefresh, + child: ListView.builder( + controller: scrollController, + shrinkWrap: true, + itemCount: m.userChatHistory.length, + padding: EdgeInsets.zero, + itemBuilder: (BuildContext context, int i) { + return GestureDetector( + onTap: () { + m.logger.d(jsonEncode(m.userChatHistory[i])); + m.logger.d(jsonEncode(m.userChatHistory.length)); + }, + child: SwipeTo( + iconColor: MyColors.lightGreenColor, + child: ChatBubble( + text: m.userChatHistory[i].contant.toString(), + replyText: m.userChatHistory[i].userChatReplyResponse != null ? m.userChatHistory[i].userChatReplyResponse!.contant.toString() : "", + isSeen: m.userChatHistory[i].isSeen == true ? true : false, + isCurrentUser: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id ? true : false, + isDelivered: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id && m.userChatHistory[i].isDelivered == true ? true : false, + dateTime: m.dateFormte(m.userChatHistory[i].createdDate!), + isReplied: m.userChatHistory[i].userChatReplyResponse != null ? true : false, + userName: AppState().chatDetails!.response!.userName == m.userChatHistory[i].currentUserName.toString() ? "You" : m.userChatHistory[i].currentUserName.toString(), + ), + onRightSwipe: () { + m.chatReply(m.userChatHistory[i]); + }, + ), + ); + }, + ), + ), + ), + if (m.isMsgReply) + Row( + children: [ + Container( + height: 80, + color: MyColors.textMixColor, + width: 6, + ), + Expanded( + child: Container( + height: 80, + color: MyColors.black.withOpacity(0.10), + child: ListTile( + title: (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() ? "You" : m.repliedMsg.first.currentUserName.toString()) + .toText14(color: MyColors.lightGreenColor), + subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.white, maxLine: 2), + trailing: GestureDetector( + onTap: m.closeMe, + child: Container( + decoration: BoxDecoration( + color: MyColors.white.withOpacity(0.5), + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + ), + child: const Icon( + Icons.close, + size: 23, + color: MyColors.white, + ), + ), + ), ), - onPressed: () {}, ), - IconButton( - icon: SvgPicture.asset( - "assets/icons/chat/chat_send_icon.svg", - height: 26, - width: 35, + ), + ], + ), + if (m.isFileSelected && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") + Card( + margin: EdgeInsets.zero, + elevation: 0, + child: Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20, top: 20, bottom: 0), + child: Card( + margin: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0.0), + ), + elevation: 0, + child: Container( + height: 200, + decoration: BoxDecoration( + image: DecorationImage( + image: FileImage( + m.selectedFile, + ), + fit: BoxFit.cover), + borderRadius: const BorderRadius.all( + Radius.circular(0), + ), ), - onPressed: () { - m.sendChatMessage(m.message.text, userDetails["targetUser"].id, userDetails["targetUser"].userName); - }, + child: const SizedBox( + width: double.infinity, + height: 200, + ), + ), + ), + ), + ), + Card( + margin: EdgeInsets.zero, + child: TextField( + controller: m.message, + decoration: InputDecoration( + hintText: m.isFileSelected ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), + hintStyle: TextStyle(color: m.isFileSelected ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.only(left: m.sFileType.isNotEmpty ? 10 : 20, right: m.sFileType.isNotEmpty ? 0 : 5, top: 20, bottom: 20), + prefixIcon: m.sFileType.isNotEmpty + ? Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SvgPicture.asset( + m.getType(m.sFileType), + height: 30, + width: 25, + alignment: Alignment.center, + fit: BoxFit.cover, + ).paddingOnly(left: 20), + ], + ) + : null, + suffixIcon: Container( + width: 96, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, // added line + children: [ + if (m.sFileType.isNotEmpty) + IconButton( + padding: EdgeInsets.zero, + alignment: Alignment.centerRight, + icon: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + Container( + decoration: const BoxDecoration( + color: MyColors.redA3Color, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + child: const Icon( + Icons.close, + size: 15, + color: MyColors.white, + ), + ), + ("Clear").toText11(color: MyColors.redA3Color).paddingOnly(left: 4), + ], + ), + onPressed: () async { + m.removeAttachment(); + }, + ), + if (m.sFileType.isEmpty) + RotationTransition( + turns: const AlwaysStoppedAnimation(45 / 360), + child: IconButton( + padding: EdgeInsets.zero, + alignment: Alignment.topRight, + icon: const Icon( + Icons.attach_file_rounded, + size: 26, + color: MyColors.grey3AColor, + ), + onPressed: () async { + m.selectImageToUpload(context); + }, + ), + ), + IconButton( + alignment: Alignment.centerRight, + padding: EdgeInsets.zero, + icon: SvgPicture.asset( + "assets/icons/chat/chat_send_icon.svg", + height: 26, + width: 26, + ), + onPressed: () { + m.sendChatMessage(userDetails["targetUser"].id, userDetails["targetUser"].userName); + }, + ) + ], ), - ], + ).paddingOnly(right: 20), ), ), ), - ), - ), - ), - ], - )); + ], + )); }, ), ); diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index f6f8e24..106a4b3 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -8,13 +8,16 @@ import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/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/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; class ChatHomeScreen extends StatefulWidget { const ChatHomeScreen({Key? key}) : super(key: key); @@ -81,45 +84,92 @@ class _ChatHomeScreenState extends State { if (m.searchedChats != null) ListView.separated( itemCount: m.searchedChats!.length, - padding: const EdgeInsets.only(top: 0), + padding: const EdgeInsets.only(top: 20), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) { - return ListTile( - leading: Stack( - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 48, - width: 48, - ), - Positioned( - right: 5, - bottom: 1, - child: Container( - width: 10, - height: 10, - decoration: BoxDecoration( - color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, - borderRadius: const BorderRadius.all( - Radius.circular(10), + return SizedBox( + height: 55, + child: ListTile( + leading: Stack( + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), ), ), - ), - ) - ], + ) + ], + ), + title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor), + // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), + trailing: SizedBox( + width: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + if (m.searchedChats![index].unreadMessageCount! > 0) + Flexible( + child: Container( + padding: EdgeInsets.zero, + alignment: Alignment.centerRight, + width: 18, + height: 18, + decoration: const BoxDecoration( + color: MyColors.redColor, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + child: (m.searchedChats![index].unreadMessageCount!.toString()) + .toText10( + color: MyColors.white, + ) + .center, + ), + ), + Flexible( + child: IconButton( + alignment: Alignment.centerRight, + padding: EdgeInsets.zero, + icon: Icon(m.searchedChats![index].isFav! ? Icons.star : Icons.star_border), + color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, + onPressed: () { + if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + if (!m.searchedChats![index].isFav!) m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + }, + ), + ) + ], + ), + ), + minVerticalPadding: 0, + onTap: () { + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": m.searchedChats![index]}, + ).then((value) { + m.clearSelections(); + }); + }, + onLongPress: () {}, ), - title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor), - subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), - trailing: ("Today").toText10(color: MyColors.lightTextColor), - minVerticalPadding: 0, - onTap: () { - Navigator.pushNamed( - context, - AppRoutes.chatDetailed, - arguments: {"targetUser": m.searchedChats![index]}, - ); - }, ); }, separatorBuilder: (BuildContext context, int index) => const Padding( @@ -129,7 +179,6 @@ class _ChatHomeScreenState extends State { ), ), ), - // if (searchedUsersList == null) Utils.getNoChatWidget(context), ], ); }), @@ -156,11 +205,9 @@ class _ChatHomeScreenState extends State { ), ), onPressed: () async { - // var userData = await ChatApiClient() - // .getChatMemberFromSearch("aamir.muhammad", 36239); showMyBottomSheet( context, - callBackFunc: (){}, + callBackFunc: () {}, child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index 16942c5..fb14141 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -183,16 +183,66 @@ class _SearchEmployeeBottomSheetState extends State { if (widget.fromChat) if (chatUsersList != null && widget.fromChat) chatUsersList!.isEmpty - ? Utils.getNoDataWidget(context) + ? Column( + children: [ + 20.height, + Utils.getNoDataWidget(context), + ], + ) : ListView( physics: const BouncingScrollPhysics(), - padding: EdgeInsets.only(top: 0, bottom: 8), - children: [ + padding: const EdgeInsets.only(top: 15,), + children: [ ListView.separated( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (cxt, index) { - return ListTile( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (BuildContext cxt, int index) { + + + + + // return ListTile( + // leading: Stack( + // children: [ + // SvgPicture.asset( + // "assets/images/user.svg", + // height: 48, + // width: 48, + // ), + // Positioned( + // right: 5, + // bottom: 1, + // child: Container( + // width: 10, + // height: 10, + // decoration: BoxDecoration( + // color: chatUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + // borderRadius: const BorderRadius.all( + // Radius.circular(10), + // ), + // ), + // ), + // ) + // ], + // ), + // title: (chatUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), + // // subtitle: (chatUsersList![index].isTyping == true ? "Something is Typing" : "Last message text").toText11(color: MyColors.normalTextColor), + // // trailing: ("Today").toText10(color: MyColors.lightTextColor), + // minVerticalPadding: 0, + // onTap: () { + // Navigator.pop(context); + // Navigator.pushNamed( + // context, + // AppRoutes.chatDetailed, + // arguments: {"targetUser": chatUsersList![index]}, + // ); + // }, + // ); + + + return SizedBox( + height: 55, + child: ListTile( leading: Stack( children: [ SvgPicture.asset( @@ -217,8 +267,6 @@ class _SearchEmployeeBottomSheetState extends State { ], ), title: (chatUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), - // subtitle: (chatUsersList![index].isTyping == true ? "Something is Typing" : "Last message text").toText11(color: MyColors.normalTextColor), - // trailing: ("Today").toText10(color: MyColors.lightTextColor), minVerticalPadding: 0, onTap: () { Navigator.pop(context); @@ -228,13 +276,21 @@ class _SearchEmployeeBottomSheetState extends State { arguments: {"targetUser": chatUsersList![index]}, ); }, - ); - }, - separatorBuilder: (BuildContext cxt, int index) => Container( - height: 1, - color: MyColors.borderE3Color, - ), - itemCount: chatUsersList?.length ?? 0), + onLongPress: () {}, + ), + ); + + + + }, + separatorBuilder: (BuildContext context, int index) => const Padding( + padding: EdgeInsets.only(right: 10, left: 70, bottom: 0,top: 0), + child: Divider( + color: Color(0xFFE5E5E5), + ), + ), + itemCount: chatUsersList?.length ?? 0, + ), 12.height, ], ).expanded, diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index 5e5ac01..9fa0336 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -13,7 +13,7 @@ class ImageOptions { static void showImageOptionsNew(BuildContext context, bool showFilesOption, Function(String, File) image) { showMyBottomSheet( context, - callBackFunc: (){}, + callBackFunc: () {}, child: AttachmentOptions( showFilesOption: showFilesOption, onCameraTap: () async { @@ -43,7 +43,12 @@ class ImageOptions { } }, onFilesTap: () async { - FilePickerResult? result = await FilePicker.platform.pickFiles(); + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ['jpg', 'jpeg ', 'pdf', 'txt', 'docx', 'doc', 'pptx', 'xlsx', 'png', 'rar', 'zip', 'xls'], + ); + List files = result!.paths.map((path) => File(path!)).toList(); + image(result!.files.first.path.toString(), files.first); }, ), ); diff --git a/pubspec.yaml b/pubspec.yaml index 633edd7..f2fbba8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -85,9 +85,13 @@ dependencies: appinio_swiper: ^1.1.1 expandable: ^5.0.1 + + #Chat signalr_netcore: ^1.3.3 logging: ^1.0.1 + swipe_to: ^1.0.2 + From 67f4fdef289f3d1165d978beea1f9c13c4be44f6 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 10 Nov 2022 16:06:25 +0300 Subject: [PATCH 19/82] Chat Fixes & Favorite Api Implementation --- lib/api/chat/chat_provider_model.dart | 88 +++---------------- lib/classes/consts.dart | 7 +- lib/ui/chat/chat_bubble.dart | 6 +- lib/ui/chat/chat_detailed_screen.dart | 59 ++++--------- lib/ui/chat/chat_home.dart | 4 +- .../search_employee_bottom_sheet.dart | 83 +++++------------ 6 files changed, 56 insertions(+), 191 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index b3f37ab..b85aa85 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -141,20 +141,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ) .build(); hubConnection.onclose( - ({Exception? error}) { - // logger.d(error); - }, + ({Exception? error}) {}, ); hubConnection.onreconnecting( - ({Exception? error}) { - // logger.d(error); - // logger.d("Reconnecting"); - }, + ({Exception? error}) {}, ); hubConnection.onreconnected( - ({String? connectionId}) { - // logger.d("Reconnected"); - }, + ({String? connectionId}) {}, ); if (hubConnection.state != HubConnectionState.Connected) { await hubConnection.start(); @@ -403,7 +396,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { sFileType = ""; message.clear(); notifyListeners(); - // scrollDown(); } void sendChatMessage(int targetUserId, String targetUserName) async { @@ -437,7 +429,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } sendChatToServer( chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, chatReplyId: repliedMsg.first.userChatHistoryId, isAttachment: false, isReply: true); -//chatReplyId } if (isFileSelected && isMsgReply) { logger.d("Attachment Message With Reply"); @@ -445,60 +436,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); sendChatToServer( - chatEventId: 2, - fileTypeId: getFileType(ext.toString()), - targetUserId: targetUserId, - targetUserName: targetUserName, - isAttachment: true, - chatReplyId: repliedMsg.first.userChatHistoryId, - isReply: true); - } - - // dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); - // if (contain.isEmpty) { - // searchedChats!.add( - // ChatUser( - // id: targetUserId, - // userName: targetUserName, - // ), - // ); - // notifyListeners(); - // } - // Uuid uuid = const Uuid(); - // dynamic fileID = fileUploadResponse.isEmpty ? null : getFileType(chatMessage); - // SingleUserChatModel data = SingleUserChatModel( - // chatEventId: fileUploadResponse.isEmpty ? 1 : 2, - // chatSource: 1, - // contant: chatMessage, - // contantNo: uuid.v4(), - // conversationId: uuid.v4(), - // createdDate: DateTime.now(), - // currentUserId: AppState().chatDetails!.response!.id, - // currentUserName: AppState().chatDetails!.response!.userName, - // targetUserId: targetUserId, - // targetUserName: targetUserName, - // fileTypeId: fileID, - // isReplied: false, - // // fileTypeResponse: FileTypeResponse( - // // fileTypeId: 0, - // // fileTypeDescription: fileUploadResponse.isEmpty ? null : fileUploadResponse.first["filePath"], - // // fileName: fileUploadResponse.isEmpty ? null : fileUploadResponse.first["filePath"], - // // fileKind: "image", - // // fileTypeName: fileUploadResponse.isEmpty ? null : fileUploadResponse.first["filePath"].toString().split(".").last), - // ); - // - // String chatData = - // '{"contant":"$chatMessage","contantNo":"${uuid.v4()}","chatEventId":${fileUploadResponse.isEmpty ? 1 : 2},"fileTypeId": $fileID,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"conversationId":"${uuid.v4()}"}'; - // await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); - // userChatHistory.add(data); - // message.clear(); - // notifyListeners(); - // scrollDown(); - } - - void scrollListener() { - if (userChatHistory.length < paginationVal) { - print("Get New Data"); + chatEventId: 2, + fileTypeId: getFileType(ext.toString()), + targetUserId: targetUserId, + targetUserName: targetUserName, + isAttachment: true, + chatReplyId: repliedMsg.first.userChatHistoryId, + isReply: true, + ); } } @@ -513,18 +458,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } else { Utils.showToast("Max 1 mb size is allowed to upload"); } - //Utils.showLoading(context); notifyListeners(); - //Utils.hideLoading(context); - // Utils.showLoading(context); - // await m.uploadAttachments(AppState().chatDetails!.response!.id.toString(), file).then((value) { - // if (value == null) { - // m.logger.d("Returned EMPTY"); - // } else { - // m.sendChatMessage(value.isEmpty ? m.message.text : value.first["filePath"], userDetails["targetUser"].id, userDetails["targetUser"].userName, value); - // } - // }); - // Utils.hideLoading(context); }); } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index c98d136..c5788f9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -10,6 +10,7 @@ class ApiConsts { static String user = baseUrlServices + "api/User/"; static String cocRest = baseUrlServices + "COCWS.svc/REST/"; + //Chat static String chatServerBaseUrl = "https://apiderichat.hmg.com"; static String chatServerBaseApiUrl = "https://apiderichat.hmg.com/api/"; static String chatHubConnectionUrl = chatServerBaseUrl + "/ConnectionChatHub"; @@ -18,12 +19,6 @@ class ApiConsts { static String chatSingleUserHistoryUrl = "UserChatHistory/GetUserChatHistory"; static String chatMediaImageUploadUrl = "shared/upload"; static String chatFavoriteUsers = "FavUser/getFavUserById/"; - //https://apiderichat.hmg.com/api/FavUser/getFavUserById/42062 -//https://apiderichat.hmg.com/api/shared/upload -// 42062 is CurrentUserID and 36745 is targetUserID and 0 is For Pagination - -// static String chatSearchMember = "https://apiderichat.hmg.com/api/user/getUserWithStatusAndFavAsync/aamir.muhammad/36239"; - } class SharedPrefsConsts { diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 1e8aec4..5a878ca 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -29,7 +29,7 @@ class ChatBubble extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - // padding: EdgeInsets.zero, + // padding: EdgeInsets.zero, padding: EdgeInsets.only(left: isCurrentUser ? 110 : 20, right: isCurrentUser ? 20 : 110, bottom: 9), child: Align( @@ -51,7 +51,7 @@ class ChatBubble extends StatelessWidget { borderRadius: BorderRadius.circular(10), ), child: Padding( - padding: EdgeInsets.only(top: isReplied ? 8 : 5, right:8, left: 8, bottom: 5), + padding: EdgeInsets.only(top: isReplied ? 8 : 5, right: 8, left: 8, bottom: 5), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, @@ -85,7 +85,6 @@ class ChatBubble extends StatelessWidget { ), if (isReplied) 8.height, text.toText12(color: isCurrentUser ? MyColors.grey57Color : MyColors.white), - Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, @@ -100,7 +99,6 @@ class ChatBubble extends StatelessWidget { ), ], ), - ], ), ), diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index d2d3598..fe7a968 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -8,19 +8,14 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; -import 'package:mohem_flutter_app/classes/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/ui/chat/chat_bubble.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; -import 'package:mohem_flutter_app/widgets/image_picker.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; -import 'package:sizer/sizer.dart'; import 'package:swipe_to/swipe_to.dart'; class ChatDetailScreen extends StatelessWidget { @@ -30,13 +25,13 @@ class ChatDetailScreen extends StatelessWidget { ScrollController scrollController = ScrollController(); RefreshController _refreshController = RefreshController(initialRefresh: false); - void onRefresh() async { - print("Refresh Triggered"); - await Future.delayed(Duration(milliseconds: 1000)); + void getMoreChat() async { + if (userDetails != null) { data.paginationVal = data.paginationVal + 10; data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true); } + await Future.delayed(Duration(milliseconds: 1000)); _refreshController.refreshCompleted(); } @@ -45,16 +40,6 @@ class ChatDetailScreen extends StatelessWidget { userDetails = ModalRoute.of(context)!.settings.arguments; data = Provider.of(context, listen: false); if (userDetails != null) data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: false); - // - // if (userDetails != null) { - // scrollController.addListener(() { - // if (scrollController.position.minScrollExtent == scrollController.offset) { - // data.paginationVal++; - // data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true); - // } - // }); - // } - return Scaffold( backgroundColor: const Color(0xFFF8F8F8), appBar: AppBarWidget(context, title: userDetails["targetUser"].userName, showHomeButton: false, image: userDetails["targetUser"].image), @@ -73,34 +58,28 @@ class ChatDetailScreen extends StatelessWidget { color: MyColors.gradiantEndColor, ), controller: _refreshController, - onRefresh: onRefresh, + onRefresh: getMoreChat, child: ListView.builder( controller: scrollController, shrinkWrap: true, itemCount: m.userChatHistory.length, padding: EdgeInsets.zero, itemBuilder: (BuildContext context, int i) { - return GestureDetector( - onTap: () { - m.logger.d(jsonEncode(m.userChatHistory[i])); - m.logger.d(jsonEncode(m.userChatHistory.length)); - }, - child: SwipeTo( - iconColor: MyColors.lightGreenColor, - child: ChatBubble( - text: m.userChatHistory[i].contant.toString(), - replyText: m.userChatHistory[i].userChatReplyResponse != null ? m.userChatHistory[i].userChatReplyResponse!.contant.toString() : "", - isSeen: m.userChatHistory[i].isSeen == true ? true : false, - isCurrentUser: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id ? true : false, - isDelivered: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id && m.userChatHistory[i].isDelivered == true ? true : false, - dateTime: m.dateFormte(m.userChatHistory[i].createdDate!), - isReplied: m.userChatHistory[i].userChatReplyResponse != null ? true : false, - userName: AppState().chatDetails!.response!.userName == m.userChatHistory[i].currentUserName.toString() ? "You" : m.userChatHistory[i].currentUserName.toString(), - ), - onRightSwipe: () { - m.chatReply(m.userChatHistory[i]); - }, + return SwipeTo( + iconColor: MyColors.lightGreenColor, + child: ChatBubble( + text: m.userChatHistory[i].contant.toString(), + replyText: m.userChatHistory[i].userChatReplyResponse != null ? m.userChatHistory[i].userChatReplyResponse!.contant.toString() : "", + isSeen: m.userChatHistory[i].isSeen == true ? true : false, + isCurrentUser: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id ? true : false, + isDelivered: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id && m.userChatHistory[i].isDelivered == true ? true : false, + dateTime: m.dateFormte(m.userChatHistory[i].createdDate!), + isReplied: m.userChatHistory[i].userChatReplyResponse != null ? true : false, + userName: AppState().chatDetails!.response!.userName == m.userChatHistory[i].currentUserName.toString() ? "You" : m.userChatHistory[i].currentUserName.toString(), ), + onRightSwipe: () { + m.chatReply(m.userChatHistory[i]); + }, ); }, ), @@ -203,7 +182,7 @@ class ChatDetailScreen extends StatelessWidget { ], ) : null, - suffixIcon: Container( + suffixIcon: SizedBox( width: 96, child: Row( mainAxisAlignment: MainAxisAlignment.end, diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 106a4b3..38388ca 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -27,7 +27,7 @@ class ChatHomeScreen extends StatefulWidget { } class _ChatHomeScreenState extends State { - TextEditingController search = new TextEditingController(); + TextEditingController search = TextEditingController(); late ChatProviderModel data; @override @@ -213,8 +213,6 @@ class _ChatHomeScreenState extends State { apiMode: LocaleKeys.delegate.tr(), fromChat: true, onSelectEmployee: (_selectedEmployee) { - // Navigator.pop(context); - // selectedReplacementEmployee = _selectedEmployee; setState(() {}); }, ), diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index fb14141..63ce88b 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -136,12 +136,13 @@ class _SearchEmployeeBottomSheetState extends State { }, ).expanded, IconButton( - constraints: const BoxConstraints(), - onPressed: () async { - await SystemChannels.textInput.invokeMethod('TextInput.hide'); - widget.fromChat ? fetchChatUser() : fetchUserByInput(); - }, - icon: Icon(Icons.search)) + constraints: const BoxConstraints(), + onPressed: () async { + await SystemChannels.textInput.invokeMethod('TextInput.hide'); + widget.fromChat ? fetchChatUser() : fetchUserByInput(); + }, + icon: const Icon(Icons.search), + ) ], ), if (replacementList != null) @@ -184,62 +185,21 @@ class _SearchEmployeeBottomSheetState extends State { if (chatUsersList != null && widget.fromChat) chatUsersList!.isEmpty ? Column( - children: [ - 20.height, - Utils.getNoDataWidget(context), - ], - ) + children: [ + 20.height, + Utils.getNoDataWidget(context), + ], + ) : ListView( physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.only(top: 15,), + padding: const EdgeInsets.only( + top: 15, + ), children: [ ListView.separated( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (BuildContext cxt, int index) { - - - - - // return ListTile( - // leading: Stack( - // children: [ - // SvgPicture.asset( - // "assets/images/user.svg", - // height: 48, - // width: 48, - // ), - // Positioned( - // right: 5, - // bottom: 1, - // child: Container( - // width: 10, - // height: 10, - // decoration: BoxDecoration( - // color: chatUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, - // borderRadius: const BorderRadius.all( - // Radius.circular(10), - // ), - // ), - // ), - // ) - // ], - // ), - // title: (chatUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), - // // subtitle: (chatUsersList![index].isTyping == true ? "Something is Typing" : "Last message text").toText11(color: MyColors.normalTextColor), - // // trailing: ("Today").toText10(color: MyColors.lightTextColor), - // minVerticalPadding: 0, - // onTap: () { - // Navigator.pop(context); - // Navigator.pushNamed( - // context, - // AppRoutes.chatDetailed, - // arguments: {"targetUser": chatUsersList![index]}, - // ); - // }, - // ); - - return SizedBox( height: 55, child: ListTile( @@ -279,12 +239,9 @@ class _SearchEmployeeBottomSheetState extends State { onLongPress: () {}, ), ); - - - }, separatorBuilder: (BuildContext context, int index) => const Padding( - padding: EdgeInsets.only(right: 10, left: 70, bottom: 0,top: 0), + padding: EdgeInsets.only(right: 10, left: 70, bottom: 0, top: 0), child: Divider( color: Color(0xFFE5E5E5), ), @@ -349,7 +306,9 @@ class _SearchEmployeeBottomSheetState extends State { decoration: BoxDecoration( color: Colors.transparent, border: Border.all(color: MyColors.borderColor, width: 1), - borderRadius: const BorderRadius.all(Radius.circular(100)), + borderRadius: const BorderRadius.all( + Radius.circular(100), + ), ), padding: const EdgeInsets.all(4), child: Container( @@ -357,7 +316,9 @@ class _SearchEmployeeBottomSheetState extends State { height: double.infinity, decoration: BoxDecoration( color: value == groupValue ? MyColors.grey3AColor : Colors.transparent, - borderRadius: BorderRadius.all(const Radius.circular(100)), + borderRadius: const BorderRadius.all( + Radius.circular(100), + ), ), ), ), From 6fe015d10466c850e94731fc5678f42f2650d02d Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 10 Nov 2022 16:25:48 +0300 Subject: [PATCH 20/82] fixes --- lib/ui/work_list/sheets/selected_item_sheet.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ui/work_list/sheets/selected_item_sheet.dart b/lib/ui/work_list/sheets/selected_item_sheet.dart index 4f7f6b3..54f87d0 100644 --- a/lib/ui/work_list/sheets/selected_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_item_sheet.dart @@ -140,7 +140,7 @@ class SelectedItemSheet extends StatelessWidget { Future performNetworkCall(BuildContext context, {String? email, String? userId}) async { Utils.showLoading(context); try { - await WorkListApiClient().submitComment(comment: comment, email: email, userId: userId, notificationId: notificationID, apiMode: apiMode, approverIndex: actionHistoryList!.sEQUENCE); + await WorkListApiClient().submitComment(comment: comment, email: email, userId: userId, notificationId: notificationID, apiMode: apiMode, approverIndex: actionHistoryList != null ? actionHistoryList!.sEQUENCE : null); Utils.hideLoading(context); // Navigator.pop(context); // Navigator.pop(context); @@ -212,7 +212,7 @@ class SelectedItemSheet extends StatelessWidget { : CircularAvatar( height: 40, width: 40, - ).toShimmer() + ) : (actionHistoryList != null && actionHistoryList!.eMPLOYEEIMAGE != null) ? CircularAvatar( height: 40, @@ -223,7 +223,7 @@ class SelectedItemSheet extends StatelessWidget { : CircularAvatar( height: 40, width: 40, - ).toShimmer(), + ), 16.width, Expanded( child: (name ?? "").toText12(), From ea8fd42abd83fcee9544b909c3b534096808666d Mon Sep 17 00:00:00 2001 From: "mirza.shafique" Date: Sun, 13 Nov 2022 11:12:50 +0300 Subject: [PATCH 21/82] Otp clear & resend fixed --- lib/classes/consts.dart | 4 +- lib/dialogs/otp_dialog.dart | 125 ++++++++++++--------- lib/ui/login/forgot_password_screen.dart | 28 +++-- lib/ui/login/login_screen.dart | 4 +- lib/ui/login/verify_last_login_screen.dart | 16 ++- lib/ui/login/verify_login_screen.dart | 4 +- 6 files changed, 105 insertions(+), 76 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index c5788f9..646e498 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/dialogs/otp_dialog.dart b/lib/dialogs/otp_dialog.dart index 3952e70..9158b94 100644 --- a/lib/dialogs/otp_dialog.dart +++ b/lib/dialogs/otp_dialog.dart @@ -11,10 +11,12 @@ import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/otp_widget.dart'; import 'package:sizer/sizer.dart'; +final ValueNotifier otpFieldClear = ValueNotifier(""); + class OtpDialog { final int type; final int? mobileNo; - final Function(String) onSuccess; + final Function(String, TextEditingController _pinPutController) onSuccess; final Function onFailure; final BuildContext context; final Function onResendCode; @@ -96,58 +98,70 @@ class OtpDialog { 6.height, (LocaleKeys.pleaseEnterTheVerificationCodeSentTo.tr() + ' xxxxxxxx' + mobileNo.toString().substring(mobileNo.toString().length - 3)).toText16(), 18.height, - Directionality( - textDirection: TextDirection.ltr, - child: Center( - child: OTPWidget( - autoFocus: true, - controller: _pinPutController, - defaultBorderColor: const Color(0xffD8D8D8), - maxLength: 4, - onTextChanged: (text) {}, - pinBoxColor: Colors.white, - onDone: (code) => _onOtpCallBack(code, null), - textBorderColor: const Color(0xffD8D8D8), - pinBoxWidth: 60, - pinBoxHeight: 60, - pinTextStyle: const TextStyle(fontSize: 24.0, color: MyColors.darkTextColor), - pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition, - pinTextAnimatedSwitcherDuration: const Duration(milliseconds: 300), - pinBoxRadius: 10, - keyboardType: TextInputType.number, - ), - ), - ), - 10.height, - stopTimer - ? Row( - children: [ - Expanded( - child: LocaleKeys.codeExpire.tr().toText16( - color: MyColors.redColor, - ), - ), - 12.width, - Image.asset( - "assets/icons/ic_alarm.png", - width: 20, - height: 20, - color: MyColors.redColor, - ), - ], - ) - : RichText( - text: TextSpan( - text: LocaleKeys.theVerificationCodeWillExpireIn.tr() + '\n', - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -0.48), - children: [ - TextSpan( - text: displayTime, - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.textMixColor, letterSpacing: -0.48), + ValueListenableBuilder( + builder: (BuildContext context, String value, Widget? child) { + // This builder will only get called when the _counter + // is updated. + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Directionality( + textDirection: TextDirection.ltr, + child: Center( + child: OTPWidget( + autoFocus: true, + controller: _pinPutController, + defaultBorderColor: const Color(0xffD8D8D8), + maxLength: 4, + onTextChanged: (text) {}, + pinBoxColor: Colors.white, + onDone: (code) => _onOtpCallBack(code, null), + textBorderColor: const Color(0xffD8D8D8), + pinBoxWidth: 60, + pinBoxHeight: 60, + pinTextStyle: const TextStyle(fontSize: 24.0, color: MyColors.darkTextColor), + pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition, + pinTextAnimatedSwitcherDuration: const Duration(milliseconds: 300), + pinBoxRadius: 10, + keyboardType: TextInputType.number, ), - ], + ), ), - ), + 10.height, + stopTimer + ? Row( + children: [ + Expanded( + child: LocaleKeys.codeExpire.tr().toText16( + color: MyColors.redColor, + ), + ), + 12.width, + Image.asset( + "assets/icons/ic_alarm.png", + width: 20, + height: 20, + color: MyColors.redColor, + ), + ], + ) + : RichText( + text: TextSpan( + text: LocaleKeys.theVerificationCodeWillExpireIn.tr() + '\n', + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -0.48), + children: [ + TextSpan( + text: displayTime, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.textMixColor, letterSpacing: -0.48), + ), + ], + ), + ), + ], + ); + }, + valueListenable: otpFieldClear, + ), 18.height, DefaultButton( stopTimer ? LocaleKeys.resend.tr() : LocaleKeys.cancel.tr(), @@ -238,14 +252,15 @@ class OtpDialog { }); } - static void hideSMSBox(context) { - Navigator.pop(context); + void hideSMSBox(context) { + onFailure(); } void _onOtpCallBack(String otpCode, bool? isAutofill) { if (otpCode.length == 4) { - stopTimer = true; - onSuccess(otpCode); + // stopTimer = true; + otpFieldClear.value = otpCode; + onSuccess(otpCode, _pinPutController); } } diff --git a/lib/ui/login/forgot_password_screen.dart b/lib/ui/login/forgot_password_screen.dart index 6c1868e..b2d5c92 100644 --- a/lib/ui/login/forgot_password_screen.dart +++ b/lib/ui/login/forgot_password_screen.dart @@ -50,17 +50,25 @@ class _ForgotPasswordScreenState extends State { context, 1, int.tryParse(_basicMemberInformation?.pMOBILENUMBER ?? ""), - (value) async { + (value,TextEditingController _pinPutController) async { Utils.showLoading(context); - GenericResponseModel? genericResponseModel = await LoginApiClient().checkPublicActivationCode(value, employeeId.text); - if (genericResponseModel?.errorMessage != null) { - Utils.showToast(genericResponseModel?.errorMessage ?? ""); - return; - } - Utils.hideLoading(context); - await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: employeeId.text); - Navigator.pop(context); - Navigator.pop(context); + try{ + GenericResponseModel? genericResponseModel = await LoginApiClient().checkPublicActivationCode(value, employeeId.text); + if (genericResponseModel?.errorMessage != null) { + Utils.showToast(genericResponseModel?.errorMessage ?? ""); + return; + } + Utils.hideLoading(context); + await Navigator.pushNamed(context, AppRoutes.newPassword, arguments: employeeId.text); + Navigator.pop(context); + Navigator.pop(context); + }catch(ex){ + print(ex); + _pinPutController.clear(); + otpFieldClear.value = ""; + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } }, () => { Navigator.pop(context), diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 20fa8bc..97282d3 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -142,8 +142,8 @@ class _LoginScreenState extends State { isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool; if (!kReleaseMode) { // username.text = "15444"; // Maha User - // username.text = "15153"; // Tamer User - // password.text = "Abcd@12345"; + username.text = "15153"; // Tamer User + password.text = "Abcd@12345"; // username.text = "206535"; // Hashim User // password.text = "Namira786"; diff --git a/lib/ui/login/verify_last_login_screen.dart b/lib/ui/login/verify_last_login_screen.dart index 0b07b43..81d1ba2 100644 --- a/lib/ui/login/verify_last_login_screen.dart +++ b/lib/ui/login/verify_last_login_screen.dart @@ -335,16 +335,16 @@ class _VerifyLastLoginScreenState extends State { if (!isDirectLogin) BasicMemberInformationModel? memberInformationModel = await LoginApiClient().mohemmSendActivationCodeByOTPNotificationType(0, AppState().memberLoginList?.pMOBILENUMBER, sendVerificationFlat, AppState().getUserName); - if (isDirectLogin) performDirectApiCall(_title, _icon, _flag, ""); + if (isDirectLogin) performDirectApiCall(_title, _icon, _flag, "", null); if (!isDirectLogin) Utils.hideLoading(context); if (!isDirectLogin) OtpDialog( context, sendVerificationFlat, int.tryParse(AppState().memberLoginList?.pMOBILENUMBER ?? ""), - (value) async { + (value, TextEditingController _pinPutController) async { Utils.showLoading(context); - performDirectApiCall(_title, _icon, _flag, value); + performDirectApiCall(_title, _icon, _flag, value, _pinPutController); }, () => { Navigator.pop(context), @@ -359,7 +359,7 @@ class _VerifyLastLoginScreenState extends State { } } - Future performDirectApiCall(String _title, String _icon, int _flag, String value, {bool isDirectLogin = false}) async { + Future performDirectApiCall(String _title, String _icon, int _flag, String value, TextEditingController? _pinPutController, {bool isDirectLogin = false}) async { try { GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(false, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW( @@ -372,14 +372,18 @@ class _VerifyLastLoginScreenState extends State { mobileLoginInfoListModel!.deviceToken!, Platform.isAndroid ? "android" : "ios"); AppState().setMemberInformationListModel = genericResponseModel!.memberInformationList?.first; - if (genericResponseModel?.errorMessage != null) { - Utils.showToast(genericResponseModel?.errorMessage ?? ""); + if (genericResponseModel.errorMessage != null) { + Utils.showToast(genericResponseModel.errorMessage ?? ""); // Navigator.pop(context); } Utils.hideLoading(context); Navigator.pop(context); Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboard, (Route route) => false); } catch (ex) { + if (_pinPutController != null) { + _pinPutController.clear(); + otpFieldClear.value = ""; + } Utils.hideLoading(context); Utils.handleException(ex, context, null); } diff --git a/lib/ui/login/verify_login_screen.dart b/lib/ui/login/verify_login_screen.dart index 8dba16c..ce21b63 100644 --- a/lib/ui/login/verify_login_screen.dart +++ b/lib/ui/login/verify_login_screen.dart @@ -617,7 +617,7 @@ class _VerifyLoginScreenState extends State { context, sendVerificationFlat, int.tryParse(AppState().memberLoginList?.pMOBILENUMBER ?? ""), - (value) async { + (value, TextEditingController _pinPutController) async { Utils.showLoading(context); try { GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(true, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); @@ -652,6 +652,8 @@ class _VerifyLoginScreenState extends State { Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboard, (Route route) => false); } catch (ex) { print(ex); + _pinPutController.clear(); + otpFieldClear.value = ""; Utils.hideLoading(context); Utils.handleException(ex, context, null); } From c2a4df89bb518fdb775c3a9957ab14b3f2cf63c2 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 13 Nov 2022 11:19:21 +0300 Subject: [PATCH 22/82] offers & discouts --- .../offers_and_discounts/offers_and_discounts_home.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart b/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart index 45247dc..343eed8 100644 --- a/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart +++ b/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart @@ -173,7 +173,7 @@ class _OffersAndDiscountsHomeState extends State { tag: "ItemImage" + getOffersList.rowID!, transitionOnUserGestures: true, child: AspectRatio( - aspectRatio: 148 / 127, + aspectRatio: 118 / 127, child: ClipRRect( borderRadius: BorderRadius.circular(6), child: Image.network( @@ -192,10 +192,10 @@ class _OffersAndDiscountsHomeState extends State { // // launchUrl(Uri.parse(url!)); // // } // ), - getOffersList.description!.toText12(maxLine: 2, color: const Color(0xff535353)), + // getOffersList.description!.toText12(maxLine: 2, color: const Color(0xff535353)), // 8.height, getOffersList.discount!.toText14(isBold: true, maxlines: 1), - 10.height, + 20.height, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [checkDate(getOffersList.endDate!), SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4)], @@ -211,7 +211,7 @@ class _OffersAndDiscountsHomeState extends State { if (enteredKeyword.isEmpty) { results = getOffersList; } else { - if(AppState().isArabic(context)) { + if (AppState().isArabic(context)) { results = getOffersList.where((offer) => offer.titleAR!.toLowerCase().contains(enteredKeyword.toLowerCase())).toList(); } else { results = getOffersList.where((offer) => offer.title!.toLowerCase().contains(enteredKeyword.toLowerCase())).toList(); From 55ff08c3f3f3e813f7258e30ea796d099e58d9fe Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 13 Nov 2022 13:50:35 +0300 Subject: [PATCH 23/82] Chat Favorite Screen & Fixes --- assets/langs/ar-SA.json | 5 +- assets/langs/en-US.json | 5 +- lib/api/chat/chat_provider_model.dart | 45 ++-- lib/classes/consts.dart | 4 +- lib/config/routes.dart | 5 +- lib/generated/locale_keys.g.dart | 2 + lib/ui/chat/chat_bubble.dart | 4 +- lib/ui/chat/chat_detailed_screen.dart | 3 +- lib/ui/chat/chat_home.dart | 275 +++++++------------------ lib/ui/chat/chat_home_screen.dart | 226 ++++++++++++++++++++ lib/ui/chat/favorite_users_screen.dart | 102 +++++++++ lib/widgets/image_picker.dart | 2 +- 12 files changed, 445 insertions(+), 233 deletions(-) create mode 100644 lib/ui/chat/chat_home_screen.dart create mode 100644 lib/ui/chat/favorite_users_screen.dart diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index f72ea36..bdec4f0 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -498,5 +498,8 @@ "verification": "تَحَقّق", "resend": "إعادة إرسال", "codeExpire": "انتهت صلاحية رمز التحقق", - "typeheretoreply": "اكتب هنا للرد" + "typeheretoreply": "اكتب هنا للرد", + "favorite" : "مفضل", + "searchfromchat": "البحث من الدردشة" + } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index e0b9019..1cd1a33 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -498,5 +498,8 @@ "resend": "Resend", "codeExpire": "The verification code has been expired", "allQuestionsCorrect": "You have answered all questions correct", - "typeheretoreply": "Type here to reply" + "typeheretoreply": "Type here to reply", + "favorite" : "Favorite", + "searchfromchat": "Search from chat" + } \ No newline at end of file diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index b85aa85..4e79374 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -33,6 +33,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { String sFileType = ""; bool isMsgReply = false; List repliedMsg = []; + List favUsersList = []; int paginationVal = 0; Future getUserAutoLoginToken() async { @@ -60,25 +61,26 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { token: AppState().chatDetails!.response!.token, ); - logger.d(AppState().chatDetails!.response!.token); + //logger.d(AppState().chatDetails!.response!.token); ChatUserModel recentChat = userToList(response.body); Response favRes = await ApiClient().getJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}", token: AppState().chatDetails!.response!.token, ); - print("============================== Fav Response ====================================="); - ChatUserModel favUsersList = userToList(favRes.body); - for (var user in recentChat.response!) { - for (var favUser in favUsersList.response!) { - logger.d(favUser.isFav); - if (user.id == favUser.id) { - user.isFav = favUser.isFav; + ChatUserModel favUList = userToList(favRes.body); + if (favUList.response != null) { + favUsersList = favUList.response!; + for (dynamic user in recentChat.response!) { + for (dynamic favUser in favUList.response!) { + if (user.id == favUser.id) { + user.isFav = favUser.isFav; + } } } } - pChatHistory = recentChat.response; + pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase()!.compareTo(b.userName!.toLowerCase()!)); searchedChats = pChatHistory; isLoading = false; notifyListeners(); @@ -87,7 +89,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore}) async { isLoading = true; if (!loadMore) paginationVal = 0; - logger.d(paginationVal); isChatScreenActive = true; Response response = await ApiClient().getJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", @@ -150,24 +151,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ({String? connectionId}) {}, ); if (hubConnection.state != HubConnectionState.Connected) { + print("================= Connection Established =========================="); await hubConnection.start(); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - hubConnection.on("OnUserTypingAsync", onUserTyping); + //hubConnection.on("OnUserTypingAsync", onUserTyping); // hubConnection.on("OnUserCountAsync", userCountAsync); - // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); + hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); - } else { - hubConnection.on("OnUpdateUserStatusAsync", changeStatus); - hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - - hubConnection.on("OnUserTypingAsync", onUserTyping); - // hubConnection.on("OnUserCountAsync", userCountAsync); - // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); - // hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); - hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); } isLoading = false; notifyListeners(); @@ -189,8 +182,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void userCountAsync(List? args) { List items = args!.toList(); - print("---------------------------------User Count Async -------------------------------------"); - logger.d(items); + //print("---------------------------------User Count Async -------------------------------------"); + //logger.d(items); // for (var user in searchedChats!) { // if (user.id == items.first["id"]) { // user.userStatus = items.first["userStatus"]; @@ -537,7 +530,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } String dateFormte(DateTime data) { - DateFormat f = new DateFormat('hh:mm a dd MMM yyyy'); + DateFormat f = DateFormat('hh:mm a dd MMM yyyy'); f.format(data); return f.format(data); } @@ -547,9 +540,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token); fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); if (favoriteChatUser.response != null) { - for (var user in searchedChats!) { + for (ChatUser user in searchedChats!) { if (user.id == favoriteChatUser.response!.targetUserId!) { user.isFav = favoriteChatUser.response!.isFav; + favUsersList.add(user); } } } @@ -566,6 +560,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { user.isFav = favoriteChatUser.response!.isFav; } } + favUsersList.removeWhere((ChatUser element) => element.id == targetUserID); } notifyListeners(); } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index c5788f9..ede22e3 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 1fcbf2e..ab3fb9a 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -5,6 +5,7 @@ import 'package:mohem_flutter_app/ui/attendance/vacation_rule_screen.dart'; import 'package:mohem_flutter_app/ui/bottom_sheets/attendence_details_bottom_sheet.dart'; 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/survey_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart'; @@ -177,6 +178,7 @@ class AppRoutes { //Chat static const String chat = "/chat"; static const String chatDetailed = "/chatDetailed"; + static const String chatFavoriteUsers = "/chatFavoriteUsers"; //Marathon static const String marathonIntroScreen = "/marathonIntroScreen"; @@ -287,8 +289,9 @@ class AppRoutes { changePassword: (BuildContext context) => ChangePasswordScreen(), //Chat - chat: (BuildContext context) => ChatHomeScreen(), + chat: (BuildContext context) => ChatHome(), chatDetailed: (BuildContext context) => ChatDetailScreen(), + chatFavoriteUsers: (BuildContext context) => ChatFavoriteUsersScreen(), // Marathon marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(), diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index f52bb89..f5d4960 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -485,5 +485,7 @@ abstract class LocaleKeys { static const resend = 'resend'; static const codeExpire = 'codeExpire'; static const typeheretoreply = 'typeheretoreply'; + static const favorite = 'favorite'; + static const searchfromchat = 'searchfromchat'; } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 5a878ca..d9bd599 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -36,7 +36,7 @@ class ChatBubble extends StatelessWidget { alignment: isCurrentUser ? Alignment.centerRight : Alignment.centerLeft, child: DecoratedBox( decoration: BoxDecoration( - color: Colors.white, + color: MyColors.white, gradient: isCurrentUser ? null : const LinearGradient( @@ -89,7 +89,7 @@ class ChatBubble extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : Colors.white.withOpacity(0.7)), + dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7)), if (isCurrentUser) 5.width, if (isCurrentUser) Icon( diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index fe7a968..c13e6d3 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -26,7 +26,6 @@ class ChatDetailScreen extends StatelessWidget { RefreshController _refreshController = RefreshController(initialRefresh: false); void getMoreChat() async { - if (userDetails != null) { data.paginationVal = data.paginationVal + 10; data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true); @@ -63,7 +62,7 @@ class ChatDetailScreen extends StatelessWidget { controller: scrollController, shrinkWrap: true, itemCount: m.userChatHistory.length, - padding: EdgeInsets.zero, + padding: const EdgeInsets.only(top: 20), itemBuilder: (BuildContext context, int i) { return SwipeTo( iconColor: MyColors.lightGreenColor, diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 38388ca..5176273 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -1,224 +1,103 @@ -import 'dart:convert'; - import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; -import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/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/ui/chat/chat_home_screen.dart'; +import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; +import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/items_for_sale.dart'; +import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/my_posted_ads_fragment.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; -import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; -import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; -import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; -import 'package:provider/provider.dart'; -import 'package:sizer/sizer.dart'; -class ChatHomeScreen extends StatefulWidget { - const ChatHomeScreen({Key? key}) : super(key: key); +class ChatHome extends StatefulWidget { + const ChatHome({Key? key}) : super(key: key); @override - State createState() => _ChatHomeScreenState(); + State createState() => _ChatHomeState(); } -class _ChatHomeScreenState extends State { - TextEditingController search = TextEditingController(); - late ChatProviderModel data; - - @override - void initState() { - super.initState(); - data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().whenComplete(() { - data.getUserRecentChats(); - }); - } - - @override - void dispose() { - super.dispose(); - } +class _ChatHomeState extends State { + int tabIndex = 0; + PageController controller = PageController(); @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: Colors.white, - appBar: AppBarWidget(context, title: LocaleKeys.mychats.tr(), showHomeButton: false), - body: Consumer(builder: (BuildContext context, ChatProviderModel m, Widget? child) { - return m.isLoading - ? ChatHomeShimmer() - : ListView( - shrinkWrap: true, - physics: const AlwaysScrollableScrollPhysics(), - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 20), - child: TextField( - onChanged: (String val) { - m.filter(val); - }, - decoration: InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: const BorderSide( - color: Color(0xFFE5E5E5), - ), - ), - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), - hintText: "Search from chat", - hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic), - filled: true, - fillColor: const Color(0xFFF7F7F7), - ), - ), - ), - if (m.searchedChats != null) - ListView.separated( - itemCount: m.searchedChats!.length, - padding: const EdgeInsets.only(top: 20), - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (BuildContext context, int index) { - return SizedBox( - height: 55, - child: ListTile( - leading: Stack( - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 48, - width: 48, - ), - Positioned( - right: 5, - bottom: 1, - child: Container( - width: 10, - height: 10, - decoration: BoxDecoration( - color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, - borderRadius: const BorderRadius.all( - Radius.circular(10), - ), - ), - ), - ) - ], - ), - title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor), - // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), - trailing: SizedBox( - width: 60, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - if (m.searchedChats![index].unreadMessageCount! > 0) - Flexible( - child: Container( - padding: EdgeInsets.zero, - alignment: Alignment.centerRight, - width: 18, - height: 18, - decoration: const BoxDecoration( - color: MyColors.redColor, - borderRadius: BorderRadius.all( - Radius.circular(20), - ), - ), - child: (m.searchedChats![index].unreadMessageCount!.toString()) - .toText10( - color: MyColors.white, - ) - .center, - ), - ), - Flexible( - child: IconButton( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(m.searchedChats![index].isFav! ? Icons.star : Icons.star_border), - color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, - onPressed: () { - if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); - if (!m.searchedChats![index].isFav!) m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); - }, - ), - ) - ], - ), - ), - minVerticalPadding: 0, - onTap: () { - Navigator.pushNamed( - context, - AppRoutes.chatDetailed, - arguments: {"targetUser": m.searchedChats![index]}, - ).then((value) { - m.clearSelections(); - }); - }, - onLongPress: () {}, - ), - ); - }, - separatorBuilder: (BuildContext context, int index) => const Padding( - padding: EdgeInsets.only(right: 10, left: 70), - child: Divider( - color: Color(0xFFE5E5E5), - ), - ), - ), + backgroundColor: MyColors.white, + appBar: AppBarWidget( + context, + title: LocaleKeys.chat.tr(), + showHomeButton: true, + ), + body: 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, ], - ); - }), - floatingActionButton: FloatingActionButton( - child: Container( - width: 60, - height: 60, - decoration: const BoxDecoration( - shape: BoxShape.circle, - gradient: LinearGradient( - transform: GradientRotation(.46), - begin: Alignment.topRight, - end: Alignment.bottomLeft, - colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, + ), + ), + child: Row( + children: [ + myTab(LocaleKeys.mychats.tr(), 0), + myTab( + LocaleKeys.favorite.tr(), + 1) ], ), ), - child: const Icon( - Icons.add, - size: 30, - color: MyColors.white, - ), - ), - onPressed: () async { - showMyBottomSheet( - context, - callBackFunc: () {}, - child: SearchEmployeeBottomSheet( - title: LocaleKeys.searchForEmployee.tr(), - apiMode: LocaleKeys.delegate.tr(), - fromChat: true, - onSelectEmployee: (_selectedEmployee) { - setState(() {}); - }, - ), - ); - }, + PageView( + controller: controller, + physics: const NeverScrollableScrollPhysics(), + onPageChanged: (int pageIndex) { + setState(() { + tabIndex = pageIndex; + }); + }, + children: [ChatHomeScreen(), ChatFavoriteUsersScreen()], + ).expanded, + ], ), ); } + + Widget myTab(String title, int index) { + bool isSelected = (index == tabIndex); + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + title.toText12(color: isSelected ? MyColors.white : MyColors.white.withOpacity(.74), isCenter: true), + 4.height, + Container( + height: 8, + width: 8, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: isSelected ? MyColors.white : Colors.transparent, + ), + ).onPress(() { + setState(() { + // showFabOptions = true; + }); + }) + ], + ).onPress(() { + controller.jumpToPage(index); + }).expanded; + } } diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart new file mode 100644 index 0000000..328354b --- /dev/null +++ b/lib/ui/chat/chat_home_screen.dart @@ -0,0 +1,226 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; +import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; +import 'package:provider/provider.dart'; + +class ChatHomeScreen extends StatefulWidget { + const ChatHomeScreen({Key? key}) : super(key: key); + + @override + State createState() => _ChatHomeScreenState(); +} + +class _ChatHomeScreenState extends State { + TextEditingController search = TextEditingController(); + late ChatProviderModel data; + + @override + void initState() { + super.initState(); + data = Provider.of(context, listen: false); + data.getUserAutoLoginToken().whenComplete(() { + data.getUserRecentChats(); + }); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.white, + body: Consumer(builder: (BuildContext context, ChatProviderModel m, Widget? child) { + return m.isLoading + ? ChatHomeShimmer() + : ListView( + shrinkWrap: true, + physics: const AlwaysScrollableScrollPhysics(), + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + child: TextField( + onChanged: (String val) { + m.filter(val); + }, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE5E5E5), + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE5E5E5), + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE5E5E5), + ), + ), + contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + hintText: LocaleKeys.searchfromchat.tr(), + hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic), + filled: true, + fillColor: const Color(0xFFF7F7F7), + ), + ), + ), + if (m.searchedChats != null) + ListView.separated( + itemCount: m.searchedChats!.length, + padding: const EdgeInsets.only(bottom: 80), + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return SizedBox( + height: 55, + child: ListTile( + leading: Stack( + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), + ), + ), + ) + ], + ), + title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor), + // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), + trailing: SizedBox( + width: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + if (m.searchedChats![index].unreadMessageCount! > 0) + Flexible( + child: Container( + padding: EdgeInsets.zero, + alignment: Alignment.centerRight, + width: 18, + height: 18, + decoration: const BoxDecoration( + color: MyColors.redColor, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + child: (m.searchedChats![index].unreadMessageCount!.toString()) + .toText10( + color: MyColors.white, + ) + .center, + ), + ), + Flexible( + child: IconButton( + alignment: Alignment.centerRight, + padding: EdgeInsets.zero, + icon: Icon(m.searchedChats![index].isFav! ? Icons.star : Icons.star_border), + color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, + onPressed: () { + if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + if (!m.searchedChats![index].isFav!) m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + }, + ), + ) + ], + ), + ), + minVerticalPadding: 0, + onTap: () { + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": m.searchedChats![index]}, + ).then((value) { + m.clearSelections(); + }); + }, + onLongPress: () {}, + ), + ); + }, + separatorBuilder: (BuildContext context, int index) => const Padding( + padding: EdgeInsets.only(right: 10, left: 70), + child: Divider( + color: Color(0xFFE5E5E5), + ), + ), + ), + ], + ); + }), + floatingActionButton: FloatingActionButton( + child: Container( + width: 60, + height: 60, + decoration: const BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + transform: GradientRotation(.46), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), + ), + child: const Icon( + Icons.add, + size: 30, + color: MyColors.white, + ), + ), + onPressed: () async { + showMyBottomSheet( + context, + callBackFunc: () {}, + child: SearchEmployeeBottomSheet( + title: LocaleKeys.searchForEmployee.tr(), + apiMode: LocaleKeys.delegate.tr(), + fromChat: true, + onSelectEmployee: (_selectedEmployee) { + setState(() {}); + }, + ), + ); + }, + ), + ); + } +} diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart new file mode 100644 index 0000000..b84b827 --- /dev/null +++ b/lib/ui/chat/favorite_users_screen.dart @@ -0,0 +1,102 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; +import 'package:provider/provider.dart'; + +class ChatFavoriteUsersScreen extends StatelessWidget { + const ChatFavoriteUsersScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Scaffold( + backgroundColor: MyColors.white, + body: Consumer(builder: (BuildContext context, ChatProviderModel m, Widget? child) { + return m.isLoading + ? ChatHomeShimmer() + : ListView( + shrinkWrap: true, + physics: const AlwaysScrollableScrollPhysics(), + padding: const EdgeInsets.only(top: 20), + children: [ + if (m.favUsersList != null && m.favUsersList.isNotEmpty) + ListView.separated( + itemCount: m.favUsersList!.length, + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return SizedBox( + height: 55, + child: ListTile( + leading: Stack( + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: m.favUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), + ), + ), + ) + ], + ), + title: (m.favUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), + // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), + trailing: IconButton( + alignment: Alignment.centerRight, + padding: EdgeInsets.zero, + icon: Icon(m.favUsersList![index].isFav! ? Icons.star : Icons.star_border), + color: m.favUsersList![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, + onPressed: () { + if (m.favUsersList![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.favUsersList![index].id!); + }, + ), + minVerticalPadding: 0, + onTap: () { + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": m.favUsersList![index]}, + ).then((value) { + m.clearSelections(); + }); + }, + onLongPress: () {}, + ), + ); + }, + separatorBuilder: (BuildContext context, int index) => const Padding( + padding: EdgeInsets.only(right: 10, left: 70), + child: Divider( + color: Color(0xFFE5E5E5), + ), + ), + ) + else + Utils.getNoDataWidget(context).expanded + ], + ); + }), + ); + } +} diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index 9fa0336..f92f9f4 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -48,7 +48,7 @@ class ImageOptions { allowedExtensions: ['jpg', 'jpeg ', 'pdf', 'txt', 'docx', 'doc', 'pptx', 'xlsx', 'png', 'rar', 'zip', 'xls'], ); List files = result!.paths.map((path) => File(path!)).toList(); - image(result!.files.first.path.toString(), files.first); + image(result.files.first.path.toString(), files.first); }, ), ); From cffe185cdad9f6ecc1b65a53b49399173b75a3c3 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 13 Nov 2022 16:32:53 +0300 Subject: [PATCH 24/82] ITG Count fixes --- lib/app_state/app_state.dart | 6 ++++++ lib/classes/consts.dart | 4 ++-- lib/ui/login/login_screen.dart | 4 ++-- lib/ui/work_list/item_history_screen.dart | 12 ++++++++---- lib/ui/work_list/itg_detail_screen.dart | 6 ++++++ lib/ui/work_list/work_list_screen.dart | 1 + 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 9e61872..49f4186 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -120,6 +120,12 @@ class AppState { set setItgWorkListIndex(int? _itgWorkListIndex) => itgWorkListIndex = _itgWorkListIndex; + String? itgRequestType; + + set setItgRequestType(String? _itgRequestType) => itgRequestType = _itgRequestType; + + String? get getItgRequestType => itgRequestType; + UserAutoLoginModel? chatDetails; set setchatUserDetails(UserAutoLoginModel details) => chatDetails = details; diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 646e498..789ef40 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 97282d3..20fa8bc 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -142,8 +142,8 @@ class _LoginScreenState extends State { isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool; if (!kReleaseMode) { // username.text = "15444"; // Maha User - username.text = "15153"; // Tamer User - password.text = "Abcd@12345"; + // username.text = "15153"; // Tamer User + // password.text = "Abcd@12345"; // username.text = "206535"; // Hashim User // password.text = "Namira786"; diff --git a/lib/ui/work_list/item_history_screen.dart b/lib/ui/work_list/item_history_screen.dart index 782e34d..fb1066b 100644 --- a/lib/ui/work_list/item_history_screen.dart +++ b/lib/ui/work_list/item_history_screen.dart @@ -86,9 +86,9 @@ class _ItemHistoryScreenState extends State { padding: const EdgeInsets.all(21), physics: const BouncingScrollPhysics(), children: [ - if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData(), - if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData(), - if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData() + if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData() else Utils.getNoDataWidget(context), + if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData() else Utils.getNoDataWidget(context), + if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData() else Utils.getNoDataWidget(context) ], ), ); @@ -163,7 +163,11 @@ class _ItemHistoryScreenState extends State { ItemDetailViewCol(LocaleKeys.balanceQuantity.tr(), poItemHistoryList[index].bALANCEQUANTITY?.toString() ?? ""), ItemDetailViewCol(LocaleKeys.netPrice.tr(), poItemHistoryList[index].nETPRICE?.toString() ?? ""), ), - ItemDetailGrid(ItemDetailViewCol(LocaleKeys.closureStatus.tr(), poItemHistoryList[index].cLOSEDCODE ?? ""), Container(), isItLast: true,) + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.closureStatus.tr(), poItemHistoryList[index].cLOSEDCODE ?? ""), + Container(), + isItLast: true, + ) ], ).objectContainerView(), separatorBuilder: (cxt, index) => 12.height, diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index 0a29a72..bbb0267 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -14,6 +14,7 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/allowed_actions_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/itg_request_model.dart'; import 'package:mohem_flutter_app/models/itg_forms_models/request_detail_model.dart'; +import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/work_list/itg_fragments/approval_level_fragment.dart'; import 'package:mohem_flutter_app/ui/work_list/itg_fragments/request_detail_fragment.dart'; import 'package:mohem_flutter_app/ui/work_list/sheets/delegate_sheet.dart'; @@ -21,6 +22,7 @@ import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dialogs/itg_comments_dialog.dart'; +import 'package:provider/provider.dart'; class ItgDetailScreen extends StatefulWidget { ItgDetailScreen({Key? key}) : super(key: key); @@ -42,8 +44,11 @@ class _ItgDetailScreenState extends State { List allowedActionList = []; + late DashboardProviderModel providerData; + @override void initState() { + providerData = Provider.of(context, listen: false); super.initState(); } @@ -78,6 +83,7 @@ class _ItgDetailScreenState extends State { void getDataFromState() { if (requestDetails == null) { requestDetails = AppState().requestAllList![AppState().itgWorkListIndex!]; // ModalRoute.of(context)!.settings.arguments as WorkListResponseModel; + providerData.itgFormsModel!.totalCount = providerData.itgFormsModel!.totalCount! - 1; getItgData(); } } diff --git a/lib/ui/work_list/work_list_screen.dart b/lib/ui/work_list/work_list_screen.dart index 9471568..8efd789 100644 --- a/lib/ui/work_list/work_list_screen.dart +++ b/lib/ui/work_list/work_list_screen.dart @@ -347,6 +347,7 @@ class _WorkListScreenState extends State { return InkWell( onTap: () async { AppState().setItgWorkListIndex = index; + AppState().setItgRequestType = requestDetails.requestType; var shouldReloadData = await Navigator.pushNamed(context, AppRoutes.itgDetail); if (shouldReloadData != null) { if (shouldReloadData.toString() == "delegate_reload") { From 5412dcaf35a35317b849551cefb04ba3227aa5b5 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 14 Nov 2022 08:28:41 +0300 Subject: [PATCH 25/82] Chat Favorite Screen & Fixes --- lib/api/chat/chat_provider_model.dart | 20 +++++++------------- lib/ui/chat/chat_detailed_screen.dart | 17 ++++++++--------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 4e79374..b826753 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -60,8 +60,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}", token: AppState().chatDetails!.response!.token, ); - - //logger.d(AppState().chatDetails!.response!.token); ChatUserModel recentChat = userToList(response.body); Response favRes = await ApiClient().getJsonForResponse( @@ -71,6 +69,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ChatUserModel favUList = userToList(favRes.body); if (favUList.response != null) { favUsersList = favUList.response!; + favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); for (dynamic user in recentChat.response!) { for (dynamic favUser in favUList.response!) { if (user.id == favUser.id) { @@ -80,7 +79,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } pChatHistory = recentChat.response; - pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase()!.compareTo(b.userName!.toLowerCase()!)); + pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); searchedChats = pChatHistory; isLoading = false; notifyListeners(); @@ -94,8 +93,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", token: AppState().chatDetails!.response!.token, ); - - logger.d(response.body); if (response.statusCode == 204) { if (!loadMore) userChatHistory = []; Utils.showToast("No More Data To Load"); @@ -134,7 +131,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future buildHubConnection() async { HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); - hubConnection = await HubConnectionBuilder() + hubConnection = HubConnectionBuilder() .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]) .configureLogging( @@ -162,8 +159,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); } - isLoading = false; - notifyListeners(); + // notifyListeners(); } void updateUserChatStatus(List? args) { @@ -171,7 +167,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (dynamic cItem in items[0]) { for (SingleUserChatModel chat in userChatHistory) { if (chat.userChatHistoryId.toString() == cItem["userChatHistoryId"].toString()) { - logger.d(jsonEncode(chat)); chat.isSeen = cItem["isSeen"]; chat.isDelivered = cItem["isDelivered"]; notifyListeners(); @@ -182,7 +177,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void userCountAsync(List? args) { List items = args!.toList(); - //print("---------------------------------User Count Async -------------------------------------"); + //logger.d("---------------------------------User Count Async -------------------------------------"); //logger.d(items); // for (var user in searchedChats!) { // if (user.id == items.first["id"]) { @@ -256,13 +251,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } userChatHistory.add(data.first); notifyListeners(); - logger.d(isChatScreenActive); // if (isChatScreenActive) scrollDown(); } void onUserTyping(List? parameters) { - print("==================== Typing Active =================="); - logger.d(parameters); + // print("==================== Typing Active =================="); + // logger.d(parameters); for (ChatUser user in searchedChats!) { if (user.id == parameters![1] && parameters[0] == true) { user.isTyping = parameters[0] as bool?; diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index c13e6d3..369bf3c 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,8 +1,5 @@ import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; @@ -23,14 +20,14 @@ class ChatDetailScreen extends StatelessWidget { dynamic userDetails; late ChatProviderModel data; ScrollController scrollController = ScrollController(); - RefreshController _refreshController = RefreshController(initialRefresh: false); + final RefreshController _refreshController = RefreshController(initialRefresh: false); void getMoreChat() async { if (userDetails != null) { data.paginationVal = data.paginationVal + 10; data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true); } - await Future.delayed(Duration(milliseconds: 1000)); + await Future.delayed(const Duration(milliseconds: 1000)); _refreshController.refreshCompleted(); } @@ -61,6 +58,7 @@ class ChatDetailScreen extends StatelessWidget { child: ListView.builder( controller: scrollController, shrinkWrap: true, + reverse: false, itemCount: m.userChatHistory.length, padding: const EdgeInsets.only(top: 20), itemBuilder: (BuildContext context, int i) { @@ -137,10 +135,11 @@ class ChatDetailScreen extends StatelessWidget { height: 200, decoration: BoxDecoration( image: DecorationImage( - image: FileImage( - m.selectedFile, - ), - fit: BoxFit.cover), + image: FileImage( + m.selectedFile, + ), + fit: BoxFit.cover, + ), borderRadius: const BorderRadius.all( Radius.circular(0), ), From 83aabd05552aee12222c46317efcf259f447892b Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 14 Nov 2022 09:35:53 +0300 Subject: [PATCH 26/82] Chat Favorite Screen & Fixes --- lib/generated/codegen_loader.g.dart | 8 +- lib/ui/chat/chat_detailed_screen.dart | 4 +- lib/ui/chat/chat_home_screen.dart | 250 +++++++++++++------------ lib/ui/chat/favorite_users_screen.dart | 149 ++++++++------- 4 files changed, 209 insertions(+), 202 deletions(-) diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index e9dd08c..49dac5c 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -514,7 +514,9 @@ class CodegenLoader extends AssetLoader{ "verification": "تَحَقّق", "resend": "إعادة إرسال", "codeExpire": "انتهت صلاحية رمز التحقق", - "typeheretoreply": "اكتب هنا للرد" + "typeheretoreply": "اكتب هنا للرد", + "favorite": "مفضل", + "searchfromchat": "البحث من الدردشة" }; static const Map en_US = { "mohemm": "Mohemm", @@ -1016,7 +1018,9 @@ static const Map en_US = { "resend": "Resend", "codeExpire": "The verification code has been expired", "allQuestionsCorrect": "You have answered all questions correct", - "typeheretoreply": "Type here to reply" + "typeheretoreply": "Type here to reply", + "favorite": "Favorite", + "searchfromchat": "Search from chat" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 369bf3c..7dfb321 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -16,10 +16,12 @@ import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:swipe_to/swipe_to.dart'; class ChatDetailScreen extends StatelessWidget { - ChatDetailScreen({Key? key}) : super(key: key); dynamic userDetails; + late ChatProviderModel data; + ScrollController scrollController = ScrollController(); + final RefreshController _refreshController = RefreshController(initialRefresh: false); void getMoreChat() async { diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 328354b..f10cc26 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -43,147 +43,149 @@ class _ChatHomeScreenState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: MyColors.white, - body: Consumer(builder: (BuildContext context, ChatProviderModel m, Widget? child) { - return m.isLoading - ? ChatHomeShimmer() - : ListView( - shrinkWrap: true, - physics: const AlwaysScrollableScrollPhysics(), - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), - child: TextField( - onChanged: (String val) { - m.filter(val); - }, - decoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: const BorderSide( - color: Color(0xFFE5E5E5), + body: Consumer( + builder: (BuildContext context, ChatProviderModel m, Widget? child) { + return m.isLoading + ? ChatHomeShimmer() + : ListView( + shrinkWrap: true, + physics: const AlwaysScrollableScrollPhysics(), + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + child: TextField( + onChanged: (String val) { + m.filter(val); + }, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE5E5E5), + ), ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: const BorderSide( - color: Color(0xFFE5E5E5), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE5E5E5), + ), ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: const BorderSide( - color: Color(0xFFE5E5E5), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE5E5E5), + ), ), + contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + hintText: LocaleKeys.searchfromchat.tr(), + hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic), + filled: true, + fillColor: const Color(0xFFF7F7F7), ), - contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), - hintText: LocaleKeys.searchfromchat.tr(), - hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic), - filled: true, - fillColor: const Color(0xFFF7F7F7), ), ), - ), - if (m.searchedChats != null) - ListView.separated( - itemCount: m.searchedChats!.length, - padding: const EdgeInsets.only(bottom: 80), - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (BuildContext context, int index) { - return SizedBox( - height: 55, - child: ListTile( - leading: Stack( - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 48, - width: 48, - ), - Positioned( - right: 5, - bottom: 1, - child: Container( - width: 10, - height: 10, - decoration: BoxDecoration( - color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, - borderRadius: const BorderRadius.all( - Radius.circular(10), - ), - ), + if (m.searchedChats != null) + ListView.separated( + itemCount: m.searchedChats!.length, + padding: const EdgeInsets.only(bottom: 80), + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return SizedBox( + height: 55, + child: ListTile( + leading: Stack( + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, ), - ) - ], - ), - title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor), - // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), - trailing: SizedBox( - width: 60, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - if (m.searchedChats![index].unreadMessageCount! > 0) - Flexible( - child: Container( - padding: EdgeInsets.zero, - alignment: Alignment.centerRight, - width: 18, - height: 18, - decoration: const BoxDecoration( - color: MyColors.redColor, - borderRadius: BorderRadius.all( - Radius.circular(20), - ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: m.searchedChats![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + borderRadius: const BorderRadius.all( + Radius.circular(10), ), - child: (m.searchedChats![index].unreadMessageCount!.toString()) - .toText10( - color: MyColors.white, - ) - .center, ), ), - Flexible( - child: IconButton( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(m.searchedChats![index].isFav! ? Icons.star : Icons.star_border), - color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, - onPressed: () { - if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); - if (!m.searchedChats![index].isFav!) m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); - }, - ), ) ], ), + title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor), + // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), + trailing: SizedBox( + width: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + if (m.searchedChats![index].unreadMessageCount! > 0) + Flexible( + child: Container( + padding: EdgeInsets.zero, + alignment: Alignment.centerRight, + width: 18, + height: 18, + decoration: const BoxDecoration( + color: MyColors.redColor, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + child: (m.searchedChats![index].unreadMessageCount!.toString()) + .toText10( + color: MyColors.white, + ) + .center, + ), + ), + Flexible( + child: IconButton( + alignment: Alignment.centerRight, + padding: EdgeInsets.zero, + icon: Icon(m.searchedChats![index].isFav! ? Icons.star : Icons.star_border), + color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, + onPressed: () { + if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + if (!m.searchedChats![index].isFav!) m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + }, + ), + ) + ], + ), + ), + minVerticalPadding: 0, + onTap: () { + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": m.searchedChats![index]}, + ).then((value) { + m.clearSelections(); + }); + }, + onLongPress: () {}, ), - minVerticalPadding: 0, - onTap: () { - Navigator.pushNamed( - context, - AppRoutes.chatDetailed, - arguments: {"targetUser": m.searchedChats![index]}, - ).then((value) { - m.clearSelections(); - }); - }, - onLongPress: () {}, + ); + }, + separatorBuilder: (BuildContext context, int index) => const Padding( + padding: EdgeInsets.only(right: 10, left: 70), + child: Divider( + color: Color(0xFFE5E5E5), ), - ); - }, - separatorBuilder: (BuildContext context, int index) => const Padding( - padding: EdgeInsets.only(right: 10, left: 70), - child: Divider( - color: Color(0xFFE5E5E5), ), ), - ), - ], - ); - }), + ], + ); + }, + ), floatingActionButton: FloatingActionButton( child: Container( width: 60, diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index b84b827..2e3a3f2 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -12,91 +12,90 @@ import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart' import 'package:provider/provider.dart'; class ChatFavoriteUsersScreen extends StatelessWidget { - const ChatFavoriteUsersScreen({Key? key}) : super(key: key); - @override Widget build(BuildContext context) { - // TODO: implement build return Scaffold( backgroundColor: MyColors.white, - body: Consumer(builder: (BuildContext context, ChatProviderModel m, Widget? child) { - return m.isLoading - ? ChatHomeShimmer() - : ListView( - shrinkWrap: true, - physics: const AlwaysScrollableScrollPhysics(), - padding: const EdgeInsets.only(top: 20), - children: [ - if (m.favUsersList != null && m.favUsersList.isNotEmpty) - ListView.separated( - itemCount: m.favUsersList!.length, - padding: EdgeInsets.zero, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (BuildContext context, int index) { - return SizedBox( - height: 55, - child: ListTile( - leading: Stack( - children: [ - SvgPicture.asset( - "assets/images/user.svg", - height: 48, - width: 48, - ), - Positioned( - right: 5, - bottom: 1, - child: Container( - width: 10, - height: 10, - decoration: BoxDecoration( - color: m.favUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, - borderRadius: const BorderRadius.all( - Radius.circular(10), - ), + body: Consumer( + builder: (BuildContext context, ChatProviderModel m, Widget? child) { + if (m.isLoading) { + return ChatHomeShimmer(); + } else { + return m.favUsersList != null && m.favUsersList.isNotEmpty + ? ListView.separated( + itemCount: m.favUsersList!.length, + padding: const EdgeInsets.only(top: 20), + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return SizedBox( + height: 55, + child: ListTile( + leading: Stack( + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 48, + width: 48, + ), + Positioned( + right: 5, + bottom: 1, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: m.favUsersList![index].userStatus == 1 ? MyColors.green2DColor : Colors.red, + borderRadius: const BorderRadius.all( + Radius.circular(10), ), ), - ) - ], - ), - title: (m.favUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), - // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), - trailing: IconButton( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(m.favUsersList![index].isFav! ? Icons.star : Icons.star_border), - color: m.favUsersList![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, - onPressed: () { - if (m.favUsersList![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.favUsersList![index].id!); - }, - ), - minVerticalPadding: 0, - onTap: () { - Navigator.pushNamed( - context, - AppRoutes.chatDetailed, - arguments: {"targetUser": m.favUsersList![index]}, - ).then((value) { - m.clearSelections(); - }); + ), + ) + ], + ), + title: (m.favUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), + trailing: IconButton( + alignment: Alignment.centerRight, + padding: EdgeInsets.zero, + icon: Icon(m.favUsersList![index].isFav! ? Icons.star : Icons.star_border), + color: m.favUsersList![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, + onPressed: () { + if (m.favUsersList![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.favUsersList![index].id!); }, - onLongPress: () {}, ), - ); - }, - separatorBuilder: (BuildContext context, int index) => const Padding( - padding: EdgeInsets.only(right: 10, left: 70), - child: Divider( - color: Color(0xFFE5E5E5), + minVerticalPadding: 0, + onTap: () { + Navigator.pushNamed( + context, + AppRoutes.chatDetailed, + arguments: {"targetUser": m.favUsersList![index]}, + ).then( + (Object? value) { + m.clearSelections(); + }, + ); + }, + ), + ); + }, + separatorBuilder: (BuildContext context, int index) => const Padding( + padding: EdgeInsets.only(right: 10, left: 70), + child: Divider( + color: Color( + 0xFFE5E5E5, ), ), - ) - else - Utils.getNoDataWidget(context).expanded - ], - ); - }), + ), + ) + : Column( + children: [ + Utils.getNoDataWidget(context).expanded, + ], + ); + } + }, + ), ); } } From 3e5ce90c9a3885bc85c23f328bc1822abedbace9 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 14 Nov 2022 09:39:23 +0300 Subject: [PATCH 27/82] Chat Favorite Screen & Fixes --- lib/ui/chat/chat_detailed_screen.dart | 10 +++++++++- lib/ui/chat/favorite_users_screen.dart | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 7dfb321..e653fbe 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -15,7 +15,15 @@ import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:swipe_to/swipe_to.dart'; -class ChatDetailScreen extends StatelessWidget { +class ChatDetailScreen extends StatefulWidget { + // ignore: prefer_const_constructors_in_immutables + ChatDetailScreen({Key? key}) : super(key: key); + + @override + State createState() => _ChatDetailScreenState(); +} + +class _ChatDetailScreenState extends State { dynamic userDetails; late ChatProviderModel data; diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index 2e3a3f2..a41c1b8 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -12,6 +12,8 @@ import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart' import 'package:provider/provider.dart'; class ChatFavoriteUsersScreen extends StatelessWidget { + const ChatFavoriteUsersScreen({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( @@ -89,7 +91,7 @@ class ChatFavoriteUsersScreen extends StatelessWidget { ), ) : Column( - children: [ + children: [ Utils.getNoDataWidget(context).expanded, ], ); From 027b6ca7b6558405caae824569454dac334b9eac Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 14 Nov 2022 10:05:03 +0300 Subject: [PATCH 28/82] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 30 +++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index b826753..a4ea408 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -148,7 +148,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ({String? connectionId}) {}, ); if (hubConnection.state != HubConnectionState.Connected) { - print("================= Connection Established =========================="); + if (kDebugMode) { + print("================= Connection Established =========================="); + } await hubConnection.start(); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); @@ -176,7 +178,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void userCountAsync(List? args) { - List items = args!.toList(); + dynamic items = args!.toList(); //logger.d("---------------------------------User Count Async -------------------------------------"); //logger.d(items); // for (var user in searchedChats!) { @@ -188,8 +190,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void updateChatHistoryWindow(List? args) { - List items = args!.toList(); - print("---------------------------------Update Chat History Windows Async -------------------------------------"); + dynamic items = args!.toList(); + if (kDebugMode) { + print("---------------------------------Update Chat History Windows Async -------------------------------------"); + } logger.d(items); // for (var user in searchedChats!) { // if (user.id == items.first["id"]) { @@ -200,21 +204,25 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void chatNotDelivered(List? args) { - List items = args!.toList(); - print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------"); + dynamic items = args!.toList(); + if (kDebugMode) { + print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------"); + } logger.d(items); // for (var user in searchedChats!) { // if (user.id == items.first["id"]) { // user.userStatus = items.first["userStatus"]; // } // } - // notifyListeners(); + // notifyListeners();2 } void changeStatus(List? args) { - // print("================= Status Online // Offline ===================="); - List items = args!.toList(); - // logger.d(items); + if (kDebugMode) { + print("================= Status Online // Offline ===================="); + } + dynamic items = args!.toList(); + logger.d(items); for (ChatUser user in searchedChats!) { if (user.id == items.first["id"]) { user.userStatus = items.first["userStatus"]; @@ -348,7 +356,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // } Future sendChatToServer( - {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { + {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { Uuid uuid = const Uuid(); SingleUserChatModel data = SingleUserChatModel( chatEventId: chatEventId, From 93e7f7c862d02cd7d6c5b8bd849e2fcdb5350425 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 14 Nov 2022 10:13:25 +0300 Subject: [PATCH 29/82] Chat Fixes --- lib/classes/consts.dart | 4 ++-- lib/ui/chat/chat_home_screen.dart | 2 +- lib/ui/chat/favorite_users_screen.dart | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 646e498..c5788f9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index f10cc26..b4483dc 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -117,7 +117,7 @@ class _ChatHomeScreenState extends State { ) ], ), - title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor), + title: (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor), // subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), trailing: SizedBox( width: 60, diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index a41c1b8..8b5eba0 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -56,7 +56,7 @@ class ChatFavoriteUsersScreen extends StatelessWidget { ) ], ), - title: (m.favUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), + title: (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor), trailing: IconButton( alignment: Alignment.centerRight, padding: EdgeInsets.zero, From 4ff3a5093bd2bc70f49d81df6d6fa2e0a539db67 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Mon, 14 Nov 2022 10:22:16 +0300 Subject: [PATCH 30/82] Action duration implemented --- lib/classes/date_uitl.dart | 76 ++++++++----- lib/extensions/string_extensions.dart | 3 +- lib/ui/work_list/item_history_screen.dart | 101 +++++++++++------- .../worklist_fragments/actions_fragment.dart | 28 ++++- 4 files changed, 140 insertions(+), 68 deletions(-) diff --git a/lib/classes/date_uitl.dart b/lib/classes/date_uitl.dart index 73945f8..f7b8192 100644 --- a/lib/classes/date_uitl.dart +++ b/lib/classes/date_uitl.dart @@ -381,6 +381,30 @@ class DateUtil { return ""; } + static String formatDuration(Duration d) { + var seconds = d.inSeconds; + var days = seconds ~/ Duration.secondsPerDay; + seconds -= days * Duration.secondsPerDay; + var hours = seconds ~/ Duration.secondsPerHour; + seconds -= hours * Duration.secondsPerHour; + var minutes = seconds ~/ Duration.secondsPerMinute; + seconds -= minutes * Duration.secondsPerMinute; + + List tokens = []; + if (days != 0) { + tokens.add('$days days'); + } + if (tokens.isNotEmpty || hours != 0) { + tokens.add('$hours hours'); + } + if (tokens.isNotEmpty || minutes != 0) { + tokens.add('$minutes mins'); + } + tokens.add('$seconds secs'); + + return tokens.join(' '); + } + /// get data formatted like 26/4/2020 /// [dateTime] convert DateTime to data formatted according to language static String getDayMonthYearDateFormattedLang(DateTime dateTime, bool isArabic) { @@ -431,30 +455,30 @@ class DateUtil { return "/Date(" + DateFormat('mm-dd-yyy').parse(isoDate).millisecondsSinceEpoch.toString() + ")/"; } - // static String getDay(DayOfWeek dayOfWeek) { - // switch (dayOfWeek) { - // case DayOfWeek.Monday: - // return "Monday"; - // break; - // case DayOfWeek.Tuesday: - // return "Tuesday"; - // break; - // case DayOfWeek.Wednesday: - // return "Wednesday"; - // break; - // case DayOfWeek.Thursday: - // return "Thursday"; - // break; - // case DayOfWeek.Friday: - // return "Friday"; - // break; - // case DayOfWeek.Saturday: - // return "Saturday"; - // break; - // case DayOfWeek.Sunday: - // return "Sunday"; - // break; - // } - // return ""; - // } +// static String getDay(DayOfWeek dayOfWeek) { +// switch (dayOfWeek) { +// case DayOfWeek.Monday: +// return "Monday"; +// break; +// case DayOfWeek.Tuesday: +// return "Tuesday"; +// break; +// case DayOfWeek.Wednesday: +// return "Wednesday"; +// break; +// case DayOfWeek.Thursday: +// return "Thursday"; +// break; +// case DayOfWeek.Friday: +// return "Friday"; +// break; +// case DayOfWeek.Saturday: +// return "Saturday"; +// break; +// case DayOfWeek.Sunday: +// return "Sunday"; +// break; +// } +// return ""; +// } } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 9af8f2b..8bc15e7 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -22,8 +22,9 @@ extension EmailValidator on String { style: TextStyle(fontSize: 10, fontStyle: fontStyle ?? FontStyle.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4), ); - Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isBold = false}) => Text( + Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isBold = false, int maxLine = 0}) => Text( this, + maxLines: (maxLine > 0) ? maxLine : null, style: TextStyle( fontSize: 11, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600), diff --git a/lib/ui/work_list/item_history_screen.dart b/lib/ui/work_list/item_history_screen.dart index fb1066b..562b59f 100644 --- a/lib/ui/work_list/item_history_screen.dart +++ b/lib/ui/work_list/item_history_screen.dart @@ -86,9 +86,9 @@ class _ItemHistoryScreenState extends State { padding: const EdgeInsets.all(21), physics: const BouncingScrollPhysics(), children: [ - if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData() else Utils.getNoDataWidget(context), - if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData() else Utils.getNoDataWidget(context), - if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData() else Utils.getNoDataWidget(context) + if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData(), + if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData(), + if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData() ], ), ); @@ -102,21 +102,39 @@ class _ItemHistoryScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - ItemDetailView(LocaleKeys.requestNumber.tr(), moItemHistoryList[index].rEQUESTNUMBER ?? ""), - ItemDetailView(LocaleKeys.uom.tr(), moItemHistoryList[index].uNITOFMEASURE ?? ""), - ItemDetailView(LocaleKeys.quantity.tr(), moItemHistoryList[index].qUANTITY?.toString() ?? ""), - ItemDetailView(LocaleKeys.dateRequired.tr(), moItemHistoryList[index].dATEREQUIRED ?? ""), - ItemDetailView(LocaleKeys.lineStatus.tr(), moItemHistoryList[index].lINESTATUSDIS ?? ""), - ItemDetailView(LocaleKeys.statusDate.tr(), moItemHistoryList[index].sTATUSDATE ?? ""), - ItemDetailView(LocaleKeys.transactionType.tr(), moItemHistoryList[index].tRANSACTIONTYPENAME ?? ""), - ItemDetailView(LocaleKeys.organization.tr(), moItemHistoryList[index].oRGANIZATIONNAME ?? ""), - ItemDetailView(LocaleKeys.operatingCode.tr(), moItemHistoryList[index].oRGANIZATIONCODE ?? ""), - ItemDetailView(LocaleKeys.operatingUnit.tr(), moItemHistoryList[index].oPERATINGUNITNAME ?? ""), - ItemDetailView(LocaleKeys.fromSubInventory.tr(), moItemHistoryList[index].fROMSUBINVENTORYCODE ?? ""), - ItemDetailView(LocaleKeys.fromLocator.tr(), moItemHistoryList[index].fROMLOCATOR ?? ""), - ItemDetailView(LocaleKeys.toSubInventory.tr(), moItemHistoryList[index].tOSUBINVENTORYCODE ?? ""), - ItemDetailView(LocaleKeys.toLocator.tr(), moItemHistoryList[index].tOLOCATOR ?? ""), - ItemDetailView(LocaleKeys.shipToLocation.tr(), moItemHistoryList[index].sHIPTOLOCATION ?? ""), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.requestNumber.tr(), moItemHistoryList[index].rEQUESTNUMBER ?? ""), + ItemDetailViewCol(LocaleKeys.uom.tr(), moItemHistoryList[index].uNITOFMEASURE ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.quantity.tr(), moItemHistoryList[index].qUANTITY?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.dateRequired.tr(), moItemHistoryList[index].dATEREQUIRED ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.lineStatus.tr(), moItemHistoryList[index].lINESTATUSDIS ?? ""), + ItemDetailViewCol(LocaleKeys.statusDate.tr(), moItemHistoryList[index].sTATUSDATE ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.transactionType.tr(), moItemHistoryList[index].tRANSACTIONTYPENAME ?? ""), + ItemDetailViewCol(LocaleKeys.organization.tr(), moItemHistoryList[index].oRGANIZATIONNAME ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.operatingCode.tr(), moItemHistoryList[index].oRGANIZATIONCODE ?? ""), + ItemDetailViewCol(LocaleKeys.operatingUnit.tr(), moItemHistoryList[index].oPERATINGUNITNAME ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.fromSubInventory.tr(), moItemHistoryList[index].fROMSUBINVENTORYCODE ?? ""), + ItemDetailViewCol(LocaleKeys.fromLocator.tr(), moItemHistoryList[index].fROMLOCATOR ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.toSubInventory.tr(), moItemHistoryList[index].tOSUBINVENTORYCODE ?? ""), + ItemDetailViewCol(LocaleKeys.toLocator.tr(), moItemHistoryList[index].tOLOCATOR ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.shipToLocation.tr(), moItemHistoryList[index].sHIPTOLOCATION ?? ""), + Container(), + isItLast: true, + ), ], ).objectContainerView(), separatorBuilder: (cxt, index) => 12.height, @@ -131,10 +149,6 @@ class _ItemHistoryScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - // ItemDetailGrid( - // ItemDetailViewCol(LocaleKeys.from.tr(), workListData!.fROMUSER ?? ""), - // ItemDetailViewCol(LocaleKeys.to.tr(), workListData!.tOUSER ?? ""), - // ), ItemDetailGrid( ItemDetailViewCol(LocaleKeys.operatingUnit.tr(), poItemHistoryList[index].oUNAME ?? ""), ItemDetailViewCol(LocaleKeys.poNumber.tr(), poItemHistoryList[index].pONUMBER ?? ""), @@ -182,20 +196,35 @@ class _ItemHistoryScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - ItemDetailView(LocaleKeys.quotationNumber.tr(), quotationAnalysisList[index].qUOTNUM ?? ""), - ItemDetailView(LocaleKeys.vendorName.tr(), quotationAnalysisList[index].vENDORNAME ?? ""), - ItemDetailView(LocaleKeys.itemCode.tr(), quotationAnalysisList[index].iTEMCODE ?? ""), - ItemDetailView(LocaleKeys.description.tr(), quotationAnalysisList[index].iTEMDESC ?? ""), - ItemDetailView(LocaleKeys.quotationQty.tr(), quotationAnalysisList[index].qUOTQTY?.toString() ?? ""), - ItemDetailView(LocaleKeys.quotationUOM.tr(), quotationAnalysisList[index].qUOTUOM ?? ""), - ItemDetailView(LocaleKeys.quotationNetPrice.tr(), quotationAnalysisList[index].qUOTUNITPRICE?.toString() ?? ""), - ItemDetailView(LocaleKeys.quotationLineTotal.tr(), quotationAnalysisList[index].qUOTLINETOTAL?.toString() ?? ""), - ItemDetailView(LocaleKeys.quotationBonusQuantity.tr(), quotationAnalysisList[index].qUOTBONUSQTY ?? ""), - ItemDetailView(LocaleKeys.quotationDeliveryDate.tr(), quotationAnalysisList[index].qUOTDELIVERYDATE ?? ""), - ItemDetailView(LocaleKeys.quotationMFGPartNumber.tr(), quotationAnalysisList[index].qUOTMFGPARTNUM ?? ""), - ItemDetailView(LocaleKeys.rfqNumber.tr(), quotationAnalysisList[index].rFQNUM ?? ""), - ItemDetailView(LocaleKeys.rfqQty.tr(), quotationAnalysisList[index].rFQQTY?.toString() ?? ""), - ItemDetailView(LocaleKeys.rfqUOM.tr(), quotationAnalysisList[index].rFQUOM ?? ""), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.quotationNumber.tr(), quotationAnalysisList[index].qUOTNUM ?? ""), + ItemDetailViewCol(LocaleKeys.vendorName.tr(), quotationAnalysisList[index].vENDORNAME ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.itemCode.tr(), quotationAnalysisList[index].iTEMCODE ?? ""), + ItemDetailViewCol(LocaleKeys.description.tr(), quotationAnalysisList[index].iTEMDESC ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.quotationQty.tr(), quotationAnalysisList[index].qUOTQTY?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.quotationUOM.tr(), quotationAnalysisList[index].qUOTUOM ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.quotationNetPrice.tr(), quotationAnalysisList[index].qUOTUNITPRICE?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.quotationLineTotal.tr(), quotationAnalysisList[index].qUOTLINETOTAL?.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.quotationBonusQuantity.tr(), quotationAnalysisList[index].qUOTBONUSQTY ?? ""), + ItemDetailViewCol(LocaleKeys.quotationDeliveryDate.tr(), quotationAnalysisList[index].qUOTDELIVERYDATE ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.quotationMFGPartNumber.tr(), quotationAnalysisList[index].qUOTMFGPARTNUM ?? ""), + ItemDetailViewCol(LocaleKeys.rfqNumber.tr(), quotationAnalysisList[index].rFQNUM ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol(LocaleKeys.rfqQty.tr(), quotationAnalysisList[index].rFQQTY?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.rfqUOM.tr(), quotationAnalysisList[index].rFQUOM ?? ""), + isItLast: true, + ) ], ).objectContainerView(title: "${quotationAnalysisList[index].iTEMCODE}-${quotationAnalysisList[index].iTEMDESC}"), separatorBuilder: (cxt, index) => 12.height, diff --git a/lib/ui/work_list/worklist_fragments/actions_fragment.dart b/lib/ui/work_list/worklist_fragments/actions_fragment.dart index 8a69599..439888b 100644 --- a/lib/ui/work_list/worklist_fragments/actions_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/actions_fragment.dart @@ -27,7 +27,7 @@ class ActionsFragment extends StatelessWidget { itemCount: actionHistoryList.length, padding: EdgeInsets.all(21), itemBuilder: (context, index) { - return showItem(context, actionHistoryList[index]); + return showItem(context, actionHistoryList[index], index); }, separatorBuilder: (BuildContext context, int index) { return 12.height; @@ -36,7 +36,7 @@ class ActionsFragment extends StatelessWidget { ); } - Widget showItem(BuildContext context, GetActionHistoryList actionHistory) { + Widget showItem(BuildContext context, GetActionHistoryList actionHistory, int index) { return Container( width: double.infinity, decoration: BoxDecoration( @@ -89,7 +89,9 @@ class ActionsFragment extends StatelessWidget { if (actionHistory.nOTIFICATIONDATE!.isNotEmpty) DateUtil.formatDateToDate(DateUtil.convertSimpleStringDateToDateddMMyyyy(actionHistory.nOTIFICATIONDATE!), false).toText12(color: MyColors.lightTextColor), ], - ) + ), + 10.height, + getActionDuration(index).toText11(maxLine: 1, color: const Color(0xff1FA269)) ], ), ) @@ -127,8 +129,24 @@ class ActionsFragment extends StatelessWidget { ); } + String getActionDuration(int index) { + if (actionHistoryList[index].aCTIONCODE == "SUBMIT") { + return ""; + } else if(actionHistoryList[index].aCTIONCODE == "PENDING") { + DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[++index].nOTIFICATIONDATE!); + 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].nOTIFICATIONDATE!); + Duration duration = dateTimeTo.difference(dateTimeFrom); + print(dateTimeTo); + print(dateTimeFrom); + return "Action duration: " + DateUtil.formatDuration(duration); + } + } + Color getStatusColor(String code) { - print("code:$code"); if (code == "SUBMIT") { return const Color(0xff2E303A); } else if (code == "REJECTED") { @@ -139,7 +157,7 @@ class ActionsFragment extends StatelessWidget { return MyColors.orange; } else if (code == "APPROVED" || code == "APPROVE" || code == "ANSWER_INFO") { return const Color(0xff1FA269); - } else if (code == "REQUEST_INFO"|| code == "FORWARD") { + } else if (code == "REQUEST_INFO" || code == "FORWARD") { return const Color(0xff2E303A); } else if (code != "SUBMIT" && code != "REJECT" && code != "PENDING") { return MyColors.orange; From 2fe41977d8a9f83e9e3158004b9fe8b9f859ed23 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 14 Nov 2022 10:26:36 +0300 Subject: [PATCH 31/82] Chat Fixes --- lib/ui/chat/chat_detailed_screen.dart | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index e653fbe..b9a7ea2 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,4 +1,5 @@ import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -25,6 +26,8 @@ class ChatDetailScreen extends StatefulWidget { class _ChatDetailScreenState extends State { dynamic userDetails; + bool _firstAutoscrollExecuted = false; + bool _shouldAutoscroll = false; late ChatProviderModel data; @@ -40,6 +43,47 @@ class _ChatDetailScreenState extends State { await Future.delayed(const Duration(milliseconds: 1000)); _refreshController.refreshCompleted(); } + // + // void _scrollListener() { + // _firstAutoscrollExecuted = true; + // if (scrollController.hasClients && scrollController.position.pixels == scrollController.position.maxScrollExtent) { + // _shouldAutoscroll = true; + // } else { + // _shouldAutoscroll = false; + // } + // } + // + // void _scrollToBottom() { + // scrollController.jumpTo(scrollController.position.maxScrollExtent); + // } + + // void scrollToMaxExtent() { + // WidgetsBinding.instance.addPostFrameCallback((_) { + // scrollController.animateTo( + // scrollController.position.maxScrollExtent, + // duration: const Duration(milliseconds: 100), + // curve: Curves.easeIn, + // ); + // }); + // } + + + + @override + void initState() { + // TODO: implement initState + super.initState(); + //scrollToMaxExtent(); + + // scrollController.addListener(_scrollListener); + } + + @override + void dispose() { + // TODO: implement dispose + //scrollController.removeListener(_scrollListener); + super.dispose(); + } @override Widget build(BuildContext context) { From 2934203b8b156d5ba12d8c4b16bb4a68e1afd6f3 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 14 Nov 2022 10:30:47 +0300 Subject: [PATCH 32/82] Chat Fixes --- lib/ui/chat/chat_detailed_screen.dart | 4 ++-- lib/ui/chat/chat_home_screen.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index b9a7ea2..a6c0e67 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -92,7 +92,7 @@ class _ChatDetailScreenState extends State { if (userDetails != null) data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: false); return Scaffold( backgroundColor: const Color(0xFFF8F8F8), - appBar: AppBarWidget(context, title: userDetails["targetUser"].userName, showHomeButton: false, image: userDetails["targetUser"].image), + appBar: AppBarWidget(context, title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, image: userDetails["targetUser"].image), body: Consumer( builder: (BuildContext context, ChatProviderModel m, Widget? child) { return (m.isLoading @@ -149,7 +149,7 @@ class _ChatDetailScreenState extends State { height: 80, color: MyColors.black.withOpacity(0.10), child: ListTile( - title: (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() ? "You" : m.repliedMsg.first.currentUserName.toString()) + title: (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() ? "You" : m.repliedMsg.first.currentUserName.toString().replaceAll(".", " ")) .toText14(color: MyColors.lightGreenColor), subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.white, maxLine: 2), trailing: GestureDetector( diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index b4483dc..879e390 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -167,7 +167,7 @@ class _ChatHomeScreenState extends State { context, AppRoutes.chatDetailed, arguments: {"targetUser": m.searchedChats![index]}, - ).then((value) { + ).then((Object? value) { m.clearSelections(); }); }, From f1aadf50314b4d3af6deae4ae2e5b96092b970ae Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 14 Nov 2022 10:53:17 +0300 Subject: [PATCH 33/82] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 4 ++-- lib/ui/chat/chat_detailed_screen.dart | 1 + lib/ui/chat/chat_home_screen.dart | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index a4ea408..fb9e6c5 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -219,10 +219,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void changeStatus(List? args) { if (kDebugMode) { - print("================= Status Online // Offline ===================="); + // print("================= Status Online // Offline ===================="); } dynamic items = args!.toList(); - logger.d(items); + // logger.d(items); for (ChatUser user in searchedChats!) { if (user.id == items.first["id"]) { user.userStatus = items.first["userStatus"]; diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index a6c0e67..e2d0bd7 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 879e390..32f97fa 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -37,6 +37,7 @@ class _ChatHomeScreenState extends State { @override void dispose() { super.dispose(); + data.hubConnection.stop(); } @override From d849699489cdc36fb0cfbe33b5e67aa1ad8ef8f8 Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Mon, 14 Nov 2022 11:03:06 +0300 Subject: [PATCH 34/82] fix issues --- .../attendance/monthly_attendance_screen.dart | 2 +- lib/ui/misc/request_submit_screen.dart | 23 +- .../dynamic_screens/dynamic_input_screen.dart | 228 +++++++----------- 3 files changed, 94 insertions(+), 159 deletions(-) diff --git a/lib/ui/attendance/monthly_attendance_screen.dart b/lib/ui/attendance/monthly_attendance_screen.dart index de35da0..3115e46 100644 --- a/lib/ui/attendance/monthly_attendance_screen.dart +++ b/lib/ui/attendance/monthly_attendance_screen.dart @@ -286,7 +286,7 @@ class _MonthlyAttendanceScreenState extends State { showWeekNumber: false, cellBorderColor: Colors.white, selectionDecoration: BoxDecoration( - border: Border.all(color: MyColors.white, width: 10), + border: Border.all(color: MyColors.white, width: 1), shape: BoxShape.circle, ), dataSource: MeetingDataSource(_getDataSource()), diff --git a/lib/ui/misc/request_submit_screen.dart b/lib/ui/misc/request_submit_screen.dart index 7869443..f5a2d1e 100644 --- a/lib/ui/misc/request_submit_screen.dart +++ b/lib/ui/misc/request_submit_screen.dart @@ -68,7 +68,7 @@ class _RequestSubmitScreenState extends State { } void submitRequest() async { - // try { + try { Utils.showLoading(context); List> list = []; if (attachmentFiles.isNotEmpty) { @@ -90,28 +90,28 @@ class _RequestSubmitScreenState extends State { if (params!.approvalFlag == 'phone_numbers') { await ProfileApiClient().startPhoneApprovalProcess( - LocaleKeys.submit.tr(), + "SUBMIT", comments.text, params!.pItemId, params!.transactionId, ); } else if (params!.approvalFlag == 'address') { await ProfileApiClient().startAddressApprovalProcess( - LocaleKeys.submit.tr(), + "SUBMIT", comments.text, params!.pItemId, params!.transactionId, ); } else if (params!.approvalFlag == 'family_member') { await ProfileApiClient().getApproves( - LocaleKeys.submit.tr(), + "SUBMIT", comments.text, params!.transactionId!.toInt(), params!.pItemId.toString(), ); } else if (params!.approvalFlag == 'basicDetails') { await ProfileApiClient().startBasicDetailsApprovalProcess( - LocaleKeys.submit.tr(), + "SUBMIT", comments.text, params!.pItemId, params!.transactionId, @@ -124,15 +124,14 @@ class _RequestSubmitScreenState extends State { ); } else if (params!.approvalFlag == 'eit') { await MyAttendanceApiClient().startEitApprovalProcess( - LocaleKeys.submit.tr(), + "SUBMIT", comments.text, params!.pItemId, params!.transactionId, ); }else if (params!.approvalFlag == 'endEmployment') { await TerminationDffApiClient().startTermApprovalProcess( - // "SUBMIT", - LocaleKeys.submit.tr(), + "SUBMIT", comments.text, params!.pItemId, params!.transactionId, @@ -143,10 +142,10 @@ class _RequestSubmitScreenState extends State { Utils.showToast(LocaleKeys.yourRequestHasBeenSubmittedForApprovals.tr(), longDuration: true); Navigator.of(context).popUntil((route) => route.settings.name == AppRoutes.dashboard); Navigator.pushNamed(context, AppRoutes.workList); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } @override diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 045b808..519bb6c 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -48,17 +48,6 @@ class _DynamicInputScreenState extends State { descFlexConTextTitle = genericResponseModel!.pDESCFLEXCONTEXTNAME ?? ""; getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; //getEitDffStructureList = getEitDffStructureList!.where((element) => element.dISPLAYFLAG != "N").toList(); - if (dynamicParams!.collectionNotificationList != null && dynamicParams!.collectionNotificationList!.isNotEmpty) { - getEitDffStructureList!.forEach((element) { - dynamicParams!.collectionNotificationList!.forEach((element2) { - if (element.sEGMENTNAME == element2.segmentName) { - element.fieldAnswer = element2.varchar2Value; - element.eSERVICESDV ??= ESERVICESDV(); - element.eSERVICESDV!.pIDCOLUMNNAME = element2.varchar2Value; - } - }); - }); - } Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -68,7 +57,7 @@ class _DynamicInputScreenState extends State { } void validateTransaction() async { - // try { + try { Utils.showLoading(context); List> values = getEitDffStructureList!.map((e) { String tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; @@ -102,11 +91,6 @@ class _DynamicInputScreenState extends State { values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); - if (dynamicParams!.collectionNotificationList != null && dynamicParams!.collectionNotificationList!.isNotEmpty) { - Utils.hideLoading(context); - Navigator.pop(context, values); - return; - } SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); Utils.hideLoading(context); await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, @@ -114,10 +98,10 @@ class _DynamicInputScreenState extends State { Utils.showLoading(context); await LeaveBalanceApiClient().cancelHrTransaction(submitEITTransactionList.pTRANSACTIONID!); Utils.hideLoading(context); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } String dESCFLEXCONTEXTCODE = ""; @@ -126,42 +110,19 @@ class _DynamicInputScreenState extends State { Future calGetValueSetValues(GetEITDFFStructureList structureList) async { try { Utils.showLoading(context); - List> values = []; String segmentId = structureList.cHILDSEGMENTSVS!; - if (dESCFLEXCONTEXTCODE.isEmpty) dESCFLEXCONTEXTCODE = structureList.dESCFLEXCONTEXTCODE!; List filteredList = getEitDffStructureList?.where((element) => element.cHILDSEGMENTSVSSplited!.contains(segmentId)).toList() ?? []; - - if (filteredList.isEmpty && structureList.cHILDSEGMENTSVSSplited!.isNotEmpty) { - segmentId = structureList.cHILDSEGMENTSVSSplited![0]; - filteredList = getEitDffStructureList?.where((element) => element.cHILDSEGMENTSVSSplited!.contains(segmentId)).toList() ?? []; - } - values = filteredList + List> values = filteredList .map((e) => GetSetValuesRequestModel( sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) .toJson()) .toList(); - - // if (parentValue.isNotEmpty && (structureList.vALIDATIONTYPE == "F")) { - // values = getDependenciesParams(parentValue); - // } - // if (structureList.pARENTSEGMENTSVSSplitedVS!.isNotEmpty) { - // structureList.pARENTSEGMENTSVSSplitedVS!.forEach((element2) { - // filteredList = getEitDffStructureList?.where((element) => element.sEGMENTNAME == element2.name).toList() ?? []; - // values = filteredList - // .map((e) => GetSetValuesRequestModel( - // sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) - // .toJson()) - // .toList(); - // }); - // List filteredList2 = getEitDffStructureList?.where((element) => element.fLEXVALUESETNAME == structureList.fLEXVALUESETNAME).toList() ?? []; - // } - List eServicesResponseModel = await MyAttendanceApiClient().getValueSetValues(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); List abc = genericResponseModel?.getEITDFFStructureList ?? []; getEitDffStructureList = abc; - int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); + int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == structureList.cHILDSEGMENTSVS); getEitDffStructureList![index].eSERVICESVS!.clear(); if (eServicesResponseModel.isNotEmpty) getEitDffStructureList![index].eSERVICESVS!.addAll(eServicesResponseModel); // getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; @@ -175,7 +136,7 @@ class _DynamicInputScreenState extends State { } Future getDefaultValues(GetEITDFFStructureList structureList) async { - // try { + try { Utils.showLoading(context); for (int i = 0; i < (structureList.cHILDSEGMENTSDVSplited?.length ?? 0); i++) { String segmentId = structureList.cHILDSEGMENTSDVSplited![i]; @@ -197,34 +158,15 @@ class _DynamicInputScreenState extends State { ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, getSetList); int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); getEitDffStructureList![index].eSERVICESDV = defaultValue; - GetEITDFFStructureList defaultValueCheck = getEitDffStructureList!.where((GetEITDFFStructureList element) => element.sEGMENTNAME == segmentId).toList().first; - - if (defaultValueCheck.cHILDSEGMENTSDVSplited!.isNotEmpty && defaultValueCheck.rEADONLY == 'Y') { - getDefaultValues(defaultValueCheck); - Utils.hideLoading(context); - - // GetEITDFFStructureList? parent = getEitDffStructureList!.firstWhere((element) => element.sEGMENTNAME == segmentId); - // List> getSetList = getDefaultValuesIonicLogic(parent); - // ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, defaultValueCheck.dESCFLEXCONTEXTCODE!, defaultValueCheck.dESCFLEXNAME!, getSetList); - // int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); - // getEitDffStructureList![index].eSERVICESDV = defaultValue; - } else if (defaultValueCheck.cHILDSEGMENTSVSSplited!.isNotEmpty && defaultValueCheck.rEADONLY == 'Y') { - calGetValueSetValues(defaultValueCheck); - Utils.hideLoading(context); - } - } else if (values.isNotEmpty) { - ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); - int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); - getEitDffStructureList![index].eSERVICESDV = defaultValue; } } await Future.delayed(const Duration(seconds: 1)); Utils.hideLoading(context); setState(() {}); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } // List> calGetValueSetValuesIonicLogic(GetEITDFFStructureList structureElement) { @@ -238,79 +180,79 @@ class _DynamicInputScreenState extends State { // } List> getDefaultValuesIonicLogic(GetEITDFFStructureList structureElement) { - //try { - List parentValue = structureElement.pARENTSEGMENTSVSSplitedVS ?? []; - List parentsList = structureElement.pARENTSEGMENTSDVSplited ?? []; - - List> dependenciesList = []; - String? parentVal; - bool isStandardDate = false; - bool isStandardTimeDate = false; - bool isStandardTime = false; - bool isHidden = false; - bool isReadOnlyList = false; - bool isSelectElement = false; - - // isStandardDate = this.isStandardDate(obj); - // isStandardTimeDate = this.isStandardDateTime(obj); - // isStandardTime = this.isStandardTime(obj); - if (structureElement.dISPLAYFLAG == "N") isHidden = true; - if (structureElement.vALIDATIONTYPE != "N" && structureElement.rEADONLY == "Y") { - isReadOnlyList = true; - } - if (structureElement.vALIDATIONTYPE != "N" && structureElement.rEADONLY == "N") { - isSelectElement = true; - } + try { + List parentValue = structureElement.pARENTSEGMENTSVSSplitedVS ?? []; + List parentsList = structureElement.pARENTSEGMENTSDVSplited ?? []; + + List> dependenciesList = []; + String? parentVal; + bool isStandardDate = false; + bool isStandardTimeDate = false; + bool isStandardTime = false; + bool isHidden = false; + bool isReadOnlyList = false; + bool isSelectElement = false; + + // isStandardDate = this.isStandardDate(obj); + // isStandardTimeDate = this.isStandardDateTime(obj); + // isStandardTime = this.isStandardTime(obj); + if (structureElement.dISPLAYFLAG == "N") isHidden = true; + if (structureElement.vALIDATIONTYPE != "N" && structureElement.rEADONLY == "Y") { + isReadOnlyList = true; + } + if (structureElement.vALIDATIONTYPE != "N" && structureElement.rEADONLY == "N") { + isSelectElement = true; + } - if (parentValue.isNotEmpty && (structureElement.vALIDATIONTYPE == "D" || structureElement.vALIDATIONTYPE == "Y")) { - List parValue = getDependenciesParams(parentValue); + if (parentValue.isNotEmpty && (structureElement.vALIDATIONTYPE == "D" || structureElement.vALIDATIONTYPE == "Y")) { + List parValue = getDependenciesParams(parentValue); - if (parValue.isNotEmpty) { - parentVal = parValue.first.ID_COLUMN_NAME; - } + if (parValue.isNotEmpty) { + parentVal = parValue.first.ID_COLUMN_NAME; + } - if (parentVal == null) { - return []; + if (parentVal == null) { + return []; + } } - } - if (parentsList.isNotEmpty) { - if (parentValue.isNotEmpty) { - parentsList = parentsList + parentValue.map((e) => PARENTSEGMENTSDVSplited.fromJson(e.toJson())).toList(); - // parentsList.addAll(parentValue.map((e) => PARENTSEGMENTSDVSplited.fromJson(e.toJson()))); - // parentsList.concat(parentValue); + if (parentsList.isNotEmpty) { + if (parentValue.isNotEmpty) { + parentsList = parentsList + parentValue.map((e) => PARENTSEGMENTSDVSplited.fromJson(e.toJson())).toList(); + // parentsList.addAll(parentValue.map((e) => PARENTSEGMENTSDVSplited.fromJson(e.toJson()))); + // parentsList.concat(parentValue); + } + dependenciesList = getDependenciesParams(parentsList); } - dependenciesList = getDependenciesParams(parentsList); + return dependenciesList; + // for (int i = 0; i < (structureList.cHILDSEGMENTSDVSplited?.length ?? 0); i++) { + // String segmentId = structureList.cHILDSEGMENTSDVSplited![i]; + // print("segmentId:$segmentId"); + // print("segmentName:${structureList.sEGMENTNAME}"); + // GetEITDFFStructureList? parent = getEitDffStructureList!.firstWhere((element) => element.sEGMENTNAME == segmentId); + // List parentDvRequired = parent.pARENTSEGMENTSDVSplited ?? []; + // List parentVsRequired = parent.pARENTSEGMENTSVSSplitedVS ?? []; + // + // List filteredList = + // getEitDffStructureList!.where((outerElement) => parentDvRequired.any((element) => outerElement.sEGMENTNAME == element.name && element.isRequired == "REQUIRED")).toList(); + // + // List> values = filteredList + // .map((e) => GetSetValuesRequestModel( + // sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) + // .toJson()) + // .toList(); + // print("values:$values"); + // + // ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); + // int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); + // getEitDffStructureList![index].eSERVICESDV = defaultValue; + // } + // Utils.hideLoading(context); + // setState(() {}); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + return []; } - return dependenciesList; - // for (int i = 0; i < (structureList.cHILDSEGMENTSDVSplited?.length ?? 0); i++) { - // String segmentId = structureList.cHILDSEGMENTSDVSplited![i]; - // print("segmentId:$segmentId"); - // print("segmentName:${structureList.sEGMENTNAME}"); - // GetEITDFFStructureList? parent = getEitDffStructureList!.firstWhere((element) => element.sEGMENTNAME == segmentId); - // List parentDvRequired = parent.pARENTSEGMENTSDVSplited ?? []; - // List parentVsRequired = parent.pARENTSEGMENTSVSSplitedVS ?? []; - // - // List filteredList = - // getEitDffStructureList!.where((outerElement) => parentDvRequired.any((element) => outerElement.sEGMENTNAME == element.name && element.isRequired == "REQUIRED")).toList(); - // - // List> values = filteredList - // .map((e) => GetSetValuesRequestModel( - // sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) - // .toJson()) - // .toList(); - // print("values:$values"); - // - // ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); - // int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); - // getEitDffStructureList![index].eSERVICESDV = defaultValue; - // } - // Utils.hideLoading(context); - // setState(() {}); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // return []; - // } } List> getDependenciesParams(parentsList) { @@ -318,7 +260,7 @@ class _DynamicInputScreenState extends State { for (int i = 0; i < parentsList.length; i++) { for (int j = 0; j < (getEitDffStructureList?.length ?? 0); j++) { - if (getEitDffStructureList![j].sEGMENTNAME == parentsList[i]?.name) { + if (getEitDffStructureList![j].sEGMENTNAME == parentsList[i].name) { if (getEitDffStructureList![j].dISPLAYFLAG != "N") { if (getEitDffStructureList![j].vALIDATIONTYPE == "N") { String? idColName; @@ -398,7 +340,7 @@ class _DynamicInputScreenState extends State { String? text = data?.pVALUECOLUMNNAME; String? val = data?.pIDCOLUMNNAME; - if ((val ?? "").isEmpty && parentsList[i].isRequired == "REQUIRED") { + if ((val ?? "").isEmpty && parentsList[i].IsRequired == "REQUIRED") { //alert(parentsList[i].Name +" Is required"); return []; } else {} @@ -420,8 +362,7 @@ class _DynamicInputScreenState extends State { String? text = data?.pVALUECOLUMNNAME; String? val = data?.pIDCOLUMNNAME; - /// - if ((val ?? "").isEmpty && parentsList[i].isRequired == "REQUIRED") { + if ((val ?? "").isEmpty && parentsList[i].IsRequired == "REQUIRED") { //alert(parentsList[i].Name +" Is required"); return []; } else {} @@ -514,11 +455,6 @@ class _DynamicInputScreenState extends State { model.eSERVICESDV ??= ESERVICESDV(); model.eSERVICESDV!.pIDCOLUMNNAME = text; }, - onTap: () async { - if (model.cHILDSEGMENTSDVSplited?.isNotEmpty ?? false) { - await getDefaultValues(model); - } - }, ).paddingOnly(bottom: 12); } else if (model.fORMATTYPE == "X") { String displayText = model.eSERVICESDV?.pIDCOLUMNNAME ?? (getEitDffStructureList![index].fieldAnswer ?? ""); From 29626ea408b1f2f6905b02c6cd93a7daf53b20ba Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 14 Nov 2022 12:26:50 +0300 Subject: [PATCH 35/82] Chat Fixes --- ios/Runner.xcodeproj/project.pbxproj | 6 +-- lib/api/chat/chat_provider_model.dart | 64 ++++++++++++++++++++++---- lib/classes/consts.dart | 4 +- lib/ui/chat/chat_bubble.dart | 2 +- lib/ui/chat/chat_detailed_screen.dart | 60 +++--------------------- lib/ui/chat/chat_home.dart | 6 +++ lib/ui/chat/chat_home_screen.dart | 4 +- lib/ui/chat/favorite_users_screen.dart | 2 +- 8 files changed, 76 insertions(+), 72 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 9daee21..43841a1 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -383,7 +383,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 3A359E86ZF; + DEVELOPMENT_TEAM = 99Z3UD3LJM; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; @@ -520,7 +520,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 3A359E86ZF; + DEVELOPMENT_TEAM = 99Z3UD3LJM; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; @@ -549,7 +549,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 3A359E86ZF; + DEVELOPMENT_TEAM = 99Z3UD3LJM; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index fb9e6c5..0f0e94c 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -1,10 +1,12 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'dart:math'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; +import 'package:logger/logger.dart' as L; import 'package:logging/logging.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; @@ -15,17 +17,17 @@ import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.da import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as login; import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; import 'package:mohem_flutter_app/widgets/image_picker.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:signalr_netcore/signalr_client.dart'; -import 'package:logger/logger.dart' as L; import 'package:uuid/uuid.dart'; class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { + ScrollController scrollController = ScrollController(); + TextEditingController message = TextEditingController(); List userChatHistory = []; List? pChatHistory, searchedChats; late HubConnection hubConnection; L.Logger logger = L.Logger(); - TextEditingController message = TextEditingController(); + bool isLoading = true; bool isChatScreenActive = false; late File selectedFile; @@ -36,6 +38,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List favUsersList = []; int paginationVal = 0; + //Scroll + bool _firstAutoscrollExecuted = false; + bool _shouldAutoscroll = false; + Future getUserAutoLoginToken() async { String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString(); Response response = @@ -87,12 +93,20 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore}) async { isLoading = true; + print(loadMore); + print(senderUID); + print(receiverUID); if (!loadMore) paginationVal = 0; + print(paginationVal); isChatScreenActive = true; Response response = await ApiClient().getJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", token: AppState().chatDetails!.response!.token, ); + logger.d("${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal"); + logger.d("${AppState().chatDetails!.response!.token}"); + logger.d(jsonEncode(response.body)); + logger.d(jsonEncode(response.statusCode)); if (response.statusCode == 204) { if (!loadMore) userChatHistory = []; Utils.showToast("No More Data To Load"); @@ -105,7 +119,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } isLoading = false; + //Timer(const Duration(milliseconds: 100),() => scrollToBottom()); notifyListeners(); + + // scrollToBottom(); } List getSingleUserChatModel(String str) => List.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); @@ -218,9 +235,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void changeStatus(List? args) { - if (kDebugMode) { - // print("================= Status Online // Offline ===================="); - } + if (kDebugMode) { + // print("================= Status Online // Offline ===================="); + } dynamic items = args!.toList(); // logger.d(items); for (ChatUser user in searchedChats!) { @@ -258,6 +275,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserName = temp.first.targetUserName; } userChatHistory.add(data.first); + scrollToBottom(); notifyListeners(); // if (isChatScreenActive) scrollDown(); } @@ -356,7 +374,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // } Future sendChatToServer( - {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { + {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { Uuid uuid = const Uuid(); SingleUserChatModel data = SingleUserChatModel( chatEventId: chatEventId, @@ -390,6 +408,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isMsgReply = false; sFileType = ""; message.clear(); + scrollToBottom(); notifyListeners(); } @@ -575,4 +594,33 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { repliedMsg = []; sFileType = ""; } + + void scrollListener() { + _firstAutoscrollExecuted = true; + if (scrollController.hasClients && scrollController.position.pixels == scrollController.position.maxScrollExtent) { + _shouldAutoscroll = true; + } else { + _shouldAutoscroll = false; + } + } + + void scrollToBottom() { + //scrollController.jumpTo(scrollController.position.maxScrollExtent + 100 ); + scrollController.animateTo( + scrollController.position.maxScrollExtent + 100, + duration: const Duration(milliseconds: 500), + curve: Curves.easeIn, + ); + } + +// void scrollToMaxExtent() { +// WidgetsBinding.instance.addPostFrameCallback((_) { +// scrollController.animateTo( +// scrollController.position.maxScrollExtent, +// duration: const Duration(milliseconds: 100), +// curve: Curves.easeIn, +// ); +// }); +// } + } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index c5788f9..ede22e3 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index d9bd599..c638b34 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -89,7 +89,7 @@ class ChatBubble extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7)), + dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7),), if (isCurrentUser) 5.width, if (isCurrentUser) Icon( diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index e2d0bd7..b4838f3 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -17,23 +16,14 @@ import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:swipe_to/swipe_to.dart'; -class ChatDetailScreen extends StatefulWidget { +class ChatDetailScreen extends StatelessWidget { // ignore: prefer_const_constructors_in_immutables ChatDetailScreen({Key? key}) : super(key: key); - @override - State createState() => _ChatDetailScreenState(); -} - -class _ChatDetailScreenState extends State { dynamic userDetails; - bool _firstAutoscrollExecuted = false; - bool _shouldAutoscroll = false; late ChatProviderModel data; - ScrollController scrollController = ScrollController(); - final RefreshController _refreshController = RefreshController(initialRefresh: false); void getMoreChat() async { @@ -44,53 +34,13 @@ class _ChatDetailScreenState extends State { await Future.delayed(const Duration(milliseconds: 1000)); _refreshController.refreshCompleted(); } - // - // void _scrollListener() { - // _firstAutoscrollExecuted = true; - // if (scrollController.hasClients && scrollController.position.pixels == scrollController.position.maxScrollExtent) { - // _shouldAutoscroll = true; - // } else { - // _shouldAutoscroll = false; - // } - // } - // - // void _scrollToBottom() { - // scrollController.jumpTo(scrollController.position.maxScrollExtent); - // } - - // void scrollToMaxExtent() { - // WidgetsBinding.instance.addPostFrameCallback((_) { - // scrollController.animateTo( - // scrollController.position.maxScrollExtent, - // duration: const Duration(milliseconds: 100), - // curve: Curves.easeIn, - // ); - // }); - // } - - - - @override - void initState() { - // TODO: implement initState - super.initState(); - //scrollToMaxExtent(); - - // scrollController.addListener(_scrollListener); - } - - @override - void dispose() { - // TODO: implement dispose - //scrollController.removeListener(_scrollListener); - super.dispose(); - } @override Widget build(BuildContext context) { userDetails = ModalRoute.of(context)!.settings.arguments; data = Provider.of(context, listen: false); if (userDetails != null) data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: false); + data.scrollController.addListener(data.scrollListener); return Scaffold( backgroundColor: const Color(0xFFF8F8F8), appBar: AppBarWidget(context, title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, image: userDetails["targetUser"].image), @@ -111,7 +61,7 @@ class _ChatDetailScreenState extends State { controller: _refreshController, onRefresh: getMoreChat, child: ListView.builder( - controller: scrollController, + controller: m.scrollController, shrinkWrap: true, reverse: false, itemCount: m.userChatHistory.length, @@ -150,7 +100,9 @@ class _ChatDetailScreenState extends State { height: 80, color: MyColors.black.withOpacity(0.10), child: ListTile( - title: (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() ? "You" : m.repliedMsg.first.currentUserName.toString().replaceAll(".", " ")) + title: (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() + ? "You" + : m.repliedMsg.first.currentUserName.toString().replaceAll(".", " ")) .toText14(color: MyColors.lightGreenColor), subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.white, maxLine: 2), trailing: GestureDetector( diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 5176273..d3c4d62 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/chat/chat_provider_model.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'; @@ -11,6 +12,7 @@ import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/items_for_sale.dart'; import 'package:mohem_flutter_app/ui/screens/items_for_sale/fragments/my_posted_ads_fragment.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:provider/provider.dart'; class ChatHome extends StatefulWidget { const ChatHome({Key? key}) : super(key: key); @@ -22,9 +24,13 @@ class ChatHome extends StatefulWidget { class _ChatHomeState extends State { int tabIndex = 0; PageController controller = PageController(); + late ChatProviderModel data; + @override Widget build(BuildContext context) { + data = Provider.of(context, listen: false); + data.getUserAutoLoginToken().whenComplete(() => null); return Scaffold( backgroundColor: MyColors.white, appBar: AppBarWidget( diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 32f97fa..e55f018 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -29,9 +29,7 @@ class _ChatHomeScreenState extends State { void initState() { super.initState(); data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().whenComplete(() { - data.getUserRecentChats(); - }); + data.getUserRecentChats(); } @override diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index 8b5eba0..29d4ffa 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -56,7 +56,7 @@ class ChatFavoriteUsersScreen extends StatelessWidget { ) ], ), - title: (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor), + title: (m.favUsersList![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor), trailing: IconButton( alignment: Alignment.centerRight, padding: EdgeInsets.zero, From b18ebf7a54efc4c352f183303348de6a33a4712a Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 14 Nov 2022 15:34:31 +0300 Subject: [PATCH 36/82] Chat Favorite Screen & Fixes --- lib/api/chat/chat_provider_model.dart | 32 --------------------------- lib/classes/consts.dart | 2 +- lib/ui/chat/chat_home.dart | 4 +++- lib/ui/chat/chat_home_screen.dart | 4 ---- 4 files changed, 4 insertions(+), 38 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 0f0e94c..a61a57a 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -93,20 +93,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore}) async { isLoading = true; - print(loadMore); - print(senderUID); - print(receiverUID); if (!loadMore) paginationVal = 0; - print(paginationVal); isChatScreenActive = true; Response response = await ApiClient().getJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal", token: AppState().chatDetails!.response!.token, ); - logger.d("${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal"); - logger.d("${AppState().chatDetails!.response!.token}"); - logger.d(jsonEncode(response.body)); - logger.d(jsonEncode(response.statusCode)); if (response.statusCode == 204) { if (!loadMore) userChatHistory = []; Utils.showToast("No More Data To Load"); @@ -119,10 +111,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } isLoading = false; - //Timer(const Duration(milliseconds: 100),() => scrollToBottom()); notifyListeners(); - - // scrollToBottom(); } List getSingleUserChatModel(String str) => List.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); @@ -364,15 +353,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - // void scrollDown() { - // scrollController.animateTo( - // scrollController.position.maxScrollExtent + 100, - // curve: Curves.easeOut, - // duration: const Duration(milliseconds: 300), - // ); - // notifyListeners(); - // } - Future sendChatToServer( {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { Uuid uuid = const Uuid(); @@ -605,22 +585,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void scrollToBottom() { - //scrollController.jumpTo(scrollController.position.maxScrollExtent + 100 ); scrollController.animateTo( scrollController.position.maxScrollExtent + 100, duration: const Duration(milliseconds: 500), curve: Curves.easeIn, ); } - -// void scrollToMaxExtent() { -// WidgetsBinding.instance.addPostFrameCallback((_) { -// scrollController.animateTo( -// scrollController.position.maxScrollExtent, -// duration: const Duration(milliseconds: 100), -// curve: Curves.easeIn, -// ); -// }); -// } - } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index ede22e3..93b4ea8 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server - //static String baseUrl = "https://hmgwebservices.com"; // Live 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/"; diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index d3c4d62..ea53d2e 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -30,7 +30,9 @@ class _ChatHomeState extends State { @override Widget build(BuildContext context) { data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().whenComplete(() => null); + data.getUserAutoLoginToken().then((value){ + data.getUserRecentChats(); + }); return Scaffold( backgroundColor: MyColors.white, appBar: AppBarWidget( diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index e55f018..1b351e5 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -23,19 +23,15 @@ class ChatHomeScreen extends StatefulWidget { class _ChatHomeScreenState extends State { TextEditingController search = TextEditingController(); - late ChatProviderModel data; @override void initState() { super.initState(); - data = Provider.of(context, listen: false); - data.getUserRecentChats(); } @override void dispose() { super.dispose(); - data.hubConnection.stop(); } @override From 4433f538b78d636d86508cf633ab998473d31df6 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 14 Nov 2022 15:38:15 +0300 Subject: [PATCH 37/82] Chat Favorite Screen & Fixes --- lib/api/chat/chat_provider_model.dart | 4 ---- lib/ui/chat/chat_home_screen.dart | 23 ++--------------------- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index a61a57a..d033eba 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -154,9 +154,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ({String? connectionId}) {}, ); if (hubConnection.state != HubConnectionState.Connected) { - if (kDebugMode) { - print("================= Connection Established =========================="); - } await hubConnection.start(); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); @@ -167,7 +164,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); } - // notifyListeners(); } void updateUserChatStatus(List? args) { diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 1b351e5..540a212 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -14,26 +14,9 @@ import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_s import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; -class ChatHomeScreen extends StatefulWidget { - const ChatHomeScreen({Key? key}) : super(key: key); - - @override - State createState() => _ChatHomeScreenState(); -} - -class _ChatHomeScreenState extends State { +class ChatHomeScreen extends StatelessWidget { TextEditingController search = TextEditingController(); - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -211,9 +194,7 @@ class _ChatHomeScreenState extends State { title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), fromChat: true, - onSelectEmployee: (_selectedEmployee) { - setState(() {}); - }, + onSelectEmployee: (_selectedEmployee) {}, ), ); }, From 8f80c396d132d5d38227d996f9184e03f23fe313 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 14 Nov 2022 15:50:27 +0300 Subject: [PATCH 38/82] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index d033eba..00691ec 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -260,9 +260,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserName = temp.first.targetUserName; } userChatHistory.add(data.first); - scrollToBottom(); notifyListeners(); - // if (isChatScreenActive) scrollDown(); + if (isChatScreenActive) scrollToBottom(); } void onUserTyping(List? parameters) { From b8e20633c9acb6d28f1d27582f1e3c8816f3ade9 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 14 Nov 2022 16:20:40 +0300 Subject: [PATCH 39/82] Chat Fixes --- lib/ui/chat/chat_home_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 540a212..7fb6965 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -128,7 +128,7 @@ class ChatHomeScreen extends StatelessWidget { child: IconButton( alignment: Alignment.centerRight, padding: EdgeInsets.zero, - icon: Icon(m.searchedChats![index].isFav! ? Icons.star : Icons.star_border), + icon: Icon(m.searchedChats![index].isFav! ? Icons.star_sharp : Icons.star_border), color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, onPressed: () { if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); From fb5440358430fb6d27558384504f56bb5fb7ab03 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 15 Nov 2022 09:32:30 +0300 Subject: [PATCH 40/82] Chat Favorite Screen & Fixes --- lib/api/chat/chat_provider_model.dart | 38 ++++++++++++++----- lib/ui/chat/chat_detailed_screen.dart | 5 ++- lib/ui/chat/chat_home_screen.dart | 2 +- lib/ui/chat/favorite_users_screen.dart | 2 +- .../search_employee_bottom_sheet.dart | 2 +- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 00691ec..3cfee4f 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -91,7 +91,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore}) async { + void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async { isLoading = true; if (!loadMore) paginationVal = 0; isChatScreenActive = true; @@ -100,8 +100,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { token: AppState().chatDetails!.response!.token, ); if (response.statusCode == 204) { - if (!loadMore) userChatHistory = []; - Utils.showToast("No More Data To Load"); + if (isNewChat) { + userChatHistory = []; + } else if (loadMore) { + // userChatHistory = []; + Utils.showToast("No More Data To Load"); + } } else { if (loadMore) { List temp = getSingleUserChatModel(response.body); @@ -131,7 +135,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } else { result = []; } - } catch (e) {} + } catch (e) { + if (kDebugMode) { + print(e); + } + } + ; return result; } @@ -139,11 +148,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); hubConnection = HubConnectionBuilder() .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) - .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]) - .configureLogging( - Logger("Logs Enabled"), - ) - .build(); + .withAutomaticReconnect( + retryDelays: [2000, 5000, 10000, 20000], + ).build(); hubConnection.onclose( ({Exception? error}) {}, ); @@ -157,6 +164,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await hubConnection.start(); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); + hubConnection.on("OnSeenChatUserAsync", onChatSeen); //hubConnection.on("OnUserTypingAsync", onUserTyping); // hubConnection.on("OnUserCountAsync", userCountAsync); @@ -179,6 +187,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } + void onChatSeen(List? args) { + dynamic items = args!.toList(); + logger.d("---------------------------------Chat Seen -------------------------------------"); + logger.d(items); + // for (var user in searchedChats!) { + // if (user.id == items.first["id"]) { + // user.userStatus = items.first["userStatus"]; + // } + // } + // notifyListeners(); + } + void userCountAsync(List? args) { dynamic items = args!.toList(); //logger.d("---------------------------------User Count Async -------------------------------------"); diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index b4838f3..5c05173 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -29,7 +29,7 @@ class ChatDetailScreen extends StatelessWidget { void getMoreChat() async { if (userDetails != null) { data.paginationVal = data.paginationVal + 10; - data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true); + data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false); } await Future.delayed(const Duration(milliseconds: 1000)); _refreshController.refreshCompleted(); @@ -39,7 +39,8 @@ class ChatDetailScreen extends StatelessWidget { Widget build(BuildContext context) { userDetails = ModalRoute.of(context)!.settings.arguments; data = Provider.of(context, listen: false); - if (userDetails != null) data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: false); + if (userDetails != null) + data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: false, isNewChat: userDetails["isNewChat"]); data.scrollController.addListener(data.scrollListener); return Scaffold( backgroundColor: const Color(0xFFF8F8F8), diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 7fb6965..ce866f8 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -144,7 +144,7 @@ class ChatHomeScreen extends StatelessWidget { Navigator.pushNamed( context, AppRoutes.chatDetailed, - arguments: {"targetUser": m.searchedChats![index]}, + arguments: {"targetUser": m.searchedChats![index], "isNewChat" : false}, ).then((Object? value) { m.clearSelections(); }); diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index 29d4ffa..fd118de 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -71,7 +71,7 @@ class ChatFavoriteUsersScreen extends StatelessWidget { Navigator.pushNamed( context, AppRoutes.chatDetailed, - arguments: {"targetUser": m.favUsersList![index]}, + arguments: {"targetUser": m.favUsersList![index], "isNewChat": false}, ).then( (Object? value) { m.clearSelections(); diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index 63ce88b..a30b33d 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -233,7 +233,7 @@ class _SearchEmployeeBottomSheetState extends State { Navigator.pushNamed( context, AppRoutes.chatDetailed, - arguments: {"targetUser": chatUsersList![index]}, + arguments: {"targetUser": chatUsersList![index], "isNewChat": true}, ); }, onLongPress: () {}, From 670a5fbc03a94976e922bfb7bcb8f39806cf1f9d Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 15 Nov 2022 10:18:42 +0300 Subject: [PATCH 41/82] Chat Favorite Screen & Fixes --- assets/langs/ar-SA.json | 2 +- assets/langs/en-US.json | 2 +- lib/api/chat/chat_provider_model.dart | 4 +++ lib/generated/codegen_loader.g.dart | 4 +-- lib/ui/chat/chat_home_screen.dart | 37 ++++++++++++--------------- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index bdec4f0..000e111 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -499,7 +499,7 @@ "resend": "إعادة إرسال", "codeExpire": "انتهت صلاحية رمز التحقق", "typeheretoreply": "اكتب هنا للرد", - "favorite" : "مفضل", + "favorite" : "أُفضله", "searchfromchat": "البحث من الدردشة" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 1cd1a33..c8b8322 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -499,7 +499,7 @@ "codeExpire": "The verification code has been expired", "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply", - "favorite" : "Favorite", + "favorite" : "My Favorite", "searchfromchat": "Search from chat" } \ No newline at end of file diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 3cfee4f..3498a17 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -23,6 +23,7 @@ import 'package:uuid/uuid.dart'; class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ScrollController scrollController = ScrollController(); TextEditingController message = TextEditingController(); + TextEditingController search = TextEditingController(); List userChatHistory = []; List? pChatHistory, searchedChats; late HubConnection hubConnection; @@ -582,12 +583,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void clearSelections() { + searchedChats = pChatHistory; + search.clear(); isChatScreenActive = false; paginationVal = 0; message.text = ''; isFileSelected = false; repliedMsg = []; sFileType = ""; + notifyListeners(); } void scrollListener() { diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 49dac5c..3d35ccc 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -515,7 +515,7 @@ class CodegenLoader extends AssetLoader{ "resend": "إعادة إرسال", "codeExpire": "انتهت صلاحية رمز التحقق", "typeheretoreply": "اكتب هنا للرد", - "favorite": "مفضل", + "favorite": "أُفضله", "searchfromchat": "البحث من الدردشة" }; static const Map en_US = { @@ -1019,7 +1019,7 @@ static const Map en_US = { "codeExpire": "The verification code has been expired", "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply", - "favorite": "Favorite", + "favorite": "My Favorite", "searchfromchat": "Search from chat" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index ce866f8..f66f3d5 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -32,28 +32,14 @@ class ChatHomeScreen extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), child: TextField( + controller: m.search, onChanged: (String val) { m.filter(val); }, decoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: const BorderSide( - color: Color(0xFFE5E5E5), - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: const BorderSide( - color: Color(0xFFE5E5E5), - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: const BorderSide( - color: Color(0xFFE5E5E5), - ), - ), + border: fieldBorder(radius: 5, color: 0xFFE5E5E5), + focusedBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), + enabledBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), hintText: LocaleKeys.searchfromchat.tr(), hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic), @@ -73,7 +59,7 @@ class ChatHomeScreen extends StatelessWidget { height: 55, child: ListTile( leading: Stack( - children: [ + children: [ SvgPicture.asset( "assets/images/user.svg", height: 48, @@ -144,12 +130,12 @@ class ChatHomeScreen extends StatelessWidget { Navigator.pushNamed( context, AppRoutes.chatDetailed, - arguments: {"targetUser": m.searchedChats![index], "isNewChat" : false}, + arguments: {"targetUser": m.searchedChats![index], "isNewChat": false}, ).then((Object? value) { m.clearSelections(); + m.notifyListeners(); }); }, - onLongPress: () {}, ), ); }, @@ -201,4 +187,13 @@ class ChatHomeScreen extends StatelessWidget { ), ); } + + OutlineInputBorder fieldBorder({required double radius, required int color}) { + return OutlineInputBorder( + borderRadius: BorderRadius.circular(radius), + borderSide: BorderSide( + color: Color(color), + ), + ); + } } From c190fbf5ca5fadeb8fd680ef8660dbb8cceed372 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 15 Nov 2022 11:14:52 +0300 Subject: [PATCH 42/82] Chat Favorite Screen & Fixes --- lib/api/chat/chat_provider_model.dart | 16 ++++++++++++++-- lib/ui/chat/chat_detailed_screen.dart | 14 +++++++++----- lib/ui/chat/chat_home.dart | 18 +++++++++--------- lib/ui/chat/chat_home_screen.dart | 25 ++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 3498a17..0cb67e6 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -109,10 +109,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } else { if (loadMore) { - List temp = getSingleUserChatModel(response.body); - userChatHistory.insertAll(0, temp); + List temp = getSingleUserChatModel(response.body).reversed.toList(); + userChatHistory.addAll(temp); } else { userChatHistory = getSingleUserChatModel(response.body); + userChatHistory = userChatHistory.reversed.toList(); } } isLoading = false; @@ -594,6 +595,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } + void clearAll() { + searchedChats = pChatHistory; + search.clear(); + isChatScreenActive = false; + paginationVal = 0; + message.text = ''; + isFileSelected = false; + repliedMsg = []; + sFileType = ""; + } + void scrollListener() { _firstAutoscrollExecuted = true; if (scrollController.hasClients && scrollController.position.pixels == scrollController.position.maxScrollExtent) { diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 5c05173..04e84e0 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -32,7 +32,7 @@ class ChatDetailScreen extends StatelessWidget { data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false); } await Future.delayed(const Duration(milliseconds: 1000)); - _refreshController.refreshCompleted(); + _refreshController.loadComplete(); } @override @@ -54,17 +54,21 @@ class ChatDetailScreen extends StatelessWidget { Expanded( flex: 2, child: SmartRefresher( - enablePullDown: true, - enablePullUp: false, + enablePullDown: false, + enablePullUp: true, + onLoading: () { + getMoreChat(); + }, header: const MaterialClassicHeader( color: MyColors.gradiantEndColor, ), controller: _refreshController, - onRefresh: getMoreChat, + reverse: true, child: ListView.builder( controller: m.scrollController, shrinkWrap: true, - reverse: false, + physics: const BouncingScrollPhysics(), + reverse: true, itemCount: m.userChatHistory.length, padding: const EdgeInsets.only(top: 20), itemBuilder: (BuildContext context, int i) { diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index ea53d2e..86356bb 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -26,11 +26,16 @@ class _ChatHomeState extends State { PageController controller = PageController(); late ChatProviderModel data; + @override + void dispose() { + data.clearAll(); + super.dispose(); + } @override Widget build(BuildContext context) { data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().then((value){ + data.getUserAutoLoginToken().then((value) { data.getUserRecentChats(); }); return Scaffold( @@ -41,7 +46,7 @@ class _ChatHomeState extends State { showHomeButton: true, ), body: Column( - children: [ + children: [ Container( padding: const EdgeInsets.only(left: 21, right: 21, top: 16, bottom: 16), decoration: const BoxDecoration( @@ -60,12 +65,7 @@ class _ChatHomeState extends State { ), ), child: Row( - children: [ - myTab(LocaleKeys.mychats.tr(), 0), - myTab( - LocaleKeys.favorite.tr(), - 1) - ], + children: [myTab(LocaleKeys.mychats.tr(), 0), myTab(LocaleKeys.favorite.tr(), 1)], ), ), PageView( @@ -76,7 +76,7 @@ class _ChatHomeState extends State { tabIndex = pageIndex; }); }, - children: [ChatHomeScreen(), ChatFavoriteUsersScreen()], + children: [ChatHomeScreen(), ChatFavoriteUsersScreen()], ).expanded, ], ), diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index f66f3d5..3ac291c 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -14,9 +14,20 @@ import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_s import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; -class ChatHomeScreen extends StatelessWidget { +class ChatHomeScreen extends StatefulWidget { + @override + State createState() => _ChatHomeScreenState(); +} + +class _ChatHomeScreenState extends State { TextEditingController search = TextEditingController(); + @override + void dispose() { + super.dispose(); + search.clear(); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -45,6 +56,18 @@ class ChatHomeScreen extends StatelessWidget { hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic), filled: true, fillColor: const Color(0xFFF7F7F7), + suffixIcon: m.search.text.isNotEmpty + ? IconButton( + onPressed: () { + m.clearSelections(); + }, + icon: const Icon( + Icons.clear, + size: 22, + ), + color: MyColors.redA3Color, + ) + : null, ), ), ), From 70dd6e1c991eb5a29eb5e59080bfb5407bba1d27 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 15 Nov 2022 11:55:08 +0300 Subject: [PATCH 43/82] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 0cb67e6..727fd12 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -7,7 +7,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:logger/logger.dart' as L; -import 'package:logging/logging.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -112,8 +111,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List temp = getSingleUserChatModel(response.body).reversed.toList(); userChatHistory.addAll(temp); } else { - userChatHistory = getSingleUserChatModel(response.body); - userChatHistory = userChatHistory.reversed.toList(); + userChatHistory = getSingleUserChatModel(response.body).reversed.toList(); } } isLoading = false; @@ -400,12 +398,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { String chatData = '{"contant":"${message.text}","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}'; await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); - userChatHistory.add(data); + + userChatHistory.insert(0, data); + isFileSelected = false; isMsgReply = false; sFileType = ""; message.clear(); - scrollToBottom(); notifyListeners(); } @@ -622,4 +621,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { curve: Curves.easeIn, ); } + + void msgScroll() { + scrollController.animateTo( + scrollController.position.minScrollExtent - 100, + duration: const Duration(milliseconds: 500), + curve: Curves.easeIn, + ); + } } From ae917a415476f6eec33814b6ad3d550508b7a955 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 15 Nov 2022 12:44:09 +0300 Subject: [PATCH 44/82] Chat Favorite Screen & Fixes --- lib/api/chat/chat_provider_model.dart | 13 ++++++++++--- lib/ui/chat/chat_home.dart | 17 +++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 727fd12..be5b68c 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -164,7 +164,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await hubConnection.start(); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - hubConnection.on("OnSeenChatUserAsync", onChatSeen); + // hubConnection.on("OnSeenChatUserAsync", onChatSeen); //hubConnection.on("OnUserTypingAsync", onUserTyping); // hubConnection.on("OnUserCountAsync", userCountAsync); @@ -269,6 +269,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future onMsgReceived(List? parameters) async { + print("msg Received"); List data = []; List temp = []; for (dynamic msg in parameters!) { @@ -279,9 +280,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { data.first.currentUserId = temp.first.targetUserId; data.first.currentUserName = temp.first.targetUserName; } - userChatHistory.add(data.first); + userChatHistory.insert(0, data.first); + // searchedChats!.forEach((element) { + // if (element.id == data.first.currentUserId) { + // var val = element.unreadMessageCount == null ? 0 : element.unreadMessageCount; + // element.unreadMessageCount = val! + 1; + // } + // }); notifyListeners(); - if (isChatScreenActive) scrollToBottom(); + // if (isChatScreenActive) scrollToBottom(); } void onUserTyping(List? parameters) { diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 86356bb..1fdcb33 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -26,18 +26,27 @@ class _ChatHomeState extends State { PageController controller = PageController(); late ChatProviderModel data; + + @override + void initState() { + // TODO: implement initState + super.initState(); + data = Provider.of(context, listen: false); + data.getUserAutoLoginToken().then((value) { + data.getUserRecentChats(); + }); + } + @override void dispose() { data.clearAll(); + data.hubConnection.stop(); super.dispose(); } @override Widget build(BuildContext context) { - data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().then((value) { - data.getUserRecentChats(); - }); + return Scaffold( backgroundColor: MyColors.white, appBar: AppBarWidget( From c436908d2509c72cbf754245798c7763263e7169 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 15 Nov 2022 14:23:51 +0300 Subject: [PATCH 45/82] updates & fixes --- lib/api/worklist/worklist_api_client.dart | 18 +++ .../attendance/monthly_attendance_screen.dart | 2 +- lib/ui/landing/today_attendance_screen2.dart | 2 +- lib/ui/landing/widget/services_widget.dart | 2 +- lib/ui/marathon/widgets/marathon_banner.dart | 4 +- .../dynamic_screens/dynamic_input_screen.dart | 10 +- lib/ui/my_team/view_attendance.dart | 2 +- lib/ui/profile/add_update_family_member.dart | 2 +- lib/ui/profile/family_members.dart | 3 +- lib/ui/screens/my_requests/my_requests.dart | 6 +- .../offers_and_discounts_details.dart | 4 +- lib/ui/work_list/itg_detail_screen.dart | 29 +++++ lib/ui/work_list/work_list_screen.dart | 1 - lib/ui/work_list/worklist_detail_screen.dart | 11 ++ .../worklist_fragments/actions_fragment.dart | 2 - lib/widgets/app_bar_widget.dart | 110 ++++++++++-------- 16 files changed, 135 insertions(+), 73 deletions(-) diff --git a/lib/api/worklist/worklist_api_client.dart b/lib/api/worklist/worklist_api_client.dart index d999d18..75992e7 100644 --- a/lib/api/worklist/worklist_api_client.dart +++ b/lib/api/worklist/worklist_api_client.dart @@ -403,6 +403,24 @@ class WorkListApiClient { }, url, postParams); } + Future grantITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { + String url = "${ApiConsts.cocRest}ITGGrantAccess"; + Map postParams = { + "RequestType": requestType, + "TaskID": taskId, + "ItemID": itemId, + "EmployeeNumber": employeeNumber, + "Comments": "", + "AdditionalFields": null, + "NewUserEMPId":newUserEMPId + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + ItgFormsModel responseData = ItgFormsModel.fromJson(json); + return responseData.itgRequest; + }, url, postParams); + } + Future informationITGRequest(String requestType, int taskId, int itemId, String employeeNumber, String newUserEMPId, String comments) async { String url = "${ApiConsts.cocRest}ITGRequestInformation"; Map postParams = { diff --git a/lib/ui/attendance/monthly_attendance_screen.dart b/lib/ui/attendance/monthly_attendance_screen.dart index de35da0..8b62b7f 100644 --- a/lib/ui/attendance/monthly_attendance_screen.dart +++ b/lib/ui/attendance/monthly_attendance_screen.dart @@ -431,7 +431,7 @@ class _MonthlyAttendanceScreenState extends State { expand: false, builder: (_, controller) { dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE; - DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss a").parse(dmyString); + DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss").parse(dmyString); return Column( children: [ Container( diff --git a/lib/ui/landing/today_attendance_screen2.dart b/lib/ui/landing/today_attendance_screen2.dart index 17bb03a..ada652c 100644 --- a/lib/ui/landing/today_attendance_screen2.dart +++ b/lib/ui/landing/today_attendance_screen2.dart @@ -86,7 +86,7 @@ class _TodayAttendanceScreenState extends State { child: CircularStepProgressBar( totalSteps: 16 * 4, currentStep: (model.progress * 100).toInt(), - selectedColor: MyColors.gradiantEndColor, + selectedColor: MyColors.gradiantStartColor, unselectedColor: MyColors.grey70Color, child: Center( child: Padding( diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index ae24dde..2333c18 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -74,7 +74,7 @@ class ServicesWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ Expanded( - child: data.homeMenus![parentIndex].menuEntiesList[index].prompt!.toText10(isBold: true), + child: data.homeMenus![parentIndex].menuEntiesList[index].prompt!.toText11(isBold: true), ), RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4)), ], diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index 5da5ed2..55ff715 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -142,7 +142,7 @@ class MarathonBanner extends StatelessWidget { bottom: 0, child: RotatedBox( quarterTurns: 4, - child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.darkDigitColor), + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), ).paddingAll(15), ) : Positioned( @@ -150,7 +150,7 @@ class MarathonBanner extends StatelessWidget { left: 0, child: RotatedBox( quarterTurns: 2, - child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.darkDigitColor), + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), ).paddingAll(15), ), ], diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 045b808..e602c21 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -68,7 +68,7 @@ class _DynamicInputScreenState extends State { } void validateTransaction() async { - // try { + try { Utils.showLoading(context); List> values = getEitDffStructureList!.map((e) { String tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? ""; @@ -114,10 +114,10 @@ class _DynamicInputScreenState extends State { Utils.showLoading(context); await LeaveBalanceApiClient().cancelHrTransaction(submitEITTransactionList.pTRANSACTIONID!); Utils.hideLoading(context); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } String dESCFLEXCONTEXTCODE = ""; diff --git a/lib/ui/my_team/view_attendance.dart b/lib/ui/my_team/view_attendance.dart index 90414d1..0896d5e 100644 --- a/lib/ui/my_team/view_attendance.dart +++ b/lib/ui/my_team/view_attendance.dart @@ -439,7 +439,7 @@ class _ViewAttendanceState extends State { expand: false, builder: (_, controller) { dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE; - DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss a").parse(dmyString); + DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss").parse(dmyString); return Column( children: [ Container( diff --git a/lib/ui/profile/add_update_family_member.dart b/lib/ui/profile/add_update_family_member.dart index 528e38d..36a8394 100644 --- a/lib/ui/profile/add_update_family_member.dart +++ b/lib/ui/profile/add_update_family_member.dart @@ -383,7 +383,7 @@ class _AddUpdateFamilyMemberState extends State { ), ); } else { - DateTime? picked = await showDatePicker(context: context, initialDate: selectedDate, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101)); + DateTime? picked = await showDatePicker(context: context, initialDate: selectedDate, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(1920, 1), lastDate: DateTime.now()); if (picked != null && picked != selectedDate) { time = picked; } diff --git a/lib/ui/profile/family_members.dart b/lib/ui/profile/family_members.dart index fd7bd13..25f62c0 100644 --- a/lib/ui/profile/family_members.dart +++ b/lib/ui/profile/family_members.dart @@ -128,7 +128,8 @@ class _FamilyMembersState extends State { ), DefaultButton(LocaleKeys.addNewFamilyMember.tr(), menuEntries.updateButton == 'Y' - ? () async { + ? + () async { Navigator.pushNamed(context, AppRoutes.addUpdateFamilyMember, arguments: {"relationID": relationId, "flag": 1, "actionType": "ADD"}); // ProfileScreen(); } : null).insideContainer, diff --git a/lib/ui/screens/my_requests/my_requests.dart b/lib/ui/screens/my_requests/my_requests.dart index f9d8d39..dd6147f 100644 --- a/lib/ui/screens/my_requests/my_requests.dart +++ b/lib/ui/screens/my_requests/my_requests.dart @@ -76,9 +76,7 @@ class _MyRequestsState extends State { }), ), 12.height, - Expanded( - // todo list don't have data, need to confirm later , because have issues, need fixes - + getCCPTransactionsList.isNotEmpty ? Expanded( child: ListView.separated( physics: const BouncingScrollPhysics(), shrinkWrap: true, @@ -141,7 +139,7 @@ class _MyRequestsState extends State { }, separatorBuilder: (BuildContext context, int index) => 12.height, itemCount: getCCPTransactionsList.length), - ), + ) : Container(), ], ).expanded, 1.divider, diff --git a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart index 9a308ba..325f4f3 100644 --- a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart +++ b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart @@ -176,8 +176,8 @@ class _OffersAndDiscountsDetailsState extends State { // // launchUrl(Uri.parse(url!)); // // } // ), - getOffersList.description!.toText12(maxLine: 2, color: const Color(0xff535353)), - 16.height, + // getOffersList.description!.toText12(maxLine: 2, color: const Color(0xff535353)), + // 16.height, getOffersList.discount!.toText14(isBold: true, maxlines: 1), 8.height, Row( diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index bbb0267..cf33648 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -367,6 +367,12 @@ class _ItgDetailScreenState extends State { case "Answer": performAction("Answer"); break; + case "ReportGenerated": + performDataCorrectionORReportGeneratedAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? ""); + break; + case "DataCorrected": + performDataCorrectionORReportGeneratedAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? ""); + break; } setState(() { showFabOptions = false; @@ -525,6 +531,29 @@ class _ItgDetailScreenState extends State { } } + void performDataCorrectionORReportGeneratedAction(String requestType, int taskId, int itemId, String employeeNumber) async { + try { + Utils.showLoading(context); + ITGRequest? itgRequest = await WorkListApiClient().grantITGRequest(requestType, taskId, itemId, employeeNumber, "", ""); + Utils.hideLoading(context); + Utils.showToast(LocaleKeys.yourChangeHasBeenSavedSuccessfully.tr()); + AppState().requestAllList!.removeAt(AppState().itgWorkListIndex!); + if (AppState().requestAllList!.isEmpty) { + Navigator.pop(context, "delegate_reload"); + } else { + if (AppState().requestAllList!.length <= AppState().itgWorkListIndex!) { + Navigator.pop(context, "delegate_reload"); + } else { + requestDetails = null; + getDataFromState(); + } + } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + void reloadITG() { AppState().requestAllList!.removeAt(AppState().itgWorkListIndex!); if (AppState().requestAllList!.isEmpty) { diff --git a/lib/ui/work_list/work_list_screen.dart b/lib/ui/work_list/work_list_screen.dart index 8efd789..f9f8d91 100644 --- a/lib/ui/work_list/work_list_screen.dart +++ b/lib/ui/work_list/work_list_screen.dart @@ -226,7 +226,6 @@ class _WorkListScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container(width: double.infinity, height: 1, color: MyColors.lightGreyEFColor), SizedBox( height: 40, child: ListView.separated( diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 3c05204..824edc3 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -476,6 +476,17 @@ class _WorkListDetailScreenState extends State { isUpdate: true, collectionNotificationList: getEitCollectionNotificationBodyList![0].collectionNotification)), ); break; + case "CONTINUE_ACTION": + showMyBottomSheet( + context, + callBackFunc: reloadWorkList, + child: UpdateContinueSheet( + workListData: workListData, + getEitCollectionNotificationBodyList: getEitCollectionNotificationBodyList, + dynamicParams: DynamicListViewParams(workListData!.sUBJECT!, workListData!.fUNCTIONNAME!, + isUpdate: true, collectionNotificationList: getEitCollectionNotificationBodyList![0].collectionNotification)), + ); + break; case "APPROVE_AND_FORWARD": showMyBottomSheet(context, callBackFunc: reloadWorkList, diff --git a/lib/ui/work_list/worklist_fragments/actions_fragment.dart b/lib/ui/work_list/worklist_fragments/actions_fragment.dart index 439888b..58e9ac7 100644 --- a/lib/ui/work_list/worklist_fragments/actions_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/actions_fragment.dart @@ -140,8 +140,6 @@ class ActionsFragment extends StatelessWidget { DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(actionHistoryList[index].nOTIFICATIONDATE!); DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(actionHistoryList[++index].nOTIFICATIONDATE!); Duration duration = dateTimeTo.difference(dateTimeFrom); - print(dateTimeTo); - print(dateTimeFrom); return "Action duration: " + DateUtil.formatDuration(duration); } } diff --git a/lib/widgets/app_bar_widget.dart b/lib/widgets/app_bar_widget.dart index 745dedf..35c93ba 100644 --- a/lib/widgets/app_bar_widget.dart +++ b/lib/widgets/app_bar_widget.dart @@ -6,65 +6,73 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; -AppBar AppBarWidget(BuildContext context, +PreferredSize AppBarWidget(BuildContext context, {required String title, bool showHomeButton = true, bool showNotificationButton = false, bool showMemberButton = false, String? image}) { - return AppBar( - leadingWidth: 0, - // leading: GestureDetector( - // behavior: HitTestBehavior.opaque, - // onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context), - // child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), - // ), - //titleSpacing: -1.44, - title: Row( + return PreferredSize( + preferredSize: const Size.fromHeight(57.0), + child: Column( children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: - Feedback.wrapForTap(() => Navigator.maybePop(context), context), - child: - const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), + AppBar( + leadingWidth: 0, + // leading: GestureDetector( + // behavior: HitTestBehavior.opaque, + // onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context), + // child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), + // ), + //titleSpacing: -1.44, + title: Row( + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: + Feedback.wrapForTap(() => Navigator.maybePop(context), context), + child: + const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), + ), + 4.width, + if (image != null) SvgPicture.asset( + image, + height: 40, + width: 40, + ), + if (image != null) 14.width, + title.toText24(color: MyColors.darkTextColor, isBold: true).expanded, + ], + ), + centerTitle: false, + elevation: 0, + backgroundColor: Colors.white, + actions: [ + if (showHomeButton) + IconButton( + onPressed: () { + Navigator.popUntil( + context, ModalRoute.withName(AppRoutes.dashboard)); + }, + icon: const Icon(Icons.home, color: MyColors.darkIconColor), + ), + if (showNotificationButton) + IconButton( + onPressed: () { + Navigator.pushNamed(context, AppRoutes.worklistSettings); + }, + icon: const Icon(Icons.notifications, color: MyColors.textMixColor), + ), + if (showMemberButton) + IconButton( + onPressed: () { + Navigator.pushNamed(context, AppRoutes.subordinateLeave); + }, + icon: const Icon(Icons.people, color: MyColors.textMixColor), + ), + ], ), - 4.width, - if (image != null) SvgPicture.asset( - image, - height: 40, - width: 40, - ), - if (image != null) 14.width, - title.toText24(color: MyColors.darkTextColor, isBold: true).expanded, + Container(width: double.infinity, height: 1, color: MyColors.lightGreyEFColor), ], ), - centerTitle: false, - elevation: 0, - backgroundColor: Colors.white, - actions: [ - if (showHomeButton) - IconButton( - onPressed: () { - Navigator.popUntil( - context, ModalRoute.withName(AppRoutes.dashboard)); - }, - icon: const Icon(Icons.home, color: MyColors.darkIconColor), - ), - if (showNotificationButton) - IconButton( - onPressed: () { - Navigator.pushNamed(context, AppRoutes.worklistSettings); - }, - icon: const Icon(Icons.notifications, color: MyColors.textMixColor), - ), - if (showMemberButton) - IconButton( - onPressed: () { - Navigator.pushNamed(context, AppRoutes.subordinateLeave); - }, - icon: const Icon(Icons.people, color: MyColors.textMixColor), - ), - ], ); } From 7c00f7dce8efef654c18167bcd389723c062e2f8 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 15 Nov 2022 15:26:34 +0300 Subject: [PATCH 46/82] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 19 ++++----- lib/ui/chat/chat_home_screen.dart | 57 +++++++++++++++------------ 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index be5b68c..c9767b4 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -44,6 +44,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future getUserAutoLoginToken() async { String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString(); + //userName Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}user/desktopuserlogin", {"userName": userName, "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", "loginType": 2}); login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(response.body); @@ -84,8 +85,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } } - pChatHistory = recentChat.response; - pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); + pChatHistory = recentChat.response == null ? [] : recentChat.response; + if (pChatHistory != null) pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); + searchedChats = pChatHistory; isLoading = false; notifyListeners(); @@ -164,7 +166,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await hubConnection.start(); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - // hubConnection.on("OnSeenChatUserAsync", onChatSeen); + // hubConnection.on("OnSeenChatUserAsync", onChatSeen); //hubConnection.on("OnUserTypingAsync", onUserTyping); // hubConnection.on("OnUserCountAsync", userCountAsync); @@ -288,7 +290,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // } // }); notifyListeners(); - // if (isChatScreenActive) scrollToBottom(); + // if (isChatScreenActive) scrollToBottom(); } void onUserTyping(List? parameters) { @@ -402,17 +404,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ) : null, ); - String chatData = - '{"contant":"${message.text}","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}'; - await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); - userChatHistory.insert(0, data); - isFileSelected = false; isMsgReply = false; sFileType = ""; message.clear(); notifyListeners(); + + String chatData = + '{"contant":"${message.text}","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}'; + await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); } void sendChatMessage(int targetUserId, String targetUserName) async { diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 3ac291c..d146891 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -7,7 +9,6 @@ import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; -import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; @@ -113,35 +114,41 @@ class _ChatHomeScreenState extends State { mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.max, children: [ - if (m.searchedChats![index].unreadMessageCount! > 0) - Flexible( - child: Container( - padding: EdgeInsets.zero, - alignment: Alignment.centerRight, - width: 18, - height: 18, - decoration: const BoxDecoration( - color: MyColors.redColor, - borderRadius: BorderRadius.all( - Radius.circular(20), - ), - ), - child: (m.searchedChats![index].unreadMessageCount!.toString()) - .toText10( - color: MyColors.white, - ) - .center, - ), - ), + // if (m.searchedChats![index].unreadMessageCount != null) + // Flexible( + // child: Container( + // padding: EdgeInsets.zero, + // alignment: Alignment.centerRight, + // width: 18, + // height: 18, + // decoration: const BoxDecoration( + // color: MyColors.redColor, + // borderRadius: BorderRadius.all( + // Radius.circular(20), + // ), + // ), + // child: (m.searchedChats![index].unreadMessageCount!.toString()) + // .toText10( + // color: MyColors.white, + // ) + // .center, + // ), + // ), Flexible( child: IconButton( alignment: Alignment.centerRight, padding: EdgeInsets.zero, - icon: Icon(m.searchedChats![index].isFav! ? Icons.star_sharp : Icons.star_border), - color: m.searchedChats![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, + icon: Icon(m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == false ? Icons.star_sharp : Icons.star_sharp), + color: m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == true ? MyColors.yellowColor : MyColors.grey35Color, onPressed: () { - if (m.searchedChats![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); - if (!m.searchedChats![index].isFav!) m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + + if (m.searchedChats![index].isFav == null || m.searchedChats![index].isFav == false) { + m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + }else if( m.searchedChats![index].isFav == true){ + m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + } else{ + m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + } }, ), ) From f19d734dbb3cdbd8606d9fb1235566bdb69bc771 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 15 Nov 2022 15:32:17 +0300 Subject: [PATCH 47/82] Chat Fixes --- assets/langs/ar-SA.json | 3 +-- assets/langs/en-US.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 000e111..1c5851a 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -499,7 +499,6 @@ "resend": "إعادة إرسال", "codeExpire": "انتهت صلاحية رمز التحقق", "typeheretoreply": "اكتب هنا للرد", - "favorite" : "أُفضله", + "favorite": "مفضلتي", "searchfromchat": "البحث من الدردشة" - } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index c8b8322..b4b06f0 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -499,7 +499,7 @@ "codeExpire": "The verification code has been expired", "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply", - "favorite" : "My Favorite", + "favorite" : "My Favorites", "searchfromchat": "Search from chat" } \ No newline at end of file From 1fb585a438fe398978af9d1307bd82630232edaa Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 15 Nov 2022 15:36:28 +0300 Subject: [PATCH 48/82] Chat Fixes --- lib/generated/codegen_loader.g.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 3d35ccc..a54ff37 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -515,7 +515,7 @@ class CodegenLoader extends AssetLoader{ "resend": "إعادة إرسال", "codeExpire": "انتهت صلاحية رمز التحقق", "typeheretoreply": "اكتب هنا للرد", - "favorite": "أُفضله", + "favorite": "مفضلتي", "searchfromchat": "البحث من الدردشة" }; static const Map en_US = { @@ -1019,7 +1019,7 @@ static const Map en_US = { "codeExpire": "The verification code has been expired", "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply", - "favorite": "My Favorite", + "favorite": "My Favorites", "searchfromchat": "Search from chat" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; From 55187f4e36688bcfb2006e5d38409a82a474f9b1 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 15 Nov 2022 15:52:59 +0300 Subject: [PATCH 49/82] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 4 +++- lib/classes/consts.dart | 4 ++-- lib/ui/chat/chat_detailed_screen.dart | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index c9767b4..b09ad50 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -416,7 +416,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); } - void sendChatMessage(int targetUserId, String targetUserName) async { + void sendChatMessage(int targetUserId, String targetUserName, BuildContext context) async { dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); if (contain.isEmpty) { searchedChats!.add( @@ -435,9 +435,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { sendChatToServer(chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: false, chatReplyId: null, isReply: false); } if (isFileSelected && !isMsgReply) { + Utils.showLoading(context); logger.d("Normal Attachment Message"); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); + Utils.hideLoading(context); sendChatToServer(chatEventId: 2, fileTypeId: getFileType(ext.toString()), targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: true, chatReplyId: null, isReply: false); } if (!isFileSelected && isMsgReply) { diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 93b4ea8..c5788f9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 04e84e0..782e4e2 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -252,7 +252,7 @@ class ChatDetailScreen extends StatelessWidget { width: 26, ), onPressed: () { - m.sendChatMessage(userDetails["targetUser"].id, userDetails["targetUser"].userName); + m.sendChatMessage(userDetails["targetUser"].id, userDetails["targetUser"].userName, context); }, ) ], From ab6f265ef45e94fa60ad15cd8de85f9ecd611fd8 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 15 Nov 2022 16:09:34 +0300 Subject: [PATCH 50/82] Chat Favorite Screen & Fixes --- lib/api/chat/chat_provider_model.dart | 8 +++++--- lib/classes/consts.dart | 4 ++-- lib/ui/chat/chat_home.dart | 2 -- lib/ui/chat/chat_home_screen.dart | 5 ++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index b09ad50..ead29d7 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -380,10 +380,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future sendChatToServer( {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { Uuid uuid = const Uuid(); + String msg = message.text; SingleUserChatModel data = SingleUserChatModel( chatEventId: chatEventId, chatSource: 1, - contant: message.text, + contant: msg, contantNo: uuid.v4(), conversationId: uuid.v4(), createdDate: DateTime.now(), @@ -412,7 +413,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); String chatData = - '{"contant":"${message.text}","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}'; + '{"contant":"$msg","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}'; await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); } @@ -452,9 +453,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } if (isFileSelected && isMsgReply) { logger.d("Attachment Message With Reply"); - logger.d(repliedMsg.first.userChatHistoryId); + Utils.showLoading(context); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); + Utils.hideLoading(context); sendChatToServer( chatEventId: 2, fileTypeId: getFileType(ext.toString()), diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index c5788f9..ede22e3 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 1fdcb33..738fc17 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -26,7 +26,6 @@ class _ChatHomeState extends State { PageController controller = PageController(); late ChatProviderModel data; - @override void initState() { // TODO: implement initState @@ -46,7 +45,6 @@ class _ChatHomeState extends State { @override Widget build(BuildContext context) { - return Scaffold( backgroundColor: MyColors.white, appBar: AppBarWidget( diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index d146891..38bf42c 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -141,12 +141,11 @@ class _ChatHomeScreenState extends State { icon: Icon(m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == false ? Icons.star_sharp : Icons.star_sharp), color: m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == true ? MyColors.yellowColor : MyColors.grey35Color, onPressed: () { - if (m.searchedChats![index].isFav == null || m.searchedChats![index].isFav == false) { m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); - }else if( m.searchedChats![index].isFav == true){ + } else if (m.searchedChats![index].isFav == true) { m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); - } else{ + } else { m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); } }, From bb583def642aa6aeddff9a9af9b3e2834d245569 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 15 Nov 2022 16:16:40 +0300 Subject: [PATCH 51/82] Chat Favorite Screen & Fixes --- lib/ui/chat/chat_home_screen.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 38bf42c..a22c7e0 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; From 68939f6256c1305c19c523da47314172e0acf5d0 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Wed, 16 Nov 2022 12:07:13 +0300 Subject: [PATCH 52/82] Chat Call UI --- lib/models/chat/call.dart | 117 ++++++++ lib/ui/chat/call/chat_call_screen.dart | 379 +++++++++++++++++++++++++ lib/ui/chat/chat_detailed_screen.dart | 116 +++++++- lib/widgets/app_bar_widget.dart | 29 +- pubspec.yaml | 2 + 5 files changed, 614 insertions(+), 29 deletions(-) create mode 100644 lib/models/chat/call.dart create mode 100644 lib/ui/chat/call/chat_call_screen.dart diff --git a/lib/models/chat/call.dart b/lib/models/chat/call.dart new file mode 100644 index 0000000..eacdd03 --- /dev/null +++ b/lib/models/chat/call.dart @@ -0,0 +1,117 @@ +class IncomingCallData { + String? callerID; + String? receiverID; + String? msgID; + String? notfID; + String? notificationForeground; + String? count; + String? message; + String? appointmentNo; + String? title; + String? projectID; + String? notificationType; + String? background; + String? doctorname; + String? clinicname; + String? speciality; + String? appointmentdate; + String? appointmenttime; + String? type; + String? sessionId; + String? identity; + String? name; + String? videoUrl; + String? picture; + String? token; + String? isCall; + String? sound; + String? server; + String? isWebRTC; + + IncomingCallData( + {this.msgID, + this.notfID, + this.notificationForeground, + this.count, + this.message, + this.appointmentNo, + this.title, + this.projectID, + this.notificationType, + this.background, + this.doctorname, + this.clinicname, + this.speciality, + this.appointmentdate, + this.appointmenttime, + this.type, + this.sessionId, + this.identity, + this.name, + this.videoUrl, + this.picture, + this.isCall, + this.sound}); + + IncomingCallData.fromJson(Map json) { + callerID = json['callerID']; + receiverID = json['PatientID']; + msgID = json['msgID']; + notfID = json['notfID']; + notificationForeground = json['notification_foreground']; + count = json['count']; + message = json['message']; + appointmentNo = json['AppointmentNo']; + title = json['title']; + projectID = json['ProjectID']; + notificationType = json['NotificationType']; + background = json['background']; + doctorname = json['doctorname']; + clinicname = json['clinicname']; + speciality = json['speciality']; + appointmentdate = json['appointmentdate']; + appointmenttime = json['appointmenttime']; + type = json['type']; + sessionId = json['session_id']; + token = json['token']; + identity = json['identity']; + name = json['name']; + videoUrl = json['videoUrl']; + picture = json['picture']; + isCall = json['is_call']; + sound = json['sound']; + server = json['server']; + isWebRTC = json['is_webrtc'] ?? "true"; + } + + Map toJson() { + Map data = Map(); + data['msgID'] = this.msgID; + data['notfID'] = this.notfID; + data['notification_foreground'] = this.notificationForeground; + data['count'] = this.count; + data['message'] = this.message; + data['AppointmentNo'] = this.appointmentNo; + data['title'] = this.title; + data['ProjectID'] = this.projectID; + data['NotificationType'] = this.notificationType; + data['background'] = this.background; + data['doctorname'] = this.doctorname; + data['clinicname'] = this.clinicname; + data['speciality'] = this.speciality; + data['appointmentdate'] = this.appointmentdate; + data['appointmenttime'] = this.appointmenttime; + data['type'] = this.type; + data['session_id'] = this.sessionId; + data['token'] = this.token; + data['identity'] = this.identity; + data['name'] = this.name; + data['videoUrl'] = this.videoUrl; + data['picture'] = this.picture; + data['is_call'] = this.isCall; + data['sound'] = this.sound; + data['server'] = this.server; + data['is_webrtc'] = this.isWebRTC; + return data; + } +} diff --git a/lib/ui/chat/call/chat_call_screen.dart b/lib/ui/chat/call/chat_call_screen.dart new file mode 100644 index 0000000..0bec1f0 --- /dev/null +++ b/lib/ui/chat/call/chat_call_screen.dart @@ -0,0 +1,379 @@ +import 'dart:ui'; + +import 'package:camera/camera.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:just_audio/just_audio.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/models/chat/call.dart'; + +class IncomingCall extends StatefulWidget { + IncomingCallData incomingCallData; + bool? isVideoCall; + + IncomingCall({Key? key, required this.incomingCallData, this.isVideoCall}) : super(key: key); + + @override + _IncomingCallState createState() => _IncomingCallState(); +} + +class _IncomingCallState extends State with SingleTickerProviderStateMixin { + AnimationController? _animationController; + CameraController? _controller; + Future? _initializeControllerFuture; + bool isCameraReady = false; + + @override + void initState() { + _animationController = AnimationController( + vsync: this, + duration: const Duration( + milliseconds: 500, + ), + ); + //_runAnimation(); + // connectSignaling(); + WidgetsBinding.instance.addPostFrameCallback( + (_) => _runAnimation(), + ); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: FutureBuilder( + future: _initializeControllerFuture, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Stack( + alignment: FractionalOffset.center, + children: [ + if (widget.isVideoCall!) + Positioned.fill( + child: AspectRatio( + aspectRatio: _controller!.value.aspectRatio, + child: CameraPreview( + _controller!, + ), + ), + ), + Positioned.fill( + child: ClipRect( + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), + child: Container( + decoration: BoxDecoration( + color: MyColors.grey57Color.withOpacity( + 0.7, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Container( + margin: const EdgeInsets.all(21.0), + child: Row( + children: [ + Image.asset( + "assets/images/logos/main_mohemm_logo.png", + height: 70, + width: 70, + ), + Container( + margin: const EdgeInsets.only( + left: 10.0, + right: 10.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: const [ + Text( + "Aamir Saleem Ahmad", + style: TextStyle( + fontSize: 21, + fontWeight: FontWeight.bold, + color: MyColors.white, + letterSpacing: -1.26, + height: 23 / 12, + ), + ), + Text( + "Calling...", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Color( + 0xffC6C6C6, + ), + letterSpacing: -0.48, + height: 23 / 24, + ), + ), + SizedBox( + height: 2, + ), + ], + ), + ), + ], + ), + ), + // Container( + // margin: const EdgeInsets.all(21.0), + // width: MediaQuery.of(context).size.width, + // decoration: cardRadius(15.0, color: MyColors.black, elevation: null), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisSize: MainAxisSize.min, + // children: [ + // Container( + // padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 6.0), + // child: Text( + // "TranslationBase.of(context).appoInfo", + // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.white, letterSpacing: -0.64, height: 23 / 12), + // ), + // ), + // Container( + // padding: const EdgeInsets.only(left: 16.0, right: 16.0), + // child: Text( + // "widget.incomingCallData.appointmentdate + widget.incomingCallData.appointmenttime", + // style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600), + // ), + // ), + // Container( + // padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 21.0), + // child: Text( + // "widget.incomingCallData.clinicname", + // style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600), + // ), + // ), + // ], + // ), + // ), + const Spacer(), + Container( + margin: const EdgeInsets.only( + bottom: 70.0, + left: 49, + right: 49, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + RotationTransition( + turns: Tween( + begin: 0.0, + end: -.1, + ) + .chain( + CurveTween( + curve: Curves.elasticIn, + ), + ) + .animate( + _animationController!, + ), + child: RawMaterialButton( + onPressed: () { + _submit(); + }, + elevation: 2.0, + fillColor: MyColors.green2DColor, + padding: const EdgeInsets.all( + 15.0, + ), + shape: const CircleBorder(), + child: const Icon( + Icons.call, + color: MyColors.white, + size: 35.0, + ), + ), + ), + RawMaterialButton( + onPressed: () { + backToHome(); + }, + elevation: 2.0, + fillColor: MyColors.redA3Color, + padding: const EdgeInsets.all( + 15.0, + ), + shape: const CircleBorder(), + child: const Icon( + Icons.call_end, + color: MyColors.white, + size: 35.0, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ], + ); + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, + ), + ); + } + + void _runAnimation() async { + List cameras = await availableCameras(); + CameraDescription firstCamera = cameras[1]; + _controller = CameraController( + firstCamera, + ResolutionPreset.medium, + ); + _initializeControllerFuture = _controller!.initialize(); + setState(() {}); + // setAudioFile(); + for (int i = 0; i < 100; i++) { + await _animationController!.forward(); + await _animationController!.reverse(); + } + } + + Future _submit() async { + try { + // backToHome(); + // final roomModel = RoomModel(name: widget.incomingCallData.name, token: widget.incomingCallData.sessionId, identity: widget.incomingCallData.identity); + await _controller?.dispose(); + // changeCallStatusAPI(4); + + // if (_session != null && _signaling != null) { + // await Navigator.of(context).pushReplacement( + // MaterialPageRoute( + // // fullscreenDialog: true, + // builder: (BuildContext context) { + // // if (widget.incomingCallData.isWebRTC == "true") { + // return StartVideoCall(signaling: _signaling, session: _session); + // + // // else { + // // return OpenTokConnectCallPage(apiKey: OPENTOK_API_KEY, sessionId: widget.incomingCallData.sessionId, token: widget.incomingCallData.token); + // // } + // + // // return VideoCallWebPage(receiverId: widget.incomingCallData.receiverID, callerId: widget.incomingCallData.callerID); // Web WebRTC VideoCall + // + // // return CallHomePage(receiverId: widget.incomingCallData.receiverID, callerId: widget.incomingCallData.callerID); // App WebRTC VideoCall + // }, + // ), + // ); + // } else { + // // Invalid Params/Data + // Utils.showToast("Failed to establish connection with server"); + // } + } catch (err) { + print(err); + // await PlatformExceptionAlertDialog( + // exception: err, + // ).show(context); + + Utils.showToast(err.toString()); + } + } + + // void changeCallStatusAPI(int sessionStatus) { + // LiveCareService service = new LiveCareService(); + // service.endCallAPI(widget.incomingCallData.sessionId, sessionStatus, context).then((res) {}).catchError((err) { + // print(err); + // }); + // } + + void backToHome() async { + // final connected = await signaling.declineCall(widget.incomingCallData.callerID, widget.incomingCallData.receiverID); + // LandingPage.isOpenCallPage = false; + // _signaling + // player.stop(); + // changeCallStatusAPI(3); + // _signaling.bye(_session, callRejected: true); + // _signaling.callDisconnected(_session, callRejected: true); + Navigator.of(context).pop(); + } + + // + // void disposeAudioResources() async { + // await player.dispose(); + // } + // + // void setAudioFile() async { + // player.stop(); + // await player.setVolume(1.0); // full volume + // try { + // await player.setAsset('assets/sounds/ring_60Sec.mp3').then((value) { + // player.setLoopMode(LoopMode.one); // loop ring sound + // player.play(); + // }).catchError((err) { + // print("Error: $err"); + // }); + // } catch (e) { + // print("Error: $e"); + // } + // } + // + // void connectSignaling({@required bool iAmCaller = false}) async { + // print("----------------- + Signaling Connection Started ---------------------------"); + // var caller = widget.incomingCallData.callerID; + // var receiver = widget.incomingCallData.receiverID; + // var host = widget.incomingCallData.server; + // + // var selfRole = iAmCaller ? "Caller" : "Receiver"; + // var selfId = iAmCaller ? caller : receiver; + // var selfUser = SocketUser(id: selfId, name: "$selfRole-$selfId", userAgent: DeviceInfo.userAgent, moreInfo: {}); + // + // var remoteRole = !iAmCaller ? "Caller" : "Receiver"; + // var remoteId = !iAmCaller ? caller : receiver; + // var remoteUser = SocketUser(id: remoteId, name: "$remoteRole-$remoteId", userAgent: DeviceInfo.userAgent, moreInfo: {}); + // + // var sessionId = "$caller-$receiver"; + // _session = SessionOneToOne(id: sessionId, local_user: selfUser, remote_user: remoteUser); + // + // _signaling = Signaling(host, session: _session); + // await _signaling.connect(); + // + // if (_signaling.state == SignalingState.Open) { + // return; + // } + // } + + BoxDecoration cardRadius(double radius, {required Color color, double? elevation}) { + return BoxDecoration( + shape: BoxShape.rectangle, + color: color ?? Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(radius), + ), + boxShadow: [ + BoxShadow( + color: const Color( + 0xff000000, + ).withOpacity( + .05, + ), + //spreadRadius: 5, + blurRadius: elevation ?? 27, + offset: const Offset( + -2, + 3, + ), + ), + ], + ); + } +} diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 782e4e2..6ddd19e 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -9,6 +9,8 @@ import 'package:mohem_flutter_app/classes/colors.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/chat/call.dart'; +import 'package:mohem_flutter_app/ui/chat/call/chat_call_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; @@ -16,15 +18,18 @@ import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:swipe_to/swipe_to.dart'; -class ChatDetailScreen extends StatelessWidget { +class ChatDetailScreen extends StatefulWidget { // ignore: prefer_const_constructors_in_immutables ChatDetailScreen({Key? key}) : super(key: key); - dynamic userDetails; + @override + State createState() => _ChatDetailScreenState(); +} +class _ChatDetailScreenState extends State { + dynamic userDetails; late ChatProviderModel data; - - final RefreshController _refreshController = RefreshController(initialRefresh: false); + final RefreshController _rc = RefreshController(initialRefresh: false); void getMoreChat() async { if (userDetails != null) { @@ -32,19 +37,54 @@ class ChatDetailScreen extends StatelessWidget { data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false); } await Future.delayed(const Duration(milliseconds: 1000)); - _refreshController.loadComplete(); + _rc.loadComplete(); } @override - Widget build(BuildContext context) { - userDetails = ModalRoute.of(context)!.settings.arguments; + void initState() { + super.initState(); data = Provider.of(context, listen: false); if (userDetails != null) - data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: false, isNewChat: userDetails["isNewChat"]); - data.scrollController.addListener(data.scrollListener); + data.getSingleUserChatHistory( + senderUID: AppState().chatDetails!.response!.id.toString(), + receiverUID: userDetails["targetUser"].id, + loadMore: false, + isNewChat: userDetails["isNewChat"], + ); + //data.scrollController.addListener(data.scrollListener); + } + + @override + Widget build(BuildContext context) { + userDetails = ModalRoute.of(context)!.settings.arguments; return Scaffold( backgroundColor: const Color(0xFFF8F8F8), - appBar: AppBarWidget(context, title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, image: userDetails["targetUser"].image), + appBar: AppBarWidget(context, + title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, + showHomeButton: false, + image: userDetails["targetUser"].image, + actions: [ + IconButton( + onPressed: () { + makeCall("AUDIO"); + }, + icon: SvgPicture.asset( + "assets/images/call.svg", + width: 25, + height: 25, + ), + ), + IconButton( + onPressed: () { + makeCall("VIDEO"); + }, + icon: SvgPicture.asset( + "assets/images/call.svg", + width: 25, + height: 25, + ), + ), + ]), body: Consumer( builder: (BuildContext context, ChatProviderModel m, Widget? child) { return (m.isLoading @@ -62,7 +102,7 @@ class ChatDetailScreen extends StatelessWidget { header: const MaterialClassicHeader( color: MyColors.gradiantEndColor, ), - controller: _refreshController, + controller: _rc, reverse: true, child: ListView.builder( controller: m.scrollController, @@ -136,11 +176,11 @@ class ChatDetailScreen extends StatelessWidget { margin: EdgeInsets.zero, elevation: 0, child: Padding( - padding: const EdgeInsets.only(left: 20.0, right: 20, top: 20, bottom: 0), + padding: const EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 0), child: Card( margin: EdgeInsets.zero, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(0.0), + borderRadius: BorderRadius.circular(0), ), elevation: 0, child: Container( @@ -267,4 +307,54 @@ class ChatDetailScreen extends StatelessWidget { ), ); } + + void makeCall(String callType) async { + // final server = await SelectionDialog( + // context, + // title: "Select Server", + // items: ["https://livecareturn.hmg.com:8086", "https://104.197.179.1:8086"] + // ).show(); + + Map json = { + "callerID": "9920", + "PatientID": "1231755", + "msgID": "123", + "notfID": "123", + "notification_foreground": "true", + "count": "1", + "message": "Doctor is calling ", + "AppointmentNo": "123", + "title": "Rayyan Hospital", + "ProjectID": "123", + "NotificationType": "10", + "background": "1", + "doctorname": "Dr Sulaiman Al Habib", + "clinicname": "ENT Clinic", + "speciality": "Speciality", + "appointmentdate": "Sun, 15th Dec, 2019", + "appointmenttime": "09:00", + "type": "video", + "session_id": + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0LTE1OTg3NzQ1MDYiLCJpc3MiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0Iiwic3ViIjoiQUNhYWQ1YTNmOGM2NGZhNjczNTY3NTYxNTc0N2YyNmMyYiIsImV4cCI6MTU5ODc3ODEwNiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiSGFyb29uMSIsInZpZGVvIjp7InJvb20iOiJTbWFsbERhaWx5U3RhbmR1cCJ9fX0.7XUS5uMQQJfkrBZu9EjQ6STL6R7iXkso6BtO1HmrQKk", + "identity": "Haroon1", + "name": "SmallDailyStandup", + "videoUrl": "video", + "picture": "video", + "is_call": "true", + "is_webrtc": "true", + // "server": "https://192.168.8.163:8086", + "server": "https://livecareturn.hmg.com:8086", + }; + + IncomingCallData incomingCallData = IncomingCallData.fromJson(json); + await Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => IncomingCall( + incomingCallData: incomingCallData, + isVideoCall: callType == "VIDEO" ? true : false, + ), + ), + ); + } } diff --git a/lib/widgets/app_bar_widget.dart b/lib/widgets/app_bar_widget.dart index 745dedf..d3e7c97 100644 --- a/lib/widgets/app_bar_widget.dart +++ b/lib/widgets/app_bar_widget.dart @@ -7,11 +7,7 @@ import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; AppBar AppBarWidget(BuildContext context, - {required String title, - bool showHomeButton = true, - bool showNotificationButton = false, - bool showMemberButton = false, - String? image}) { + {required String title, bool showHomeButton = true, bool showNotificationButton = false, bool showMemberButton = false, String? image, bool, List? actions}) { return AppBar( leadingWidth: 0, // leading: GestureDetector( @@ -24,17 +20,16 @@ AppBar AppBarWidget(BuildContext context, children: [ GestureDetector( behavior: HitTestBehavior.opaque, - onTap: - Feedback.wrapForTap(() => Navigator.maybePop(context), context), - child: - const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), + onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context), + child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), ), 4.width, - if (image != null) SvgPicture.asset( - image, - height: 40, - width: 40, - ), + if (image != null) + SvgPicture.asset( + image, + height: 40, + width: 40, + ), if (image != null) 14.width, title.toText24(color: MyColors.darkTextColor, isBold: true).expanded, ], @@ -46,8 +41,7 @@ AppBar AppBarWidget(BuildContext context, if (showHomeButton) IconButton( onPressed: () { - Navigator.popUntil( - context, ModalRoute.withName(AppRoutes.dashboard)); + Navigator.popUntil(context, ModalRoute.withName(AppRoutes.dashboard)); }, icon: const Icon(Icons.home, color: MyColors.darkIconColor), ), @@ -65,6 +59,9 @@ AppBar AppBarWidget(BuildContext context, }, icon: const Icon(Icons.people, color: MyColors.textMixColor), ), + + + ...actions??[] ], ); } diff --git a/pubspec.yaml b/pubspec.yaml index 8947c12..5a7c1c5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -91,6 +91,8 @@ dependencies: signalr_netcore: ^1.3.3 logging: ^1.0.1 swipe_to: ^1.0.2 + flutter_webrtc: ^0.9.16 + camera: ^0.10.0+4 From 00dee97bca969b495a5568fcbc96022f287f2904 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Wed, 16 Nov 2022 16:44:46 +0300 Subject: [PATCH 53/82] Chat Count Api / Chat Token Updates / Chat Call UI --- lib/api/chat/chat_provider_model.dart | 42 +++++++--- lib/api/dashboard_api_client.dart | 10 ++- lib/classes/consts.dart | 4 +- .../chat/chat_count_conversation_model.dart | 25 ++++++ .../chat/get_user_login_token_model.dart | 81 ++++++++++++------- lib/provider/dashboard_provider_model.dart | 22 ++++- lib/ui/chat/call/chat_call_screen.dart | 2 + lib/ui/chat/chat_detailed_screen.dart | 28 ++++--- lib/ui/chat/chat_home.dart | 9 ++- lib/ui/landing/dashboard_screen.dart | 33 ++++++-- .../search_employee_bottom_sheet.dart | 2 +- 11 files changed, 191 insertions(+), 67 deletions(-) create mode 100644 lib/models/chat/chat_count_conversation_model.dart diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index ead29d7..cedc158 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -7,6 +7,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:logger/logger.dart' as L; +import 'package:logging/logging.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -27,6 +28,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? pChatHistory, searchedChats; late HubConnection hubConnection; L.Logger logger = L.Logger(); + bool hubConInitialized = false; bool isLoading = true; bool isChatScreenActive = false; @@ -43,13 +45,27 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool _shouldAutoscroll = false; Future getUserAutoLoginToken() async { - String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString(); - //userName - Response response = - await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}user/desktopuserlogin", {"userName": userName, "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", "loginType": 2}); - login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(response.body); - AppState().setchatUserDetails = userLoginResponse; - await buildHubConnection(); + Response response = await ApiClient().postJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", + { + "employeeNumber": int.parse( + AppState().memberInformationList!.eMPLOYEENUMBER.toString(), + ), + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" + }, + ); + login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson( + response.body, + ); + + if (userLoginResponse.response != null) { + hubConInitialized = true; + AppState().setchatUserDetails = userLoginResponse; + await buildHubConnection(); + } else { + Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); + return; + } } Future?> getChatMemberFromSearch(String sName, int cUserId) async { @@ -95,6 +111,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async { isLoading = true; + if (isNewChat) userChatHistory = []; if (!loadMore) paginationVal = 0; isChatScreenActive = true; Response response = await ApiClient().getJsonForResponse( @@ -151,8 +168,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection = HubConnectionBuilder() .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) .withAutomaticReconnect( - retryDelays: [2000, 5000, 10000, 20000], - ).build(); + retryDelays: [2000, 5000, 10000, 20000], + ) + .configureLogging(Logger("Loggin")) + .build(); hubConnection.onclose( ({Exception? error}) {}, ); @@ -173,6 +192,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); + } } @@ -215,9 +235,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void updateChatHistoryWindow(List? args) { dynamic items = args!.toList(); - if (kDebugMode) { - print("---------------------------------Update Chat History Windows Async -------------------------------------"); - } + print("---------------------------------Update Chat History Windows Async -------------------------------------"); logger.d(items); // for (var user in searchedChats!) { // if (user.id == items.first["id"]) { diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index cce2207..9747e5c 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -1,10 +1,12 @@ import 'dart:async'; import 'dart:convert'; +import 'package:http/http.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/date_uitl.dart'; +import 'package:mohem_flutter_app/models/chat/chat_count_conversation_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart'; @@ -15,7 +17,6 @@ import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:uuid/uuid.dart'; - class DashboardApiClient { static final DashboardApiClient _instance = DashboardApiClient._internal(); @@ -178,4 +179,11 @@ class DashboardApiClient { return responseData; }, url, postParams); } + + Future getChatCount() async { + Response response = await ApiClient().getJsonForResponse( + "${ApiConsts.chatServerBaseApiUrl}user/unreadconversationcount/${AppState().getUserName}", + ); + return chatUnreadCovnCountModelFromJson(response.body); + } } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index ede22e3..c5788f9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/models/chat/chat_count_conversation_model.dart b/lib/models/chat/chat_count_conversation_model.dart new file mode 100644 index 0000000..e584d32 --- /dev/null +++ b/lib/models/chat/chat_count_conversation_model.dart @@ -0,0 +1,25 @@ +import 'dart:convert'; + +ChatUnreadCovnCountModel chatUnreadCovnCountModelFromJson(String str) => ChatUnreadCovnCountModel.fromJson(json.decode(str)); + +String chatUnreadCovnCountModelToJson(ChatUnreadCovnCountModel data) => json.encode(data.toJson()); + +class ChatUnreadCovnCountModel { + ChatUnreadCovnCountModel({ + this.singleChatCount, + this.groupChatCount, + }); + + int? singleChatCount; + int? groupChatCount; + + factory ChatUnreadCovnCountModel.fromJson(Map json) => ChatUnreadCovnCountModel( + singleChatCount: json["singleChatCount"] == null ? null : json["singleChatCount"], + groupChatCount: json["groupChatCount"] == null ? null : json["groupChatCount"], + ); + + Map toJson() => { + "singleChatCount": singleChatCount == null ? null : singleChatCount, + "groupChatCount": groupChatCount == null ? null : groupChatCount, + }; +} diff --git a/lib/models/chat/get_user_login_token_model.dart b/lib/models/chat/get_user_login_token_model.dart index 8afd3a9..8d55461 100644 --- a/lib/models/chat/get_user_login_token_model.dart +++ b/lib/models/chat/get_user_login_token_model.dart @@ -1,4 +1,3 @@ - import 'dart:convert'; UserAutoLoginModel userAutoLoginModelFromJson(String str) => UserAutoLoginModel.fromJson(json.decode(str)); @@ -7,22 +6,22 @@ String userAutoLoginModelToJson(UserAutoLoginModel data) => json.encode(data.toJ class UserAutoLoginModel { UserAutoLoginModel({ - this.response, + this.response, this.errorResponses, }); Response? response; - dynamic? errorResponses; + List? errorResponses; factory UserAutoLoginModel.fromJson(Map json) => UserAutoLoginModel( - response: json["response"] == null ? null : Response.fromJson(json["response"]), - errorResponses: json["errorResponses"], - ); + response: json["response"] == null ? null : Response.fromJson(json["response"]), + errorResponses: json["errorResponses"] == null ? null : List.from(json["errorResponses"].map((x) => ErrorResponse.fromJson(x))), + ); Map toJson() => { - "response": response == null ? null : response!.toJson(), - "errorResponses": errorResponses, - }; + "response": response == null ? null : response!.toJson(), + "errorResponses": errorResponses == null ? null : List.from(errorResponses!.map((x) => x.toJson())), + }; } class Response { @@ -51,28 +50,48 @@ class Response { String? encryptedUserName; factory Response.fromJson(Map json) => Response( - id: json["id"] == null ? null : json["id"], - userName: json["userName"] == null ? null : json["userName"], - email: json["email"] == null ? null : json["email"], - phone: json["phone"] == null ? null : json["phone"], - title: json["title"] == null ? null : json["title"], - token: json["token"] == null ? null : json["token"], - isDomainUser: json["isDomainUser"] == null ? null : json["isDomainUser"], - isActiveCode: json["isActiveCode"] == null ? null : json["isActiveCode"], - encryptedUserId: json["encryptedUserId"] == null ? null : json["encryptedUserId"], - encryptedUserName: json["encryptedUserName"] == null ? null : json["encryptedUserName"], - ); + id: json["id"] == null ? null : json["id"], + userName: json["userName"] == null ? null : json["userName"], + email: json["email"] == null ? null : json["email"], + phone: json["phone"] == null ? null : json["phone"], + title: json["title"] == null ? null : json["title"], + token: json["token"] == null ? null : json["token"], + isDomainUser: json["isDomainUser"] == null ? null : json["isDomainUser"], + isActiveCode: json["isActiveCode"] == null ? null : json["isActiveCode"], + encryptedUserId: json["encryptedUserId"] == null ? null : json["encryptedUserId"], + encryptedUserName: json["encryptedUserName"] == null ? null : json["encryptedUserName"], + ); + + Map toJson() => { + "id": id == null ? null : id, + "userName": userName == null ? null : userName, + "email": email == null ? null : email, + "phone": phone == null ? null : phone, + "title": title == null ? null : title, + "token": token == null ? null : token, + "isDomainUser": isDomainUser == null ? null : isDomainUser, + "isActiveCode": isActiveCode == null ? null : isActiveCode, + "encryptedUserId": encryptedUserId == null ? null : encryptedUserId, + "encryptedUserName": encryptedUserName == null ? null : encryptedUserName, + }; +} + +class ErrorResponse { + ErrorResponse({ + this.fieldName, + this.message, + }); + + String? fieldName; + String? message; + + factory ErrorResponse.fromJson(Map json) => ErrorResponse( + fieldName: json["fieldName"] == null ? null : json["fieldName"], + message: json["message"] == null ? null : json["message"], + ); Map toJson() => { - "id": id == null ? null : id, - "userName": userName == null ? null : userName, - "email": email == null ? null : email, - "phone": phone == null ? null : phone, - "title": title == null ? null : title, - "token": token == null ? null : token, - "isDomainUser": isDomainUser == null ? null : isDomainUser, - "isActiveCode": isActiveCode == null ? null : isActiveCode, - "encryptedUserId": encryptedUserId == null ? null : encryptedUserId, - "encryptedUserName": encryptedUserName == null ? null : encryptedUserName, - }; + "fieldName": fieldName == null ? null : fieldName, + "message": message == null ? null : message, + }; } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 5b9f8f1..b38536c 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -7,6 +7,7 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/main.dart'; +import 'package:mohem_flutter_app/models/chat/chat_count_conversation_model.dart'; import 'package:mohem_flutter_app/models/dashboard/drawer_menu_item_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; @@ -34,6 +35,10 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool isWorkListLoading = true; int workListCounter = 0; + //Chat + bool isChatCounterLoding = true; + int chatUConvCounter = 0; + //Misssing Swipe bool isMissingSwipeLoading = true; int missingSwipeCounter = 0; @@ -91,6 +96,9 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { accrualList = null; leaveBalanceAccrual = null; + isChatCounterLoding = true; + chatUConvCounter = 0; + ticketBalance = 0; isServicesMenusLoading = true; homeMenus = null; @@ -266,7 +274,19 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return res; } - + void fetchChatCounts() async { + print("----------------------- Fetch Count ____________________________________"); + try { + ChatUnreadCovnCountModel response = await DashboardApiClient().getChatCount(); + chatUConvCounter = response.singleChatCount!; + isChatCounterLoding = false; + notifyListeners(); + } catch (ex) { + logger.wtf(ex); + notifyListeners(); + Utils.handleException(ex, null, null); + } + } void notify() { notifyListeners(); diff --git a/lib/ui/chat/call/chat_call_screen.dart b/lib/ui/chat/call/chat_call_screen.dart index 0bec1f0..3fce65b 100644 --- a/lib/ui/chat/call/chat_call_screen.dart +++ b/lib/ui/chat/call/chat_call_screen.dart @@ -255,6 +255,7 @@ class _IncomingCallState extends State with SingleTickerProviderSt // backToHome(); // final roomModel = RoomModel(name: widget.incomingCallData.name, token: widget.incomingCallData.sessionId, identity: widget.incomingCallData.identity); await _controller?.dispose(); + // changeCallStatusAPI(4); // if (_session != null && _signaling != null) { @@ -300,6 +301,7 @@ class _IncomingCallState extends State with SingleTickerProviderSt // final connected = await signaling.declineCall(widget.incomingCallData.callerID, widget.incomingCallData.receiverID); // LandingPage.isOpenCallPage = false; // _signaling + _animationController!.dispose(); // player.stop(); // changeCallStatusAPI(3); // _signaling.bye(_session, callRejected: true); diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 6ddd19e..2ef61f0 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -34,15 +34,25 @@ class _ChatDetailScreenState extends State { void getMoreChat() async { if (userDetails != null) { data.paginationVal = data.paginationVal + 10; - data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false); + if (userDetails != null) + data.getSingleUserChatHistory( + senderUID: AppState().chatDetails!.response!.id.toString(), + receiverUID: userDetails["targetUser"].id, + loadMore: true, + isNewChat: false, + ); } - await Future.delayed(const Duration(milliseconds: 1000)); + await Future.delayed( + const Duration( + milliseconds: 1000, + ), + ); _rc.loadComplete(); } @override - void initState() { - super.initState(); + Widget build(BuildContext context) { + userDetails = ModalRoute.of(context)!.settings.arguments; data = Provider.of(context, listen: false); if (userDetails != null) data.getSingleUserChatHistory( @@ -51,12 +61,6 @@ class _ChatDetailScreenState extends State { loadMore: false, isNewChat: userDetails["isNewChat"], ); - //data.scrollController.addListener(data.scrollListener); - } - - @override - Widget build(BuildContext context) { - userDetails = ModalRoute.of(context)!.settings.arguments; return Scaffold( backgroundColor: const Color(0xFFF8F8F8), appBar: AppBarWidget(context, @@ -66,7 +70,7 @@ class _ChatDetailScreenState extends State { actions: [ IconButton( onPressed: () { - makeCall("AUDIO"); + // makeCall("AUDIO"); }, icon: SvgPicture.asset( "assets/images/call.svg", @@ -76,7 +80,7 @@ class _ChatDetailScreenState extends State { ), IconButton( onPressed: () { - makeCall("VIDEO"); + // makeCall("VIDEO"); }, icon: SvgPicture.asset( "assets/images/call.svg", diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 738fc17..744188f 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -1,6 +1,9 @@ +import 'dart:convert'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -31,7 +34,7 @@ class _ChatHomeState extends State { // TODO: implement initState super.initState(); data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().then((value) { + data.getUserAutoLoginToken().then((Object? value) { data.getUserRecentChats(); }); } @@ -39,7 +42,9 @@ class _ChatHomeState extends State { @override void dispose() { data.clearAll(); - data.hubConnection.stop(); + if (data.hubConInitialized) { + data.hubConnection.stop(); + } super.dispose(); } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index d342072..7453603 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -71,6 +71,7 @@ class _DashboardScreenState extends State { data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchMenuEntries(); data.getCategoryOffersListAPI(context); + data.fetchChatCounts(); _refreshController.refreshCompleted(); } @@ -268,7 +269,7 @@ class _DashboardScreenState extends State { ).onPress(() { showMyBottomSheet( context, - callBackFunc: (){}, + callBackFunc: () {}, child: MarkAttendanceWidget(model, isFromDashboard: true), ); }), @@ -469,10 +470,32 @@ class _DashboardScreenState extends State { label: LocaleKeys.itemsForSale.tr(), ), BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/chat/chat.svg", - color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), + icon: Stack( + alignment: Alignment.centerLeft, + children: [ + SvgPicture.asset( + "assets/icons/chat/chat.svg", + color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color, + ).paddingAll(4), + Consumer( + builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { + if (data.chatUConvCounter == 0) { + return const SizedBox(); + } + return Positioned( + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.chatUConvCounter.toString().toText10(color: Colors.white), + ), + ); + }, + ), + ], + ), label: LocaleKeys.chat.tr(), ), ], diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index a30b33d..b88b96f 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -236,7 +236,7 @@ class _SearchEmployeeBottomSheetState extends State { arguments: {"targetUser": chatUsersList![index], "isNewChat": true}, ); }, - onLongPress: () {}, + ), ); }, From d7c0ef7bfbaef8afb6f82eb21fc7d44634091a82 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Wed, 16 Nov 2022 16:50:34 +0300 Subject: [PATCH 54/82] Chat Count Api / Chat Token Updates / Chat Call UI --- lib/ui/chat/chat_home.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 744188f..ed6b155 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -34,8 +34,11 @@ class _ChatHomeState extends State { // TODO: implement initState super.initState(); data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().then((Object? value) { + data.getUserAutoLoginToken().then((value) { data.getUserRecentChats(); + // var datae = [int.parse(AppState().memberInformationList!.eMPLOYEENUMBER.toString())]; + + // data.hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [int.parse(AppState().memberInformationList!.eMPLOYEENUMBER.toString())]); }); } From 44d76f068781e7ef22665d39fd16f3146025daeb Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 09:26:11 +0300 Subject: [PATCH 55/82] Chat Count Api / Chat Token Updates / Chat Call UI --- lib/api/chat/chat_provider_model.dart | 46 ++++++++++++++++++++++----- lib/ui/chat/chat_detailed_screen.dart | 5 +-- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index cedc158..b336ace 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -109,7 +109,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async { + Future GetUserChatHistoryNotDeliveredAsync(int userId) async { + await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); + return ""; + } + + void getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async { isLoading = true; if (isNewChat) userChatHistory = []; if (!loadMore) paginationVal = 0; @@ -134,9 +139,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } isLoading = false; + await GetUserChatHistoryNotDeliveredAsync(senderUID); notifyListeners(); } + void updateUserChatHistoryStatusAsync(List data) { + hubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); + } + List getSingleUserChatModel(String str) => List.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); ChatUserModel userToList(String str) => ChatUserModel.fromJson(json.decode(str)); @@ -170,7 +180,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { .withAutomaticReconnect( retryDelays: [2000, 5000, 10000, 20000], ) - .configureLogging(Logger("Loggin")) + .configureLogging( + Logger("Loggin"), + ) .build(); hubConnection.onclose( ({Exception? error}) {}, @@ -188,11 +200,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // hubConnection.on("OnSeenChatUserAsync", onChatSeen); //hubConnection.on("OnUserTypingAsync", onUserTyping); - // hubConnection.on("OnUserCountAsync", userCountAsync); + hubConnection.on("OnUserCountAsync", userCountAsync); hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); - } } @@ -223,6 +234,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void userCountAsync(List? args) { dynamic items = args!.toList(); + // logger.d(items); //logger.d("---------------------------------User Count Async -------------------------------------"); //logger.d(items); // for (var user in searchedChats!) { @@ -247,10 +259,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void chatNotDelivered(List? args) { dynamic items = args!.toList(); - if (kDebugMode) { - print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------"); + for (dynamic item in items[0]) { + dynamic data = [ + { + "userChatHistoryId": item["userChatHistoryId"], + "TargetUserId": item["targetUserId"], + "isDelivered": true, + "isSeen": true, + } + ]; + updateUserChatHistoryStatusAsync(data); } - logger.d(items); // for (var user in searchedChats!) { // if (user.id == items.first["id"]) { // user.userStatus = items.first["userStatus"]; @@ -289,7 +308,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future onMsgReceived(List? parameters) async { - print("msg Received"); List data = []; List temp = []; for (dynamic msg in parameters!) { @@ -307,6 +325,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // element.unreadMessageCount = val! + 1; // } // }); + logger.d(jsonEncode(data)); + + var list = [ + { + "userChatHistoryId": data.first.userChatHistoryId, + "TargetUserId": data.first.targetUserId, + "isDelivered": true, + "isSeen": isChatScreenActive ? true : false, + } + ]; + updateUserChatHistoryStatusAsync(list); + notifyListeners(); // if (isChatScreenActive) scrollToBottom(); } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 2ef61f0..71a95b5 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -36,7 +36,7 @@ class _ChatDetailScreenState extends State { data.paginationVal = data.paginationVal + 10; if (userDetails != null) data.getSingleUserChatHistory( - senderUID: AppState().chatDetails!.response!.id.toString(), + senderUID: AppState().chatDetails!.response!.id!.toInt(), receiverUID: userDetails["targetUser"].id, loadMore: true, isNewChat: false, @@ -56,11 +56,12 @@ class _ChatDetailScreenState extends State { data = Provider.of(context, listen: false); if (userDetails != null) data.getSingleUserChatHistory( - senderUID: AppState().chatDetails!.response!.id.toString(), + senderUID: AppState().chatDetails!.response!.id!.toInt(), receiverUID: userDetails["targetUser"].id, loadMore: false, isNewChat: userDetails["isNewChat"], ); + return Scaffold( backgroundColor: const Color(0xFFF8F8F8), appBar: AppBarWidget(context, From 5aa56450d9db89aa4660e38802cca8ba0ded2ba3 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 15 Nov 2022 16:04:19 +0300 Subject: [PATCH 56/82] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index b336ace..bf4c33a 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -270,6 +270,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ]; updateUserChatHistoryStatusAsync(data); } + logger.d(items); // for (var user in searchedChats!) { // if (user.id == items.first["id"]) { // user.userStatus = items.first["userStatus"]; @@ -308,6 +309,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future onMsgReceived(List? parameters) async { + print("msg Received"); List data = []; List temp = []; for (dynamic msg in parameters!) { @@ -428,11 +430,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future sendChatToServer( {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { Uuid uuid = const Uuid(); - String msg = message.text; SingleUserChatModel data = SingleUserChatModel( chatEventId: chatEventId, chatSource: 1, - contant: msg, + contant: message.text, contantNo: uuid.v4(), conversationId: uuid.v4(), createdDate: DateTime.now(), From 33609ea773dd77c2123b02b0a8fadd0688426d89 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Nov 2022 09:49:31 +0300 Subject: [PATCH 57/82] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 4 +++- lib/ui/chat/chat_detailed_screen.dart | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index bf4c33a..ff02c4d 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -50,6 +50,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { { "employeeNumber": int.parse( AppState().memberInformationList!.eMPLOYEENUMBER.toString(), + // "" ), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" }, @@ -430,10 +431,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future sendChatToServer( {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { Uuid uuid = const Uuid(); + var msg = message.text; SingleUserChatModel data = SingleUserChatModel( chatEventId: chatEventId, chatSource: 1, - contant: message.text, + contant: msg, contantNo: uuid.v4(), conversationId: uuid.v4(), createdDate: DateTime.now(), diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 71a95b5..ff661f1 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -71,7 +71,7 @@ class _ChatDetailScreenState extends State { actions: [ IconButton( onPressed: () { - // makeCall("AUDIO"); + makeCall("AUDIO"); }, icon: SvgPicture.asset( "assets/images/call.svg", @@ -81,7 +81,7 @@ class _ChatDetailScreenState extends State { ), IconButton( onPressed: () { - // makeCall("VIDEO"); + makeCall("VIDEO"); }, icon: SvgPicture.asset( "assets/images/call.svg", From 3cac5eebbc7fbc92f675600b7596a890b96d8c45 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Nov 2022 10:49:37 +0300 Subject: [PATCH 58/82] Chat Fixes --- assets/icons/chat/call.svg | 3 + assets/icons/chat/video_call.svg | 6 + lib/api/chat/chat_provider_model.dart | 4 +- lib/classes/consts.dart | 4 +- lib/provider/dashboard_provider_model.dart | 1 - ...en.dart => chat_incoming_call_screen.dart} | 1 + .../chat/call/chat_outgoing_call_screen.dart | 470 ++++++++++++++++++ lib/ui/chat/chat_bubble.dart | 12 +- lib/ui/chat/chat_detailed_screen.dart | 22 +- 9 files changed, 502 insertions(+), 21 deletions(-) create mode 100644 assets/icons/chat/call.svg create mode 100644 assets/icons/chat/video_call.svg rename lib/ui/chat/call/{chat_call_screen.dart => chat_incoming_call_screen.dart} (99%) create mode 100644 lib/ui/chat/call/chat_outgoing_call_screen.dart diff --git a/assets/icons/chat/call.svg b/assets/icons/chat/call.svg new file mode 100644 index 0000000..843daf4 --- /dev/null +++ b/assets/icons/chat/call.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/chat/video_call.svg b/assets/icons/chat/video_call.svg new file mode 100644 index 0000000..2fceee6 --- /dev/null +++ b/assets/icons/chat/video_call.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index ff02c4d..f5d896c 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -49,8 +49,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", { "employeeNumber": int.parse( - AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - // "" + //AppState().memberInformationList!.eMPLOYEENUMBER.toString(), + "210919" ), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" }, diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index c5788f9..ede22e3 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index b38536c..948e5b4 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -275,7 +275,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void fetchChatCounts() async { - print("----------------------- Fetch Count ____________________________________"); try { ChatUnreadCovnCountModel response = await DashboardApiClient().getChatCount(); chatUConvCounter = response.singleChatCount!; diff --git a/lib/ui/chat/call/chat_call_screen.dart b/lib/ui/chat/call/chat_incoming_call_screen.dart similarity index 99% rename from lib/ui/chat/call/chat_call_screen.dart rename to lib/ui/chat/call/chat_incoming_call_screen.dart index 3fce65b..923a4bd 100644 --- a/lib/ui/chat/call/chat_call_screen.dart +++ b/lib/ui/chat/call/chat_incoming_call_screen.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:ui'; import 'package:camera/camera.dart'; diff --git a/lib/ui/chat/call/chat_outgoing_call_screen.dart b/lib/ui/chat/call/chat_outgoing_call_screen.dart new file mode 100644 index 0000000..b5a47a6 --- /dev/null +++ b/lib/ui/chat/call/chat_outgoing_call_screen.dart @@ -0,0 +1,470 @@ +import 'dart:ui'; + +import 'package:camera/camera.dart'; +import 'package:flutter/cupertino.dart'; +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/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/models/chat/call.dart'; + +class OutGoingCall extends StatefulWidget { + IncomingCallData OutGoingCallData; + bool? isVideoCall; + + OutGoingCall({Key? key, required this.OutGoingCallData, this.isVideoCall}) : super(key: key); + + @override + _OutGoingCallState createState() => _OutGoingCallState(); +} + +class _OutGoingCallState extends State with SingleTickerProviderStateMixin { + AnimationController? _animationController; + CameraController? _controller; + Future? _initializeControllerFuture; + bool isCameraReady = false; + bool isMicOff = false; + bool isLoudSpeaker = false; + bool isCamOff = false; + + @override + void initState() { + _animationController = AnimationController( + vsync: this, + duration: const Duration( + milliseconds: 500, + ), + ); + //_runAnimation(); + // connectSignaling(); + WidgetsBinding.instance.addPostFrameCallback( + (_) => _runAnimation(), + ); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: FutureBuilder( + future: _initializeControllerFuture, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Stack( + alignment: FractionalOffset.center, + children: [ + if (widget.isVideoCall!) + Positioned.fill( + child: AspectRatio( + aspectRatio: _controller!.value.aspectRatio, + child: CameraPreview( + _controller!, + ), + ), + ), + Positioned.fill( + child: ClipRect( + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), + child: Container( + decoration: BoxDecoration( + color: MyColors.grey57Color.withOpacity( + 0.7, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + 40.height, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.all(21.0), + child: Container( + margin: const EdgeInsets.only( + left: 10.0, + right: 10.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + SvgPicture.asset( + "assets/images/user.svg", + height: 70, + width: 70, + fit: BoxFit.cover, + ), + 10.height, + Text( + "Aamir Saleem Ahmad", + style: TextStyle( + fontSize: 21, + fontWeight: FontWeight.bold, + color: MyColors.white, + letterSpacing: -1.26, + height: 23 / 12, + ), + ), + Text( + "Ringing...", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Color( + 0xffC6C6C6, + ), + letterSpacing: -0.48, + height: 23 / 24, + ), + ), + SizedBox( + height: 2, + ), + ], + ), + ), + ), + ], + ), + // Container( + // margin: const EdgeInsets.all(21.0), + // width: MediaQuery.of(context).size.width, + // decoration: cardRadius(15.0, color: MyColors.black, elevation: null), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisSize: MainAxisSize.min, + // children: [ + // Container( + // padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 6.0), + // child: Text( + // "TranslationBase.of(context).appoInfo", + // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.white, letterSpacing: -0.64, height: 23 / 12), + // ), + // ), + // Container( + // padding: const EdgeInsets.only(left: 16.0, right: 16.0), + // child: Text( + // "widget.OutGoingCallData.appointmentdate + widget.OutGoingCallData.appointmenttime", + // style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600), + // ), + // ), + // Container( + // padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 21.0), + // child: Text( + // "widget.OutGoingCallData.clinicname", + // style: TextStyle(fontSize: 12.0, letterSpacing: -0.48, color: Color(0xff8E8E8E), fontWeight: FontWeight.w600), + // ), + // ), + // ], + // ), + // ), + const Spacer(), + Container( + margin: const EdgeInsets.only( + bottom: 70.0, + left: 49, + right: 49, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (widget.isVideoCall!) + RotationTransition( + turns: Tween( + begin: 0.0, + end: -.1, + ) + .chain( + CurveTween( + curve: Curves.elasticIn, + ), + ) + .animate( + _animationController!, + ), + child: RawMaterialButton( + onPressed: () { + _camOff(); + }, + elevation: 2.0, + fillColor: isCamOff ? MyColors.green2DColor : Colors.grey, + padding: const EdgeInsets.all( + 15.0, + ), + shape: const CircleBorder(), + child: Icon( + isCamOff ? Icons.videocam_off : Icons.videocam, + color: MyColors.white, + size: 35.0, + ), + ), + ) + else + RotationTransition( + turns: Tween( + begin: 0.0, + end: -.1, + ) + .chain( + CurveTween( + curve: Curves.elasticIn, + ), + ) + .animate( + _animationController!, + ), + child: RawMaterialButton( + onPressed: () { + _loudOn(); + }, + elevation: 2.0, + fillColor: isLoudSpeaker ? MyColors.green2DColor : Colors.grey, + padding: const EdgeInsets.all( + 15.0, + ), + shape: const CircleBorder(), + child: const Icon( + Icons.volume_up, + color: MyColors.white, + size: 35.0, + ), + ), + ), + RotationTransition( + turns: Tween( + begin: 0.0, + end: -.1, + ) + .chain( + CurveTween( + curve: Curves.elasticIn, + ), + ) + .animate( + _animationController!, + ), + child: RawMaterialButton( + onPressed: () { + _micOff(); + }, + elevation: 2.0, + fillColor: isMicOff ? MyColors.green2DColor : Colors.grey, + padding: const EdgeInsets.all( + 15.0, + ), + shape: const CircleBorder(), + child: Icon( + isMicOff ? Icons.mic_off : Icons.mic, + color: MyColors.white, + size: 35.0, + ), + ), + ), + RawMaterialButton( + onPressed: () { + backToHome(); + }, + elevation: 2.0, + fillColor: MyColors.redA3Color, + padding: const EdgeInsets.all( + 15.0, + ), + shape: const CircleBorder(), + child: const Icon( + Icons.call_end, + color: MyColors.white, + size: 35.0, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ], + ); + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, + ), + ); + } + + void _runAnimation() async { + List cameras = await availableCameras(); + CameraDescription firstCamera = cameras[1]; + _controller = CameraController( + firstCamera, + ResolutionPreset.medium, + ); + _initializeControllerFuture = _controller!.initialize(); + setState(() {}); + // setAudioFile(); + for (int i = 0; i < 100; i++) { + await _animationController!.forward(); + await _animationController!.reverse(); + } + } + + void _micOff() { + setState(() { + isMicOff = !isMicOff; + }); + } + + void _camOff() { + setState(() { + isCamOff = !isCamOff; + }); + } + + void _loudOn() { + setState(() { + isLoudSpeaker = !isLoudSpeaker; + }); + } + + Future _submit() async { + try { + // backToHome(); + // final roomModel = RoomModel(name: widget.OutGoingCallData.name, token: widget.OutGoingCallData.sessionId, identity: widget.OutGoingCallData.identity); + await _controller?.dispose(); + + // changeCallStatusAPI(4); + + // if (_session != null && _signaling != null) { + // await Navigator.of(context).pushReplacement( + // MaterialPageRoute( + // // fullscreenDialog: true, + // builder: (BuildContext context) { + // // if (widget.OutGoingCallData.isWebRTC == "true") { + // return StartVideoCall(signaling: _signaling, session: _session); + // + // // else { + // // return OpenTokConnectCallPage(apiKey: OPENTOK_API_KEY, sessionId: widget.OutGoingCallData.sessionId, token: widget.OutGoingCallData.token); + // // } + // + // // return VideoCallWebPage(receiverId: widget.OutGoingCallData.receiverID, callerId: widget.OutGoingCallData.callerID); // Web WebRTC VideoCall + // + // // return CallHomePage(receiverId: widget.OutGoingCallData.receiverID, callerId: widget.OutGoingCallData.callerID); // App WebRTC VideoCall + // }, + // ), + // ); + // } else { + // // Invalid Params/Data + // Utils.showToast("Failed to establish connection with server"); + // } + } catch (err) { + print(err); + // await PlatformExceptionAlertDialog( + // exception: err, + // ).show(context); + + Utils.showToast(err.toString()); + } + } + + // void changeCallStatusAPI(int sessionStatus) { + // LiveCareService service = new LiveCareService(); + // service.endCallAPI(widget.OutGoingCallData.sessionId, sessionStatus, context).then((res) {}).catchError((err) { + // print(err); + // }); + // } + + void backToHome() async { + // final connected = await signaling.declineCall(widget.OutGoingCallData.callerID, widget.OutGoingCallData.receiverID); + // LandingPage.isOpenCallPage = false; + // _signaling + _animationController!.dispose(); + // player.stop(); + // changeCallStatusAPI(3); + // _signaling.bye(_session, callRejected: true); + // _signaling.callDisconnected(_session, callRejected: true); + Navigator.of(context).pop(); + } + + // + // void disposeAudioResources() async { + // await player.dispose(); + // } + // + // void setAudioFile() async { + // player.stop(); + // await player.setVolume(1.0); // full volume + // try { + // await player.setAsset('assets/sounds/ring_60Sec.mp3').then((value) { + // player.setLoopMode(LoopMode.one); // loop ring sound + // player.play(); + // }).catchError((err) { + // print("Error: $err"); + // }); + // } catch (e) { + // print("Error: $e"); + // } + // } + // + // void connectSignaling({@required bool iAmCaller = false}) async { + // print("----------------- + Signaling Connection Started ---------------------------"); + // var caller = widget.OutGoingCallData.callerID; + // var receiver = widget.OutGoingCallData.receiverID; + // var host = widget.OutGoingCallData.server; + // + // var selfRole = iAmCaller ? "Caller" : "Receiver"; + // var selfId = iAmCaller ? caller : receiver; + // var selfUser = SocketUser(id: selfId, name: "$selfRole-$selfId", userAgent: DeviceInfo.userAgent, moreInfo: {}); + // + // var remoteRole = !iAmCaller ? "Caller" : "Receiver"; + // var remoteId = !iAmCaller ? caller : receiver; + // var remoteUser = SocketUser(id: remoteId, name: "$remoteRole-$remoteId", userAgent: DeviceInfo.userAgent, moreInfo: {}); + // + // var sessionId = "$caller-$receiver"; + // _session = SessionOneToOne(id: sessionId, local_user: selfUser, remote_user: remoteUser); + // + // _signaling = Signaling(host, session: _session); + // await _signaling.connect(); + // + // if (_signaling.state == SignalingState.Open) { + // return; + // } + // } + + BoxDecoration cardRadius(double radius, {required Color color, double? elevation}) { + return BoxDecoration( + shape: BoxShape.rectangle, + color: color ?? Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(radius), + ), + boxShadow: [ + BoxShadow( + color: const Color( + 0xff000000, + ).withOpacity( + .05, + ), + //spreadRadius: 5, + blurRadius: elevation ?? 27, + offset: const Offset( + -2, + 3, + ), + ), + ], + ); + } +} diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index c638b34..6dcd6d2 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -91,12 +91,12 @@ class ChatBubble extends StatelessWidget { children: [ dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7),), if (isCurrentUser) 5.width, - if (isCurrentUser) - Icon( - isDelivered ? Icons.done_all : Icons.done_all, - color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor, - size: 14, - ), + // if (isCurrentUser) + // Icon( + // isDelivered ? Icons.done_all : Icons.done_all, + // color: isSeen ? MyColors.textMixColor : MyColors.grey9DColor, + // size: 14, + // ), ], ), ], diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index ff661f1..2c8b2d8 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -6,11 +6,12 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/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/chat/call.dart'; -import 'package:mohem_flutter_app/ui/chat/call/chat_call_screen.dart'; +import 'package:mohem_flutter_app/ui/chat/call/chat_outgoing_call_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; @@ -71,12 +72,12 @@ class _ChatDetailScreenState extends State { actions: [ IconButton( onPressed: () { - makeCall("AUDIO"); + makeCall("AUDIO"); }, icon: SvgPicture.asset( - "assets/images/call.svg", - width: 25, - height: 25, + "assets/icons/chat/call.svg", + width: 22, + height: 22, ), ), IconButton( @@ -84,11 +85,12 @@ class _ChatDetailScreenState extends State { makeCall("VIDEO"); }, icon: SvgPicture.asset( - "assets/images/call.svg", - width: 25, - height: 25, + "assets/icons/chat/video_call.svg", + width: 20, + height: 20, ), ), + 10.width, ]), body: Consumer( builder: (BuildContext context, ChatProviderModel m, Widget? child) { @@ -355,9 +357,9 @@ class _ChatDetailScreenState extends State { await Navigator.push( context, MaterialPageRoute( - builder: (BuildContext context) => IncomingCall( - incomingCallData: incomingCallData, + builder: (BuildContext context) => OutGoingCall( isVideoCall: callType == "VIDEO" ? true : false, + OutGoingCallData: incomingCallData, ), ), ); From 451b381acf34370470ac8636c96c29f6e7e8051b Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 10:52:08 +0300 Subject: [PATCH 59/82] Chat Count Api / Chat Token Updates / Chat Call UI --- lib/api/chat/chat_provider_model.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index f5d896c..bf69d58 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -49,8 +49,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", { "employeeNumber": int.parse( - //AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "210919" + AppState().memberInformationList!.eMPLOYEENUMBER.toString(), ), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" }, From 5ec6fbdf421fb5304cbcf2172817d9de29b25601 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Nov 2022 11:07:43 +0300 Subject: [PATCH 60/82] Chat Fixes --- .gitignore | 1 - lib/api/chat/chat_provider_model.dart | 4 ++-- lib/classes/consts.dart | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 034a5be..a841580 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,6 @@ pubspec.lock /build/ # Web related -lib/generated_plugin_registrant.dart # Symbolication related app.*.symbols diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index f5d896c..7227c99 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -49,8 +49,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", { "employeeNumber": int.parse( - //AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "210919" + AppState().memberInformationList!.eMPLOYEENUMBER.toString(), + //"210919" ), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" }, diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index ede22e3..c5788f9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; From c6cd550dbced3b1462a69d247be0687556d925c3 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Nov 2022 11:32:10 +0300 Subject: [PATCH 61/82] Chat Fixes --- ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme | 2 +- lib/ui/chat/chat_detailed_screen.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a..ac88fca 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -40,7 +40,7 @@ { actions: [ IconButton( onPressed: () { - makeCall("AUDIO"); + // makeCall("AUDIO"); }, icon: SvgPicture.asset( "assets/icons/chat/call.svg", @@ -82,7 +82,7 @@ class _ChatDetailScreenState extends State { ), IconButton( onPressed: () { - makeCall("VIDEO"); + // makeCall("VIDEO"); }, icon: SvgPicture.asset( "assets/icons/chat/video_call.svg", From 2546fb52a9100987b2ffe40033f4da1dba7b4646 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 11:32:24 +0300 Subject: [PATCH 62/82] Chat Count Api / Chat Token Updates / Chat Call UI --- lib/classes/consts.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index ede22e3..c5788f9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; From 5913452a439d135dec80841635c821ec60f88afc Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 11:34:54 +0300 Subject: [PATCH 63/82] Chat Count Api / Chat Token Updates / Chat Call UI --- lib/api/chat/chat_provider_model.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 7227c99..7439b98 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -50,7 +50,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { { "employeeNumber": int.parse( AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - //"210919" ), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" }, @@ -310,7 +309,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future onMsgReceived(List? parameters) async { - print("msg Received"); List data = []; List temp = []; for (dynamic msg in parameters!) { @@ -328,7 +326,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { // element.unreadMessageCount = val! + 1; // } // }); - logger.d(jsonEncode(data)); var list = [ { From efce6dbd0f0e7b1142737a043e9fed1b39dffb84 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 11:50:37 +0300 Subject: [PATCH 64/82] Chat Count Api / Chat Token Updates / Chat Call UI --- ios/Runner/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 2ac7a44..2797543 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -44,6 +44,8 @@ This App requires access to your location to mark your attendance. NSPhotoLibraryUsageDescription This app requires photo library access to select image as document & upload it. + NSMicrophoneUsageDescription + This app requires microphone access to for call. UIBackgroundModes remote-notification From 4d35767784b2d1264bdf3125883c09e00e2dcf50 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 12:37:03 +0300 Subject: [PATCH 65/82] Revert "Chat Count Api / Chat Token Updates / Chat Call UI" This reverts commit 826c39bafc72f27eceb7a2fbb975740e2a18c7db. --- ios/Runner/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 2ac7a44..2797543 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -44,6 +44,8 @@ This App requires access to your location to mark your attendance. NSPhotoLibraryUsageDescription This app requires photo library access to select image as document & upload it. + NSMicrophoneUsageDescription + This app requires microphone access to for call. UIBackgroundModes remote-notification From e2a1eb3c812686767225f3e59cdf958da6d90466 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 15:05:49 +0300 Subject: [PATCH 66/82] Chat Count Api / Chat Token Updates / Chat Call UI --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a841580..4a374d7 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release +/ios/ From 8cb5d9a0610f397ea0dcb8a3d9e563f6ccb928e5 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 15:15:33 +0300 Subject: [PATCH 67/82] Chat Count Api / Chat Token Updates / Chat Call UI --- lib/ui/chat/chat_detailed_screen.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index be34d7a..2c8b2d8 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -72,7 +72,7 @@ class _ChatDetailScreenState extends State { actions: [ IconButton( onPressed: () { - // makeCall("AUDIO"); + makeCall("AUDIO"); }, icon: SvgPicture.asset( "assets/icons/chat/call.svg", @@ -82,7 +82,7 @@ class _ChatDetailScreenState extends State { ), IconButton( onPressed: () { - // makeCall("VIDEO"); + makeCall("VIDEO"); }, icon: SvgPicture.asset( "assets/icons/chat/video_call.svg", From 42287f24d18b4a63377c0d62a09a17334de1bfc4 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 15:16:16 +0300 Subject: [PATCH 68/82] Chat Count Api / Chat Token Updates / Chat Call UI --- ios/Runner/Info.plist | 2 -- 1 file changed, 2 deletions(-) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 2797543..2ac7a44 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -44,8 +44,6 @@ This App requires access to your location to mark your attendance. NSPhotoLibraryUsageDescription This app requires photo library access to select image as document & upload it. - NSMicrophoneUsageDescription - This app requires microphone access to for call. UIBackgroundModes remote-notification From 1fcb6250f5264612c7062c3c9a9f13a234dd12a0 Mon Sep 17 00:00:00 2001 From: Aamir Saleem Ahmad Date: Thu, 17 Nov 2022 12:22:59 +0000 Subject: [PATCH 69/82] Revert "Chat Fixes" This reverts commit c6cd550dbced3b1462a69d247be0687556d925c3 --- ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index ac88fca..c87d15a 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -40,7 +40,7 @@ Date: Thu, 17 Nov 2022 12:24:46 +0000 Subject: [PATCH 70/82] Revert "Chat Count Api / Chat Token Updates / Chat Call UI" This reverts commit 42287f24d18b4a63377c0d62a09a17334de1bfc4 --- ios/Runner/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 2ac7a44..2797543 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -44,6 +44,8 @@ This App requires access to your location to mark your attendance. NSPhotoLibraryUsageDescription This app requires photo library access to select image as document & upload it. + NSMicrophoneUsageDescription + This app requires microphone access to for call. UIBackgroundModes remote-notification From 06e7a913dae9f92a531074dd8bd5079742cf86c6 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 17 Nov 2022 15:57:29 +0300 Subject: [PATCH 71/82] Chat Count Api / Chat Token Updates / Chat Call UI --- .../chat/call/chat_outgoing_call_screen.dart | 2 +- lib/ui/chat/chat_bubble.dart | 65 +++++++++++++--- lib/ui/chat/chat_detailed_screen.dart | 46 ++++++++++-- lib/ui/chat/chat_home.dart | 22 ++++-- lib/ui/chat/chat_home_screen.dart | 74 +++++++++++++++---- lib/ui/chat/favorite_users_screen.dart | 21 ++++-- 6 files changed, 180 insertions(+), 50 deletions(-) diff --git a/lib/ui/chat/call/chat_outgoing_call_screen.dart b/lib/ui/chat/call/chat_outgoing_call_screen.dart index b5a47a6..f049059 100644 --- a/lib/ui/chat/call/chat_outgoing_call_screen.dart +++ b/lib/ui/chat/call/chat_outgoing_call_screen.dart @@ -82,7 +82,7 @@ class _OutGoingCallState extends State with SingleTickerProviderSt Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Container( margin: const EdgeInsets.all(21.0), child: Container( diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 6dcd6d2..1696a49 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -30,7 +30,11 @@ class ChatBubble extends StatelessWidget { Widget build(BuildContext context) { return Padding( // padding: EdgeInsets.zero, - padding: EdgeInsets.only(left: isCurrentUser ? 110 : 20, right: isCurrentUser ? 20 : 110, bottom: 9), + padding: EdgeInsets.only( + left: isCurrentUser ? 110 : 20, + right: isCurrentUser ? 20 : 110, + bottom: 9, + ), child: Align( alignment: isCurrentUser ? Alignment.centerRight : Alignment.centerLeft, @@ -40,7 +44,9 @@ class ChatBubble extends StatelessWidget { gradient: isCurrentUser ? null : const LinearGradient( - transform: GradientRotation(.46), + transform: GradientRotation( + .46, + ), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ @@ -48,21 +54,33 @@ class ChatBubble extends StatelessWidget { MyColors.gradiantStartColor, ], ), - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular( + 10, + ), ), child: Padding( - padding: EdgeInsets.only(top: isReplied ? 8 : 5, right: 8, left: 8, bottom: 5), + padding: EdgeInsets.only( + top: isReplied ? 8 : 5, + right: 8, + left: 8, + bottom: 5, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ if (isReplied) ClipRRect( - borderRadius: BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular( + 5.0, + ), child: Container( decoration: BoxDecoration( border: Border( - left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), + left: BorderSide( + width: 6, + color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white, + ), ), color: isCurrentUser ? MyColors.black.withOpacity(0.10) : MyColors.black.withOpacity(0.30), ), @@ -72,10 +90,29 @@ class ChatBubble extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5), + (userName) + .toText12( + color: MyColors.gradiantStartColor, + isBold: false, + ) + .paddingOnly( + right: 5, + top: 5, + bottom: 0, + left: 5, + ), replyText - .toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4) - .paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + .toText10( + color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), + isBold: false, + maxlines: 4, + ) + .paddingOnly( + right: 5, + top: 5, + bottom: 8, + left: 5, + ), ], ), ), @@ -84,12 +121,16 @@ class ChatBubble extends StatelessWidget { ), ), if (isReplied) 8.height, - text.toText12(color: isCurrentUser ? MyColors.grey57Color : MyColors.white), + text.toText12( + color: isCurrentUser ? MyColors.grey57Color : MyColors.white, + ), Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, - children: [ - dateTime.toText12(color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7),), + children: [ + dateTime.toText12( + color: isCurrentUser ? MyColors.grey41Color.withOpacity(.5) : MyColors.white.withOpacity(0.7), + ), if (isCurrentUser) 5.width, // if (isCurrentUser) // Icon( diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 2c8b2d8..347c573 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -132,7 +132,9 @@ class _ChatDetailScreenState extends State { userName: AppState().chatDetails!.response!.userName == m.userChatHistory[i].currentUserName.toString() ? "You" : m.userChatHistory[i].currentUserName.toString(), ), onRightSwipe: () { - m.chatReply(m.userChatHistory[i]); + m.chatReply( + m.userChatHistory[i], + ); }, ); }, @@ -156,7 +158,10 @@ class _ChatDetailScreenState extends State { ? "You" : m.repliedMsg.first.currentUserName.toString().replaceAll(".", " ")) .toText14(color: MyColors.lightGreenColor), - subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.white, maxLine: 2), + subtitle: (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12( + color: MyColors.white, + maxLine: 2, + ), trailing: GestureDetector( onTap: m.closeMe, child: Container( @@ -183,7 +188,12 @@ class _ChatDetailScreenState extends State { margin: EdgeInsets.zero, elevation: 0, child: Padding( - padding: const EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 0), + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 20, + bottom: 0, + ), child: Card( margin: EdgeInsets.zero, shape: RoundedRectangleBorder( @@ -217,13 +227,21 @@ class _ChatDetailScreenState extends State { controller: m.message, decoration: InputDecoration( hintText: m.isFileSelected ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), - hintStyle: TextStyle(color: m.isFileSelected ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), + hintStyle: TextStyle( + color: m.isFileSelected ? MyColors.darkTextColor : MyColors.grey98Color, + fontSize: 14, + ), border: InputBorder.none, focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, errorBorder: InputBorder.none, disabledBorder: InputBorder.none, - contentPadding: EdgeInsets.only(left: m.sFileType.isNotEmpty ? 10 : 20, right: m.sFileType.isNotEmpty ? 0 : 5, top: 20, bottom: 20), + contentPadding: EdgeInsets.only( + left: m.sFileType.isNotEmpty ? 10 : 20, + right: m.sFileType.isNotEmpty ? 0 : 5, + top: 20, + bottom: 20, + ), prefixIcon: m.sFileType.isNotEmpty ? Row( mainAxisSize: MainAxisSize.min, @@ -267,7 +285,13 @@ class _ChatDetailScreenState extends State { color: MyColors.white, ), ), - ("Clear").toText11(color: MyColors.redA3Color).paddingOnly(left: 4), + ("Clear") + .toText11( + color: MyColors.redA3Color, + ) + .paddingOnly( + left: 4, + ), ], ), onPressed: () async { @@ -299,12 +323,18 @@ class _ChatDetailScreenState extends State { width: 26, ), onPressed: () { - m.sendChatMessage(userDetails["targetUser"].id, userDetails["targetUser"].userName, context); + m.sendChatMessage( + userDetails["targetUser"].id, + userDetails["targetUser"].userName, + context, + ); }, ) ], ), - ).paddingOnly(right: 20), + ).paddingOnly( + right: 20, + ), ), ), ), diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index ed6b155..9884d59 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -34,11 +34,8 @@ class _ChatHomeState extends State { // TODO: implement initState super.initState(); data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().then((value) { + data.getUserAutoLoginToken().then((Object? value) { data.getUserRecentChats(); - // var datae = [int.parse(AppState().memberInformationList!.eMPLOYEENUMBER.toString())]; - - // data.hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [int.parse(AppState().memberInformationList!.eMPLOYEENUMBER.toString())]); }); } @@ -73,14 +70,17 @@ class _ChatHomeState extends State { transform: GradientRotation(.83), begin: Alignment.topRight, end: Alignment.bottomLeft, - colors: [ + colors: [ MyColors.gradiantEndColor, MyColors.gradiantStartColor, ], ), ), child: Row( - children: [myTab(LocaleKeys.mychats.tr(), 0), myTab(LocaleKeys.favorite.tr(), 1)], + children: [ + myTab(LocaleKeys.mychats.tr(), 0), + myTab(LocaleKeys.favorite.tr(), 1), + ], ), ), PageView( @@ -91,7 +91,10 @@ class _ChatHomeState extends State { tabIndex = pageIndex; }); }, - children: [ChatHomeScreen(), ChatFavoriteUsersScreen()], + children: [ + ChatHomeScreen(), + ChatFavoriteUsersScreen(), + ], ).expanded, ], ), @@ -104,7 +107,10 @@ class _ChatHomeState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - title.toText12(color: isSelected ? MyColors.white : MyColors.white.withOpacity(.74), isCenter: true), + title.toText12( + color: isSelected ? MyColors.white : MyColors.white.withOpacity(.74), + isCenter: true, + ), 4.height, Container( height: 8, diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index a22c7e0..05623f7 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -40,21 +40,41 @@ class _ChatHomeScreenState extends State { physics: const AlwaysScrollableScrollPhysics(), children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + padding: const EdgeInsets.symmetric( + vertical: 20, + horizontal: 20, + ), child: TextField( controller: m.search, onChanged: (String val) { m.filter(val); }, decoration: InputDecoration( - border: fieldBorder(radius: 5, color: 0xFFE5E5E5), - focusedBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), - enabledBorder: fieldBorder(radius: 5, color: 0xFFE5E5E5), - contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + border: fieldBorder( + radius: 5, + color: 0xFFE5E5E5, + ), + focusedBorder: fieldBorder( + radius: 5, + color: 0xFFE5E5E5, + ), + enabledBorder: fieldBorder( + radius: 5, + color: 0xFFE5E5E5, + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 10, + ), hintText: LocaleKeys.searchfromchat.tr(), - hintStyle: const TextStyle(color: MyColors.lightTextColor, fontStyle: FontStyle.italic), + hintStyle: const TextStyle( + color: MyColors.lightTextColor, + fontStyle: FontStyle.italic, + ), filled: true, - fillColor: const Color(0xFFF7F7F7), + fillColor: const Color( + 0xFFF7F7F7, + ), suffixIcon: m.search.text.isNotEmpty ? IconButton( onPressed: () { @@ -73,7 +93,9 @@ class _ChatHomeScreenState extends State { if (m.searchedChats != null) ListView.separated( itemCount: m.searchedChats!.length, - padding: const EdgeInsets.only(bottom: 80), + padding: const EdgeInsets.only( + bottom: 80, + ), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) { @@ -136,15 +158,26 @@ class _ChatHomeScreenState extends State { child: IconButton( alignment: Alignment.centerRight, padding: EdgeInsets.zero, - icon: Icon(m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == false ? Icons.star_sharp : Icons.star_sharp), + icon: Icon( + m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == false ? Icons.star_sharp : Icons.star_sharp, + ), color: m.searchedChats![index].isFav != null && m.searchedChats![index].isFav == true ? MyColors.yellowColor : MyColors.grey35Color, onPressed: () { if (m.searchedChats![index].isFav == null || m.searchedChats![index].isFav == false) { - m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + m.favoriteUser( + userID: AppState().chatDetails!.response!.id!, + targetUserID: m.searchedChats![index].id!, + ); } else if (m.searchedChats![index].isFav == true) { - m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + m.unFavoriteUser( + userID: AppState().chatDetails!.response!.id!, + targetUserID: m.searchedChats![index].id!, + ); } else { - m.favoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.searchedChats![index].id!); + m.favoriteUser( + userID: AppState().chatDetails!.response!.id!, + targetUserID: m.searchedChats![index].id!, + ); } }, ), @@ -167,9 +200,14 @@ class _ChatHomeScreenState extends State { ); }, separatorBuilder: (BuildContext context, int index) => const Padding( - padding: EdgeInsets.only(right: 10, left: 70), + padding: EdgeInsets.only( + right: 10, + left: 70, + ), child: Divider( - color: Color(0xFFE5E5E5), + color: Color( + 0xFFE5E5E5, + ), ), ), ), @@ -217,9 +255,13 @@ class _ChatHomeScreenState extends State { OutlineInputBorder fieldBorder({required double radius, required int color}) { return OutlineInputBorder( - borderRadius: BorderRadius.circular(radius), + borderRadius: BorderRadius.circular( + radius, + ), borderSide: BorderSide( - color: Color(color), + color: Color( + color, + ), ), ); } diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index fd118de..7ef0f84 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -34,7 +34,7 @@ class ChatFavoriteUsersScreen extends StatelessWidget { height: 55, child: ListTile( leading: Stack( - children: [ + children: [ SvgPicture.asset( "assets/images/user.svg", height: 48, @@ -56,14 +56,22 @@ class ChatFavoriteUsersScreen extends StatelessWidget { ) ], ), - title: (m.favUsersList![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor), + title: (m.favUsersList![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14( + color: MyColors.darkTextColor, + ), trailing: IconButton( alignment: Alignment.centerRight, padding: EdgeInsets.zero, - icon: Icon(m.favUsersList![index].isFav! ? Icons.star : Icons.star_border), + icon: Icon( + m.favUsersList![index].isFav! ? Icons.star : Icons.star_border, + ), color: m.favUsersList![index].isFav! ? MyColors.yellowColor : MyColors.grey35Color, onPressed: () { - if (m.favUsersList![index].isFav!) m.unFavoriteUser(userID: AppState().chatDetails!.response!.id!, targetUserID: m.favUsersList![index].id!); + if (m.favUsersList![index].isFav!) + m.unFavoriteUser( + userID: AppState().chatDetails!.response!.id!, + targetUserID: m.favUsersList![index].id!, + ); }, ), minVerticalPadding: 0, @@ -82,7 +90,10 @@ class ChatFavoriteUsersScreen extends StatelessWidget { ); }, separatorBuilder: (BuildContext context, int index) => const Padding( - padding: EdgeInsets.only(right: 10, left: 70), + padding: EdgeInsets.only( + right: 10, + left: 70, + ), child: Divider( color: Color( 0xFFE5E5E5, From a64ae80a4ae76f8b4d48b47e828c765c0eaf0d7e Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 20 Nov 2022 10:10:08 +0300 Subject: [PATCH 72/82] Chat Updates --- .../chat/call/chat_outgoing_call_screen.dart | 116 ++++++------------ lib/ui/landing/dashboard_screen.dart | 6 +- 2 files changed, 42 insertions(+), 80 deletions(-) diff --git a/lib/ui/chat/call/chat_outgoing_call_screen.dart b/lib/ui/chat/call/chat_outgoing_call_screen.dart index f049059..25bc05d 100644 --- a/lib/ui/chat/call/chat_outgoing_call_screen.dart +++ b/lib/ui/chat/call/chat_outgoing_call_screen.dart @@ -102,7 +102,7 @@ class _OutGoingCallState extends State with SingleTickerProviderSt fit: BoxFit.cover, ), 10.height, - Text( + const Text( "Aamir Saleem Ahmad", style: TextStyle( fontSize: 21, @@ -112,7 +112,7 @@ class _OutGoingCallState extends State with SingleTickerProviderSt height: 23 / 12, ), ), - Text( + const Text( "Ringing...", style: TextStyle( fontSize: 16, @@ -124,7 +124,7 @@ class _OutGoingCallState extends State with SingleTickerProviderSt height: 23 / 24, ), ), - SizedBox( + const SizedBox( height: 2, ), ], @@ -177,96 +177,54 @@ class _OutGoingCallState extends State with SingleTickerProviderSt mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (widget.isVideoCall!) - RotationTransition( - turns: Tween( - begin: 0.0, - end: -.1, - ) - .chain( - CurveTween( - curve: Curves.elasticIn, - ), - ) - .animate( - _animationController!, - ), - child: RawMaterialButton( - onPressed: () { - _camOff(); - }, - elevation: 2.0, - fillColor: isCamOff ? MyColors.green2DColor : Colors.grey, - padding: const EdgeInsets.all( - 15.0, - ), - shape: const CircleBorder(), - child: Icon( - isCamOff ? Icons.videocam_off : Icons.videocam, - color: MyColors.white, - size: 35.0, - ), + RawMaterialButton( + onPressed: () { + _camOff(); + }, + elevation: 2.0, + fillColor: isCamOff ? MyColors.green2DColor : Colors.grey, + padding: const EdgeInsets.all( + 15.0, ), - ) - else - RotationTransition( - turns: Tween( - begin: 0.0, - end: -.1, - ) - .chain( - CurveTween( - curve: Curves.elasticIn, - ), - ) - .animate( - _animationController!, - ), - child: RawMaterialButton( - onPressed: () { - _loudOn(); - }, - elevation: 2.0, - fillColor: isLoudSpeaker ? MyColors.green2DColor : Colors.grey, - padding: const EdgeInsets.all( - 15.0, - ), - shape: const CircleBorder(), - child: const Icon( - Icons.volume_up, - color: MyColors.white, - size: 35.0, - ), + shape: const CircleBorder(), + child: Icon( + isCamOff ? Icons.videocam_off : Icons.videocam, + color: MyColors.white, + size: 35.0, ), - ), - RotationTransition( - turns: Tween( - begin: 0.0, - end: -.1, ) - .chain( - CurveTween( - curve: Curves.elasticIn, - ), - ) - .animate( - _animationController!, - ), - child: RawMaterialButton( + else + RawMaterialButton( onPressed: () { - _micOff(); + _loudOn(); }, elevation: 2.0, - fillColor: isMicOff ? MyColors.green2DColor : Colors.grey, + fillColor: isLoudSpeaker ? MyColors.green2DColor : Colors.grey, padding: const EdgeInsets.all( 15.0, ), shape: const CircleBorder(), - child: Icon( - isMicOff ? Icons.mic_off : Icons.mic, + child: const Icon( + Icons.volume_up, color: MyColors.white, size: 35.0, ), ), + RawMaterialButton( + onPressed: () { + _micOff(); + }, + elevation: 2.0, + fillColor: isMicOff ? MyColors.green2DColor : Colors.grey, + padding: const EdgeInsets.all( + 15.0, + ), + shape: const CircleBorder(), + child: Icon( + isMicOff ? Icons.mic_off : Icons.mic, + color: MyColors.white, + size: 35.0, + ), ), RawMaterialButton( onPressed: () { diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 7453603..a6c08c3 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -13,6 +13,7 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/landing/widget/app_drawer.dart'; @@ -515,7 +516,10 @@ class _DashboardScreenState extends State { } else if (index == 3) { Navigator.pushNamed(context, AppRoutes.itemsForSale); } else if (index == 4) { - Navigator.pushNamed(context, AppRoutes.chat); + Navigator.pushNamed(context, AppRoutes.chat).then((Object? value) { + logger.d("Again Api Call"); + data.fetchChatCounts(); + }); } }, ), From 5708c93ae5972c67c2b34513b81c8b5171466009 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 20 Nov 2022 10:20:46 +0300 Subject: [PATCH 73/82] Chat Updates --- lib/ui/landing/dashboard_screen.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index a6c08c3..c568e6f 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -480,9 +480,6 @@ class _DashboardScreenState extends State { ).paddingAll(4), Consumer( builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { - if (data.chatUConvCounter == 0) { - return const SizedBox(); - } return Positioned( right: 0, top: 0, @@ -517,7 +514,6 @@ class _DashboardScreenState extends State { Navigator.pushNamed(context, AppRoutes.itemsForSale); } else if (index == 4) { Navigator.pushNamed(context, AppRoutes.chat).then((Object? value) { - logger.d("Again Api Call"); data.fetchChatCounts(); }); } From 4f88f30368740e8e671a78cda2738b675d060eb9 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 20 Nov 2022 10:26:14 +0300 Subject: [PATCH 74/82] updates --- lib/ui/landing/dashboard_screen.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 165793b..45eea24 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -479,9 +479,9 @@ class _DashboardScreenState extends State { ).paddingAll(4), Consumer( builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { - if (data.chatUConvCounter == 0) { - return const SizedBox(); - } + // if (data.chatUConvCounter == 0) { + // return const SizedBox(); + // } return Positioned( right: 0, top: 0, From 86ac29946fb2fea5ba17ea84d2e763f76064c170 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 20 Nov 2022 12:19:54 +0300 Subject: [PATCH 75/82] Chat Updates & Counter Event Modifications --- lib/api/chat/chat_provider_model.dart | 144 ++++++++++++++++++++------ lib/ui/chat/chat_home.dart | 2 +- lib/ui/chat/chat_home_screen.dart | 42 ++++---- 3 files changed, 134 insertions(+), 54 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 7439b98..2e8bcb8 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -44,7 +44,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool _firstAutoscrollExecuted = false; bool _shouldAutoscroll = false; - Future getUserAutoLoginToken() async { + Future getUserAutoLoginToken(BuildContext cxt) async { Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", { @@ -76,7 +76,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return searchUserJsonModel(response.body); } - List searchUserJsonModel(String str) => List.from(json.decode(str).map((x) => ChatUser.fromJson(x))); + List searchUserJsonModel(String str) => List.from( + json.decode(str).map( + (x) => ChatUser.fromJson(x), + ), + ); void getUserRecentChats() async { Response response = await ApiClient().getJsonForResponse( @@ -90,9 +94,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { token: AppState().chatDetails!.response!.token, ); ChatUserModel favUList = userToList(favRes.body); + GetUserChatHistoryNotDeliveredAsync( + userId: int.parse( + AppState().chatDetails!.response!.id.toString(), + ), + ); if (favUList.response != null) { favUsersList = favUList.response!; - favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); + favUsersList.sort( + (ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo( + b.userName!.toLowerCase(), + ), + ); for (dynamic user in recentChat.response!) { for (dynamic favUser in favUList.response!) { if (user.id == favUser.id) { @@ -101,16 +114,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } } - pChatHistory = recentChat.response == null ? [] : recentChat.response; - if (pChatHistory != null) pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase())); + pChatHistory = recentChat.response ?? []; + pChatHistory!.sort( + (ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo( + b.userName!.toLowerCase(), + ), + ); searchedChats = pChatHistory; isLoading = false; notifyListeners(); } - Future GetUserChatHistoryNotDeliveredAsync(int userId) async { - await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]); + Future GetUserChatHistoryNotDeliveredAsync({required int userId}) async { + await hubConnection.invoke( + "GetUserChatHistoryNotDeliveredAsync", + args: [userId], + ); return ""; } @@ -132,35 +152,89 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } else { if (loadMore) { - List temp = getSingleUserChatModel(response.body).reversed.toList(); - userChatHistory.addAll(temp); + List temp = getSingleUserChatModel( + response.body, + ).reversed.toList(); + userChatHistory.addAll( + temp, + ); } else { - userChatHistory = getSingleUserChatModel(response.body).reversed.toList(); + userChatHistory = getSingleUserChatModel( + response.body, + ).reversed.toList(); } } + await GetUserChatHistoryNotDeliveredAsync( + userId: senderUID, + ); isLoading = false; - await GetUserChatHistoryNotDeliveredAsync(senderUID); notifyListeners(); + markRead( + userChatHistory, + receiverUID, + ); + } + + void markRead(List data, reciverID) { + for (SingleUserChatModel element in data!) { + if (!element.isSeen!) { + dynamic data = [ + { + "userChatHistoryId": element.userChatHistoryId, + "TargetUserId": element.targetUserId, + "isDelivered": true, + "isSeen": true, + } + ]; + updateUserChatHistoryStatusAsync(data); + } + } + for (ChatUser element in searchedChats!) { + if (element.id == reciverID) { + element.unreadMessageCount = 0; + notifyListeners(); + } + } } void updateUserChatHistoryStatusAsync(List data) { - hubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]); + hubConnection.invoke( + "UpdateUserChatHistoryStatusAsync", + args: [data], + ); } - List getSingleUserChatModel(String str) => List.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x))); + List getSingleUserChatModel(String str) => List.from( + json.decode(str).map( + (x) => SingleUserChatModel.fromJson(x), + ), + ); - ChatUserModel userToList(String str) => ChatUserModel.fromJson(json.decode(str)); + ChatUserModel userToList(String str) => ChatUserModel.fromJson( + json.decode(str), + ); Future uploadAttachments(String userId, File file) async { dynamic result; - dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}')); + dynamic request = MultipartRequest( + 'POST', + Uri.parse( + '${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}', + ), + ); request.fields.addAll({'userId': userId, 'fileSource': '1'}); request.files.add(await MultipartFile.fromPath('files', file.path)); - request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'}); + request.headers.addAll( + { + 'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}', + }, + ); try { StreamedResponse response = await request.send(); if (response.statusCode == 200) { - result = jsonDecode(await response.stream.bytesToString()); + result = jsonDecode( + await response.stream.bytesToString(), + ); } else { result = []; } @@ -176,7 +250,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future buildHubConnection() async { HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); hubConnection = HubConnectionBuilder() - .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) + .withUrl( + ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", + options: httpOp, + ) .withAutomaticReconnect( retryDelays: [2000, 5000, 10000, 20000], ) @@ -194,6 +271,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ({String? connectionId}) {}, ); if (hubConnection.state != HubConnectionState.Connected) { + print("Started"); await hubConnection.start(); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); @@ -260,23 +338,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void chatNotDelivered(List? args) { dynamic items = args!.toList(); for (dynamic item in items[0]) { - dynamic data = [ - { - "userChatHistoryId": item["userChatHistoryId"], - "TargetUserId": item["targetUserId"], - "isDelivered": true, - "isSeen": true, + searchedChats!.forEach((element) { + if (element.id == item["currentUserId"]) { + var val = element.unreadMessageCount == null ? 0 : element.unreadMessageCount; + element.unreadMessageCount = val! + 1; } - ]; - updateUserChatHistoryStatusAsync(data); + }); + // dynamic data = [ + // { + // "userChatHistoryId": item["userChatHistoryId"], + // "TargetUserId": item["targetUserId"], + // "isDelivered": true, + // "isSeen": true, + // } + // ]; + // updateUserChatHistoryStatusAsync(data); } - logger.d(items); - // for (var user in searchedChats!) { - // if (user.id == items.first["id"]) { - // user.userStatus = items.first["userStatus"]; - // } - // } - // notifyListeners();2 + notifyListeners(); } void changeStatus(List? args) { diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 9884d59..06a2c32 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -34,7 +34,7 @@ class _ChatHomeState extends State { // TODO: implement initState super.initState(); data = Provider.of(context, listen: false); - data.getUserAutoLoginToken().then((Object? value) { + data.getUserAutoLoginToken(context).then((Object? value) { data.getUserRecentChats(); }); } diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 05623f7..816aaec 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -7,6 +7,7 @@ import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; @@ -134,26 +135,26 @@ class _ChatHomeScreenState extends State { mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.max, children: [ - // if (m.searchedChats![index].unreadMessageCount != null) - // Flexible( - // child: Container( - // padding: EdgeInsets.zero, - // alignment: Alignment.centerRight, - // width: 18, - // height: 18, - // decoration: const BoxDecoration( - // color: MyColors.redColor, - // borderRadius: BorderRadius.all( - // Radius.circular(20), - // ), - // ), - // child: (m.searchedChats![index].unreadMessageCount!.toString()) - // .toText10( - // color: MyColors.white, - // ) - // .center, - // ), - // ), + if (m.searchedChats![index].unreadMessageCount! > 0) + Flexible( + child: Container( + padding: EdgeInsets.zero, + alignment: Alignment.centerRight, + width: 18, + height: 18, + decoration: const BoxDecoration( + color: MyColors.redColor, + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + child: (m.searchedChats![index].unreadMessageCount!.toString()) + .toText10( + color: MyColors.white, + ) + .center, + ), + ), Flexible( child: IconButton( alignment: Alignment.centerRight, @@ -192,6 +193,7 @@ class _ChatHomeScreenState extends State { AppRoutes.chatDetailed, arguments: {"targetUser": m.searchedChats![index], "isNewChat": false}, ).then((Object? value) { + // m.GetUserChatHistoryNotDeliveredAsync(userId: int.parse(AppState().chatDetails!.response!.id.toString())); m.clearSelections(); m.notifyListeners(); }); From ba1a5c66ef76a24acc701b7fe0132d15395bb6d1 Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Sun, 20 Nov 2022 12:34:32 +0300 Subject: [PATCH 76/82] fix issues --- lib/api/my_attendance_api_client.dart | 30 +++++++++++++++---- lib/models/generic_response_model.dart | 4 +-- .../dynamic_screens/dynamic_input_screen.dart | 21 ++++++++----- .../dynamic_listview_screen.dart | 7 +++-- .../services_menu_list_screen.dart | 8 +++-- lib/ui/my_team/create_request.dart | 5 ++-- lib/ui/my_team/team_members.dart | 6 ++-- .../dynamic_input_basic_details_screen.dart | 22 ++++++++++---- .../dynamic_listview_screen.dart | 7 +++-- 9 files changed, 77 insertions(+), 33 deletions(-) diff --git a/lib/api/my_attendance_api_client.dart b/lib/api/my_attendance_api_client.dart index 72d9bcb..c11885c 100644 --- a/lib/api/my_attendance_api_client.dart +++ b/lib/api/my_attendance_api_client.dart @@ -18,47 +18,59 @@ class MyAttendanceApiClient { factory MyAttendanceApiClient() => _instance; - Future?> getEitTransaction(String pFunctionName) async { + Future?> getEitTransaction(String pFunctionName, String? empID) async { String url = "${ApiConsts.erpRest}GET_EIT_TRANSACTIONS"; Map postParams = {"P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1, "P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E", "P_FUNCTION_NAME": pFunctionName}; postParams.addAll(AppState().postParamsJson); + // postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + if('P_SELECTED_EMPLOYEE_NUMBER'.isNotEmpty){ + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + // AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + print(empID); + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.getEITTransactionList ?? []; }, url, postParams); } - Future getEitDffStructure(String pFunctionName) async { + Future getEitDffStructure(String pFunctionName, String? empID) async { String url = "${ApiConsts.erpRest}GET_EIT_DFF_STRUCTURE"; Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E", "P_FUNCTION_NAME": pFunctionName}; postParams.addAll(AppState().postParamsJson); + if('P_SELECTED_EMPLOYEE_NUMBER'.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData; }, url, postParams); } - Future> getValueSetValues(String pSegmentName, String pDescFlexContextCode, String pDescFlexName, List> list) async { + Future> getValueSetValues(String pSegmentName, String pDescFlexContextCode, String pDescFlexName, List> list,{ String? empID, String? parentValue}) async { String url = "${ApiConsts.erpRest}GET_VALUE_SET_VALUES"; Map postParams = { "P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E", "P_PAGE_LIMIT": 1000, "P_PAGE_NUM": 1, - "P_PARENT_VALUE": null, + "P_PARENT_VALUE": empID!.isNotEmpty? parentValue : null, "P_SEGMENT_NAME": pSegmentName, "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, "P_DESC_FLEX_NAME": pDescFlexName, "GetValueSetValuesTBL": list, }; postParams.addAll(AppState().postParamsJson); + if('P_SELECTED_EMPLOYEE_NUMBER'.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.getValueSetValuesList ?? []; }, url, postParams); } - Future getDefaultValue(String pSegmentName, String pDescFlexContextCode, String pDescFlexName, List> list) async { + Future getDefaultValue(String pSegmentName, String pDescFlexContextCode, String pDescFlexName, List> list, String? empID) async { String url = "${ApiConsts.erpRest}GET_DEFAULT_VALUE"; Map postParams = { "P_SELECTED_RESP_ID": -999, @@ -70,13 +82,16 @@ class MyAttendanceApiClient { "GetValueSetValuesTBL": list, }; postParams.addAll(AppState().postParamsJson); + if('P_SELECTED_EMPLOYEE_NUMBER'.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return ESERVICESDV.fromJson(responseData.getDefaultValueList!.toJson()); }, url, postParams); } - Future validateEitTransaction(String pDescFlexContextCode, String pFunctionName, List> list) async { + Future validateEitTransaction(String pDescFlexContextCode, String pFunctionName, List> list, { String? empID}) async { String url = "${ApiConsts.erpRest}VALIDATE_EIT_TRANSACTION"; Map postParams = { "P_SELECTED_RESP_ID": -999, @@ -86,6 +101,9 @@ class MyAttendanceApiClient { "EITTransactionTBL": list, }; postParams.addAll(AppState().postParamsJson); + if('P_SELECTED_EMPLOYEE_NUMBER'.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData; //ESERVICESDV.fromJson(responseData.getDefaultValueList!.toJson()); diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 5cfc4aa..cd7043c 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -334,7 +334,7 @@ class GenericResponseModel { String? sFHGetPrNotificationBodyList; StartAbsenceApprovalProccess? startAbsenceApprovalProccess; StartAddressApprovalProcess? startAddressApprovalProcessList; - String? startBasicDetApprProcessList; + StartAddressApprovalProcess? startBasicDetApprProcessList; String? startCeiApprovalProcess; String? startContactApprovalProcessList; StartEitApprovalProcess? startEitApprovalProcess; @@ -1294,7 +1294,7 @@ class GenericResponseModel { startAbsenceApprovalProccess = json['StartAbsenceApprovalProccess'] != null ? StartAbsenceApprovalProccess.fromJson(json['StartAbsenceApprovalProccess']) : null; startAddressApprovalProcessList = json['StartAddressApprovalProcessList'] != null ? StartAddressApprovalProcess.fromJson(json['StartAddressApprovalProcessList']) : null; - startBasicDetApprProcessList = json['StartBasicDetApprProcessList']; + startBasicDetApprProcessList = json['StartAddressApprovalProcessList'] != null ? StartAddressApprovalProcess.fromJson(json['StartAddressApprovalProcessList']) : null; startCeiApprovalProcess = json['StartCeiApprovalProcess']; startContactApprovalProcessList = json['StartContactApprovalProcessList']; diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 519bb6c..6cda072 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/leave_balance_api_client.dart'; import 'package:mohem_flutter_app/api/my_attendance_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -43,7 +44,8 @@ class _DynamicInputScreenState extends State { void getTransactionsStructure() async { try { Utils.showLoading(context); - genericResponseModel = await MyAttendanceApiClient().getEitDffStructure(dynamicParams!.dynamicId); + + genericResponseModel = await MyAttendanceApiClient().getEitDffStructure(dynamicParams!.dynamicId, dynamicParams!.selectedEmp); dESCFLEXCONTEXTCODE = genericResponseModel!.pDESCFLEXCONTEXTCODE ?? ""; descFlexConTextTitle = genericResponseModel!.pDESCFLEXCONTEXTNAME ?? ""; getEitDffStructureList = genericResponseModel?.getEITDFFStructureList ?? []; @@ -90,7 +92,7 @@ class _DynamicInputScreenState extends State { values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_EXTRA_INFO_ID", nUMBERVALUE: -1, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); - genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); + genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID:dynamicParams!.selectedEmp ??''); SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values); Utils.hideLoading(context); await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, @@ -112,14 +114,14 @@ class _DynamicInputScreenState extends State { Utils.showLoading(context); String segmentId = structureList.cHILDSEGMENTSVS!; if (dESCFLEXCONTEXTCODE.isEmpty) dESCFLEXCONTEXTCODE = structureList.dESCFLEXCONTEXTCODE!; - List filteredList = getEitDffStructureList?.where((element) => element.cHILDSEGMENTSVSSplited!.contains(segmentId)).toList() ?? []; - List> values = filteredList + List> values = filteredList .map((e) => GetSetValuesRequestModel( sEGMENTNAME: e.sEGMENTNAME, vALUECOLUMNNAME: e.eSERVICESDV!.pVALUECOLUMNNAME, dESCRIPTION: "", iDCOLUMNNAME: e.eSERVICESDV!.pIDCOLUMNNAME, fLEXVALUESETNAME: e.fLEXVALUESETNAME) .toJson()) .toList(); - List eServicesResponseModel = await MyAttendanceApiClient().getValueSetValues(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, values); + List eServicesResponseModel = await MyAttendanceApiClient().getValueSetValues(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, + values, empID:dynamicParams!.selectedEmp ??'', parentValue: structureList.eSERVICESDV!.pVALUECOLUMNNAME ); List abc = genericResponseModel?.getEITDFFStructureList ?? []; getEitDffStructureList = abc; int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == structureList.cHILDSEGMENTSVS); @@ -155,7 +157,7 @@ class _DynamicInputScreenState extends State { List> getSetList = getDefaultValuesIonicLogic(parent); if (getSetList.isNotEmpty) { - ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, getSetList); + ESERVICESDV defaultValue = await MyAttendanceApiClient().getDefaultValue(segmentId, structureList.dESCFLEXCONTEXTCODE!, structureList.dESCFLEXNAME!, getSetList, dynamicParams!.selectedEmp); int index = getEitDffStructureList!.indexWhere((element) => element.sEGMENTNAME == segmentId); getEitDffStructureList![index].eSERVICESDV = defaultValue; } @@ -340,7 +342,7 @@ class _DynamicInputScreenState extends State { String? text = data?.pVALUECOLUMNNAME; String? val = data?.pIDCOLUMNNAME; - if ((val ?? "").isEmpty && parentsList[i].IsRequired == "REQUIRED") { + if ((val ?? "").isEmpty && parentsList[i].isRequired == "REQUIRED") { //alert(parentsList[i].Name +" Is required"); return []; } else {} @@ -362,7 +364,7 @@ class _DynamicInputScreenState extends State { String? text = data?.pVALUECOLUMNNAME; String? val = data?.pIDCOLUMNNAME; - if ((val ?? "").isEmpty && parentsList[i].IsRequired == "REQUIRED") { + if ((val ?? "").isEmpty && parentsList[i].isRequired == "REQUIRED") { //alert(parentsList[i].Name +" Is required"); return []; } else {} @@ -392,6 +394,9 @@ class _DynamicInputScreenState extends State { Widget build(BuildContext context) { if (dynamicParams == null) { dynamicParams = ModalRoute.of(context)!.settings.arguments as DynamicListViewParams; + if(dynamicParams!.selectedEmp.isNotEmpty){ + AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams!.selectedEmp; + } getTransactionsStructure(); } return Scaffold( diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index ec52304..5c4053c 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -18,9 +18,11 @@ class DynamicListViewParams { String requestID; String colsURL; bool isUpdate; + List? collectionNotificationList; + final String selectedEmp; - DynamicListViewParams(this.title, this.dynamicId, {this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = '', this.colsURL = '', this.isUpdate = false, this.collectionNotificationList}); + DynamicListViewParams(this.title, this.dynamicId, {this.selectedEmp ='', this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = '', this.colsURL = '', this.isUpdate = false, this.collectionNotificationList}); } class DynamicListViewScreen extends StatefulWidget { @@ -35,6 +37,7 @@ class DynamicListViewScreen extends StatefulWidget { class _DynamicListViewScreenState extends State { List? getEITTransactionList; DynamicListViewParams? dynamicParams; + // String? empId; @override void initState() { @@ -44,7 +47,7 @@ class _DynamicListViewScreenState extends State { void getTransactions() async { try { Utils.showLoading(context); - getEITTransactionList = await MyAttendanceApiClient().getEitTransaction(dynamicParams!.dynamicId); + getEITTransactionList = await MyAttendanceApiClient().getEitTransaction(dynamicParams!.dynamicId, dynamicParams!.selectedEmp); getEITTransactionList?.forEach((element) { element.collectionTransaction = element.collectionTransaction?.where((elemen) => elemen.dISPLAYFLAG == "Y").toList() ?? []; }); diff --git a/lib/ui/my_attendance/services_menu_list_screen.dart b/lib/ui/my_attendance/services_menu_list_screen.dart index c05e035..cd76132 100644 --- a/lib/ui/my_attendance/services_menu_list_screen.dart +++ b/lib/ui/my_attendance/services_menu_list_screen.dart @@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart'; +import 'package:mohem_flutter_app/models/my_team/get_employee_subordinates_list.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; @@ -16,8 +17,9 @@ import 'package:provider/provider.dart'; class ServicesMenuListScreenParams { final String title; final List list; - - ServicesMenuListScreenParams(this.title, this.list); + final String selectedEmp; + GetEmployeeSubordinatesList? getEmployeeSubordinates; + ServicesMenuListScreenParams(this.title, this.list, {this.selectedEmp =''}); } class ServicesMenuListScreen extends StatelessWidget { @@ -56,7 +58,7 @@ class ServicesMenuListScreen extends StatelessWidget { return; } if (servicesMenuData.list[index].requestType == "EIT") { - Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(servicesMenuData.list[index].prompt!, servicesMenuData.list[index].functionName!)); + Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(servicesMenuData.list[index].prompt!, servicesMenuData.list[index].functionName!, selectedEmp: servicesMenuData.selectedEmp)); } else { if (servicesMenuData.list[index].requestType == "TERMINATION") { Navigator.pushNamed(context, AppRoutes.endEmploymentScreen, diff --git a/lib/ui/my_team/create_request.dart b/lib/ui/my_team/create_request.dart index a4c6c83..53205c9 100644 --- a/lib/ui/my_team/create_request.dart +++ b/lib/ui/my_team/create_request.dart @@ -65,13 +65,14 @@ class _CreateRequestState extends State { return menus; } - void handleOnPress(context, Menus menu) { + void handleOnPress(context, Menus menu) { + if (menu.menuEntry.menuEntryType == "FUNCTION") { if (menu.menuEntry.requestType == "EIT") { Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(menu.menuEntry.prompt!, menu.menuEntry.functionName!)); } else {} } else { - Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(menu.menuEntry.prompt!, menu.menuEntiesList)); + Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(menu.menuEntry.prompt!, menu.menuEntiesList, selectedEmp: getEmployeeSubordinates?.eMPLOYEENUMBER??'')); } return; } diff --git a/lib/ui/my_team/team_members.dart b/lib/ui/my_team/team_members.dart index 50bf7e7..e7336bb 100644 --- a/lib/ui/my_team/team_members.dart +++ b/lib/ui/my_team/team_members.dart @@ -14,7 +14,8 @@ import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:url_launcher/url_launcher.dart'; class TeamMembers extends StatefulWidget { - const TeamMembers({Key? key}) : super(key: key); + final String? selectedEmp; + const TeamMembers({this.selectedEmp, Key? key}) : super(key: key); @override _TeamMembersState createState() => _TeamMembersState(); @@ -25,6 +26,7 @@ class _TeamMembersState extends State { String searchEmpName =""; String searchEmpNo = ""; String? empId; + List getEmployeeSubordinatesList = []; GetEmployeeSubordinatesList? getEmployeeSubordinates; @@ -37,7 +39,7 @@ class _TeamMembersState extends State { try { Utils.showLoading(context); getEmployeeSubordinatesList = await MyTeamApiClient().getEmployeeSubordinates(searchEmpEmail.toString(), searchEmpName.toString(), searchEmpNo.toString()); - getEmployeeSubordinatesList = await MyTeamApiClient().employeeSubordinates(searchEmpEmail.toString(), searchEmpName.toString(), searchEmpNo.toString(),getEmployeeSubordinates?.eMPLOYEENUMBER); + // getEmployeeSubordinatesList = await MyTeamApiClient().employeeSubordinates(searchEmpEmail.toString(), searchEmpName.toString(), searchEmpNo.toString(),getEmployeeSubordinates?.eMPLOYEENUMBER); Utils.hideLoading(context); setState(() {}); } catch (ex) { diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_basic_details_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_basic_details_screen.dart index 3127bec..444b83e 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_basic_details_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_basic_details_screen.dart @@ -80,11 +80,23 @@ class _DynamicInputScreenState extends State { } }); } else { - getBasicDetDffStructureList?.forEach((element) { - element.userBasicDetail = new GetEmployeeBasicDetailsList(); + // getBasicDetDffStructureList?.forEach((element) { + // element.userBasicDetail = new GetEmployeeBasicDetailsList(); + // }); + // getBasicDetColsStructureList?.forEach((element) { + // element.userBasicDetail = GetEmployeeBasicDetailsList(); + // }); + getBasicDetDffStructureList?.forEach((GetBasicDetDffStructureList element) { + element.userBasicDetail = + dynamicParams!.getEmployeeBasicDetailsList!.singleWhere((GetEmployeeBasicDetailsList userDetail) => userDetail.aPPLICATIONCOLUMNNAME == element.aPPLICATIONCOLUMNNAME); }); - getBasicDetColsStructureList?.forEach((element) { - element.userBasicDetail = GetEmployeeBasicDetailsList(); + getBasicDetColsStructureList?.forEach((GetBasicDetColsStructureList element) { + element.userBasicDetail = + dynamicParams!.getEmployeeBasicDetailsList!.singleWhere((GetEmployeeBasicDetailsList userDetail) => userDetail.aPPLICATIONCOLUMNNAME == element.aPPLICATIONCOLUMNNAME); + if (element.objectValuesList != null) { + ObjectValuesList dropDownListValue = element.objectValuesList!.singleWhere((ObjectValuesList dropdown) => dropdown.cODE == element.userBasicDetail!.vARCHAR2VALUE); + element.userBasicDetail!.sEGMENTVALUEDSP = dropDownListValue.mEANING; + } }); } @@ -369,7 +381,7 @@ class _DynamicInputScreenState extends State { //values.add(ValidateEitTransactionModel(dATEVALUE: null, nAME: "PEI_OBJECT_VERSION_NUMBER", nUMBERVALUE: 0, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: null).toJson()); List> valuesCols = getBasicDetColsStructureList!.map((e) { if (e.dATATYPE == 'NUMBER') { - numberValue = e.userBasicDetail!.nUMBERVALUE!; + numberValue = e.userBasicDetail!.nUMBERVALUE ?? 0; } return ValidateEitTransactionModel( dATEVALUE: e.userBasicDetail!.dATEVALUE ?? "", nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberValue, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: e.userBasicDetail!.vARCHAR2VALUE ?? "") diff --git a/lib/ui/profile/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_listview_screen.dart index ed35527..dce4662 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_listview_screen.dart @@ -17,7 +17,8 @@ class DynamicListViewParams { String dynamicId; String uRL; String requestID; - DynamicListViewParams(this.title, this.dynamicId, {this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = ''}); + final String selectedEmp; + DynamicListViewParams(this.title, this.dynamicId, {this.selectedEmp ='', this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = ''}); } class DynamicListViewScreen extends StatefulWidget { @@ -38,9 +39,9 @@ class _DynamicListViewScreenState extends State { } void getTransactions() async { - try { + try { Utils.showLoading(context); - getEITTransactionList = await MyAttendanceApiClient().getEitTransaction(dynamicParams!.dynamicId); + getEITTransactionList = await MyAttendanceApiClient().getEitTransaction(dynamicParams!.dynamicId, dynamicParams!.selectedEmp); Utils.hideLoading(context); setState(() {}); } catch (ex) { From fab16db8b3350f58eb67c6db381cc35c4f7033b4 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 20 Nov 2022 15:29:25 +0300 Subject: [PATCH 77/82] Chat Updates & Counter Event Modifications --- lib/api/chat/chat_provider_model.dart | 50 ++++++++++++++------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 2e8bcb8..7dbc0be 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -29,7 +29,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { late HubConnection hubConnection; L.Logger logger = L.Logger(); bool hubConInitialized = false; - + String chatCID = ''; bool isLoading = true; bool isChatScreenActive = false; late File selectedFile; @@ -40,17 +40,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List favUsersList = []; int paginationVal = 0; - //Scroll - bool _firstAutoscrollExecuted = false; - bool _shouldAutoscroll = false; - Future getUserAutoLoginToken(BuildContext cxt) async { Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", { - "employeeNumber": int.parse( + "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - ), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" }, ); @@ -173,6 +168,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { userChatHistory, receiverUID, ); + generateConvId(); + } + + void generateConvId() async { + Uuid uuid = const Uuid(); + chatCID = uuid.v4(); } void markRead(List data, reciverID) { @@ -506,13 +507,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future sendChatToServer( {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async { Uuid uuid = const Uuid(); + var msg = message.text; SingleUserChatModel data = SingleUserChatModel( chatEventId: chatEventId, chatSource: 1, contant: msg, contantNo: uuid.v4(), - conversationId: uuid.v4(), + conversationId: chatCID, createdDate: DateTime.now(), currentUserId: AppState().chatDetails!.response!.id, currentUserName: AppState().chatDetails!.response!.userName, @@ -743,22 +745,22 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { sFileType = ""; } - void scrollListener() { - _firstAutoscrollExecuted = true; - if (scrollController.hasClients && scrollController.position.pixels == scrollController.position.maxScrollExtent) { - _shouldAutoscroll = true; - } else { - _shouldAutoscroll = false; - } - } - - void scrollToBottom() { - scrollController.animateTo( - scrollController.position.maxScrollExtent + 100, - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - ); - } + // void scrollListener() { + // _firstAutoscrollExecuted = true; + // if (scrollController.hasClients && scrollController.position.pixels == scrollController.position.maxScrollExtent) { + // _shouldAutoscroll = true; + // } else { + // _shouldAutoscroll = false; + // } + // } + // + // void scrollToBottom() { + // scrollController.animateTo( + // scrollController.position.maxScrollExtent + 100, + // duration: const Duration(milliseconds: 500), + // curve: Curves.easeIn, + // ); + // } void msgScroll() { scrollController.animateTo( From c1f3f17c89fbe496f16b794986a38db0fad275e8 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 20 Nov 2022 15:32:51 +0300 Subject: [PATCH 78/82] Chat Updates & Counter Event Modifications --- lib/api/chat/chat_provider_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 7dbc0be..ac26c38 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -541,7 +541,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); String chatData = - '{"contant":"$msg","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}'; + '{"contant":"$msg","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"$chatCID"}'; await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); } From 2e88275285242704602d82b3e7e26758cf997f93 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 21 Nov 2022 09:31:53 +0300 Subject: [PATCH 79/82] Chat Updates & Counter Event Modifications --- lib/api/chat/chat_provider_model.dart | 18 +- lib/classes/consts.dart | 4 +- lib/models/chat/call.dart | 226 ++++++++++-------- .../chat/call/chat_incoming_call_screen.dart | 2 +- .../chat/call/chat_outgoing_call_screen.dart | 5 +- lib/ui/chat/chat_detailed_screen.dart | 69 +++--- lib/ui/chat/chat_home.dart | 4 +- 7 files changed, 173 insertions(+), 155 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index ac26c38..868aa7a 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -43,11 +43,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future getUserAutoLoginToken(BuildContext cxt) async { Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", - { - "employeeNumber": - AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" - }, + {"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG"}, ); login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson( response.body, @@ -58,7 +54,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { AppState().setchatUserDetails = userLoginResponse; await buildHubConnection(); } else { - Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); + Utils.showToast( + userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", + ); return; } } @@ -94,7 +92,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { AppState().chatDetails!.response!.id.toString(), ), ); - if (favUList.response != null) { + if (favUList.response != null && recentChat.response != null) { favUsersList = favUList.response!; favUsersList.sort( (ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo( @@ -249,7 +247,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future buildHubConnection() async { - HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); + HttpConnectionOptions httpOp = HttpConnectionOptions( + skipNegotiation: false, + logMessageContent: true, + ); hubConnection = HubConnectionBuilder() .withUrl( ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", @@ -272,7 +273,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ({String? connectionId}) {}, ); if (hubConnection.state != HubConnectionState.Connected) { - print("Started"); await hubConnection.start(); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index ede22e3..c5788f9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local 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/"; diff --git a/lib/models/chat/call.dart b/lib/models/chat/call.dart index eacdd03..20f6a79 100644 --- a/lib/models/chat/call.dart +++ b/lib/models/chat/call.dart @@ -1,117 +1,133 @@ -class IncomingCallData { - String? callerID; - String? receiverID; - String? msgID; - String? notfID; +// To parse this JSON data, do +// +// final callDataModel = callDataModelFromJson(jsonString); + +import 'dart:convert'; + +class CallDataModel { + CallDataModel({ + this.callerId, + this.callReciverId, + this.notificationForeground, + this.message, + this.title, + this.type, + this.identity, + this.name, + this.isCall, + this.isWebrtc, + this.contant, + this.contantNo, + this.chatEventId, + this.fileTypeId, + this.currentUserId, + this.chatSource, + this.userChatHistoryLineRequestList, + this.server, + }); + + String? callerId; + String? callReciverId; String? notificationForeground; - String? count; String? message; - String? appointmentNo; String? title; - String? projectID; - String? notificationType; - String? background; - String? doctorname; - String? clinicname; - String? speciality; - String? appointmentdate; - String? appointmenttime; String? type; - String? sessionId; String? identity; String? name; - String? videoUrl; - String? picture; - String? token; String? isCall; - String? sound; + String? isWebrtc; + String? contant; + String? contantNo; + String? chatEventId; + dynamic? fileTypeId; + String? currentUserId; + String? chatSource; + List? userChatHistoryLineRequestList; String? server; - String? isWebRTC; - IncomingCallData( - {this.msgID, - this.notfID, - this.notificationForeground, - this.count, - this.message, - this.appointmentNo, - this.title, - this.projectID, - this.notificationType, - this.background, - this.doctorname, - this.clinicname, - this.speciality, - this.appointmentdate, - this.appointmenttime, - this.type, - this.sessionId, - this.identity, - this.name, - this.videoUrl, - this.picture, - this.isCall, - this.sound}); + factory CallDataModel.fromRawJson(String str) => CallDataModel.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory CallDataModel.fromJson(Map json) => CallDataModel( + callerId: json["callerID"] == null ? null : json["callerID"], + callReciverId: json["callReciverID"] == null ? null : json["callReciverID"], + notificationForeground: json["notification_foreground"] == null ? null : json["notification_foreground"], + message: json["message"] == null ? null : json["message"], + title: json["title"] == null ? null : json["title"], + type: json["type"] == null ? null : json["type"], + identity: json["identity"] == null ? null : json["identity"], + name: json["name"] == null ? null : json["name"], + isCall: json["is_call"] == null ? null : json["is_call"], + isWebrtc: json["is_webrtc"] == null ? null : json["is_webrtc"], + contant: json["contant"] == null ? null : json["contant"], + contantNo: json["contantNo"] == null ? null : json["contantNo"], + chatEventId: json["chatEventId"] == null ? null : json["chatEventId"], + fileTypeId: json["fileTypeId"], + currentUserId: json["currentUserId"] == null ? null : json["currentUserId"], + chatSource: json["chatSource"] == null ? null : json["chatSource"], + userChatHistoryLineRequestList: json["userChatHistoryLineRequestList"] == null + ? null + : List.from( + json["userChatHistoryLineRequestList"].map( + (x) => UserChatHistoryLineRequestList.fromJson(x), + ), + ), + server: json["server"] == null ? null : json["server"], + ); + + Map toJson() => { + "callerID": callerId == null ? null : callerId, + "callReciverID": callReciverId == null ? null : callReciverId, + "notification_foreground": notificationForeground == null ? null : notificationForeground, + "message": message == null ? null : message, + "title": title == null ? null : title, + "type": type == null ? null : type, + "identity": identity == null ? null : identity, + "name": name == null ? null : name, + "is_call": isCall == null ? null : isCall, + "is_webrtc": isWebrtc == null ? null : isWebrtc, + "contant": contant == null ? null : contant, + "contantNo": contantNo == null ? null : contantNo, + "chatEventId": chatEventId == null ? null : chatEventId, + "fileTypeId": fileTypeId, + "currentUserId": currentUserId == null ? null : currentUserId, + "chatSource": chatSource == null ? null : chatSource, + "userChatHistoryLineRequestList": userChatHistoryLineRequestList == null + ? null + : List.from( + userChatHistoryLineRequestList!.map( + (x) => x.toJson(), + ), + ), + "server": server == null ? null : server, + }; +} + +class UserChatHistoryLineRequestList { + UserChatHistoryLineRequestList({ + this.isSeen, + this.isDelivered, + this.targetUserId, + this.targetUserStatus, + }); + + bool? isSeen; + bool? isDelivered; + int? targetUserId; + int? targetUserStatus; - IncomingCallData.fromJson(Map json) { - callerID = json['callerID']; - receiverID = json['PatientID']; - msgID = json['msgID']; - notfID = json['notfID']; - notificationForeground = json['notification_foreground']; - count = json['count']; - message = json['message']; - appointmentNo = json['AppointmentNo']; - title = json['title']; - projectID = json['ProjectID']; - notificationType = json['NotificationType']; - background = json['background']; - doctorname = json['doctorname']; - clinicname = json['clinicname']; - speciality = json['speciality']; - appointmentdate = json['appointmentdate']; - appointmenttime = json['appointmenttime']; - type = json['type']; - sessionId = json['session_id']; - token = json['token']; - identity = json['identity']; - name = json['name']; - videoUrl = json['videoUrl']; - picture = json['picture']; - isCall = json['is_call']; - sound = json['sound']; - server = json['server']; - isWebRTC = json['is_webrtc'] ?? "true"; - } + factory UserChatHistoryLineRequestList.fromJson(Map json) => UserChatHistoryLineRequestList( + isSeen: json["isSeen"] == null ? null : json["isSeen"], + isDelivered: json["isDelivered"] == null ? null : json["isDelivered"], + targetUserId: json["targetUserId"] == null ? null : json["targetUserId"], + targetUserStatus: json["targetUserStatus"] == null ? null : json["targetUserStatus"], + ); - Map toJson() { - Map data = Map(); - data['msgID'] = this.msgID; - data['notfID'] = this.notfID; - data['notification_foreground'] = this.notificationForeground; - data['count'] = this.count; - data['message'] = this.message; - data['AppointmentNo'] = this.appointmentNo; - data['title'] = this.title; - data['ProjectID'] = this.projectID; - data['NotificationType'] = this.notificationType; - data['background'] = this.background; - data['doctorname'] = this.doctorname; - data['clinicname'] = this.clinicname; - data['speciality'] = this.speciality; - data['appointmentdate'] = this.appointmentdate; - data['appointmenttime'] = this.appointmenttime; - data['type'] = this.type; - data['session_id'] = this.sessionId; - data['token'] = this.token; - data['identity'] = this.identity; - data['name'] = this.name; - data['videoUrl'] = this.videoUrl; - data['picture'] = this.picture; - data['is_call'] = this.isCall; - data['sound'] = this.sound; - data['server'] = this.server; - data['is_webrtc'] = this.isWebRTC; - return data; - } + Map toJson() => { + "isSeen": isSeen == null ? null : isSeen, + "isDelivered": isDelivered == null ? null : isDelivered, + "targetUserId": targetUserId == null ? null : targetUserId, + "targetUserStatus": targetUserStatus == null ? null : targetUserStatus, + }; } diff --git a/lib/ui/chat/call/chat_incoming_call_screen.dart b/lib/ui/chat/call/chat_incoming_call_screen.dart index b98763a..a0b8247 100644 --- a/lib/ui/chat/call/chat_incoming_call_screen.dart +++ b/lib/ui/chat/call/chat_incoming_call_screen.dart @@ -7,7 +7,7 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; class IncomingCall extends StatefulWidget { - IncomingCallData incomingCallData; + CallDataModel incomingCallData; bool? isVideoCall; IncomingCall({Key? key, required this.incomingCallData, this.isVideoCall}) : super(key: key); diff --git a/lib/ui/chat/call/chat_outgoing_call_screen.dart b/lib/ui/chat/call/chat_outgoing_call_screen.dart index 25bc05d..627c24a 100644 --- a/lib/ui/chat/call/chat_outgoing_call_screen.dart +++ b/lib/ui/chat/call/chat_outgoing_call_screen.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:ui'; import 'package:camera/camera.dart'; @@ -7,10 +8,11 @@ import 'package:flutter_svg/flutter_svg.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/main.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; class OutGoingCall extends StatefulWidget { - IncomingCallData OutGoingCallData; + CallDataModel OutGoingCallData; bool? isVideoCall; OutGoingCall({Key? key, required this.OutGoingCallData, this.isVideoCall}) : super(key: key); @@ -36,6 +38,7 @@ class _OutGoingCallState extends State with SingleTickerProviderSt milliseconds: 500, ), ); + logger.d(jsonEncode(widget.OutGoingCallData)); //_runAnimation(); // connectSignaling(); WidgetsBinding.instance.addPostFrameCallback( diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 347c573..4a8e70c 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -10,6 +11,7 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; import 'package:mohem_flutter_app/ui/chat/call/chat_outgoing_call_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart'; @@ -17,6 +19,7 @@ import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; +import 'package:signalr_netcore/signalr_client.dart'; import 'package:swipe_to/swipe_to.dart'; class ChatDetailScreen extends StatefulWidget { @@ -55,13 +58,14 @@ class _ChatDetailScreenState extends State { Widget build(BuildContext context) { userDetails = ModalRoute.of(context)!.settings.arguments; data = Provider.of(context, listen: false); - if (userDetails != null) + if (userDetails != null) { data.getSingleUserChatHistory( senderUID: AppState().chatDetails!.response!.id!.toInt(), receiverUID: userDetails["targetUser"].id, loadMore: false, isNewChat: userDetails["isNewChat"], ); + } return Scaffold( backgroundColor: const Color(0xFFF8F8F8), @@ -72,7 +76,10 @@ class _ChatDetailScreenState extends State { actions: [ IconButton( onPressed: () { - makeCall("AUDIO"); + // makeCall( + // callType: "AUDIO", + // con: data.hubConnection, + // ); }, icon: SvgPicture.asset( "assets/icons/chat/call.svg", @@ -82,7 +89,10 @@ class _ChatDetailScreenState extends State { ), IconButton( onPressed: () { - makeCall("VIDEO"); + // makeCall( + // callType: "VIDEO", + // con: data.hubConnection, + // ); }, icon: SvgPicture.asset( "assets/icons/chat/video_call.svg", @@ -345,45 +355,34 @@ class _ChatDetailScreenState extends State { ); } - void makeCall(String callType) async { - // final server = await SelectionDialog( - // context, - // title: "Select Server", - // items: ["https://livecareturn.hmg.com:8086", "https://104.197.179.1:8086"] - // ).show(); - - Map json = { - "callerID": "9920", - "PatientID": "1231755", - "msgID": "123", - "notfID": "123", + void makeCall({required String callType, required HubConnection con}) async { + print("================== Make call Triggered ============================"); + logger.d(jsonEncode(AppState().chatDetails!.response)); + Map json = { + "callerID": AppState().chatDetails!.response!.id!.toString(), + "callReciverID": userDetails["targetUser"].id.toString(), "notification_foreground": "true", - "count": "1", - "message": "Doctor is calling ", - "AppointmentNo": "123", - "title": "Rayyan Hospital", - "ProjectID": "123", - "NotificationType": "10", - "background": "1", - "doctorname": "Dr Sulaiman Al Habib", - "clinicname": "ENT Clinic", - "speciality": "Speciality", - "appointmentdate": "Sun, 15th Dec, 2019", - "appointmenttime": "09:00", - "type": "video", - "session_id": - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0LTE1OTg3NzQ1MDYiLCJpc3MiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0Iiwic3ViIjoiQUNhYWQ1YTNmOGM2NGZhNjczNTY3NTYxNTc0N2YyNmMyYiIsImV4cCI6MTU5ODc3ODEwNiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiSGFyb29uMSIsInZpZGVvIjp7InJvb20iOiJTbWFsbERhaWx5U3RhbmR1cCJ9fX0.7XUS5uMQQJfkrBZu9EjQ6STL6R7iXkso6BtO1HmrQKk", - "identity": "Haroon1", - "name": "SmallDailyStandup", - "videoUrl": "video", - "picture": "video", + "message": "Aamir is calling ", + "title": "Video Call", + "type": callType == "VIDEO" ? "Video" : "Audio", + "identity": "Aamir.Muhammad", + "name": "Aamir Saleem Ahmad", "is_call": "true", "is_webrtc": "true", + "contant": "Start video Call Aamir.Muhammad", + "contantNo": "775d1f11-62d9-6fcc-91f6-21f8c14559fb", + "chatEventId": "3", + "fileTypeId": null, + "currentUserId": "266642", + "chatSource": "1", + "userChatHistoryLineRequestList": [ + {"isSeen": false, "isDelivered": false, "targetUserId": 341682, "targetUserStatus": 4} + ], // "server": "https://192.168.8.163:8086", "server": "https://livecareturn.hmg.com:8086", }; - IncomingCallData incomingCallData = IncomingCallData.fromJson(json); + CallDataModel incomingCallData = CallDataModel.fromJson(json); await Navigator.push( context, MaterialPageRoute( diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 06a2c32..b2db98a 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -34,18 +34,18 @@ class _ChatHomeState extends State { // TODO: implement initState super.initState(); data = Provider.of(context, listen: false); - data.getUserAutoLoginToken(context).then((Object? value) { + data.getUserAutoLoginToken(context).whenComplete(() { data.getUserRecentChats(); }); } @override void dispose() { + super.dispose(); data.clearAll(); if (data.hubConInitialized) { data.hubConnection.stop(); } - super.dispose(); } @override From 76169e5cb883f81e708ffcf46c18478723a06fd6 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 21 Nov 2022 09:53:27 +0300 Subject: [PATCH 80/82] Chat Updates & Counter Event Modifications --- lib/api/chat/chat_provider_model.dart | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 868aa7a..83827c3 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -87,11 +87,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { token: AppState().chatDetails!.response!.token, ); ChatUserModel favUList = userToList(favRes.body); - GetUserChatHistoryNotDeliveredAsync( - userId: int.parse( - AppState().chatDetails!.response!.id.toString(), - ), - ); + if (favUList.response != null && recentChat.response != null) { favUsersList = favUList.response!; favUsersList.sort( @@ -119,7 +115,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } - Future GetUserChatHistoryNotDeliveredAsync({required int userId}) async { + Future getUserChatHistoryNotDeliveredAsync({required int userId}) async { await hubConnection.invoke( "GetUserChatHistoryNotDeliveredAsync", args: [userId], @@ -157,7 +153,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ).reversed.toList(); } } - await GetUserChatHistoryNotDeliveredAsync( + await getUserChatHistoryNotDeliveredAsync( userId: senderUID, ); isLoading = false; @@ -274,6 +270,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ); if (hubConnection.state != HubConnectionState.Connected) { await hubConnection.start(); + getUserChatHistoryNotDeliveredAsync( + userId: int.parse( + AppState().chatDetails!.response!.id.toString(), + ), + ); hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); // hubConnection.on("OnSeenChatUserAsync", onChatSeen); @@ -565,14 +566,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } if (isFileSelected && !isMsgReply) { Utils.showLoading(context); - logger.d("Normal Attachment Message"); + //logger.d("Normal Attachment Message"); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); Utils.hideLoading(context); sendChatToServer(chatEventId: 2, fileTypeId: getFileType(ext.toString()), targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: true, chatReplyId: null, isReply: false); } if (!isFileSelected && isMsgReply) { - logger.d("Normal Text Message With Reply"); + // logger.d("Normal Text Message With Reply"); if (message.text == null || message.text.isEmpty) { return; } @@ -580,7 +581,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, chatReplyId: repliedMsg.first.userChatHistoryId, isAttachment: false, isReply: true); } if (isFileSelected && isMsgReply) { - logger.d("Attachment Message With Reply"); + // logger.d("Attachment Message With Reply"); Utils.showLoading(context); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); From 32ee7920412f618859eeb67da139bf7db3f30c9e Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 21 Nov 2022 09:54:14 +0300 Subject: [PATCH 81/82] Chat Updates & Counter Event Modifications --- lib/api/chat/chat_provider_model.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 83827c3..69f0fe5 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -573,7 +573,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { sendChatToServer(chatEventId: 2, fileTypeId: getFileType(ext.toString()), targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: true, chatReplyId: null, isReply: false); } if (!isFileSelected && isMsgReply) { - // logger.d("Normal Text Message With Reply"); + // logger.d("Normal Text Message With Reply"); if (message.text == null || message.text.isEmpty) { return; } @@ -581,7 +581,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, chatReplyId: repliedMsg.first.userChatHistoryId, isAttachment: false, isReply: true); } if (isFileSelected && isMsgReply) { - // logger.d("Attachment Message With Reply"); + // logger.d("Attachment Message With Reply"); Utils.showLoading(context); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); String? ext = getFileExtension(selectedFile.path); From ab5de25c8118690f266877b7819f3872f333f578 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 21 Nov 2022 09:56:29 +0300 Subject: [PATCH 82/82] Chat Updates & Counter Event Modifications --- lib/api/chat/chat_provider_model.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index 69f0fe5..7a27c1f 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -43,7 +43,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future getUserAutoLoginToken(BuildContext cxt) async { Response response = await ApiClient().postJsonForResponse( "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin", - {"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG"}, + { + "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", + }, ); login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson( response.body,