diff --git a/android/app/build.gradle b/android/app/build.gradle index cd780fb..1901f3a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -18,14 +18,9 @@ if (keystorePropertiesFile.exists()) { android { namespace 'hmg.cloudSolutions.mohem' - compileSdk 36 // Changed from 36 to a supported version + compileSdk 36 ndkVersion '28.2.13676358' - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - coreLibraryDesugaringEnabled true - } kotlinOptions { jvmTarget = '1.8' @@ -38,14 +33,18 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "hmg.cloudSolutions.mohem" - minSdkVersion 28 -// targetSdk = flutter.targetSdkVersion + minSdkVersion 30 targetSdk 35 + targetSdk = flutter.targetSdkVersion versionCode flutter.versionCode versionName flutter.versionName multiDexEnabled true } + compileOptions { + coreLibraryDesugaringEnabled true + } + buildFeatures{ buildConfig true } @@ -77,6 +76,7 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.1.20" + implementation 'androidx.multidex:multidex:2.0.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' implementation 'com.huawei.hms:push:6.11.0.300' diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index d990020..6aac74d 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -391,7 +391,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -530,7 +530,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -561,7 +561,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index b2ee4c2..ae5fda8 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -10,6 +10,7 @@ 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/dashboard/get_accrual_balances_list_model.dart'; +import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_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'; import 'package:mohem_flutter_app/models/dashboard/list_menu.dart'; @@ -101,6 +102,21 @@ class DashboardApiClient { ); } + Future> getTicketAccuralBalance(String effectiveDate, {String? empID}) async { + String url = "${ApiConsts.erpRest}GET_TICKET_ACCRUAL_BALANCES"; + Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; + postParams.addAll(AppState().postParamsJson); + if (empID != null) postParams["P_SELECTED_EMPLOYEE_NUMBER"] = empID; + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAccrualBalancesTicketList ?? []; + }, + url, + postParams, + ); + } + Future getOpenMissingSwipes() async { String url = "${ApiConsts.erpRest}GET_OPEN_MISSING_SWIPES"; Map postParams = {}; @@ -173,6 +189,21 @@ class DashboardApiClient { ); } + Future getTicketBalance() async { + String url = "${ApiConsts.erpRest}GET_TICKET_BALANCE"; + Map postParams = {"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER}; + + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, + url, + postParams, + ); + } + Future getBookingSSOAuthRedirection({required String clientID}) async { String url = "${ApiConsts.ssoAuthRedirection}?grantType=mohemm"; //https://sso-uat.hmg.com/api/auth/connect?grantType=mohemm' @@ -183,6 +214,7 @@ class DashboardApiClient { "PersonId": AppState().memberInformationList?.eMPLOYEENUMBER, "Username": AppState().memberInformationList?.eMPLOYEENUMBER, "Language": "US", + "SessionId": AppState().postParamsObject?.pSessionId, }; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( @@ -196,7 +228,8 @@ class DashboardApiClient { } Future getBookingSSOFinalRedirection({required String token}) async { - token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhjZTE2OWM0YjIwYjQ2ZWM5YTQyOTU3Y2ZhODUzNzQ1IiwidHlwIjoiSldUIn0.eyJ0ZW5hbnRfaWQiOiJhOWY0ZDFhMDU5NmQ0YWVhOGY4MzA5OTJlYzRiZGFjMSIsImVpZCI6IjExNzkzMCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3NpZCI6Ijk2MDI0OGM1NzA3YzQ3MmFhYTEzM2I1N2ZhODE1ZmVhIiwibGFuZ3VhZ2UiOiJVUyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6IjExNzkzMEBobWcuY29tIiwiZXhwIjoxNzgyNDc1NzY5LCJpc3MiOiJodHRwczovL3Nzby11YXQuaG1nLmNvbSIsImF1ZCI6ImE5ZjRkMWEwNTk2ZDRhZWE4ZjgzMDk5MmVjNGJkYWMxIn0.rJcLVsG8D0XECyLERCTD2uqGeWyvp-OBVGE9uL2qKrX4etFUHgdFt_5kYF6edFTtGy-0PIZadHDmv7e-IOhVWHm5HVMClaukiXoRXR8cDN8XA1wfme3Kd-U5PXN-IRh49AyRTzLO0rYNPvH81ScosWGlsFSkOvA-0hJNa2adHdtvgNvB8wJshSU5p7sAmF8mjdDY6aInG19etu2iEuUDwHHA4ZY_ts4hboHo8fE392hFaYGonExoD7bpW5RMx5xKWeRCmWpG_PK8Aw_z1jGzdB9PANus4pteRGuln1J-kmo2lQC9pVrSyZATAKp1HfgfyZ_vUhaHEfM69cMWaCslJQ"; + token = + "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhjZTE2OWM0YjIwYjQ2ZWM5YTQyOTU3Y2ZhODUzNzQ1IiwidHlwIjoiSldUIn0.eyJ0ZW5hbnRfaWQiOiJhOWY0ZDFhMDU5NmQ0YWVhOGY4MzA5OTJlYzRiZGFjMSIsImVpZCI6IjExNzkzMCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3NpZCI6Ijk2MDI0OGM1NzA3YzQ3MmFhYTEzM2I1N2ZhODE1ZmVhIiwibGFuZ3VhZ2UiOiJVUyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6IjExNzkzMEBobWcuY29tIiwiZXhwIjoxNzgyNDc1NzY5LCJpc3MiOiJodHRwczovL3Nzby11YXQuaG1nLmNvbSIsImF1ZCI6ImE5ZjRkMWEwNTk2ZDRhZWE4ZjgzMDk5MmVjNGJkYWMxIn0.rJcLVsG8D0XECyLERCTD2uqGeWyvp-OBVGE9uL2qKrX4etFUHgdFt_5kYF6edFTtGy-0PIZadHDmv7e-IOhVWHm5HVMClaukiXoRXR8cDN8XA1wfme3Kd-U5PXN-IRh49AyRTzLO0rYNPvH81ScosWGlsFSkOvA-0hJNa2adHdtvgNvB8wJshSU5p7sAmF8mjdDY6aInG19etu2iEuUDwHHA4ZY_ts4hboHo8fE392hFaYGonExoD7bpW5RMx5xKWeRCmWpG_PK8Aw_z1jGzdB9PANus4pteRGuln1J-kmo2lQC9pVrSyZATAKp1HfgfyZ_vUhaHEfM69cMWaCslJQ"; var request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG')); request.fields.addAll({'JWTToken': token}); diff --git a/lib/api/eit_api_client.dart b/lib/api/eit_api_client.dart index 9e4f292..d473aaf 100644 --- a/lib/api/eit_api_client.dart +++ b/lib/api/eit_api_client.dart @@ -19,13 +19,26 @@ class EITApiClient { factory EITApiClient() => _instance; - Future?> getEITTransactions(String functionName) async { + Future getEITTransactions(String functionName, {bool isCompleteList = false}) async { String url = "${ApiConsts.erpRest}GET_EIT_TRANSACTIONS"; Map postParams = {'P_FUNCTION_NAME': functionName, "P_MENU_TYPE": "E", "P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1}; postParams.addAll(AppState().postParamsJson); - return await ApiClient().postJsonForObject((json) { - List? responseData = GetEitTransactionsModel.fromJson(json['GetEITTransactionList'][0]).collectionTransaction; - return responseData; - }, url, postParams); + return await ApiClient().postJsonForObject( + (json) { + if (isCompleteList) { + List> responseData = []; + json['GetEITTransactionList'].forEach((element) { + var transactionList = GetEitTransactionsModel.fromJson(element).collectionTransaction; + if (transactionList != null) responseData.add(transactionList); + }); + return responseData; + } else { + List? responseData = GetEitTransactionsModel.fromJson(json['GetEITTransactionList'][0]).collectionTransaction; + return responseData; + } + }, + url, + postParams, + ); } } diff --git a/lib/models/dashboard/get_accural_ticket_balance_model.dart b/lib/models/dashboard/get_accural_ticket_balance_model.dart new file mode 100644 index 0000000..cc6520d --- /dev/null +++ b/lib/models/dashboard/get_accural_ticket_balance_model.dart @@ -0,0 +1,25 @@ +import 'dart:convert'; + +class GetTicketAccuralBalanceModel { + int? accrualNetEntitlement; + String? accuralPlanCode; + + GetTicketAccuralBalanceModel({ + this.accrualNetEntitlement, + this.accuralPlanCode, + }); + + factory GetTicketAccuralBalanceModel.fromRawJson(String str) => GetTicketAccuralBalanceModel.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetTicketAccuralBalanceModel.fromJson(Map json) => GetTicketAccuralBalanceModel( + accrualNetEntitlement: json["ACCRUAL_NET_ENTITLEMENT"], + accuralPlanCode: json["ACCURAL_PLAN_CODE"], + ); + + Map toJson() => { + "ACCRUAL_NET_ENTITLEMENT": accrualNetEntitlement, + "ACCURAL_PLAN_CODE": accuralPlanCode, + }; +} diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 8c653aa..df94c8b 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -5,6 +5,7 @@ import 'package:mohem_flutter_app/models/add_attachment_list_model.dart'; import 'package:mohem_flutter_app/models/basic_member_information_model.dart'; import 'package:mohem_flutter_app/models/dashboard/event_activity.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; +import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_open_missing_swipes_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_open_notifications_list.dart'; @@ -178,6 +179,7 @@ class GenericResponseModel { List? getAbsenceDffStructureList; List? getAbsenceTransactionList; List? getAccrualBalancesList; + List? getAccrualBalancesTicketList; List? getActionHistoryList; List? getPRActionHistoryList; List? getAddressDffStructureList; @@ -453,6 +455,7 @@ class GenericResponseModel { this.getAbsenceDffStructureList, this.getAbsenceTransactionList, this.getAccrualBalancesList, + this.getAccrualBalancesTicketList, this.getActionHistoryList, this.getPRActionHistoryList, this.getAddressDffStructureList, @@ -785,6 +788,8 @@ class GenericResponseModel { } getAccrualBalancesList = json["GetAccrualBalancesList"] == null ? null : List.from(json["GetAccrualBalancesList"].map((x) => GetAccrualBalancesList.fromJson(x))); + getAccrualBalancesTicketList = + json["GetAccrualBalancesTicketList"] == null ? null : List.from(json["GetAccrualBalancesTicketList"].map((x) => GetTicketAccuralBalanceModel.fromJson(x))); if (json['GetActionHistoryList'] != null) { getActionHistoryList = []; @@ -1551,6 +1556,7 @@ class GenericResponseModel { data['GetAbsenceTransactionList'] = this.getAbsenceTransactionList!.map((v) => v.toJson()).toList(); } data['GetAccrualBalancesList'] = this.getAccrualBalancesList; + data['GetAccrualBalancesTicketList'] = this.getAccrualBalancesTicketList; if (this.getActionHistoryList != null) { data['GetActionHistoryList'] = this.getActionHistoryList!.map((v) => v.toJson()).toList(); @@ -1962,9 +1968,9 @@ class PortalDirectionData { Map toJson() => {"P_REDIRECTION": pRedirection, "ClientID": clientID}; } - class TicketBookingResult { final bool success; final String? clientId; + TicketBookingResult(this.success, this.clientId); -} \ No newline at end of file +} diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index fc53773..05c9ebb 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -11,6 +11,7 @@ import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/dashboard/drawer_menu_item_model.dart'; import 'package:mohem_flutter_app/models/dashboard/event_activity.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; +import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_open_notifications_list.dart'; import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart'; @@ -18,6 +19,7 @@ import 'package:mohem_flutter_app/models/dashboard/list_menu.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/dashboard/mohemm_itg_pending_task_responseitem.dart'; +import 'package:mohem_flutter_app/models/eit/get_eit_transaction_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; @@ -44,10 +46,12 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { //Leave and Ticket Balance bool isLeaveTicketBalanceLoading = true; List? accrualList; + List? accrualTicketBalanceList; GetAccrualBalancesList? leaveBalanceAccrual; double get leaveBalance => leaveBalanceAccrual?.accrualNetEntitlement ?? 0; double ticketBalance = 0; + double walletBalance = 0; //Menu Entries bool isServicesMenusLoading = true; @@ -56,6 +60,8 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? getMenuEntriesList; EventActivityList? eventActivity; + TicketBookingResult? ticketBookingResponse; + List>? ticketHistoryTransactionList = []; //Offers And Discounts bool isOffersLoading = true; @@ -99,6 +105,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isLeaveTicketBalanceLoading = true; accrualList = null; + accrualTicketBalanceList = null; leaveBalanceAccrual = null; ticketBalance = 0; @@ -201,6 +208,20 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isLeaveTicketBalanceLoading = false; leaveBalanceAccrual = accrualList![0]; ticketBalance = (accrualList![1].accrualNetEntitlement ?? 0.0) + (accrualList![2].accrualNetEntitlement ?? 0.0) + (accrualList![3].accrualNetEntitlement ?? 0.0); + walletBalance = (accrualList![4].accrualNetEntitlement ?? 0.0); + notifyListeners(); + } catch (ex) { + isLeaveTicketBalanceLoading = false; + logger.wtf(ex); + notifyListeners(); + Utils.handleException(ex, context, null); + } + } + + Future fetchTicketAccuralBalance(context, DateTime date) async { + try { + accrualTicketBalanceList = await DashboardApiClient().getTicketAccuralBalance(DateFormat("MM/dd/yyyy", "en_US").format(date)); + isLeaveTicketBalanceLoading = false; notifyListeners(); } catch (ex) { isLeaveTicketBalanceLoading = false; @@ -285,19 +306,34 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - Future fetchTicketBooking() async { + Future fetchTicketBooking() async { try { GenericResponseModel? genericResponseModel = await DashboardApiClient().getTicketBookingRedirection(); if (genericResponseModel?.portalDirectionData?.pRedirection!.toLowerCase() == "alma") { - return TicketBookingResult(true, genericResponseModel?.portalDirectionData?.clientID); + ticketBookingResponse = TicketBookingResult(true, genericResponseModel?.portalDirectionData?.clientID); + return; } - return TicketBookingResult(false, null); + ticketBookingResponse = TicketBookingResult(false, null); + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + Utils.handleException(ex, null, null); + ticketBookingResponse = TicketBookingResult(false, null); // Ensure a return value in case of an exception + } + } + + void fetchTicketBalance() async { + try { + GenericResponseModel? ticketResponse = await DashboardApiClient().getTicketBalance(); + logger.d("Ticket Balance Response: ${ticketResponse?.toJson()}"); + print(" ========= Ticket Balance Response ======= "); } catch (ex) { logger.wtf(ex); isEventLoadingLoading = false; notifyListeners(); Utils.handleException(ex, null, null); - return TicketBookingResult(false, null); // Ensure a return value in case of an exception + // ticketBookingResponse = TicketBookingResult(false, null); // Ensure a return value in case of an exception } } diff --git a/lib/provider/eit_provider_model.dart b/lib/provider/eit_provider_model.dart index 1543184..75a210f 100644 --- a/lib/provider/eit_provider_model.dart +++ b/lib/provider/eit_provider_model.dart @@ -18,6 +18,7 @@ import 'package:mohem_flutter_app/widgets/Updater.dart'; class EITProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? eitTransactionList; late bool isEitLoaded = false; + void getEITList(String functionName) async { try { eitTransactionList = await EITApiClient().getEITTransactions(functionName); diff --git a/lib/ui/landing/itg/its_add_screen_video_image.dart b/lib/ui/landing/itg/its_add_screen_video_image.dart index 103fde1..2076d7c 100644 --- a/lib/ui/landing/itg/its_add_screen_video_image.dart +++ b/lib/ui/landing/itg/its_add_screen_video_image.dart @@ -146,7 +146,7 @@ class _ITGAdsScreenState extends State { centerTitle: true, automaticallyImplyLeading: false, backgroundColor: Colors.white, - title: (AppState().isArabic(context) ? advertisementData!.advertisementTitleAr! : advertisementData!.advertisementTitleAr!).toText24(color: MyColors.darkTextColor, isBold: true), + title: (AppState().isArabic(context) ? advertisementData!.advertisementTitleAr! : advertisementData!.advertisementTitle!).toText24(color: MyColors.darkTextColor, isBold: true), //advertisementData!.viewAttachFileColl!.first.base64String!.toText24(color: MyColors.darkTextColor, isBold: true), ) diff --git a/lib/ui/landing/widget/menus_widget.dart b/lib/ui/landing/widget/menus_widget.dart index 64855ee..bc5dceb 100644 --- a/lib/ui/landing/widget/menus_widget.dart +++ b/lib/ui/landing/widget/menus_widget.dart @@ -27,114 +27,99 @@ class MenusWidget extends StatelessWidget { children: [ data.isWorkListLoading ? MenuShimmer().onPress(() { - data.fetchWorkListCounter(context, showLoading: true); - }) + data.fetchWorkListCounter(context, showLoading: true); + }) : Container( - decoration: BoxDecoration( - color: Color(namesColor[0]), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.workList.tr().toText12(color: Colors.white), - Row( - children: [ - Expanded( - child: data.workListCounter.toString().toText16(color: Colors.white, isBold: true, maxlines: 1), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), - ).onPress(() { - Navigator.pushNamed(context, AppRoutes.workList); - }), + decoration: BoxDecoration(color: Color(namesColor[0]), borderRadius: BorderRadius.circular(10)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.workList.tr().toText12(color: Colors.white), + Row( + children: [ + Expanded(child: data.workListCounter.toString().toText16(color: Colors.white, isBold: true, maxlines: 1)), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.workList); + }), data.isMissingSwipeLoading ? MenuShimmer().onPress(() { - data.fetchWorkListCounter(context); - }) + data.fetchWorkListCounter(context); + }) : Container( - decoration: BoxDecoration( - color: Color(namesColor[1]), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.missingSwipes.tr().toText12(color: Colors.white), - Row( - children: [ - Expanded( - child: data.missingSwipeCounter.toString().toText16(color: Colors.white, isBold: true, maxlines: 1), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), - ).onPress(() { - Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.missingSwipes.tr(), "HMG_OTL_MISSING_SWIPE_EIT_SS")); - }), + decoration: BoxDecoration(color: Color(namesColor[1]), borderRadius: BorderRadius.circular(10)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.missingSwipes.tr().toText12(color: Colors.white), + Row( + children: [ + Expanded(child: data.missingSwipeCounter.toString().toText16(color: Colors.white, isBold: true, maxlines: 1)), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.missingSwipes.tr(), "HMG_OTL_MISSING_SWIPE_EIT_SS")); + }), data.isLeaveTicketBalanceLoading ? MenuShimmer().onPress(() { - data.fetchWorkListCounter(context); - }) + data.fetchWorkListCounter(context); + }) : Container( - decoration: BoxDecoration( - color: Color(namesColor[2]), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.leaveBalance.tr().toText12(color: Colors.white), - Row( - children: [ - Expanded( - child: data.leaveBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), - ).onPress(() { - Navigator.pushNamed(context, AppRoutes.leaveBalance); - }), + decoration: BoxDecoration(color: Color(namesColor[2]), borderRadius: BorderRadius.circular(10)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.leaveBalance.tr().toText12(color: Colors.white), + Row( + children: [ + Expanded(child: data.leaveBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1)), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.leaveBalance); + }), data.isLeaveTicketBalanceLoading ? MenuShimmer().onPress(() { - data.fetchWorkListCounter(context); - }) + data.fetchWorkListCounter(context); + }) : Container( - decoration: BoxDecoration( - color: Color(namesColor[3]), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.ticketBalance.tr().toText12(color: Colors.white), - Row( - children: [ - Expanded( - child: data.ticketBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1), - ), - RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), - ], - ) - ], - ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), - ).onPress( - () { - Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); - }, - ) + decoration: BoxDecoration(color: Color(namesColor[3]), borderRadius: BorderRadius.circular(10)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + data.ticketBookingResponse != null && data.ticketBookingResponse!.success + ? "Wallet Balance".toText12(color: Colors.white) + : LocaleKeys.ticketBalance.tr().toText12(color: Colors.white), + Row( + children: [ + Expanded( + child: + data.ticketBookingResponse != null && data.ticketBookingResponse!.success + ? data.walletBalance.toStringAsFixed(0).toText16(color: Colors.white, isBold: true, maxlines: 1) + : data.ticketBalance.toStringAsFixed(2).toText16(color: Colors.white, isBold: true, maxlines: 1), + ), + RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white)), + ], + ), + ], + ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); + }), ], ); }, diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 426765d..deea7e9 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -5,6 +5,7 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:mohem_flutter_app/api/eit_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/inAppWebView.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; @@ -14,12 +15,14 @@ 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/dashboard/get_accural_ticket_balance_model.dart'; import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/sso_auth_model.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/ui/my_attendance/services_menu_list_screen.dart'; +import 'package:mohem_flutter_app/ui/screens/ticket/ticket_detailed_screen.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:mohem_flutter_app/widgets/sso_webview_widget.dart'; import 'package:provider/provider.dart'; @@ -254,22 +257,25 @@ class ServicesWidget extends StatelessWidget { } } else { if (menuEntry.menuName == "HMG_TICKET_REQUESTS") { - // Utils.showLoading(context); - // TicketBookingResult response = await pro.fetchTicketBooking(); - // Utils.hideLoading(context); - // if (response.success) { - // SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: response.clientId); - // if (ssoToken != null) { - // logger.d(ssoToken.data!.toJson()); - // logger.d(ssoToken.data!.accessToken); - // dynamic url = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); - // Navigator.push(context, MaterialPageRoute(builder: (context) => SsoLoginWebView(url: url ?? "", jwtToken: ssoToken.data!.accessToken!))); - // } - // } else { + Utils.showLoading(context); + //Ticket Work + if (pro.ticketBookingResponse != null && pro.ticketBookingResponse!.success) { + SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: pro.ticketBookingResponse!.clientId); + if (ssoToken != null) { + dynamic url = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); + await pro.fetchTicketAccuralBalance(context, DateTime.now()); + pro.ticketHistoryTransactionList = await EITApiClient().getEITTransactions("HMG_TICKET_ITENARY_HR_EIT_SS", isCompleteList: true); + + + Utils.hideLoading(context); + // Here Need Work + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => TicketDetailedScreen(url: url, jwtToken: ssoToken.data!.accessToken))); + } + } else { List _menuList = pro.getMenuEntriesList?.where((element) => element.parentMenuName == menuEntry.menuName && (element.menuEntryType == "FUNCTION" || element.menuEntryType == "MENU")).toList() ?? []; Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(menuEntry.prompt!, _menuList.isEmpty ? menuList : _menuList)); - // } + } } else { List _menuList = pro.getMenuEntriesList?.where((element) => element.parentMenuName == menuEntry.menuName && (element.menuEntryType == "FUNCTION" || element.menuEntryType == "MENU")).toList() ?? []; diff --git a/lib/ui/screens/ticket/ticket_detailed_screen.dart b/lib/ui/screens/ticket/ticket_detailed_screen.dart new file mode 100644 index 0000000..d406153 --- /dev/null +++ b/lib/ui/screens/ticket/ticket_detailed_screen.dart @@ -0,0 +1,187 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/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/models/dashboard/get_accural_ticket_balance_model.dart'; +import 'package:mohem_flutter_app/provider/dashboard_provider_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/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; +import 'package:mohem_flutter_app/widgets/sso_webview_widget.dart'; +import 'package:provider/provider.dart'; + +class TicketDetailedScreen extends StatefulWidget { + final String? url; + final String? jwtToken; + + const TicketDetailedScreen({super.key, this.url, this.jwtToken}); + + @override + State createState() => _TicketDetailedScreenState(); +} + +class _TicketDetailedScreenState extends State { + DashboardProviderModel? dashboardProviderModel; + late DateTime accrualDateTime; + + @override + void initState() { + dashboardProviderModel = Provider.of(context, listen: false); + accrualDateTime = DateTime.now(); + super.initState(); + } + + void changeAccrualDate(bool showLoading) async { + try { + if (showLoading) Utils.showLoading(context); + await dashboardProviderModel?.fetchTicketAccuralBalance(context, accrualDateTime); + if (showLoading) Utils.hideLoading(context); + setState(() {}); + } catch (ex) { + if (showLoading) Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBarWidget(context, title: "Ticket Details"), + body: Column( + children: [ + ListView( + padding: const EdgeInsets.all(21), + physics: const BouncingScrollPhysics(), + children: [ + if (dashboardProviderModel == null && dashboardProviderModel?.accrualTicketBalanceList == null) ...[Utils.getNoDataWidget(context).paddingOnly(top: 50)] else ...[ + Container( + padding: const EdgeInsets.all(16.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12.0), + boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.2), spreadRadius: 2, blurRadius: 5, offset: const Offset(0, 3))], + ), + child: Column( + children: [ + Row( + children: [ + "Current Ticket Balance".toText20().expanded, + Row( + children: [ + const Icon(Icons.calendar_month_rounded, color: MyColors.darkIconColor, size: 16), + 5.width, + DateUtil.formatDateToDate(accrualDateTime, AppState().isArabic(context)).toText13(isUnderLine: true), + 8.width, + ], + ).onPress(() async { + DateTime selectedDate = await Utils.selectDate(context, accrualDateTime); + if (selectedDate != accrualDateTime) { + accrualDateTime = selectedDate; + changeAccrualDate(true); + } + }), + ], + ), + 8.height, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + dashboardProviderModel!.accrualTicketBalanceList!.map((GetTicketAccuralBalanceModel item) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 6.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + item.accuralPlanCode.toString().replaceAll('_', ' ').toCamelCase.toText14(), + item.accrualNetEntitlement.toString().toText16(color: MyColors.textMixColor, isBold: true), + ], + ), + ); + }).toList(), + ), + ], + ), + ), + const SizedBox(height: 21), + dashboardProviderModel == null && dashboardProviderModel!.ticketHistoryTransactionList == null + ? const SizedBox() + : ListView( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + children: [ + "Tickets History".toText20().expanded, + 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: EdgeInsets.zero, + itemBuilder: (BuildContext cxt, int cardIndex) { + var transactionDetails = dashboardProviderModel!.ticketHistoryTransactionList![cardIndex]; + const allowedSegmentNames = { + "TICKETS_ROUTE", + "TRAVELER_NAME", + "TICKETS_EFFECTIVE_DATE", + "TICKET_ARRIVAL", + "TICKET_AMOUNT", + "TICKET_COMP_SHARE", + "TICKET_EMP_SHARE", + }; + var uniqueDetails = + transactionDetails + .where((item) => item.dISPLAYFLAG != 'N' && item.sEGMENTPROMPT != null && item.sEGMENTPROMPT!.isNotEmpty && allowedSegmentNames.contains(item.sEGMENTNAME)) + .toList(); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: (uniqueDetails.length / 2).ceil(), + itemBuilder: (context, rowIndex) { + int firstIndex = rowIndex * 2; + int? secondIndex = (firstIndex + 1 < uniqueDetails.length) ? firstIndex + 1 : null; + bool isLastRow = (rowIndex == (uniqueDetails.length / 2).ceil() - 1); + var item1 = uniqueDetails[firstIndex]; + var child1 = ItemDetailViewCol(item1.sEGMENTPROMPT!, item1.vARCHAR2VALUE ?? item1.nUMBERVALUE?.toString() ?? ""); + Widget child2; + if (secondIndex != null) { + var item2 = uniqueDetails[secondIndex]; + child2 = ItemDetailViewCol(item2.sEGMENTPROMPT!, item2.vARCHAR2VALUE ?? item2.nUMBERVALUE?.toString() ?? ""); + } else { + child2 = const SizedBox(); // Empty widget if there is no second item + } + return ItemDetailGrid(child1, child2, isItLast: isLastRow); + }, + ), + ], + ).objectContainerView(); + }, + separatorBuilder: (BuildContext cxt, int index) => 12.height, + itemCount: dashboardProviderModel!.ticketHistoryTransactionList!.length, + ), + ], + ), + ], + ], + ).expanded, + DefaultButton("Proceed For Booking", () { + if (widget.url != null && widget.jwtToken != null) { + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => SsoLoginWebView(url: widget.url, jwtToken: widget.jwtToken))); + } + }).insideContainer, + ], + ), + ); + } +} diff --git a/lib/widgets/sso_webview_widget.dart b/lib/widgets/sso_webview_widget.dart index e5f2759..070f270 100644 --- a/lib/widgets/sso_webview_widget.dart +++ b/lib/widgets/sso_webview_widget.dart @@ -4,10 +4,10 @@ import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class SsoLoginWebView extends StatefulWidget { - final String url; - final String jwtToken; + final String? url; + final String? jwtToken; - SsoLoginWebView({required this.url, required this.jwtToken}); + SsoLoginWebView({this.url, this.jwtToken}); @override State createState() => _SsoLoginWebViewState();