From babe36232e850654df13bdc40498f7f5667884e7 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 15 Mar 2023 14:51:03 +0300 Subject: [PATCH 1/7] Image slider fixed --- lib/ui/screens/items_for_sale/item_for_sale_detail.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/ui/screens/items_for_sale/item_for_sale_detail.dart b/lib/ui/screens/items_for_sale/item_for_sale_detail.dart index dec86c0..a853e1a 100644 --- a/lib/ui/screens/items_for_sale/item_for_sale_detail.dart +++ b/lib/ui/screens/items_for_sale/item_for_sale_detail.dart @@ -142,6 +142,7 @@ class _ItemForSaleDetailPageState extends State { } List getItemImages() { + int index = 0; List itemImages = []; getItemsForSaleList.itemAttachments!.forEach((element) { itemImages.add( @@ -150,12 +151,13 @@ class _ItemForSaleDetailPageState extends State { child: ClipRRect( borderRadius: BorderRadius.circular(6), child: Image.network( - getItemsForSaleList.itemAttachments![0].filePath!, + getItemsForSaleList.itemAttachments![index].filePath!, fit: BoxFit.cover, ), ), ), ); + index++; }); return itemImages; } From b1e140fb7570db9059a297da7d01cc57f577d860 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 19 Mar 2023 15:00:38 +0300 Subject: [PATCH 2/7] PR Details implemented --- lib/api/worklist/worklist_api_client.dart | 25 ++ lib/classes/notifications.dart | 27 +- lib/models/generic_response_model.dart | 20 ++ .../get_pr_action_history_list_model.dart | 68 ++++ lib/ui/landing/dashboard_screen.dart | 8 +- lib/ui/work_list/item_history_screen.dart | 327 ++++++++++++++++-- lib/ui/work_list/worklist_detail_screen.dart | 3 - .../attachments_fragment.dart | 1 - .../worklist_fragments/request_fragment.dart | 2 +- 9 files changed, 438 insertions(+), 43 deletions(-) create mode 100644 lib/models/get_pr_action_history_list_model.dart diff --git a/lib/api/worklist/worklist_api_client.dart b/lib/api/worklist/worklist_api_client.dart index 51e5c80..628701f 100644 --- a/lib/api/worklist/worklist_api_client.dart +++ b/lib/api/worklist/worklist_api_client.dart @@ -14,6 +14,7 @@ import 'package:mohem_flutter_app/models/get_mo_notification_body_list_model.dar import 'package:mohem_flutter_app/models/get_notification_buttons_list_model.dart'; import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart'; import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart'; +import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart'; import 'package:mohem_flutter_app/models/get_pr_information_list.dart'; import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart'; @@ -91,6 +92,16 @@ class WorkListApiClient { }, url, postParams); } + Future> getPRAttachments(String pOLineID) async { + String url = "${ApiConsts.erpRest}GET_PR_ATTACHMENTS"; + Map postParams = {"P_PO_LINE_ID": pOLineID}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPRAttachmentList ?? []; + }, url, postParams); + } + 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}; @@ -115,6 +126,20 @@ class WorkListApiClient { }, url, postParams); } + Future> getActionHistoryForPR(String pOLineID) async { + String url = "${ApiConsts.erpRest}GET_PR_ACTION_HISTORY"; + Map postParams = { + "P_PO_LINE_ID": pOLineID, + "P_PAGE_LIMIT": 100, + "P_PAGE_NUM": 1, + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getPRActionHistoryList?.reversed.toList() ?? []; + }, url, postParams); + } + Future> getNotificationButtons(int pNotificationID) async { String url = "${ApiConsts.erpRest}GET_NOTIFICATION_BUTTONS"; Map postParams = {"P_NOTIFICATION_ID": pNotificationID}; diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index e3d7997..9528616 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -4,6 +4,7 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + // import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; import 'package:huawei_push/huawei_push.dart' as huawei_push; import 'package:mohem_flutter_app/app_state/app_state.dart'; @@ -70,18 +71,17 @@ class AppNotifications { if (Platform.isAndroid) { // await hmsApiAvailability.isHMSAvailable().then((value) async { if (!(await Utils.isGoogleServicesAvailable())) { - huawei_push.Push.enableLogger(); - var result = await huawei_push.Push.setAutoInitEnabled(true); + var result = await huawei_push.Push.setAutoInitEnabled(true); - huawei_push.Push.onNotificationOpenedApp.listen((message) { - // newMessage(toFirebaseRemoteMessage(message)); - }, onError: (e) => print(e.toString())); + huawei_push.Push.onNotificationOpenedApp.listen((message) { + // newMessage(toFirebaseRemoteMessage(message)); + }, onError: (e) => print(e.toString())); - huawei_push.Push.onMessageReceivedStream.listen((message) { - // newMessage(toFirebaseRemoteMessage(message)); - }, onError: (e) => print(e.toString())); - } + huawei_push.Push.onMessageReceivedStream.listen((message) { + // newMessage(toFirebaseRemoteMessage(message)); + }, onError: (e) => print(e.toString())); + } // }).catchError((err) { // print(err); // }); @@ -116,8 +116,10 @@ class AppNotifications { } void _handleOpenApp(RemoteMessage message) { - Utils.saveStringFromPrefs("isAppOpendByChat", "true"); - Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); + if (message.data.isNotEmpty && message.data["type"] == 'chat') { + Utils.saveStringFromPrefs("isAppOpendByChat", "true"); + Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); + } } } @@ -131,4 +133,7 @@ Future backgroundMessageHandler(RemoteMessage message) async { await Firebase.initializeApp(); Utils.saveStringFromPrefs("isAppOpendByChat", "false"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); + if (message.data.isNotEmpty && message.data["type"] == 'call') { + // ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message); + } } diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index a5677af..a9006eb 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -28,6 +28,7 @@ import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart'; import 'package:mohem_flutter_app/models/get_notification_buttons_list_model.dart'; import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart'; import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart'; +import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart'; import 'package:mohem_flutter_app/models/get_pr_information_list.dart'; import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart'; @@ -170,9 +171,11 @@ class GenericResponseModel { List? getAbsenceTransactionList; List? getAccrualBalancesList; List? getActionHistoryList; + List? getPRActionHistoryList; List? getAddressDffStructureList; List? getApprovesList; List? getAttachementList; + List? getPRAttachmentList; GetAttendanceTracking? getAttendanceTrackingList; List? getBasicDetColsStructureList; List? getBasicDetDffStructureList; @@ -436,10 +439,12 @@ class GenericResponseModel { this.getAbsenceTransactionList, this.getAccrualBalancesList, this.getActionHistoryList, + this.getPRActionHistoryList, this.getAddressDffStructureList, this.getAddressNotificationBodyList, this.getApprovesList, this.getAttachementList, + this.getPRAttachmentList, this.getAttendanceTrackingList, this.getBasicDetColsStructureList, this.getBasicDetDffStructureList, @@ -751,6 +756,13 @@ class GenericResponseModel { }); } + if (json['PR_Action_History_List'] != null) { + getPRActionHistoryList = []; + json['PR_Action_History_List'].forEach((v) { + getPRActionHistoryList!.add(GetPRActionHistoryList.fromJson(v)); + }); + } + if (json['GetAddressDffStructureList'] != null) { getAddressDffStructureList = []; json['GetAddressDffStructureList'].forEach((v) { @@ -772,6 +784,14 @@ class GenericResponseModel { getAttachementList!.add(GetAttachementList.fromJson(v)); }); } + + if (json['PR_Attachments_List'] != null) { + getPRAttachmentList = []; + json['PR_Attachments_List'].forEach((v) { + getPRAttachmentList!.add(GetAttachementList.fromJson(v)); + }); + } + getAttendanceTrackingList = json["GetAttendanceTrackingList"] == null ? null : GetAttendanceTracking.fromMap(json["GetAttendanceTrackingList"]); if (json['GetBasicDetColsStructureList'] != null) { getBasicDetColsStructureList = []; diff --git a/lib/models/get_pr_action_history_list_model.dart b/lib/models/get_pr_action_history_list_model.dart new file mode 100644 index 0000000..d57668d --- /dev/null +++ b/lib/models/get_pr_action_history_list_model.dart @@ -0,0 +1,68 @@ +class GetPRActionHistoryList { + String? aCTION; + String? aCTIONCODE; + String? aPPROVALDATE; + String? eMAILADDRESS; + String? eMPLOYEEIMAGE; + int? fROMROWNUM; + String? nAME; + String? nOTE; + int? nOOFROWS; + String? pOSITIONTITLE; + int? rOWNUM; + int? sEQUENCE; + int? tOROWNUM; + Null? uSERNAME; + + GetPRActionHistoryList( + {this.aCTION, + this.aCTIONCODE, + this.aPPROVALDATE, + this.eMAILADDRESS, + this.eMPLOYEEIMAGE, + this.fROMROWNUM, + this.nAME, + this.nOTE, + this.nOOFROWS, + this.pOSITIONTITLE, + this.rOWNUM, + this.sEQUENCE, + this.tOROWNUM, + this.uSERNAME}); + + GetPRActionHistoryList.fromJson(Map json) { + aCTION = json['ACTION']; + aCTIONCODE = json['ACTION_CODE']; + aPPROVALDATE = json['APPROVAL_DATE']; + eMAILADDRESS = json['EMAIL_ADDRESS']; + eMPLOYEEIMAGE = json['EMPLOYEE_IMAGE']; + fROMROWNUM = json['FROM_ROW_NUM']; + nAME = json['NAME']; + nOTE = json['NOTE']; + nOOFROWS = json['NO_OF_ROWS']; + pOSITIONTITLE = json['POSITION_TITLE']; + rOWNUM = json['ROW_NUM']; + sEQUENCE = json['SEQUENCE']; + tOROWNUM = json['TO_ROW_NUM']; + uSERNAME = json['USER_NAME']; + } + + Map toJson() { + Map data = new Map(); + data['ACTION'] = this.aCTION; + data['ACTION_CODE'] = this.aCTIONCODE; + data['APPROVAL_DATE'] = this.aPPROVALDATE; + data['EMAIL_ADDRESS'] = this.eMAILADDRESS; + data['EMPLOYEE_IMAGE'] = this.eMPLOYEEIMAGE; + data['FROM_ROW_NUM'] = this.fROMROWNUM; + data['NAME'] = this.nAME; + data['NOTE'] = this.nOTE; + data['NO_OF_ROWS'] = this.nOOFROWS; + data['POSITION_TITLE'] = this.pOSITIONTITLE; + data['ROW_NUM'] = this.rOWNUM; + data['SEQUENCE'] = this.sEQUENCE; + data['TO_ROW_NUM'] = this.tOROWNUM; + data['USER_NAME'] = this.uSERNAME; + return data; + } +} diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 817d4b5..58fc76a 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -26,7 +26,6 @@ import 'package:mohem_flutter_app/ui/landing/widget/services_widget.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_banner.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; -import 'package:mohem_flutter_app/widgets/dialogs/dialogs.dart'; import 'package:mohem_flutter_app/widgets/mark_attendance_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart'; @@ -98,7 +97,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb cProvider.getUserAutoLoginToken().whenComplete(() async { if (!cProvider.disbaleChatForThisUser) { String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); - if (isAppOpendByChat != null && isAppOpendByChat == "true") { + if (isAppOpendByChat != "null" && isAppOpendByChat == "true") { Utils.showLoading(context); cProvider.buildHubConnection(); Future.delayed(const Duration(seconds: 2), () async { @@ -128,6 +127,11 @@ class _DashboardScreenState extends State with WidgetsBindingOb if (chatHubConnection.state == HubConnectionState.Connected) { Utils.hideLoading(context); Navigator.pushNamed(context, AppRoutes.chat); + String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); + if (isAppOpendByChat != "null" || isAppOpendByChat == "true") { + Utils.saveStringFromPrefs("isAppOpendByChat", "false"); + Utils.saveStringFromPrefs("notificationData", "null"); + } } } diff --git a/lib/ui/work_list/item_history_screen.dart b/lib/ui/work_list/item_history_screen.dart index 5aa18b3..7bc39fb 100644 --- a/lib/ui/work_list/item_history_screen.dart +++ b/lib/ui/work_list/item_history_screen.dart @@ -1,16 +1,29 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/get_attachement_list_model.dart'; import 'package:mohem_flutter_app/models/get_mo_Item_history_list_model.dart'; import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart'; +import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart'; import 'package:mohem_flutter_app/models/get_pr_information_list.dart'; import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; +import 'package:open_file/open_file.dart'; +import 'package:path_provider/path_provider.dart'; class ItemHistoryScreenParams { String? title; @@ -21,8 +34,10 @@ class ItemHistoryScreenParams { int? pOrgId; bool isPRInfo; GetPRInformationList? getPRInformationList; + String pOLineID; - ItemHistoryScreenParams({@required this.title, this.isItemHistory = true, this.isMO = true, this.isPRInfo = false, this.getPRInformationList, this.pItemId, this.pPoHeaderId, this.pOrgId}); + ItemHistoryScreenParams( + {@required this.title, this.isItemHistory = true, this.isMO = true, this.isPRInfo = false, this.getPRInformationList, this.pItemId, this.pPoHeaderId, this.pOrgId, this.pOLineID = ""}); } class ItemHistoryScreen extends StatefulWidget { @@ -40,6 +55,9 @@ class _ItemHistoryScreenState extends State { List moItemHistoryList = []; List poItemHistoryList = []; List quotationAnalysisList = []; + List actionHistoryList = []; + List getAttachmentList = []; + int tabIndex = 0; @override void initState() { @@ -49,6 +67,7 @@ class _ItemHistoryScreenState extends State { @override void dispose() { super.dispose(); + actionHistoryList.clear(); } void loadData() { @@ -60,6 +79,34 @@ class _ItemHistoryScreenState extends State { } } + void getActionsDataFromApi() async { + if (actionHistoryList.isEmpty) { + try { + Utils.showLoading(context); + actionHistoryList = await WorkListApiClient().getActionHistoryForPR(_screenParams!.pOLineID); + Utils.hideLoading(context); + setState(() {}); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + } + + void getAttachmentsDataFromApi() async { + if (getAttachmentList.isEmpty) { + try { + Utils.showLoading(context); + getAttachmentList = await WorkListApiClient().getPRAttachments(_screenParams!.pOLineID!); + Utils.hideLoading(context); + setState(() {}); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + } + void getDataFromApi() async { try { Utils.showLoading(context); @@ -88,7 +135,7 @@ class _ItemHistoryScreenState extends State { appBar: AppBarWidget(context, title: _screenParams?.title ?? ""), backgroundColor: Colors.white, body: ListView( - padding: const EdgeInsets.all(21), + padding: _screenParams!.isPRInfo ? const EdgeInsets.all(0) : const EdgeInsets.all(21), physics: const BouncingScrollPhysics(), children: [ if (_screenParams!.isPRInfo) prLinesDataView(), @@ -102,32 +149,232 @@ class _ItemHistoryScreenState extends State { } Widget prLinesDataView() { + return Column( + children: [ + Container( + padding: const EdgeInsets.only(left: 21, right: 21, top: 16, bottom: 16), + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(25), + bottomRight: Radius.circular(25), + ), + gradient: LinearGradient( + transform: GradientRotation(.83), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), + ), + child: Row( + children: [ + myTab(LocaleKeys.info.tr(), 0), + myTab(LocaleKeys.actions.tr(), 1), + myTab(LocaleKeys.attachments.tr(), 2), + ], + ), + ), + if (tabIndex == 0) _screenParams!.getPRInformationList!.pRHeader![0].dESCRIPTION!.toText14().paddingOnly(top: 20, right: 21, left: 21), + if (tabIndex == 0) + ListView.separated( + padding: const EdgeInsets.all(21), + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (cxt, index) => Column( + children: [ + ItemDetailGrid( + ItemDetailViewCol("Cost Center", _screenParams!.getPRInformationList!.pRLines![index].cOSTCENTER ?? ""), + ItemDetailViewCol("Code", _screenParams!.getPRInformationList!.pRLines![index].iTEMCODE ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol("Unit", _screenParams!.getPRInformationList!.pRLines![index].uOM ?? ""), + ItemDetailViewCol("Price (SAR)", _screenParams!.getPRInformationList!.pRLines![index].uNITPRICE.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol("Amount (SAR)", _screenParams!.getPRInformationList!.pRLines![index].lINEAMOUNT.toString() ?? ""), + ItemDetailViewCol("Quantity", _screenParams!.getPRInformationList!.pRLines![index].qUANTITY.toString() ?? ""), + ), + ItemDetailGrid( + ItemDetailViewCol("AMU (Last 3 months)", _screenParams!.getPRInformationList!.pRLines![index].iTEMAMU.toString() ?? ""), + ItemDetailViewCol("PR Number", _screenParams!.getPRInformationList!.pRHeader![0].pRNUMBER!.toString() ?? ""), + isItLast: true, + ), + ], + ).objectContainerView(), + separatorBuilder: (cxt, index) => 12.height, + itemCount: _screenParams!.getPRInformationList!.pRLines!.length), + if (tabIndex == 1) getPRActionsHistory(), //"ACTIONS".toText14().paddingOnly(top: 20, right: 21, left: 21), + if (tabIndex == 2) getPRAttachments(), + ], + ); + } + + String determineFileIcon(String fileContentType) { + String icon = ""; + switch (fileContentType) { + case "pdf": + icon = "assets/images/pdf.svg"; + break; + case "xls": + icon = "assets/images/xls.svg"; + break; + case "xlsx": + icon = "assets/images/xls.svg"; + break; + case "png": + icon = "assets/images/png.svg"; + break; + case "jpg": + icon = "assets/images/jpg.svg"; + break; + case "jpeg": + icon = "assets/images/jpg.svg"; + break; + } + return icon; + } + + Future _createFileFromString(String encodedStr, String ext) async { + Uint8List bytes = base64.decode(encodedStr); + String dir = (await getApplicationDocumentsDirectory()).path; + File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); + await file.writeAsBytes(bytes); + return file.path; + } + + Widget getPRAttachments() { return ListView.separated( + itemCount: getAttachmentList.length, + shrinkWrap: true, + itemBuilder: (context, index) { + return Row( + children: [ + SvgPicture.asset(determineFileIcon(getAttachmentList[index].fILECONTENTTYPE ?? "")), + 12.width, + (getAttachmentList[index].fILENAME ?? "").toText16().expanded, + ], + ).objectContainerView().onPress(() async { + try { + String path = await _createFileFromString(getAttachmentList[index].fILEDATA ?? "", getAttachmentList[index].fILECONTENTTYPE ?? ""); + OpenFile.open(path); + } catch (ex) { + Utils.showToast("Cannot open file."); + } + }); + }, + separatorBuilder: (BuildContext context, int index) => 12.height, + ).paddingAll(21); + } + + Widget getPRActionsHistory() { + return SingleChildScrollView( + child: ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemBuilder: (cxt, index) => Column( - children: [ - ItemDetailGrid( - ItemDetailViewCol("Cost Center", _screenParams!.getPRInformationList!.pRLines![index].cOSTCENTER ?? ""), - ItemDetailViewCol("Code", _screenParams!.getPRInformationList!.pRLines![index].iTEMCODE ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol("Unit", _screenParams!.getPRInformationList!.pRLines![index].uOM ?? ""), - ItemDetailViewCol("Price (SAR)", _screenParams!.getPRInformationList!.pRLines![index].uNITPRICE.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol("Amount (SAR)", _screenParams!.getPRInformationList!.pRLines![index].lINEAMOUNT.toString() ?? ""), - ItemDetailViewCol("Quantity", _screenParams!.getPRInformationList!.pRLines![index].qUANTITY.toString() ?? ""), - ), - ItemDetailGrid( - ItemDetailViewCol("AMU (Last 3 months)", _screenParams!.getPRInformationList!.pRLines![index].iTEMAMU.toString() ?? ""), - Container(), - isItLast: true, - ), - ], - ).objectContainerView(), - separatorBuilder: (cxt, index) => 12.height, - itemCount: _screenParams!.getPRInformationList!.pRLines!.length); + itemCount: actionHistoryList.length, + padding: EdgeInsets.all(21), + itemBuilder: (context, index) { + return showItem(context, actionHistoryList[index], index); + }, + separatorBuilder: (BuildContext context, int index) { + return 12.height; + }, + ), + ); + } + + Widget showItem(BuildContext context, GetPRActionHistoryList actionHistory, int index) { + return Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: const Color(0xff000000).withOpacity(.05), + blurRadius: 26, + offset: const Offset(0, -3), + ), + ], + ), + clipBehavior: Clip.antiAlias, + child: Stack( + clipBehavior: Clip.antiAlias, + children: [ + Positioned( + left: -20, + top: -10, + child: Transform.rotate( + angle: 15, + child: Container( + width: 50, + height: 30, + color: getStatusColor(actionHistory.aCTIONCODE!), + ), + ), + ), + Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + actionHistory.eMPLOYEEIMAGE != null + ? CircularAvatar(url: actionHistory.eMPLOYEEIMAGE ?? "", isImageBase64: true, height: 34, width: 34) + : CircularAvatar(url: "https://cdn4.iconfinder.com/data/icons/professions-2-2/151/89-512.png", isImageBase64: false, height: 34, width: 34), + 9.width, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + actionHistory.nAME!.toText16(), + if ((actionHistory.nOTE ?? "").isNotEmpty) "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color), + 4.height, + Row( + children: [ + actionHistory.aCTION!.toText10(color: getStatusColor(actionHistory.aCTIONCODE!)), + 8.width, + if (actionHistory.aPPROVALDATE!.isNotEmpty) + DateUtil.formatDateToDate(DateUtil.convertSimpleStringDateToDateddMMyyyy(actionHistory.aPPROVALDATE!), false).toText12(color: MyColors.lightTextColor), + ], + ), + 10.height, + // getActionDuration(index).toText11(maxLine: 1, color: const Color(0xff1FA269)) + ], + ), + ) + ], + ).paddingOnly(top: 19, left: 16, right: 16, bottom: 12), + ], + ), + ], + ), + ); + } + + Color getStatusColor(String code) { + if (code == "SUBMIT") { + return const Color(0xff2E303A); + } else if (code == "REJECTED") { + return MyColors.redColor; + } else if (code == "REJECT") { + return MyColors.redColor; + } else if (code == "PENDING") { + return MyColors.orange; + } else if (code == "APPROVED" || code == "APPROVE" || code == "ANSWER_INFO") { + return const Color(0xff1FA269); + } else if (code == "REQUEST_INFO" || code == "FORWARD") { + return const Color(0xff2E303A); + } else if (code != "SUBMIT" && code != "REJECT" && code != "PENDING") { + return MyColors.orange; + } else { + return const Color(0xff2E303A); + } + } + + Widget getActionHistory() { + return Container(); } Widget loadMoItemHistoryData() { @@ -266,4 +513,34 @@ class _ItemHistoryScreenState extends State { separatorBuilder: (cxt, index) => 12.height, itemCount: quotationAnalysisList.length); } + + Widget myTab(String title, int index) { + bool isSelected = (index == tabIndex); + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + title.toText12(color: isSelected ? Colors.white : Colors.white.withOpacity(.74), isCenter: true), + 4.height, + Container( + height: 8, + width: 8, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: isSelected ? Colors.white : Colors.transparent, + ), + ) + ], + ).onPress(() { + setState(() { + if (index == 1) { + getActionsDataFromApi(); + } + if (index == 2) { + getAttachmentsDataFromApi(); + } + tabIndex = index; + }); + }).expanded; + } } diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 1558063..0a4f8cc 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -148,9 +148,6 @@ class _WorkListDetailScreenState extends State { } else if (workListData!.rEQUESTTYPE == "ADDRESS") { getAddressNotificationBody(); } - // getBasicNTFBody = await WorkListApiClient().getBasicDetNTFBody(workListData!.nOTIFICATIONID!, -999); - // getAbsenceCollectionNotifications = await WorkListApiClient().getAbsenceNotificationBody(workListData!.nOTIFICATIONID!, -999); - // subordinatesLeavesModel = await WorkListApiClient().getSubordinatesLeaves("", ""); } if (workListData!.iTEMTYPE == "STAMP") { getStampNotificationBody(); diff --git a/lib/ui/work_list/worklist_fragments/attachments_fragment.dart b/lib/ui/work_list/worklist_fragments/attachments_fragment.dart index b351683..bc1bde6 100644 --- a/lib/ui/work_list/worklist_fragments/attachments_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/attachments_fragment.dart @@ -22,7 +22,6 @@ class AttachmentsFragment extends StatelessWidget { return ListView.separated( itemCount: getAttachmentList.length, itemBuilder: (context, index) { - return Row( children: [ SvgPicture.asset(determineFileIcon(getAttachmentList[index].fILECONTENTTYPE ?? "")), diff --git a/lib/ui/work_list/worklist_fragments/request_fragment.dart b/lib/ui/work_list/worklist_fragments/request_fragment.dart index 5a77597..b2bc0b6 100644 --- a/lib/ui/work_list/worklist_fragments/request_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/request_fragment.dart @@ -294,7 +294,7 @@ class RequestFragment extends StatelessWidget { context, AppRoutes.itemHistory, arguments: ItemHistoryScreenParams( - isItemHistory: false, isMO: false, isPRInfo: true, getPRInformationList: getPRInformationList, title: "PR Details", pItemId: 0, pPoHeaderId: 0), + isItemHistory: false, isMO: false, isPRInfo: true, getPRInformationList: getPRInformationList, title: "PR Details", pItemId: 0, pPoHeaderId: 0, pOLineID: poLineID), ); } catch (ex) { Utils.hideLoading(context); From 6e35a6f9cc33c73d39dd3e4c51f0f5079260dede Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 21 Mar 2023 12:02:42 +0300 Subject: [PATCH 3/7] Confirm dialog in worklist fixed --- .../work_list/sheets/selected_item_sheet.dart | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/lib/ui/work_list/sheets/selected_item_sheet.dart b/lib/ui/work_list/sheets/selected_item_sheet.dart index 424aa4c..85395a6 100644 --- a/lib/ui/work_list/sheets/selected_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_item_sheet.dart @@ -6,7 +6,6 @@ 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'; @@ -144,26 +143,30 @@ class SelectedItemSheet extends StatelessWidget { forwardToUser = filtered.first; } - showDialog( - context: context, - builder: (cxt) => AcceptRejectInputDialog( - message: title != null ? null : LocaleKeys.requestedItems.tr(), - // title: title, - notificationGetRespond: notificationNoteInput, - actionMode: apiMode, - onTap: (note) { - performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: [ - if ((apiMode == "FORWARD" || apiMode == "APPROVE_AND_FORWARD") && forwardToUser != null) - {"ATTRIBUTE_NAME": "FORWARD_TO_USERNAME_RESPONSE", "ATTRIBUTE_TEXT_VALUE": actionHistoryList?.uSERNAME}, - if (notificationNoteInput != null) - { - "ATTRIBUTE_NAME": notificationNoteInput.attributeName, - if (notificationNoteInput.attributeType == "number") "ATTRIBUTE_NUMBER_VALUE": note else if (notificationNoteInput.attributeType == "VARCHAR2") "ATTRIBUTE_TEXT_VALUE": note - } - ]); - }, - ), - ); + if (notificationNoteInput == null) { + performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: []); + } else { + showDialog( + context: context, + builder: (cxt) => AcceptRejectInputDialog( + message: title != null ? null : LocaleKeys.requestedItems.tr(), + // title: title, + notificationGetRespond: notificationNoteInput, + actionMode: apiMode, + onTap: (note) { + performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: [ + if ((apiMode == "FORWARD" || apiMode == "APPROVE_AND_FORWARD") && forwardToUser != null) + {"ATTRIBUTE_NAME": "FORWARD_TO_USERNAME_RESPONSE", "ATTRIBUTE_TEXT_VALUE": actionHistoryList?.uSERNAME}, + if (notificationNoteInput != null) + { + "ATTRIBUTE_NAME": notificationNoteInput.attributeName, + if (notificationNoteInput.attributeType == "number") "ATTRIBUTE_NUMBER_VALUE": note else if (notificationNoteInput.attributeType == "VARCHAR2") "ATTRIBUTE_TEXT_VALUE": note + } + ]); + }, + ), + ); + } } void getUserInformation(BuildContext context) async { From 571b8bd7af9a2e62517a1c588e38751d0bad5133 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 21 Mar 2023 12:04:19 +0300 Subject: [PATCH 4/7] itg active directory password change added. --- assets/langs/ar-SA.json | 5 +- assets/langs/en-US.json | 17 +- lib/api/login_api_client.dart | 11 ++ lib/classes/consts.dart | 1 + lib/config/routes.dart | 4 +- lib/generated/codegen_loader.g.dart | 10 +- lib/generated/locale_keys.g.dart | 3 + lib/provider/dashboard_provider_model.dart | 25 ++- .../itg/change_itg_ad_password_screen.dart | 166 ++++++++++++++++++ .../services_menu_list_screen.dart | 3 + 10 files changed, 231 insertions(+), 14 deletions(-) create mode 100644 lib/ui/landing/itg/change_itg_ad_password_screen.dart diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 6b4dca7..4b7acc9 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -43,6 +43,7 @@ "newString": "جديد", "setTheNewPassword": "قم بتعيين كلمة المرور الجديدة", "typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه", + "typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه", "confirmPassword": "تأكيد كلمة المرور", "update": "تحديث", "title": "عنوان", @@ -527,5 +528,7 @@ "myTeam": "فريقي", "youCanPlayDemo": "لكن يمكنك لعب العرض", "connectHmgWifi": "قم بتوصيل HMG WIFI", - "connectedHmgWifi": "اتصال HMG WIFI" + "connectedHmgWifi": "اتصال HMG WIFI", + "itgForms": "نماذج (ITG)", + "resetAdPassword": "إعادة تعيين كلمة مرور AD" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 3aa2705..3f460a1 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -43,6 +43,7 @@ "newString": "New", "setTheNewPassword": "Set the new password", "typeYourNewPasswordBelow": "Type your new password below", + "typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below", "confirmPassword": "Confirm Password", "update": "Update", "title": "Title", @@ -425,7 +426,7 @@ "typeCurrentPasswordBelow": "Type Your Current password below", "currentPassword": "Current password", "concurrentReports": "Concurrent Reports", - "EnterNewAddressMoved" : "Enter a new address if you have moved", + "EnterNewAddressMoved": "Enter a new address if you have moved", "CorrectAddress": "Correct or amend this address", "SelectChangeWantToMake": "Select the type of change you want to make", "profile": { @@ -470,7 +471,7 @@ "gameTime": "Game Time:", "joinMarathon": "Join Marathon", "joinDemoMarathon": "Join Demo Marathon", - "demo":"Demo", + "demo": "Demo", "minutes": "Minutes", "seconds": "Seconds", "note": "Note:", @@ -518,14 +519,16 @@ "startingIn": "Starting in", "youAreOutOfContest": "You are out of the contest.", "winners": "WINNERS!!!", - "expireAfter":"Expires After", - "oneWeek":"1 Week", - "twoWeek":"2 Week", + "expireAfter": "Expires After", + "oneWeek": "1 Week", + "twoWeek": "2 Week", "noUpcoming": "There is no upcoming", "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", "noWinner": "Sad! No one won today.", - "myTeam" : "My Team", + "myTeam": "My Team", "youCanPlayDemo": "But you can play demo", "connectHmgWifi": "Connect HMG WIFI", - "connectedHmgWifi": "Connected HMG WIFI" + "connectedHmgWifi": "Connected HMG WIFI", + "itgForms": "ITG Forms", + "resetAdPassword": "Reset AD Password" } \ No newline at end of file diff --git a/lib/api/login_api_client.dart b/lib/api/login_api_client.dart index 7da7754..1b6b19e 100644 --- a/lib/api/login_api_client.dart +++ b/lib/api/login_api_client.dart @@ -145,4 +145,15 @@ class LoginApiClient { return responseData; }, url, postParams); } + + Future changePasswordFromActiveDirectorySession(String password, String email) async { + String url = "${ApiConsts.authenticationRest}SetPassword"; + Map postParams = {"EmailAddress": email, "Password": password, "generalid": "Cs2020@2016\$2958"}; + postParams.addAll(AppState().postParamsJson); + postParams["LogInTokenID"] = "@acT!V3D!r3Ct0rY"; // hard code token for active directory + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, url, postParams); + } } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 4d3025e..32b3fc7 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -8,6 +8,7 @@ class ApiConsts { static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; + static String authenticationRest = baseUrlServices + "Authentication.svc/REST/"; static String erpRest = baseUrlServices + "ERP.svc/REST/"; static String swpRest = baseUrlServices + "SWP.svc/REST/"; static String user = baseUrlServices + "api/User/"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 947bbcd..7ccb6ce 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_home.dart'; import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; +import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen2.dart'; @@ -177,6 +178,7 @@ class AppRoutes { static const String subordinateLeave = "/subordinateLeave"; static const String changePassword = "/changePassword"; + static const String changeItgAdPasswordScreen = "/changeItgAdPasswordScreen"; //Chat static const String chat = "/chat"; @@ -289,7 +291,7 @@ class AppRoutes { subordinateLeave: (BuildContext context) => SubordinateLeave(), changePassword: (BuildContext context) => ChangePasswordScreen(), - + changeItgAdPasswordScreen: (BuildContext context) => ChangeItgAdPasswordScreen(), //Chat chat: (BuildContext context) => ChatHome(), chatDetailed: (BuildContext context) => ChatDetailScreen(), diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 6a9040d..ba21c29 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -59,6 +59,7 @@ class CodegenLoader extends AssetLoader{ "newString": "جديد", "setTheNewPassword": "قم بتعيين كلمة المرور الجديدة", "typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه", + "typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه", "confirmPassword": "تأكيد كلمة المرور", "update": "تحديث", "title": "عنوان", @@ -543,7 +544,9 @@ class CodegenLoader extends AssetLoader{ "myTeam": "فريقي", "youCanPlayDemo": "لكن يمكنك لعب العرض", "connectHmgWifi": "قم بتوصيل HMG WIFI", - "connectedHmgWifi": "اتصال HMG WIFI" + "connectedHmgWifi": "اتصال HMG WIFI", + "itgForms": "نماذج (ITG)", + "resetAdPassword": "إعادة تعيين كلمة مرور AD" }; static const Map en_US = { "mohemm": "Mohemm", @@ -590,6 +593,7 @@ static const Map en_US = { "newString": "New", "setTheNewPassword": "Set the new password", "typeYourNewPasswordBelow": "Type your new password below", + "typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below", "confirmPassword": "Confirm Password", "update": "Update", "title": "Title", @@ -1074,7 +1078,9 @@ static const Map en_US = { "myTeam": "My Team", "youCanPlayDemo": "But you can play demo", "connectHmgWifi": "Connect HMG WIFI", - "connectedHmgWifi": "Connected HMG WIFI" + "connectedHmgWifi": "Connected HMG WIFI", + "itgForms": "ITG Forms", + "resetAdPassword": "Reset AD Password" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 0e87cb4..343bf38 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -44,6 +44,7 @@ abstract class LocaleKeys { static const newString = 'newString'; static const setTheNewPassword = 'setTheNewPassword'; static const typeYourNewPasswordBelow = 'typeYourNewPasswordBelow'; + static const typeYourNewActiveDirectoryPasswordBelow = 'typeYourNewActiveDirectoryPasswordBelow'; static const confirmPassword = 'confirmPassword'; static const update = 'update'; static const title = 'title'; @@ -514,5 +515,7 @@ abstract class LocaleKeys { static const youCanPlayDemo = 'youCanPlayDemo'; static const connectHmgWifi = 'connectHmgWifi'; static const connectedHmgWifi = 'connectedHmgWifi'; + static const itgForms = 'itgForms'; + static const resetAdPassword = 'resetAdPassword'; } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index d0f33df..0e18544 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -66,7 +66,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (attendanceTracking?.pSwipeIn != null) { isTimeRemainingInSeconds = calculateSeconds(attendanceTracking!.pRemainingHours ?? "00:00:00"); int totalShiftTimeInSeconds = calculateSeconds(attendanceTracking!.pScheduledHours ?? "00:00:00"); - if(isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) { + if (isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) { progress = 0; } else { progress = (isTimeRemainingInSeconds / totalShiftTimeInSeconds); @@ -245,7 +245,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - void getCategoryOffersListAPI(BuildContext context) async { + void getCategoryOffersListAPI(BuildContext context) async { try { // Utils.showLoading(context); getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 10); @@ -262,7 +262,25 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List menus = []; for (int i = 0; i < getMenuEntriesList.length; i++) { if (getMenuEntriesList[i].parentMenuName!.isEmpty) { - menus.add(Menus(getMenuEntriesList[i], getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList())); + GetMenuEntriesList abc = GetMenuEntriesList(requestType: "itg_forms", prompt: LocaleKeys.itgForms.tr()); + List list = getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList(); + + if (getMenuEntriesList[i].menuName == "MBL_E_PROFESSIONALS_01") { + // hard coding this check to add change password for Active Directory + + GetMenuEntriesList activeDirectoryEntry = GetMenuEntriesList( + requestType: "RESET_ITG_AD_PASSWORD", + prompt: LocaleKeys.resetAdPassword.tr(), + parentMenuName: 'ITG_FORMS', + menuName: LocaleKeys.itgForms.tr(), + menuEntryType: "FUNCTION", //Reset AD Password + ); + getMenuEntriesList.add(activeDirectoryEntry); + + list.add(GetMenuEntriesList(requestType: "ITG_FORMS", prompt: LocaleKeys.itgForms.tr(), menuName: 'ITG_FORMS')); + } + + menus.add(Menus(getMenuEntriesList[i], list)); } } return menus; @@ -272,6 +290,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification(); return res; } + void notify() { notifyListeners(); } diff --git a/lib/ui/landing/itg/change_itg_ad_password_screen.dart b/lib/ui/landing/itg/change_itg_ad_password_screen.dart new file mode 100644 index 0000000..cc84f96 --- /dev/null +++ b/lib/ui/landing/itg/change_itg_ad_password_screen.dart @@ -0,0 +1,166 @@ +import 'package:easy_localization/src/public_ext.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/login_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/generic_response_model.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/input_widget.dart'; + +class ChangeItgAdPasswordScreen extends StatefulWidget { + ChangeItgAdPasswordScreen({Key? key}) : super(key: key); + + @override + _ChangeItgAdPasswordScreenState createState() { + return _ChangeItgAdPasswordScreenState(); + } +} + +class _ChangeItgAdPasswordScreenState extends State { + TextEditingController password = TextEditingController(); + TextEditingController confirmPassword = TextEditingController(); + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + void setNewPassword() async { + Utils.showLoading(context); + try { + GenericResponseModel response = await LoginApiClient().changePasswordFromActiveDirectorySession(password.text, AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!); + Utils.hideLoading(context); + if ((response.messageStatus ?? 0) == 1) { + Utils.showToast(LocaleKeys.passwordChangedSuccessfully.tr()); + Navigator.pop(context); + } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, (msg) { + Utils.confirmDialog(context, msg); + }); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), + onPressed: () => Navigator.pop(context), + ), + ), + body: Column( + children: [ + ListView( + padding: const EdgeInsets.all(21), + children: [ + LocaleKeys.changePassword.tr().toText24(isBold: true), + LocaleKeys.typeYourNewActiveDirectoryPasswordBelow.tr().toText16(), + 16.height, + InputWidget( + LocaleKeys.password.tr(), + "**********", + password, + onChange: (value) { + setState(() {}); + }, + ), + 12.height, + InputWidget( + LocaleKeys.confirmPassword.tr(), + "**********", + confirmPassword, + isTextIsPassword: true, + onChange: (value) { + setState(() {}); + }, + ), + 16.height, + passwordConstraintsUI(LocaleKeys.doNotUseRecentPassword.tr(), true), + 8.height, + passwordConstraintsUI(LocaleKeys.atLeastOneLowercase.tr(), checkRegEx(r'[a-z]')), + // 8.height, + // passwordConstraintsUI(LocaleKeys.atLeastOneUppercase.tr(), checkRegEx(r'[A-Z]')), + 8.height, + passwordConstraintsUI(LocaleKeys.atLeastOneNumeric.tr(), checkRegEx(r'[0-9]')), + 8.height, + passwordConstraintsUI(LocaleKeys.minimum8Characters.tr(), password.text.length >= 8), + 8.height, + passwordConstraintsUI(LocaleKeys.doNotAddRepeatingLetters.tr(), checkRepeatedChars(password.text)), + // 8.height, + // passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')), + 8.height, + passwordConstraintsUI(LocaleKeys.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text), + ], + ).expanded, + DefaultButton(LocaleKeys.changePassword.tr(), (!isPasswordCompliant(password.text, 8)) ? null : setNewPassword).insideContainer + ], + ), + ); + } + + bool checkRegEx(String pattern) { + return RegExp(pattern).hasMatch(password.text); + } + + String recentPassword = ""; + + bool isPasswordCompliant(String? password, int minLength) { + if (password == null || password.isEmpty) { + return false; + } + + // bool hasUppercase = password.contains(RegExp(r'[A-Z]')); + bool hasDigits = password.contains(RegExp(r'[0-9]')); + bool hasLowercase = password.contains(RegExp(r'[a-z]')); + // bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]')); + bool hasMinLength = password.length >= minLength; + bool isMatched = password == confirmPassword.text; + + return hasDigits && hasLowercase && hasMinLength && isMatched && checkRepeatedChars(password); + } + + bool checkRepeatedChars(String password) { + bool isNonRepeatedLetters = true; + if (password.length > 2) { + for (int i = 0; i < password.length; i++) { + String char = password[i]; + try { + if (char == password[i + 1]) { + isNonRepeatedLetters = false; + break; + } + } catch (ex) {} + } + } + return isNonRepeatedLetters; + } + + Widget passwordConstraintsUI(String description, bool check) { + return Row( + children: [ + 4.width, + SizedBox( + width: 12, + height: 12, + child: Checkbox(fillColor: MaterialStateProperty.all(MyColors.gradiantEndColor), shape: const CircleBorder(), value: check, onChanged: null), + ), + 8.width, + description.toText14() + ], + ); + } +} diff --git a/lib/ui/my_attendance/services_menu_list_screen.dart b/lib/ui/my_attendance/services_menu_list_screen.dart index 8e44324..44aac6a 100644 --- a/lib/ui/my_attendance/services_menu_list_screen.dart +++ b/lib/ui/my_attendance/services_menu_list_screen.dart @@ -57,6 +57,9 @@ class ServicesMenuListScreen extends StatelessWidget { } else if (servicesMenuData.list[index].requestType == "ABSENCE") { Navigator.pushNamed(context, AppRoutes.leaveBalance, arguments: servicesMenuData.selectedEmp); return; + } else if (servicesMenuData.list[index].requestType == "RESET_ITG_AD_PASSWORD") { + Navigator.pushNamed(context, AppRoutes.changeItgAdPasswordScreen); + return; } if (servicesMenuData.list[index].requestType == "EIT") { Navigator.pushNamed(context, AppRoutes.dynamicScreen, From 1dca3076d927615cba8ad51c6b7c6ed5db93ce0f Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 4 Apr 2023 15:51:08 +0300 Subject: [PATCH 5/7] Survey dynamic questions --- lib/app_state/app_state.dart | 2 +- lib/models/itg/itg_response_model.dart | 5 +- lib/models/itg/survey_model.dart | 148 +++++++++ lib/ui/landing/dashboard_screen.dart | 15 +- lib/ui/landing/itg/survey_screen.dart | 310 +++++++++++++----- lib/ui/work_list/item_history_screen.dart | 13 +- .../worklist_fragments/actions_fragment.dart | 15 +- lib/widgets/mark_attendance_widget.dart | 27 +- 8 files changed, 444 insertions(+), 91 deletions(-) create mode 100644 lib/models/itg/survey_model.dart diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 293afbb..7ccdd4f 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -90,7 +90,7 @@ class AppState { String get getHuaweiPushToken => _huaweiPushToken; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.5, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.8, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/models/itg/itg_response_model.dart b/lib/models/itg/itg_response_model.dart index 4dff106..dff7869 100644 --- a/lib/models/itg/itg_response_model.dart +++ b/lib/models/itg/itg_response_model.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:mohem_flutter_app/models/itg/advertisement.dart'; +import 'package:mohem_flutter_app/models/itg/survey_model.dart'; MohemmItgResponseItem mohemmItgResponseItemFromJson(String str) => MohemmItgResponseItem.fromJson(json.decode(str)); @@ -103,7 +104,7 @@ class ItgResponseData { final bool? isDeleted; final bool? showDelete; final Advertisement? advertisement; - final dynamic survey; + final SurveyModel? survey; final dynamic isActive; final dynamic pageSize; final dynamic pageNo; @@ -126,7 +127,7 @@ class ItgResponseData { isDeleted: json["isDeleted"] == null ? null : json["isDeleted"], showDelete: json["showDelete"] == null ? null : json["showDelete"], advertisement: json["advertisement"] == null ? null : Advertisement.fromJson(json["advertisement"]), - survey: json["survey"], + survey: json["survey"] == null ? null : SurveyModel.fromJson(json["survey"]), isActive: json["isActive"], pageSize: json["pageSize"], pageNo: json["pageNo"], diff --git a/lib/models/itg/survey_model.dart b/lib/models/itg/survey_model.dart new file mode 100644 index 0000000..7cdbbdd --- /dev/null +++ b/lib/models/itg/survey_model.dart @@ -0,0 +1,148 @@ +class SurveyModel { + int? surveyId; + String? referenceNo; + String? title; + String? description; + List? questions; + bool? isActive; + Null? pageSize; + Null? pageNo; + Null? languageId; + + SurveyModel({this.surveyId, this.referenceNo, this.title, this.description, this.questions, this.isActive, this.pageSize, this.pageNo, this.languageId}); + + SurveyModel.fromJson(Map json) { + surveyId = json['surveyId']; + referenceNo = json['referenceNo']; + title = json['title']; + description = json['description']; + if (json['questions'] != null) { + questions = []; + json['questions'].forEach((v) { + questions!.add(new Questions.fromJson(v)); + }); + } + isActive = json['isActive']; + pageSize = json['pageSize']; + pageNo = json['pageNo']; + languageId = json['languageId']; + } + + Map toJson() { + Map data = new Map(); + data['surveyId'] = this.surveyId; + data['referenceNo'] = this.referenceNo; + data['title'] = this.title; + data['description'] = this.description; + if (this.questions != null) { + data['questions'] = this.questions!.map((v) => v.toJson()).toList(); + } + data['isActive'] = this.isActive; + data['pageSize'] = this.pageSize; + data['pageNo'] = this.pageNo; + data['languageId'] = this.languageId; + return data; + } +} + +class Questions { + int? questionId; + String? title; + bool? isRequired; + String? type; + int? sequenceNo; + Null? surveyId; + List? options; + Null? rspPercentage; + Null? isActive; + Null? pageSize; + Null? pageNo; + Null? languageId; + + Questions({this.questionId, this.title, this.isRequired, this.type, this.sequenceNo, this.surveyId, this.options, this.rspPercentage, this.isActive, this.pageSize, this.pageNo, this.languageId}); + + Questions.fromJson(Map json) { + questionId = json['questionId']; + title = json['title']; + isRequired = json['isRequired']; + type = json['type']; + sequenceNo = json['sequenceNo']; + surveyId = json['surveyId']; + if (json['options'] != null) { + options = []; + json['options'].forEach((v) { + options!.add(new Options.fromJson(v)); + }); + } + rspPercentage = json['rspPercentage']; + isActive = json['isActive']; + pageSize = json['pageSize']; + pageNo = json['pageNo']; + languageId = json['languageId']; + } + + Map toJson() { + Map data = new Map(); + data['questionId'] = this.questionId; + data['title'] = this.title; + data['isRequired'] = this.isRequired; + data['type'] = this.type; + data['sequenceNo'] = this.sequenceNo; + data['surveyId'] = this.surveyId; + if (this.options != null) { + data['options'] = this.options!.map((v) => v.toJson()).toList(); + } + data['rspPercentage'] = this.rspPercentage; + data['isActive'] = this.isActive; + data['pageSize'] = this.pageSize; + data['pageNo'] = this.pageNo; + data['languageId'] = this.languageId; + return data; + } +} + +class Options { + int? optionId; + String? title; + bool? isCommentsRequired; + int? sequenceNo; + int? questionId; + Null? rspPercentage; + Null? count; + Null? isActive; + Null? pageSize; + Null? pageNo; + Null? languageId; + + Options({this.optionId, this.title, this.isCommentsRequired, this.sequenceNo, this.questionId, this.rspPercentage, this.count, this.isActive, this.pageSize, this.pageNo, this.languageId}); + + Options.fromJson(Map json) { + optionId = json['optionId']; + title = json['title']; + isCommentsRequired = json['isCommentsRequired']; + sequenceNo = json['sequenceNo']; + questionId = json['questionId']; + rspPercentage = json['rspPercentage']; + count = json['count']; + isActive = json['isActive']; + pageSize = json['pageSize']; + pageNo = json['pageNo']; + languageId = json['languageId']; + } + + Map toJson() { + Map data = new Map(); + data['optionId'] = this.optionId; + data['title'] = this.title; + data['isCommentsRequired'] = this.isCommentsRequired; + data['sequenceNo'] = this.sequenceNo; + data['questionId'] = this.questionId; + data['rspPercentage'] = this.rspPercentage; + data['count'] = this.count; + data['isActive'] = this.isActive; + data['pageSize'] = this.pageSize; + data['pageNo'] = this.pageNo; + data['languageId'] = this.languageId; + return data; + } +} diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 58fc76a..2db09d0 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -162,7 +162,20 @@ class _DashboardScreenState extends State with WidgetsBindingOb if (val!.result!.data != null) { print("-------------------- Survey ----------------------------"); if (val.result!.data!.notificationType == "Survey") { - Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); + DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( + (value) { + if (value!.mohemmItgResponseItem!.statusCode == 200) { + if (value.mohemmItgResponseItem!.result!.data != null) { + // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); + Navigator.pushNamed(context, AppRoutes.survey, arguments: value.mohemmItgResponseItem!.result!.data); + // Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { + // "masterId": val.result!.data!.notificationMasterId, + // "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, + // }); + } + } + }, + ); } else { print("------------------------------------------- Ads --------------------"); DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then( diff --git a/lib/ui/landing/itg/survey_screen.dart b/lib/ui/landing/itg/survey_screen.dart index 6240934..a212f92 100644 --- a/lib/ui/landing/itg/survey_screen.dart +++ b/lib/ui/landing/itg/survey_screen.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; @@ -7,15 +5,14 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; +import 'package:mohem_flutter_app/models/itg/survey_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; -import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; class SurveyScreen extends StatefulWidget { const SurveyScreen({Key? key}) : super(key: key); @@ -31,75 +28,98 @@ class _SurveyScreenState extends State { ItgResponseData? itgResponseData; + List answeredQuestions = []; + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback( + (_) => initAnswersList(), + ); + super.initState(); + } + @override Widget build(BuildContext context) { - if (itgResponseData == null) itgResponseData = ModalRoute.of(context)!.settings.arguments as ItgResponseData; + itgResponseData ??= ModalRoute.of(context)!.settings.arguments as ItgResponseData; return Scaffold( backgroundColor: MyColors.backgroundColor, body: Column( children: [ Expanded( - child: ListView( - scrollDirection: Axis.vertical, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 124.height, - LocaleKeys.feedbackUserExperience.tr().toText19(), - 27.height, - LocaleKeys.rateUI.tr().toText16(), - 22.height, - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - RatingBar.builder( - initialRating: 3, - minRating: starRating, - direction: Axis.horizontal, - allowHalfRating: false, - itemCount: 5, - itemPadding: EdgeInsets.symmetric(horizontal: 8), - itemBuilder: (context, _) => Icon( - Icons.star, - color: Colors.amber, - ), - onRatingUpdate: (rating) { - starRating = rating; - }, - ) - ], - ).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true), - 39.height, - LocaleKeys.rateUI2.tr().toText16(), - 10.height, - GridView( - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7), - physics: const NeverScrollableScrollPhysics(), - padding: const EdgeInsets.only(top: 0), - shrinkWrap: true, - children: [ - optionUI("poor.svg", 1), - optionUI("bad.svg", 2), - optionUI("normal.svg", 3), - optionUI("good.svg", 4), - optionUI("xcellent.svg", 5), - ], - ), - 27.height, - DynamicTextFieldWidget( - LocaleKeys.description.tr(), - LocaleKeys.typeHere.tr(), - lines: 3, - onChange: (v) { - reviewText = v; - }, - ), - 150.height - ], - ).paddingOnly(left: 21, right: 21), - ], + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 32.height, + itgResponseData?.survey?.title?.toText24() ?? const Text(""), + 8.height, + itgResponseData?.survey?.description?.toText16() ?? const Text(""), + + ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: itgResponseData?.survey?.questions?.length, + itemBuilder: (cxt, index) { + // return itgResponseData?.survey?.questions?[index].title?.toText14() ?? const Text(""); + return answeredQuestions.isNotEmpty ? getSurveyWidget(itgResponseData?.survey?.questions![index], index) : Container(); + }, + ), + + // LocaleKeys.feedbackUserExperience.tr().toText19(), + // 27.height, + // LocaleKeys.rateUI.tr().toText16(), + // 22.height, + // Row( + // crossAxisAlignment: CrossAxisAlignment.center, + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // RatingBar.builder( + // initialRating: 3, + // minRating: starRating, + // direction: Axis.horizontal, + // allowHalfRating: false, + // itemCount: 5, + // itemPadding: EdgeInsets.symmetric(horizontal: 8), + // itemBuilder: (context, _) => Icon( + // Icons.star, + // color: Colors.amber, + // ), + // onRatingUpdate: (rating) { + // starRating = rating; + // }, + // ) + // ], + // ).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true), + // 39.height, + // LocaleKeys.rateUI2.tr().toText16(), + // 10.height, + // GridView( + // gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7), + // physics: const NeverScrollableScrollPhysics(), + // padding: const EdgeInsets.only(top: 0), + // shrinkWrap: true, + // children: [ + // optionUI("poor.svg", 1), + // optionUI("bad.svg", 2), + // optionUI("normal.svg", 3), + // optionUI("good.svg", 4), + // optionUI("xcellent.svg", 5), + // ], + // ), + // 27.height, + // DynamicTextFieldWidget( + // LocaleKeys.description.tr(), + // LocaleKeys.typeHere.tr(), + // lines: 3, + // onChange: (v) { + // reviewText = v; + // }, + // ), + // 150.height + ], + ).paddingOnly(left: 21, right: 21), )), DefaultButton( LocaleKeys.submitSurvey.tr(), @@ -111,7 +131,7 @@ class _SurveyScreenState extends State { )); } - Widget optionUI(String icon, int index) { + Widget optionUI(String icon, int? index, int answerIndex) { return (_selectedIndex == index ? SvgPicture.asset( 'assets/images/' + icon, @@ -126,22 +146,131 @@ class _SurveyScreenState extends State { disablePadding: true, )) .onPress(() { - _selectedIndex = index; + _selectedIndex = index!; + answeredQuestions[answerIndex] = _selectedIndex.toString(); setState(() {}); }); } + void initAnswersList() { + answeredQuestions.clear(); + itgResponseData?.survey?.questions?.forEach((element) { + if (element.type != "Stars") { + answeredQuestions.add(element.options![0].optionId.toString()); + } else { + answeredQuestions.add("3"); + } + }); + setState(() {}); + } + + Widget getSurveyWidget(Questions? question, int parentIndex) { + if (question?.type == "Expressions") { + // Expressions = radio buttons + return Column( + children: [ + 24.height, + question?.title?.toText18() ?? const Text(""), + 16.height, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 50.0, + child: ListView.builder( + scrollDirection: Axis.horizontal, + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: question?.options?.length, + itemBuilder: (cxt, index) { + return radioOption(question?.options?[index].title ?? "", question?.options?[index].optionId.toString() ?? "", answeredQuestions[parentIndex], parentIndex); + }, + ), + ), + ], + ).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true), + ], + ); + } else if (question?.type == "Stars") { + // Stars = star rating + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + 24.height, + question?.title?.toText18() ?? Text(""), + 16.height, + RatingBar.builder( + initialRating: 3, + minRating: starRating, + direction: Axis.horizontal, + allowHalfRating: false, + itemCount: 5, + itemPadding: EdgeInsets.symmetric(horizontal: 8), + itemBuilder: (context, _) => Icon( + Icons.star, + color: Colors.amber, + ), + onRatingUpdate: (rating) { + starRating = rating; + answeredQuestions[parentIndex] = rating.toInt().toString(); + }, + ).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true), + ], + ); + } else if (question?.type == "Faces") { + // Faces = face rating + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + 24.height, + question?.title?.toText18() ?? Text("asdasdasdasd"), + 16.height, + GridView( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7), + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.only(top: 0), + shrinkWrap: true, + children: [ + optionUI("poor.svg", question?.options?[0].optionId, parentIndex), + optionUI("bad.svg", question?.options?[1].optionId, parentIndex), + optionUI("normal.svg", question?.options?[2].optionId, parentIndex), + optionUI("good.svg", question?.options?[3].optionId, parentIndex), + optionUI("xcellent.svg", question?.options?[4].optionId, parentIndex), + ], + ), + ], + ); + } else { + return Container(); + } + return Container(); + } + void performAPI() async { Utils.showLoading(context); + List> itgAnswersList = []; + int index = 0; try { + answeredQuestions.forEach((element) { + itgAnswersList.add({ + "questionId": itgResponseData?.survey?.questions![index].questionId, + "optionId": itgResponseData?.survey?.questions![index].type != "Stars" ? answeredQuestions[index] : null, + "starRating": itgResponseData?.survey?.questions![index].type == "Stars" ? answeredQuestions[index] : null + }); + index++; + }); + ItgMainRes? res = await DashboardApiClient().submitItgForm( comment: reviewText, masterId: itgResponseData!.notificationMasterId ?? "", - itgList: [ - {"questionId": "1", "optionId": null, "starRating": starRating}, - {"questionId": "2", "optionId": "4", "starRating": _selectedIndex} - ], - serviceId: itgResponseData!.serviceId ?? 0); + // itgList: [ + // {"questionId": "1", "optionId": null, "starRating": starRating}, + // {"questionId": "2", "optionId": "4", "starRating": _selectedIndex} + // ], + itgList: itgAnswersList, + serviceId: itgResponseData!.survey!.surveyId ?? 0); Utils.hideLoading(context); if (res!.mohemmItgResponseItem!.statusCode == 200) { @@ -157,4 +286,39 @@ class _SurveyScreenState extends State { }); } } + + Widget radioOption(String title, String value, String groupValue, int answerIndex) { + return Row( + children: [ + Container( + width: 24, + height: 24, + decoration: BoxDecoration( + color: Colors.transparent, + border: Border.all(color: MyColors.borderColor, width: 1), + borderRadius: const BorderRadius.all( + Radius.circular(100), + ), + ), + padding: const EdgeInsets.all(4), + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: value == answeredQuestions[answerIndex] ? MyColors.greenColor : Colors.transparent, + borderRadius: const BorderRadius.all( + Radius.circular(100), + ), + ), + ), + ), + 6.width, + title.toText12(color: MyColors.grey57Color), + 12.width + ], + ).onPress(() { + answeredQuestions[answerIndex] = value; + setState(() {}); + }); + } } diff --git a/lib/ui/work_list/item_history_screen.dart b/lib/ui/work_list/item_history_screen.dart index 7bc39fb..88abf06 100644 --- a/lib/ui/work_list/item_history_screen.dart +++ b/lib/ui/work_list/item_history_screen.dart @@ -329,7 +329,18 @@ class _ItemHistoryScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ actionHistory.nAME!.toText16(), - if ((actionHistory.nOTE ?? "").isNotEmpty) "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color), + if ((actionHistory.nOTE ?? "").isNotEmpty) + SelectableText( + actionHistory.nOTE!, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: MyColors.grey57Color, + letterSpacing: -0.72, + ), + ), + + // "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color), 4.height, Row( children: [ diff --git a/lib/ui/work_list/worklist_fragments/actions_fragment.dart b/lib/ui/work_list/worklist_fragments/actions_fragment.dart index 98b5b72..1d88129 100644 --- a/lib/ui/work_list/worklist_fragments/actions_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/actions_fragment.dart @@ -82,7 +82,20 @@ class ActionsFragment extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ actionHistory.nAME!.toText16(), - if ((actionHistory.nOTE ?? "").isNotEmpty) "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color), + + if ((actionHistory.nOTE ?? "").isNotEmpty) + SelectableText( + actionHistory.nOTE!, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: MyColors.grey57Color, + letterSpacing: -0.72, + ), + ), + + // if ((actionHistory.nOTE ?? "").isNotEmpty) "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color), + 4.height, Row( children: [ diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 8a52a78..f11fafe 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -26,6 +26,7 @@ import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart'; import 'package:mohem_flutter_app/widgets/qr_scanner_dialog.dart'; import 'package:nfc_manager/nfc_manager.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:platform_device_id/platform_device_id.dart'; import 'package:wifi_iot/wifi_iot.dart'; class MarkAttendanceWidget extends StatefulWidget { @@ -53,6 +54,8 @@ class _MarkAttendanceWidgetState extends State { } void checkAttendanceAvailability() async { + String? deviceID = await PlatformDeviceId.getDeviceId; + print("Platform Device ID: $deviceID"); bool isAvailable = await NfcManager.instance.isAvailable(); setState(() { AppState().privilegeListModel!.forEach((PrivilegeListModel element) { @@ -131,7 +134,7 @@ class _MarkAttendanceWidgetState extends State { children: [ // if (isNfcEnabled) attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () { - if (isNfcLocationEnabled) { + // if (isNfcLocationEnabled) { if (AppState().getIsHuawei) { checkHuaweiLocationPermission("NFC"); } else { @@ -143,13 +146,13 @@ class _MarkAttendanceWidgetState extends State { } }, context); } - } else { - performNfcAttendance(widget.model); - } + // } else { + // performNfcAttendance(widget.model); + // } }), if (isWifiEnabled) attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () { - if (isWifiLocationEnabled) { + // if (isWifiLocationEnabled) { if (AppState().getIsHuawei) { checkHuaweiLocationPermission("WIFI"); } else { @@ -161,13 +164,13 @@ class _MarkAttendanceWidgetState extends State { } }, context); } - } else { - performWifiAttendance(widget.model); - } + // } else { + // performWifiAttendance(widget.model); + // } }), if (isQrEnabled) attendanceMethod("QR", "assets/images/ic_qr.svg", isQrEnabled, () async { - if (isQrLocationEnabled) { + // if (isQrLocationEnabled) { if (AppState().getIsHuawei) { checkHuaweiLocationPermission("QR"); } else { @@ -179,9 +182,9 @@ class _MarkAttendanceWidgetState extends State { } }, context); } - } else { - performQrCodeAttendance(widget.model); - } + // } else { + // performQrCodeAttendance(widget.model); + // } // performQrCodeAttendance(model); }), ], From 1f369e912253e34e01315b75d4a2fe2d26d2109e Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 5 Apr 2023 14:40:33 +0300 Subject: [PATCH 6/7] survey updates --- lib/ui/landing/itg/survey_screen.dart | 149 ++++++++------------------ 1 file changed, 45 insertions(+), 104 deletions(-) diff --git a/lib/ui/landing/itg/survey_screen.dart b/lib/ui/landing/itg/survey_screen.dart index a212f92..fce206f 100644 --- a/lib/ui/landing/itg/survey_screen.dart +++ b/lib/ui/landing/itg/survey_screen.dart @@ -24,7 +24,7 @@ class SurveyScreen extends StatefulWidget { class _SurveyScreenState extends State { String reviewText = ""; double starRating = 1; - int _selectedIndex = 5; + int _selectedIndex = 0; ItgResponseData? itgResponseData; @@ -46,80 +46,29 @@ class _SurveyScreenState extends State { body: Column( children: [ Expanded( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 32.height, - itgResponseData?.survey?.title?.toText24() ?? const Text(""), - 8.height, - itgResponseData?.survey?.description?.toText16() ?? const Text(""), - - ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: itgResponseData?.survey?.questions?.length, - itemBuilder: (cxt, index) { - // return itgResponseData?.survey?.questions?[index].title?.toText14() ?? const Text(""); - return answeredQuestions.isNotEmpty ? getSurveyWidget(itgResponseData?.survey?.questions![index], index) : Container(); - }, - ), - - // LocaleKeys.feedbackUserExperience.tr().toText19(), - // 27.height, - // LocaleKeys.rateUI.tr().toText16(), - // 22.height, - // Row( - // crossAxisAlignment: CrossAxisAlignment.center, - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // RatingBar.builder( - // initialRating: 3, - // minRating: starRating, - // direction: Axis.horizontal, - // allowHalfRating: false, - // itemCount: 5, - // itemPadding: EdgeInsets.symmetric(horizontal: 8), - // itemBuilder: (context, _) => Icon( - // Icons.star, - // color: Colors.amber, - // ), - // onRatingUpdate: (rating) { - // starRating = rating; - // }, - // ) - // ], - // ).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true), - // 39.height, - // LocaleKeys.rateUI2.tr().toText16(), - // 10.height, - // GridView( - // gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7), - // physics: const NeverScrollableScrollPhysics(), - // padding: const EdgeInsets.only(top: 0), - // shrinkWrap: true, - // children: [ - // optionUI("poor.svg", 1), - // optionUI("bad.svg", 2), - // optionUI("normal.svg", 3), - // optionUI("good.svg", 4), - // optionUI("xcellent.svg", 5), - // ], - // ), - // 27.height, - // DynamicTextFieldWidget( - // LocaleKeys.description.tr(), - // LocaleKeys.typeHere.tr(), - // lines: 3, - // onChange: (v) { - // reviewText = v; - // }, - // ), - // 150.height - ], - ).paddingOnly(left: 21, right: 21), + child: ListView( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + 32.height, + itgResponseData?.survey?.title?.toText24() ?? const Text(""), + 8.height, + itgResponseData?.survey?.description?.toText16() ?? const Text(""), + ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: itgResponseData?.survey?.questions?.length, + itemBuilder: (cxt, index) { + return answeredQuestions.isNotEmpty ? getSurveyWidget(itgResponseData?.survey?.questions![index], index) : Container(); + }, + ), + ], + ).paddingOnly(left: 21, right: 21), + ), + ], )), DefaultButton( LocaleKeys.submitSurvey.tr(), @@ -156,6 +105,9 @@ class _SurveyScreenState extends State { answeredQuestions.clear(); itgResponseData?.survey?.questions?.forEach((element) { if (element.type != "Stars") { + if(element.type == "Faces") { + _selectedIndex = element.options![0].optionId!; + } answeredQuestions.add(element.options![0].optionId.toString()); } else { answeredQuestions.add("3"); @@ -172,24 +124,18 @@ class _SurveyScreenState extends State { 24.height, question?.title?.toText18() ?? const Text(""), 16.height, - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox( - height: 50.0, - child: ListView.builder( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.zero, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: question?.options?.length, - itemBuilder: (cxt, index) { - return radioOption(question?.options?[index].title ?? "", question?.options?[index].optionId.toString() ?? "", answeredQuestions[parentIndex], parentIndex); - }, - ), - ), - ], + GridView.builder( + padding: EdgeInsets.zero, + itemCount: question?.options?.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return radioOption(question?.options?[index].title ?? "", question?.options?[index].optionId.toString() ?? "", answeredQuestions[parentIndex], parentIndex); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: (4.0), + ), ).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true), ], ); @@ -207,8 +153,8 @@ class _SurveyScreenState extends State { direction: Axis.horizontal, allowHalfRating: false, itemCount: 5, - itemPadding: EdgeInsets.symmetric(horizontal: 8), - itemBuilder: (context, _) => Icon( + itemPadding: const EdgeInsets.symmetric(horizontal: 8), + itemBuilder: (context, _) => const Icon( Icons.star, color: Colors.amber, ), @@ -262,15 +208,8 @@ class _SurveyScreenState extends State { index++; }); - ItgMainRes? res = await DashboardApiClient().submitItgForm( - comment: reviewText, - masterId: itgResponseData!.notificationMasterId ?? "", - // itgList: [ - // {"questionId": "1", "optionId": null, "starRating": starRating}, - // {"questionId": "2", "optionId": "4", "starRating": _selectedIndex} - // ], - itgList: itgAnswersList, - serviceId: itgResponseData!.survey!.surveyId ?? 0); + ItgMainRes? res = await DashboardApiClient() + .submitItgForm(comment: reviewText, masterId: itgResponseData!.notificationMasterId ?? "", itgList: itgAnswersList, serviceId: itgResponseData!.survey!.surveyId ?? 0); Utils.hideLoading(context); if (res!.mohemmItgResponseItem!.statusCode == 200) { @@ -289,6 +228,8 @@ class _SurveyScreenState extends State { Widget radioOption(String title, String value, String groupValue, int answerIndex) { return Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ Container( width: 24, From 45fdb4a466343d03c232adc42a7a3da75cd9e8c8 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 9 Apr 2023 15:51:21 +0300 Subject: [PATCH 7/7] updates --- lib/ui/landing/itg/survey_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/landing/itg/survey_screen.dart b/lib/ui/landing/itg/survey_screen.dart index fce206f..59f3c14 100644 --- a/lib/ui/landing/itg/survey_screen.dart +++ b/lib/ui/landing/itg/survey_screen.dart @@ -110,7 +110,7 @@ class _SurveyScreenState extends State { } answeredQuestions.add(element.options![0].optionId.toString()); } else { - answeredQuestions.add("3"); + answeredQuestions.add("4"); } }); setState(() {});