From c8fa64171e4534872c015ca47b22a4ef63e27a81 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Sun, 24 Aug 2025 14:40:28 +0300 Subject: [PATCH 1/6] coreLibraryDesugaringEnabled --- android/app/build.gradle | 8 ++++++++ ios/Runner.xcodeproj/project.pbxproj | 6 +++--- lib/ui/landing/widget/services_widget.dart | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 217706e..c4619f4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -20,6 +20,7 @@ android { namespace 'hmg.cloudSolutions.mohem' compileSdk 36 + kotlinOptions { jvmTarget = '1.8' } @@ -35,6 +36,11 @@ android { targetSdk = flutter.targetSdkVersion versionCode flutter.versionCode versionName flutter.versionName + multiDexEnabled true + } + + compileOptions { + coreLibraryDesugaringEnabled true } signingConfigs { @@ -64,4 +70,6 @@ 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.0.3' } diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index ea4aec9..a9aed20 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/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 7d2c2b2..0bd9acc 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -256,13 +256,14 @@ class ServicesWidget extends StatelessWidget { 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!); + Utils.hideLoading(context); Navigator.push(context, MaterialPageRoute(builder: (context) => SsoLoginWebView(url: url ?? "", jwtToken: ssoToken.data!.accessToken!))); } } else { From 1bcecde59bde0b6ce32645bb9adfde135a74938d Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Tue, 26 Aug 2025 10:39:53 +0300 Subject: [PATCH 2/6] ticket changes moved to dashboard --- lib/provider/dashboard_provider_model.dart | 9 +- lib/ui/landing/dashboard_screen.dart | 495 ++++++++++----------- lib/ui/landing/widget/services_widget.dart | 7 +- 3 files changed, 240 insertions(+), 271 deletions(-) diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 0dcebed..6686574 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -56,6 +56,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? getMenuEntriesList; EventActivityList? eventActivity; + TicketBookingResult? ticketBookingResponse; //Offers And Discounts bool isOffersLoading = true; @@ -285,19 +286,19 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - Future fetchTicketBooking() async { + void 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 TicketBookingResult(false, null); + ticketBookingResponse = TicketBookingResult(false, null); } 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/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 4640c25..2ddd706 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -159,6 +159,9 @@ class _DashboardScreenState extends State with WidgetsBindingOb } if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon(); _refreshController.refreshCompleted(); + + data.fetchTicketBooking(); + //continue here } int ermIndex = 0; @@ -175,10 +178,11 @@ class _DashboardScreenState extends State with WidgetsBindingOb if (list[ermIndex].notificationType == "Survey") { await Navigator.pushNamed(context, AppRoutes.survey, arguments: response.mohemmItgResponseItem!.result!.data!.first); } else { - await Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { - "masterId": list[ermIndex].notificationMasterId, - "advertisement": response.mohemmItgResponseItem!.result!.data!.first.advertisement, - }); + await Navigator.pushNamed( + context, + AppRoutes.advertisement, + arguments: {"masterId": list[ermIndex].notificationMasterId, "advertisement": response.mohemmItgResponseItem!.result!.data!.first.advertisement}, + ); } } ermIndex++; @@ -241,53 +245,44 @@ class _DashboardScreenState extends State with WidgetsBindingOb children: [ Row( children: [ - Builder(builder: (BuildContext context) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Image.memory( - Utils.dataFromBase64String( - AppState().memberInformationList!.eMPLOYEEIMAGE ?? "", - ), - errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { - return SvgPicture.asset( - "assets/images/user.svg", - height: 34, - width: 34, - ); - }, - width: 34, - height: 34, - fit: BoxFit.cover, - ).circle(50), - // CircularAvatar( - // width: 34, - // height: 34, - // url: "https://cdn4.iconfinder.com/data/icons/professions-2-2/151/89-512.png", - // ), - 8.width, - SvgPicture.asset("assets/images/side_nav.svg"), - ], - ).onPress(() { - _scaffoldState.currentState!.openDrawer(); - }); - }), + Builder( + builder: (BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Image.memory( + Utils.dataFromBase64String(AppState().memberInformationList!.eMPLOYEEIMAGE ?? ""), + errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { + return SvgPicture.asset("assets/images/user.svg", height: 34, width: 34); + }, + width: 34, + height: 34, + fit: BoxFit.cover, + ).circle(50), + // CircularAvatar( + // width: 34, + // height: 34, + // url: "https://cdn4.iconfinder.com/data/icons/professions-2-2/151/89-512.png", + // ), + 8.width, + SvgPicture.asset("assets/images/side_nav.svg"), + ], + ).onPress(() { + _scaffoldState.currentState!.openDrawer(); + }); + }, + ), Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28).expanded, - SvgPicture.asset( - "assets/images/announcements.svg", - matchTextDirection: true, - ).onPress(() async { + SvgPicture.asset("assets/images/announcements.svg", matchTextDirection: true).onPress(() async { await Navigator.pushNamed(context, AppRoutes.announcements); - }) + }), ], ).paddingOnly(left: 21, right: 21, top: 48, bottom: 7), Expanded( child: SmartRefresher( enablePullDown: true, enablePullUp: false, - header: const MaterialClassicHeader( - color: MyColors.gradiantEndColor, - ), + header: const MaterialClassicHeader(color: MyColors.gradiantEndColor), controller: _refreshController, onRefresh: () { _onRefresh(false); @@ -311,161 +306,155 @@ class _DashboardScreenState extends State with WidgetsBindingOb return (model.isAttendanceTrackingLoading ? GetAttendanceTrackingShimmer() : Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(15), - gradient: const LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ]), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + gradient: const LinearGradient( + transform: GradientRotation(.46), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [MyColors.gradiantEndColor, MyColors.gradiantStartColor], ), - child: Stack( - alignment: Alignment.center, - children: [ - if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.markAttendance.tr().toText14(color: Colors.white, isBold: true), - if (model.isTimeRemainingInSeconds == 0) DateTime.now().toString().split(" ")[0].toText12(color: Colors.white), - if (model.isTimeRemainingInSeconds != 0) - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 9.height, - Directionality( - textDirection: ui.TextDirection.ltr, - child: CountdownTimer( - endTime: model.endTime, - onEnd: null, - endWidget: "00:00:00".toText14(color: Colors.white, isBold: true), - textStyle: const TextStyle(color: Colors.white, fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold), - ), - ), - LocaleKeys.timeLeftToday.tr().toText12(color: Colors.white), - 9.height, - ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(20)), - child: LinearProgressIndicator( - value: model.progress, - minHeight: 8, - valueColor: const AlwaysStoppedAnimation(Colors.white), - backgroundColor: const Color(0xff196D73), - ), - ), - ], - ), - ], - ).paddingOnly(top: 12, right: 15, left: 12), - ), - Row( + ), + child: Stack( + alignment: Alignment.center, + children: [ + if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( + LocaleKeys.markAttendance.tr().toText14(color: Colors.white, isBold: true), + if (model.isTimeRemainingInSeconds == 0) DateTime.now().toString().split(" ")[0].toText12(color: Colors.white), + if (model.isTimeRemainingInSeconds != 0) + Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.checkIn.tr().toText12(color: Colors.white), - (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn) - .toString() - .toText14(color: Colors.white, isBold: true), - 4.height, + 9.height, + Directionality( + textDirection: ui.TextDirection.ltr, + child: CountdownTimer( + endTime: model.endTime, + onEnd: null, + endWidget: "00:00:00".toText14(color: Colors.white, isBold: true), + textStyle: const TextStyle(color: Colors.white, fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold), + ), + ), + LocaleKeys.timeLeftToday.tr().toText12(color: Colors.white), + 9.height, + ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(20)), + child: LinearProgressIndicator( + value: model.progress, + minHeight: 8, + valueColor: const AlwaysStoppedAnimation(Colors.white), + backgroundColor: const Color(0xff196D73), + ), + ), ], - ).paddingOnly(left: 12, right: 12), - ), - Container( - margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0), - width: 45, - height: 45, - padding: const EdgeInsets.only(left: 10, right: 10), - decoration: BoxDecoration( - color: Color(0xff259EA4), - borderRadius: BorderRadius.only( - bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15), - bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), - ), ), - child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/biometrics.svg" : "assets/images/biometrics.svg"), - ).onPress(() { - showMyBottomSheet( - context, - callBackFunc: () {}, - child: MarkAttendanceWidget(model, isFromDashboard: true), - ); - }), ], - ), - ], - ), - ], - ), - ).onPress( - () { - Navigator.pushNamed(context, AppRoutes.todayAttendance); - }, - )) + ).paddingOnly(top: 12, right: 15, left: 12), + ), + Row( + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.checkIn.tr().toText12(color: Colors.white), + (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn).toString().toText14( + color: Colors.white, + isBold: true, + ), + 4.height, + ], + ).paddingOnly(left: 12, right: 12), + ), + Container( + margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0), + width: 45, + height: 45, + padding: const EdgeInsets.only(left: 10, right: 10), + decoration: BoxDecoration( + color: Color(0xff259EA4), + borderRadius: BorderRadius.only( + bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15), + bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), + ), + ), + child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/biometrics.svg" : "assets/images/biometrics.svg"), + ).onPress(() { + showMyBottomSheet(context, callBackFunc: () {}, child: MarkAttendanceWidget(model, isFromDashboard: true)); + }), + ], + ), + ], + ), + ], + ), + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.todayAttendance); + })) .animatedSwither(); }, ), ), ), 9.width, - Expanded( - child: MenusWidget(), - ), + Expanded(child: MenusWidget()), ], ), ], ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), eventActivityWidget(context), - Consumer(builder: (BuildContext context, DashboardProviderModel model, Widget? child) { - if (!model.isOffersLoading && model.getOffersList.isEmpty) { - return const SizedBox(); - } - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - LocaleKeys.offers.tr().toText12(), - Row( - children: [ - LocaleKeys.discounts.tr().toText24(isBold: true), - 6.width, - Container( + Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + if (!model.isOffersLoading && model.getOffersList.isEmpty) { + return const SizedBox(); + } + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + LocaleKeys.offers.tr().toText12(), + Row( + children: [ + LocaleKeys.discounts.tr().toText24(isBold: true), + 6.width, + Container( padding: const EdgeInsets.only(left: 8, right: 8), - decoration: BoxDecoration( - color: MyColors.yellowColor, - borderRadius: BorderRadius.circular(10), - ), - child: LocaleKeys.newString.tr().toText10(isBold: true)), - ], - ), - ], + decoration: BoxDecoration(color: MyColors.yellowColor, borderRadius: BorderRadius.circular(10)), + child: LocaleKeys.newString.tr().toText10(isBold: true), + ), + ], + ), + ], + ), ), - ), - LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { - Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); - }) - ], - ).paddingOnly(left: 21, right: 21), - Consumer( - builder: (BuildContext context, DashboardProviderModel model, Widget? child) { - return SizedBox( - height: 103 + 33, - child: ListView.separated( + LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + }), + ], + ).paddingOnly(left: 21, right: 21), + Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + return SizedBox( + height: 103 + 33, + child: ListView.separated( shrinkWrap: true, physics: const BouncingScrollPhysics(), padding: const EdgeInsets.only(left: 21, right: 21, top: 13), @@ -474,57 +463,53 @@ class _DashboardScreenState extends State with WidgetsBindingOb return model.isOffersLoading ? const OffersShimmerWidget() : InkWell( - onTap: () { - navigateToDetails(data.getOffersList[index]); - }, - child: SizedBox( - width: 73, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 73, - height: 73, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all( - Radius.circular(100), - ), - border: Border.all(color: MyColors.lightGreyE3Color, width: 1), - ), - child: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(50), - ), - child: Hero( - tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, - transitionOnUserGestures: true, - child: Image.network( - data.getOffersList[index].logo ?? "", - fit: BoxFit.contain, - ), - ), - ), + onTap: () { + navigateToDetails(data.getOffersList[index]); + }, + child: SizedBox( + width: 73, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 73, + height: 73, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all(Radius.circular(100)), + border: Border.all(color: MyColors.lightGreyE3Color, width: 1), ), - 4.height, - Expanded( - child: AppState().isArabic(context) - ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) - : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(50)), + child: Hero( + tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, + transitionOnUserGestures: true, + child: Image.network(data.getOffersList[index].logo ?? "", fit: BoxFit.contain), + ), ), - ], - ), + ), + 4.height, + Expanded( + child: + AppState().isArabic(context) + ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) + : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), + ), + ], ), - ); + ), + ); }, separatorBuilder: (BuildContext cxt, int index) => 8.width, - itemCount: 9), - ); - }, - ), - ], - ); - }), + itemCount: 9, + ), + ); + }, + ), + ], + ); + }, + ), Container( width: double.infinity, padding: const EdgeInsets.only(top: 31), @@ -588,38 +573,24 @@ class _DashboardScreenState extends State with WidgetsBindingOb ), ), ), - ) + ), ], ), - drawer: SafeArea( - child: AppDrawer(onLanguageChange: _onRefresh), - ), + drawer: SafeArea(child: AppDrawer(onLanguageChange: _onRefresh)), bottomNavigationBar: SizedBox( height: Platform.isAndroid ? 70 : 100, child: BottomNavigationBar( items: [ + BottomNavigationBarItem(icon: SvgPicture.asset("assets/icons/home.svg", color: currentIndex == 0 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), label: LocaleKeys.home.tr()), BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/home.svg", - color: currentIndex == 0 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), - label: LocaleKeys.home.tr(), - ), - BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/create_req.svg", - color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), + icon: SvgPicture.asset("assets/icons/create_req.svg", color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), label: LocaleKeys.mowadhafhiRequest.tr(), ), BottomNavigationBarItem( icon: Stack( alignment: Alignment.centerLeft, children: [ - SvgPicture.asset( - "assets/icons/work_list.svg", - color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), + SvgPicture.asset("assets/icons/work_list.svg", color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), Consumer( builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { if (data.workListCounter == 0) { @@ -642,10 +613,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb label: LocaleKeys.workList.tr(), ), BottomNavigationBarItem( - icon: SvgPicture.asset( - "assets/icons/item_for_sale.svg", - color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color, - ).paddingAll(4), + icon: SvgPicture.asset("assets/icons/item_for_sale.svg", color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), label: LocaleKeys.itemsForSale.tr(), ), BottomNavigationBarItem( @@ -654,28 +622,29 @@ class _DashboardScreenState extends State with WidgetsBindingOb children: [ SvgPicture.asset( "assets/icons/chat/chat.svg", - color: !checkIfPrivilegedForChat() - ? MyColors.lightGreyE3Color - : currentIndex == 4 + color: + !checkIfPrivilegedForChat() + ? MyColors.lightGreyE3Color + : currentIndex == 4 ? MyColors.grey3AColor : cProvider.disbaleChatForThisUser - ? MyColors.lightGreyE3Color - : MyColors.grey98Color, + ? MyColors.lightGreyE3Color + : MyColors.grey98Color, ).paddingAll(4), Consumer( builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { return !checkIfPrivilegedForChat() ? const SizedBox() : Positioned( - right: 0, - top: 0, - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - alignment: Alignment.center, - decoration: BoxDecoration(color: cProvider.disbaleChatForThisUser ? MyColors.pinkDarkColor : MyColors.redColor, borderRadius: BorderRadius.circular(17)), - child: data.chatUConvCounter.toString().toText10(color: Colors.white), - ), - ); + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: cProvider.disbaleChatForThisUser ? MyColors.pinkDarkColor : MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.chatUConvCounter.toString().toText10(color: Colors.white), + ), + ); }, ), ], @@ -712,9 +681,9 @@ class _DashboardScreenState extends State with WidgetsBindingOb Widget eventActivityWidget(BuildContext context) { return (context.watch().isEventLoadingLoading) ? const MarathonBannerShimmer().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) - : (context.watch().eventActivity != null && context.watch().eventActivity!.isActive ==true) - ? const EventActivityBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) - : const SizedBox(); + : (context.watch().eventActivity != null && context.watch().eventActivity!.isActive == true) + ? const EventActivityBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) + : const SizedBox(); } void navigateToDetails(OffersListModel offersListModelObj) { diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 0bd9acc..5695217 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -255,10 +255,9 @@ class ServicesWidget extends StatelessWidget { } else { if (menuEntry.menuName == "HMG_TICKET_REQUESTS") { Utils.showLoading(context); - TicketBookingResult response = await pro.fetchTicketBooking(); - - if (response.success) { - SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: response.clientId); +//Ticket Work + if (pro.ticketBookingResponse != null && pro.ticketBookingResponse!.success) { + SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: pro.ticketBookingResponse!.clientId); if (ssoToken != null) { logger.d(ssoToken.data!.toJson()); logger.d(ssoToken.data!.accessToken); From cca95cee6a65146e2021d327e9a3b6e90ce5f6dd Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Wed, 17 Sep 2025 11:16:23 +0300 Subject: [PATCH 3/6] ticket changes moved to dashboard & wallet balance --- lib/api/dashboard_api_client.dart | 19 ++- lib/provider/dashboard_provider_model.dart | 20 ++- lib/ui/landing/dashboard_screen.dart | 6 +- lib/ui/landing/widget/menus_widget.dart | 181 ++++++++++----------- lib/ui/landing/widget/services_widget.dart | 2 +- 5 files changed, 126 insertions(+), 102 deletions(-) diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 28226ce..4fc8545 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -170,6 +170,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' @@ -180,6 +195,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( @@ -193,7 +209,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/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 6686574..beddf0c 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -48,6 +48,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { double get leaveBalance => leaveBalanceAccrual?.accrualNetEntitlement ?? 0; double ticketBalance = 0; + double walletBalance = 0; //Menu Entries bool isServicesMenusLoading = true; @@ -202,6 +203,8 @@ 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); + print("================ Ticket Balance: $ticketBalance ==============="); notifyListeners(); } catch (ex) { isLeaveTicketBalanceLoading = false; @@ -286,11 +289,12 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - void fetchTicketBooking() async { + Future fetchTicketBooking() async { try { GenericResponseModel? genericResponseModel = await DashboardApiClient().getTicketBookingRedirection(); if (genericResponseModel?.portalDirectionData?.pRedirection!.toLowerCase() == "alma") { ticketBookingResponse = TicketBookingResult(true, genericResponseModel?.portalDirectionData?.clientID); + return; } ticketBookingResponse = TicketBookingResult(false, null); } catch (ex) { @@ -302,6 +306,20 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } + 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); + // ticketBookingResponse = TicketBookingResult(false, null); // Ensure a return value in case of an exception + } + } + Future fetchSSOAuthRedirection({String? clientID}) async { try { SSOAuthModel? ssoResponse = await DashboardApiClient().getBookingSSOAuthRedirection(clientID: clientID!); diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 2ddd706..8c0e415 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -148,6 +148,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb data.fetchAttendanceTracking(context); data.fetchWorkListCounter(context); data.fetchMissingSwipe(context); + data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchMenuEntries(); data.fetchEventActivity(); @@ -160,7 +161,10 @@ class _DashboardScreenState extends State with WidgetsBindingOb if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon(); _refreshController.refreshCompleted(); - data.fetchTicketBooking(); + await data.fetchTicketBooking(); + // if (data.ticketBookingResponse != null && !data.ticketBookingResponse!.success) { + // // data.fetchTicketBalance(); + // } //continue here } 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 5695217..6dfeab5 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -255,7 +255,7 @@ class ServicesWidget extends StatelessWidget { } else { if (menuEntry.menuName == "HMG_TICKET_REQUESTS") { Utils.showLoading(context); -//Ticket Work + //Ticket Work if (pro.ticketBookingResponse != null && pro.ticketBookingResponse!.success) { SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: pro.ticketBookingResponse!.clientId); if (ssoToken != null) { From c7e44965d6fb68f57cd1afaa042f2d5bd67f68c5 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Wed, 15 Oct 2025 11:15:04 +0300 Subject: [PATCH 4/6] Get Ticket Accural Balance Changes --- lib/api/dashboard_api_client.dart | 16 +++ .../get_accural_ticket_balance_model.dart | 25 ++++ lib/models/generic_response_model.dart | 10 +- lib/provider/dashboard_provider_model.dart | 17 ++- lib/ui/landing/widget/services_widget.dart | 8 +- .../ticket/ticket_detailed_screen.dart | 124 ++++++++++++++++++ lib/widgets/sso_webview_widget.dart | 6 +- 7 files changed, 197 insertions(+), 9 deletions(-) create mode 100644 lib/models/dashboard/get_accural_ticket_balance_model.dart create mode 100644 lib/ui/screens/ticket/ticket_detailed_screen.dart diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 4fc8545..1d45bbf 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -8,6 +8,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'; @@ -98,6 +99,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 = {}; 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 74cef13..b7e786c 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'; @@ -177,6 +178,7 @@ class GenericResponseModel { List? getAbsenceDffStructureList; List? getAbsenceTransactionList; List? getAccrualBalancesList; + List? getAccrualBalancesTicketList; List? getActionHistoryList; List? getPRActionHistoryList; List? getAddressDffStructureList; @@ -451,6 +453,7 @@ class GenericResponseModel { this.getAbsenceDffStructureList, this.getAbsenceTransactionList, this.getAccrualBalancesList, + this.getAccrualBalancesTicketList, this.getActionHistoryList, this.getPRActionHistoryList, this.getAddressDffStructureList, @@ -782,6 +785,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 = []; @@ -1545,6 +1550,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(); @@ -1955,9 +1961,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 beddf0c..9e421ab 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'; @@ -44,6 +45,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { //Leave and Ticket Balance bool isLeaveTicketBalanceLoading = true; List? accrualList; + List? accrualTicketBalanceList; GetAccrualBalancesList? leaveBalanceAccrual; double get leaveBalance => leaveBalanceAccrual?.accrualNetEntitlement ?? 0; @@ -101,6 +103,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isLeaveTicketBalanceLoading = true; accrualList = null; + accrualTicketBalanceList = null; leaveBalanceAccrual = null; ticketBalance = 0; @@ -204,7 +207,19 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { 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); - print("================ Ticket Balance: $ticketBalance ==============="); + 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; diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 6dfeab5..723adb9 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -14,12 +14,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'; @@ -259,11 +261,11 @@ class ServicesWidget extends StatelessWidget { if (pro.ticketBookingResponse != null && pro.ticketBookingResponse!.success) { SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: pro.ticketBookingResponse!.clientId); if (ssoToken != null) { - logger.d(ssoToken.data!.toJson()); - logger.d(ssoToken.data!.accessToken); dynamic url = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!); + await pro.fetchTicketAccuralBalance(context, DateTime.now()); Utils.hideLoading(context); - Navigator.push(context, MaterialPageRoute(builder: (context) => SsoLoginWebView(url: url ?? "", jwtToken: ssoToken.data!.accessToken!))); + // Here Need Work + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => TicketDetailedScreen(url: url, jwtToken: ssoToken.data!.accessToken))); } } else { List _menuList = 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..fe41527 --- /dev/null +++ b/lib/ui/screens/ticket/ticket_detailed_screen.dart @@ -0,0 +1,124 @@ +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/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 ...[ + // const BalancesDashboardWidget("Current Ticket Balance", false, showLoading: false), 12.height, + 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(), + ), + ], + ), + ), + ], + ], + ).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(); From 0b08606813201dc0152331159d6964b8f7f11a32 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Tue, 21 Oct 2025 10:22:43 +0300 Subject: [PATCH 5/6] Ticket History --- lib/api/eit_api_client.dart | 23 ++++-- lib/provider/dashboard_provider_model.dart | 2 + lib/provider/eit_provider_model.dart | 1 + lib/ui/landing/widget/services_widget.dart | 4 + .../ticket/ticket_detailed_screen.dart | 75 +++++++++++++++++-- 5 files changed, 94 insertions(+), 11 deletions(-) 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/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 6e441b3..05c9ebb 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -19,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'; @@ -60,6 +61,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { EventActivityList? eventActivity; TicketBookingResult? ticketBookingResponse; + List>? ticketHistoryTransactionList = []; //Offers And Discounts bool isOffersLoading = true; 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/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 723adb9..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'; @@ -263,6 +264,9 @@ class ServicesWidget extends StatelessWidget { 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))); diff --git a/lib/ui/screens/ticket/ticket_detailed_screen.dart b/lib/ui/screens/ticket/ticket_detailed_screen.dart index fe41527..d406153 100644 --- a/lib/ui/screens/ticket/ticket_detailed_screen.dart +++ b/lib/ui/screens/ticket/ticket_detailed_screen.dart @@ -1,3 +1,5 @@ +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'; @@ -12,6 +14,7 @@ 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'; @@ -54,27 +57,26 @@ class _TicketDetailedScreenState extends State { backgroundColor: Colors.white, appBar: AppBarWidget(context, title: "Ticket Details"), body: Column( - children: [ + children: [ ListView( padding: const EdgeInsets.all(21), physics: const BouncingScrollPhysics(), children: [ if (dashboardProviderModel == null && dashboardProviderModel?.accrualTicketBalanceList == null) ...[Utils.getNoDataWidget(context).paddingOnly(top: 50)] else ...[ - // const BalancesDashboardWidget("Current Ticket Balance", false, showLoading: false), 12.height, 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))], + boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.2), spreadRadius: 2, blurRadius: 5, offset: const Offset(0, 3))], ), child: Column( - children: [ + children: [ Row( - children: [ + children: [ "Current Ticket Balance".toText20().expanded, Row( - children: [ + children: [ const Icon(Icons.calendar_month_rounded, color: MyColors.darkIconColor, size: 16), 5.width, DateUtil.formatDateToDate(accrualDateTime, AppState().isArabic(context)).toText13(isUnderLine: true), @@ -109,6 +111,67 @@ class _TicketDetailedScreenState extends State { ], ), ), + 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, From c191d4c0c093be9a9f91c371ecdd4a5e7cceb20c Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Tue, 21 Oct 2025 11:09:56 +0300 Subject: [PATCH 6/6] Survey Title Key Fix --- lib/ui/landing/itg/its_add_screen_video_image.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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), )