From 676e662967bf7c3d37b70d648a8c1a7534692cea Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Thu, 23 Oct 2025 09:09:23 +0300 Subject: [PATCH 01/17] Survey title key fix --- lib/api/api_client.dart | 71 ++-- lib/classes/consts.dart | 17 +- lib/classes/utils.dart | 13 + lib/ui/landing/dashboard_screen.dart | 316 ++++++++++++------ lib/ui/landing/widget/app_drawer.dart | 124 +++---- .../offers_and_discounts_home.dart | 2 +- 6 files changed, 339 insertions(+), 204 deletions(-) diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index fb415d4..74a12c8 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -2,10 +2,13 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:http/io_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/exceptions/api_exception.dart'; import 'package:mohem_flutter_app/main.dart'; // ignore_for_file: avoid_annotating_with_dynamic @@ -13,18 +16,14 @@ import 'package:mohem_flutter_app/main.dart'; typedef FactoryConstructor = U Function(dynamic); class APIError { - int? errorCode; + dynamic errorCode; int? errorType; String? errorMessage; - int? errorStatusCode; + int? errorStatusCode; + APIError(this.errorCode, this.errorMessage, this.errorType, this.errorStatusCode); - Map toJson() => { - 'errorCode': errorCode, - 'errorMessage': errorMessage, - 'errorType': errorType, - 'ErrorStatusCode': errorStatusCode - }; + Map toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage, 'errorType': errorType, 'ErrorStatusCode': errorStatusCode}; @override String toString() { @@ -46,22 +45,22 @@ APIException _throwAPIException(Response response) { APIError? apiError; if (response.body != null && response.body.isNotEmpty) { var jsonError = jsonDecode(response.body); - apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'],jsonError['ErrorStatusCode']); + apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'], jsonError['ErrorStatusCode']); } return APIException(APIException.BAD_REQUEST, error: apiError); case 401: - return APIException(APIException.UNAUTHORIZED); + return const APIException(APIException.UNAUTHORIZED); case 403: - return APIException(APIException.FORBIDDEN); + return const APIException(APIException.FORBIDDEN); case 404: - return APIException(APIException.NOT_FOUND); + return const APIException(APIException.NOT_FOUND); case 500: - return APIException(APIException.INTERNAL_SERVER_ERROR); + return const APIException(APIException.INTERNAL_SERVER_ERROR); case 444: var downloadUrl = response.headers["location"]; return APIException(APIException.UPGRADE_REQUIRED, arguments: downloadUrl); default: - return APIException(APIException.OTHER); + return const APIException(APIException.OTHER); } } @@ -72,8 +71,16 @@ class ApiClient { factory ApiClient() => _instance; - Future postJsonForObject(FactoryConstructor factoryConstructor, String url, T jsonObject, - {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async { + Future postJsonForObject( + FactoryConstructor factoryConstructor, + String url, + T jsonObject, { + String? token, + Map? queryParameters, + Map? headers, + int retryTimes = 0, + bool isFormData = false, + }) async { var _headers = {'Accept': 'application/json'}; if (headers != null && headers.isNotEmpty) { _headers.addAll(headers); @@ -102,6 +109,9 @@ class ApiClient { if (jsonData["ErrorMessage"] == null) { return factoryConstructor(jsonData); + } else if (jsonData["MessageStatus"] == 2 && jsonData["IsOTPMaxLimitExceed"] == true) { + await Utils.performLogout(AppRoutes.navigatorKey.currentContext, null); + throw const APIException(APIException.UNAUTHORIZED, error: null); } else { APIError? apiError; apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage'], jsonData['ErrorType'] ?? 0, jsonData['ErrorStatusCode']); @@ -116,8 +126,15 @@ class ApiClient { } } - Future postJsonForResponse(String url, T jsonObject, - {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async { + Future postJsonForResponse( + String url, + T jsonObject, { + String? token, + Map? queryParameters, + Map? headers, + int retryTimes = 0, + bool isFormData = false, + }) async { String? requestBody; late Map stringObj; if (jsonObject != null) { @@ -152,9 +169,9 @@ class ApiClient { var queryString = new Uri(queryParameters: queryParameters).query; url = url + '?' + queryString; } - var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 120)); + var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(const Duration(seconds: 120)); - if (response. statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { return response; } else { throw _throwAPIException(response); @@ -162,7 +179,7 @@ class ApiClient { } on SocketException catch (e) { if (retryTimes > 0) { print('will retry after 3 seconds...'); - await Future.delayed(Duration(seconds: 3)); + await Future.delayed(const Duration(seconds: 3)); return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); @@ -170,7 +187,7 @@ class ApiClient { } on HttpException catch (e) { if (retryTimes > 0) { print('will retry after 3 seconds...'); - await Future.delayed(Duration(seconds: 3)); + await Future.delayed(const Duration(seconds: 3)); return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); @@ -180,7 +197,7 @@ class ApiClient { } on ClientException catch (e) { if (retryTimes > 0) { print('will retry after 3 seconds...'); - await Future.delayed(Duration(seconds: 3)); + await Future.delayed(const Duration(seconds: 3)); return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); @@ -219,7 +236,7 @@ class ApiClient { var queryString = new Uri(queryParameters: queryParameters).query; url = url + '?' + queryString; } - var response = await _get(Uri.parse(url), headers: _headers).timeout(Duration(seconds: 60)); + var response = await _get(Uri.parse(url), headers: _headers).timeout(const Duration(seconds: 60)); if (response.statusCode >= 200 && response.statusCode < 300) { return response; @@ -229,7 +246,7 @@ class ApiClient { } on SocketException catch (e) { if (retryTimes > 0) { print('will retry after 3 seconds...'); - await Future.delayed(Duration(seconds: 3)); + await Future.delayed(const Duration(seconds: 3)); return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); @@ -237,7 +254,7 @@ class ApiClient { } on HttpException catch (e) { if (retryTimes > 0) { print('will retry after 3 seconds...'); - await Future.delayed(Duration(seconds: 3)); + await Future.delayed(const Duration(seconds: 3)); return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); @@ -247,7 +264,7 @@ class ApiClient { } on ClientException catch (e) { if (retryTimes > 0) { print('will retry after 3 seconds...'); - await Future.delayed(Duration(seconds: 3)); + await Future.delayed(const Duration(seconds: 3)); return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); } else { throw APIException(APIException.OTHER, arguments: e); diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 6b43bbd..e1ad116 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -5,17 +5,17 @@ class ApiConsts { // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver - // static String baseUrl = "http://10.201.204.101:2024"; - // static String baseUrl = "https://webservices.hmg.com"; // PreProd - // static String baseUrl = "https://hmgwebservices.com"; // Live server + // static String baseUrl = "http://10.201.204.101:2024"; + // static String baseUrl = "https://webservices.hmg.com"; // PreProd + // static String baseUrl = "https://hmgwebservices.com"; // Live server // static String baseUrl = "https://mohemm.hmg.com"; // New Live server // - // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver - // static String baseUrl = "http://10.20.200.111:1010/"; + static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver + // static String baseUrl = "http://10.20.200.111:1010/"; - // static String baseUrl = "https://webservices.hmg.com"; // PreProd - static String baseUrl = "https://mohemm.hmg.com"; + // static String baseUrl = "https://webservices.hmg.com"; // PreProd + // static String baseUrl = "https://mohemm.hmg.com"; // static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server @@ -55,6 +55,7 @@ class ApiConsts { static String marathonBaseUrlUAT = "https://marathoon.com/uatservice/api/"; static String marathonBaseUrl = marathonBaseUrlLive; + // static String marathonBaseUrl = marathonBaseUrlUAT; static String marathonBaseUrlServices = "https://marathoon.com/service/"; static String marathonParticipantLoginUrl = marathonBaseUrl + "auth/participantlogin"; @@ -86,5 +87,3 @@ class SharedPrefsConsts { static String mohemmWifiPassword = "mohemmWifiPassword"; static String editItemForSale = "editItemForSale"; } - - diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 0245bbf..6a9b16b 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -16,6 +16,7 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:mohem_flutter_app/widgets/loading_dialog.dart'; import 'package:nfc_manager/nfc_manager.dart'; @@ -386,4 +387,16 @@ class Utils { return false; } } + + static Future performLogout(BuildContext? context, ChatProviderModel? chatData) async { + AppState().isAuthenticated = false; + AppState().isLogged = false; + AppState().setPostParamsInitConfig(); + if (chatData != null) { + chatData.disposeData(); + } + // SharedPreferences prefs = await SharedPreferences.getInstance(); + // await prefs.clear(); + Navigator.pushNamedAndRemoveUntil(context!, AppRoutes.login, (Route route) => false, arguments: null); + } } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 1422fb2..a973aae 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -56,6 +56,8 @@ class _DashboardScreenState extends State with WidgetsBindingOb int currentIndex = 0; + bool isDisplayMazaya = false; + @override void initState() { WidgetsBinding.instance.addObserver(this); @@ -153,7 +155,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchMenuEntries(); data.fetchEventActivity(); - // data.getCategoryOffersListAPI(context); + data.getCategoryOffersListAPI(context); marathonProvider.getMarathonDetailsFromApi(); marathonProvider.getMarathonTutorial(); if (isFromInit) { @@ -421,116 +423,231 @@ class _DashboardScreenState extends State with WidgetsBindingOb ], ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), eventActivityWidget(context), + + if (isDisplayMazaya) ...[ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Directionality( + textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + gradient: const LinearGradient(colors: [Color(0xFF91C481), Color(0xFF7CCED7)], begin: Alignment.centerLeft, end: Alignment.centerRight), + ), + child: Padding( + padding: const EdgeInsets.all(3.0), // This creates the border width + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(17), // Slightly less than outer radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + flex: 2, + child: RichText( + text: + AppState().isArabic(context) + ? TextSpan( + children: [ + TextSpan( + text: 'اطلع على مميزات', + style: TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + TextSpan( + text: ' مزايا', + style: TextStyle( + fontSize: 16, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + letterSpacing: -0.2, + height: 24 / 16, + color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + ), + ), + ], + ) + : TextSpan( + children: [ + TextSpan( + text: LocaleKeys.explore.tr() + ' ', + style: const TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + TextSpan( + text: LocaleKeys.mazaya.tr(), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Poppins', + letterSpacing: -0.2, + height: 24 / 16, + color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + ), + ), + TextSpan( + text: ' ' + LocaleKeys.benefits.tr(), + style: const TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + ], + ), + ), + ), + const Expanded(flex: 1, child: SizedBox()), + ], + ), + const SizedBox(height: 8), + LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), + ], + ), + ), + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), + const SizedBox(height: 28), + LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + }), + ], + ), + ), + ], + ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), + ), + ), + ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), + ), + ], + ), + ], + Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Directionality( - textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - gradient: const LinearGradient(colors: [Color(0xFF91C481), Color(0xFF7CCED7)], begin: Alignment.centerLeft, end: Alignment.centerRight), + 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), + ), + ], + ), + ], + ), ), - child: Padding( - padding: const EdgeInsets.all(3.0), // This creates the border width - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(17), // Slightly less than outer radius - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 4, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( + 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), + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext cxt, int index) { + return model.isOffersLoading + ? const OffersShimmerWidget() + : InkWell( + onTap: () { + navigateToDetails(data.getOffersList[index]); + }, + child: SizedBox( + width: 73, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Expanded( - flex: 2, - child: RichText( - text: - AppState().isArabic(context) - ? TextSpan( - children: [ - TextSpan( - text: 'اطلع على مميزات', - style: TextStyle(fontSize: 16, letterSpacing: -0.2, fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', fontWeight: FontWeight.w700, height: 24 / 16, color: Color(0xFF5D5E5E)), - ), - TextSpan( - text: ' مزايا', - style: TextStyle( - fontSize: 16, - fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - fontWeight: FontWeight.w700, - letterSpacing: -0.2, - height: 24 / 16, - color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed - ), - ), - ], - ) - : TextSpan( - children: [ - TextSpan( - text: LocaleKeys.explore.tr() + ' ', - style: const TextStyle(fontSize: 16, letterSpacing: -0.2, fontFamily: 'Poppins', fontWeight: FontWeight.w700, height: 24 / 16, color: Color(0xFF5D5E5E)), - ), - TextSpan( - text: LocaleKeys.mazaya.tr(), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - fontFamily: 'Poppins', - letterSpacing: -0.2, - height: 24 / 16, - color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed - ), - ), - TextSpan( - text: ' ' + LocaleKeys.benefits.tr(), - style: const TextStyle(fontSize: 16, letterSpacing: -0.2, - fontFamily: 'Poppins',fontWeight: FontWeight.w700, height: 24 / 16, color: Color(0xFF5D5E5E)), - ), - ], - ), + 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), + ), + ), + ), + 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), ), - const Expanded(flex: 1, child: SizedBox()), ], ), - const SizedBox(height: 8), - LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), - ], - ), - ), - Expanded( - flex: 2, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), - const SizedBox(height: 28), - LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { - Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); - }), - ], - ), - ), - ], - ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), + ), + ); + }, + separatorBuilder: (BuildContext cxt, int index) => 8.width, + itemCount: 9, ), - ), - ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), + ); + }, ), ], ), + Container( width: double.infinity, padding: const EdgeInsets.only(top: 31), @@ -602,7 +719,10 @@ class _DashboardScreenState extends State with WidgetsBindingOb 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), label: LocaleKeys.mowadhafhiRequest.tr(), diff --git a/lib/ui/landing/widget/app_drawer.dart b/lib/ui/landing/widget/app_drawer.dart index 4721470..0eb0e52 100644 --- a/lib/ui/landing/widget/app_drawer.dart +++ b/lib/ui/landing/widget/app_drawer.dart @@ -49,32 +49,18 @@ class _AppDrawerState extends State { children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 24), - const Icon(Icons.clear).onPress(() => Navigator.pop(context)), - ], + children: [Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 24), const Icon(Icons.clear).onPress(() => Navigator.pop(context))], ).paddingOnly(left: 4, right: 14), Row( children: [ AppState().memberInformationList!.eMPLOYEEIMAGE == null - ? SvgPicture.asset( - "assets/images/user.svg", - height: 52, - width: 52, - ) - : CircleAvatar( - radius: 52 / 2, - backgroundImage: MemoryImage(Utils.dataFromBase64String(AppState().memberInformationList!.eMPLOYEEIMAGE!)), - backgroundColor: Colors.black, - ), + ? SvgPicture.asset("assets/images/user.svg", height: 52, width: 52) + : CircleAvatar(radius: 52 / 2, backgroundImage: MemoryImage(Utils.dataFromBase64String(AppState().memberInformationList!.eMPLOYEEIMAGE!)), backgroundColor: Colors.black), 12.width, Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppState().memberInformationList!.eMPLOYEENAME!.toText18(isBold: true), - AppState().memberInformationList!.getPositionName().toText14(weight: FontWeight.w500), - ], - ).expanded + children: [AppState().memberInformationList!.eMPLOYEENAME!.toText18(isBold: true), AppState().memberInformationList!.getPositionName().toText14(weight: FontWeight.w500)], + ).expanded, ], ).paddingOnly(left: 14, right: 14, top: 21, bottom: 21), // Row( @@ -99,67 +85,77 @@ class _AppDrawerState extends State { // ), // ], // ).paddingOnly(left: 14, right: 14, bottom: 14), - const Divider( - height: 1, - thickness: 1, - color: MyColors.lightGreyEFColor, - ), + const Divider(height: 1, thickness: 1, color: MyColors.lightGreyEFColor), ListView( padding: const EdgeInsets.only(top: 21, bottom: 21), children: [ ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: drawerMenuItemList.length, - itemBuilder: (cxt, index) { - return menuItem(drawerMenuItemList[index].icon, drawerMenuItemList[index].title, drawerMenuItemList[index].routeName, onPress: () { + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: drawerMenuItemList.length, + itemBuilder: (cxt, index) { + return menuItem( + drawerMenuItemList[index].icon, + drawerMenuItemList[index].title, + drawerMenuItemList[index].routeName, + onPress: () { Navigator.pushNamed(context, drawerMenuItemList[index].routeName); - }); - }), + }, + ); + }, + ), menuItem("assets/images/drawer/employee_id.svg", LocaleKeys.employeeDigitalID.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: EmployeeDigitialIdDialog())), if (AppState().businessCardPrivilege) - menuItem("assets/images/drawer/view_business_card.svg", LocaleKeys.viewBusinessCard.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: BusinessCardDialog(), isBusniessCard: true)), - menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: performLogout), + menuItem( + "assets/images/drawer/view_business_card.svg", + LocaleKeys.viewBusinessCard.tr(), + "", + closeDrawer: false, + onPress: () => showMDialog(context, child: BusinessCardDialog(), isBusniessCard: true), + ), + menuItem( + "assets/images/drawer/logout.svg", + LocaleKeys.logout.tr(), + "", + color: MyColors.redA3Color, + closeDrawer: false, + onPress: () async { + await Utils.performLogout(context, chatData); + }, + ), // menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: () {Navigator.pushNamed(context, AppRoutes.survey,); ], ).expanded, - const Divider( - height: 1, - thickness: 1, - color: MyColors.lightGreyEFColor, - ), + const Divider(height: 1, thickness: 1, color: MyColors.lightGreyEFColor), Row( children: [ RichText( - text: TextSpan(text: LocaleKeys.poweredBy.tr() + " ", style: const TextStyle(color: MyColors.grey98Color, fontSize: 14, letterSpacing: -0.56, fontWeight: FontWeight.w600), children: [ - TextSpan( - text: LocaleKeys.cloudSolutions.tr(), - style: const TextStyle(color: MyColors.grey3AColor, fontSize: 14, letterSpacing: -0.56, fontWeight: FontWeight.w600), - ), - ]), + text: TextSpan( + text: LocaleKeys.poweredBy.tr() + " ", + style: const TextStyle(color: MyColors.grey98Color, fontSize: 14, letterSpacing: -0.56, fontWeight: FontWeight.w600), + children: [TextSpan(text: LocaleKeys.cloudSolutions.tr(), style: const TextStyle(color: MyColors.grey3AColor, fontSize: 14, letterSpacing: -0.56, fontWeight: FontWeight.w600))], + ), ).expanded, - Image.asset("assets/images/logos/bn_cloud_soloution.jpg", width: 40, height: 40) + Image.asset("assets/images/logos/bn_cloud_soloution.jpg", width: 40, height: 40), ], - ).paddingOnly(left: 21, right: 21, top: 21) + ).paddingOnly(left: 21, right: 21, top: 21), ], ).paddingOnly(top: 21, bottom: 21), ); } Widget menuItem(String icon, String title, String routeName, {Color? color, bool closeDrawer = true, VoidCallback? onPress}) { - return Row( - children: [ - SvgPicture.asset(icon, height: 20, width: 20), - 9.width, - title.toText14(color: color, textAlign: AppState().isArabic(context) ? TextAlign.right : null).expanded, - ], - ).paddingOnly(left: 21, top: 10, bottom: 10, right: 21).onPress(closeDrawer - ? () async { - Navigator.pop(context); - Future.delayed(const Duration(microseconds: 200), onPress); - } - : onPress!); + return Row(children: [SvgPicture.asset(icon, height: 20, width: 20), 9.width, title.toText14(color: color, textAlign: AppState().isArabic(context) ? TextAlign.right : null).expanded]) + .paddingOnly(left: 21, top: 10, bottom: 10, right: 21) + .onPress( + closeDrawer + ? () async { + Navigator.pop(context); + Future.delayed(const Duration(microseconds: 200), onPress); + } + : onPress!, + ); } void postLanguageChange(BuildContext context) { @@ -170,14 +166,4 @@ class _AppDrawerState extends State { widget.onLanguageChange(); setState(() {}); } - - void performLogout() async { - AppState().isAuthenticated = false; - AppState().isLogged = false; - AppState().setPostParamsInitConfig(); - chatData.disposeData(); - // SharedPreferences prefs = await SharedPreferences.getInstance(); - // await prefs.clear(); - Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: null); - } } diff --git a/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart b/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart index f67a835..dbc2366 100644 --- a/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart +++ b/lib/ui/screens/offers_and_discounts/offers_and_discounts_home.dart @@ -39,7 +39,7 @@ class _OffersAndDiscountsHomeState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, - appBar: AppBarWidget(context, title: LocaleKeys.offerAndDiscounts.tr(), showHomeButton: true, showLogo: true, logoPath: "assets/icons/mazaya_brand.svg"), + appBar: AppBarWidget(context, title: LocaleKeys.offerAndDiscounts.tr(), showHomeButton: true, showLogo: false, logoPath: "assets/icons/mazaya_brand.svg"), body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, From 5809aa157fae7ccf1b5f378c607f3adbc9030745 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Wed, 31 Dec 2025 16:09:07 +0300 Subject: [PATCH 02/17] Ticket Attachments --- lib/api/dashboard_api_client.dart | 84 +++++++++------- lib/models/eit/get_eit_transaction_model.dart | 4 +- lib/models/eit_attachment_ticket_model.dart | 97 +++++++++++++++++++ lib/provider/dashboard_provider_model.dart | 18 ++++ lib/ui/landing/widget/menus_widget.dart | 1 + .../ticket/ticket_detailed_screen.dart | 64 ++++++++++-- 6 files changed, 224 insertions(+), 44 deletions(-) create mode 100644 lib/models/eit_attachment_ticket_model.dart diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index ae5fda8..f04080c 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -14,11 +14,11 @@ import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_mo 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'; +import 'package:mohem_flutter_app/models/eit_attachment_ticket_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/sso_auth_model.dart'; -import 'package:platform_device_id_plus/platform_device_id.dart'; // import 'package:platform_device_id/platform_device_id.dart'; // import 'package:platform_device_id/platform_device_id.dart'; @@ -33,7 +33,7 @@ class DashboardApiClient { Future getAttendanceTracking() async { String url = "${ApiConsts.erpRest}GET_Attendance_Tracking"; - Map postParams = {}; + Map postParams = {}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { @@ -47,7 +47,7 @@ class DashboardApiClient { Future getOpenNotifications() async { String url = "${ApiConsts.erpRest}GET_OPEN_NOTIFICATIONS"; - Map postParams = {}; + Map postParams = {}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { @@ -61,7 +61,7 @@ class DashboardApiClient { Future getCOCNotifications() async { String url = "${ApiConsts.cocRest}Mohemm_ITG_ReviewerAdmin_Pending_Tasks"; - Map postParams = {"Date": DateUtil.getISODateFormat(DateTime.now()), "EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER}; + Map postParams = {"Date": DateUtil.getISODateFormat(DateTime.now()), "EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { @@ -75,7 +75,7 @@ class DashboardApiClient { Future getItgFormsPendingTask() async { String url = "${ApiConsts.cocRest}ITGFormsPendingTasks"; - Map postParams = {}; + Map postParams = {}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { @@ -89,13 +89,13 @@ class DashboardApiClient { Future> getAccrualBalances(String effectiveDate, {String? empID}) async { String url = "${ApiConsts.erpRest}GET_ACCRUAL_BALANCES"; - Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; + 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.getAccrualBalancesList ?? []; + return responseData.getAccrualBalancesList ?? []; }, url, postParams, @@ -104,13 +104,13 @@ class DashboardApiClient { Future> getTicketAccuralBalance(String effectiveDate, {String? empID}) async { String url = "${ApiConsts.erpRest}GET_TICKET_ACCRUAL_BALANCES"; - Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; + 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 ?? []; + return responseData.getAccrualBalancesTicketList ?? []; }, url, postParams, @@ -119,7 +119,7 @@ class DashboardApiClient { Future getOpenMissingSwipes() async { String url = "${ApiConsts.erpRest}GET_OPEN_MISSING_SWIPES"; - Map postParams = {}; + Map postParams = {}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { @@ -134,12 +134,12 @@ class DashboardApiClient { //Menus List Future> getListMenu() async { String url = "${ApiConsts.erpRest}GET_MENU"; - Map postParams = {}; + Map postParams = {}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { GenericResponseModel responseData = GenericResponseModel.fromJson(json); - return responseData.listMenu ?? []; + return responseData.listMenu ?? []; }, url, postParams, @@ -149,7 +149,7 @@ class DashboardApiClient { //GET_MENU_ENTRIES Future getGetMenuEntries() async { String url = "${ApiConsts.erpRest}GET_MENU_ENTRIES"; - Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E"}; + Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E"}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { @@ -163,7 +163,7 @@ class DashboardApiClient { Future getEventActivity() async { String url = "${ApiConsts.erpRest}Get_EventActivity"; - Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E"}; + Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E"}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { @@ -177,7 +177,7 @@ class DashboardApiClient { Future getTicketBookingRedirection() async { String url = "${ApiConsts.erpRest}GET_PORTAL_REDIRECTION"; - Map postParams = {"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER}; + Map postParams = {"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { @@ -191,7 +191,7 @@ class DashboardApiClient { Future getTicketBalance() async { String url = "${ApiConsts.erpRest}GET_TICKET_BALANCE"; - Map postParams = {"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER}; + Map postParams = {"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( @@ -208,7 +208,7 @@ class DashboardApiClient { String url = "${ApiConsts.ssoAuthRedirection}?grantType=mohemm"; //https://sso-uat.hmg.com/api/auth/connect?grantType=mohemm' // Map postParams = {"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER}; - Map postParams = { + Map postParams = { "ClientId": clientID, // "ClientId": "a9f4d1a0596d4aea8f830992ec4bdac1", "PersonId": AppState().memberInformationList?.eMPLOYEENUMBER, @@ -227,18 +227,34 @@ class DashboardApiClient { ); } - Future getBookingSSOFinalRedirection({required String token}) async { - 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}); - - // request.headers.addAll(headers); + Future getTicketEitPDFDownload({required String peiExtraInfoId}) async { + String url = "${ApiConsts.erpRest}GET_EIT_ATTACHMENTS"; + Map postParams = { + "P_PERSON_EXTRA_INFO_ID": peiExtraInfoId, + "PersonId": AppState().memberInformationList?.eMPLOYEENUMBER, + "Username": AppState().memberInformationList?.eMPLOYEENUMBER, + "Language": "US", + "SessionId": AppState().postParamsObject?.pSessionId, + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GetEitAttachmentTicket responseData = GetEitAttachmentTicket.fromJson(json); + return responseData; + }, + url, + postParams, + ); + } + Future getBookingSSOFinalRedirection({required String token}) async { + // token = + // "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhjZTE2OWM0YjIwYjQ2ZWM5YTQyOTU3Y2ZhODUzNzQ1IiwidHlwIjoiSldUIn0.eyJ0ZW5hbnRfaWQiOiJhOWY0ZDFhMDU5NmQ0YWVhOGY4MzA5OTJlYzRiZGFjMSIsImVpZCI6IjExNzkzMCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3NpZCI6Ijk2MDI0OGM1NzA3YzQ3MmFhYTEzM2I1N2ZhODE1ZmVhIiwibGFuZ3VhZ2UiOiJVUyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6IjExNzkzMEBobWcuY29tIiwiZXhwIjoxNzgyNDc1NzY5LCJpc3MiOiJodHRwczovL3Nzby11YXQuaG1nLmNvbSIsImF1ZCI6ImE5ZjRkMWEwNTk2ZDRhZWE4ZjgzMDk5MmVjNGJkYWMxIn0.rJcLVsG8D0XECyLERCTD2uqGeWyvp-OBVGE9uL2qKrX4etFUHgdFt_5kYF6edFTtGy-0PIZadHDmv7e-IOhVWHm5HVMClaukiXoRXR8cDN8XA1wfme3Kd-U5PXN-IRh49AyRTzLO0rYNPvH81ScosWGlsFSkOvA-0hJNa2adHdtvgNvB8wJshSU5p7sAmF8mjdDY6aInG19etu2iEuUDwHHA4ZY_ts4hboHo8fE392hFaYGonExoD7bpW5RMx5xKWeRCmWpG_PK8Aw_z1jGzdB9PANus4pteRGuln1J-kmo2lQC9pVrSyZATAKp1HfgfyZ_vUhaHEfM69cMWaCslJQ"; + http.MultipartRequest request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG')); + request.fields.addAll({'JWTToken': token}); http.StreamedResponse response = await request.send(); if (response.statusCode == 302) { - print("================== post =========="); - var res = await response.stream.bytesToString(); + String res = await response.stream.bytesToString(); return response.headers["location"]; } else { print(response.reasonPhrase); @@ -256,7 +272,7 @@ class DashboardApiClient { String payrollCode = "", }) async { String url = "${ApiConsts.swpRest}AuthenticateAndSwipeUserSupportNFC"; - var uuid = Uuid(); + Uuid uuid = Uuid(); String? deviceId = ""; // Generate a v4 (random) id if (Platform.isAndroid) { @@ -266,7 +282,7 @@ class DashboardApiClient { IosDeviceInfo iosInfo = await DeviceInfoPlugin().iosInfo; deviceId = iosInfo.identifierForVendor; } - Map postParams = { + Map postParams = { "UID": deviceId, //uuid.v4(), //Mobile Id // "UID": uuid.v4(), //Mobile Id "Latitude": lat, @@ -292,10 +308,10 @@ class DashboardApiClient { //Mark Fake Location Future markFakeLocation({String lat = "0", String? long = "0", required String sourceName}) async { String url = "${ApiConsts.swpRest}CreateIssueInfo"; - var uuid = Uuid(); + Uuid uuid = Uuid(); // Generate a v4 (random) id - Map postParams = { + Map postParams = { "UID": uuid.v4(), //Mobile Id "Latitude": lat, "Longitude": long, @@ -319,7 +335,7 @@ class DashboardApiClient { Future getITGPageNotification() async { String url = "${ApiConsts.cocRest}Mohemm_ITG_GetPageNotification"; - Map postParams = { + Map postParams = { "EmployeeNumber": AppState().getUserName, "ItgEnableAt": "After Service Submission", //Mobile Id "ItgServiceName": "Login", @@ -341,7 +357,7 @@ class DashboardApiClient { Future submitItgForm({required String comment, required String masterId, required List> itgList, required int serviceId}) async { String url = "${ApiConsts.cocRest}Mohemm_ITG_Survey_Response"; - Map postParams = { + Map postParams = { "EmployeeNumber": AppState().getUserName, "ItgComments": comment, "ItgNotificationMasterId": masterId, @@ -362,7 +378,7 @@ class DashboardApiClient { Future getAdvertisementDetail(String masterID) async { String url = "${ApiConsts.cocRest}Mohemm_ITG_GetPageNotificationDetails"; - Map postParams = { + Map postParams = { "EmployeeNumber": AppState().getUserName, "ItgNotificationMasterId": masterID, //Mobile Id }; @@ -380,7 +396,7 @@ class DashboardApiClient { Future setAdvertisementViewed(String masterID, int advertisementId, String? ackValue) async { String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed"; - Map postParams = { + Map postParams = { "ItgNotificationMasterId": masterID, "EmployeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), "ItgAdvertisementId": advertisementId, diff --git a/lib/models/eit/get_eit_transaction_model.dart b/lib/models/eit/get_eit_transaction_model.dart index dffe320..eec3d98 100644 --- a/lib/models/eit/get_eit_transaction_model.dart +++ b/lib/models/eit/get_eit_transaction_model.dart @@ -30,7 +30,7 @@ class CollectionTransaction { String? dISPLAYFLAG; int? fROMROWNUM; int? nOOFROWS; - dynamic? nUMBERVALUE; + dynamic nUMBERVALUE; int? rOWNUM; String? sEGMENTNAME; String? sEGMENTPROMPT; @@ -80,7 +80,7 @@ class CollectionTransaction { } Map toJson() { - Map data = new Map(); + Map data = Map(); data['APPLICATION_COLUMN_NAME'] = this.aPPLICATIONCOLUMNNAME; data['DATATYPE'] = this.dATATYPE; data['DATE_VALUE'] = this.dATEVALUE; diff --git a/lib/models/eit_attachment_ticket_model.dart b/lib/models/eit_attachment_ticket_model.dart new file mode 100644 index 0000000..fe88831 --- /dev/null +++ b/lib/models/eit_attachment_ticket_model.dart @@ -0,0 +1,97 @@ +import 'dart:convert'; + +class GetEitAttachmentTicket { + List? getEitAttachmentList; + + GetEitAttachmentTicket({ + this.getEitAttachmentList, + }); + + factory GetEitAttachmentTicket.fromRawJson(String str) => GetEitAttachmentTicket.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetEitAttachmentTicket.fromJson(Map json) => GetEitAttachmentTicket( + getEitAttachmentList: json["GetEITAttachmentList"] == null ? [] : List.from(json["GetEITAttachmentList"]!.map((x) => GetEitAttachmentList.fromJson(x))), + ); + + Map toJson() => { + "GetEITAttachmentList": getEitAttachmentList == null ? [] : List.from(getEitAttachmentList!.map((x) => x.toJson())), + }; +} + +class GetEitAttachmentList { + int? attachedDocumentId; + int? categoryId; + int? datatypeId; + int? documentId; + String? entityName; + String? fileContentType; + String? fileData; + int? fileId; + String? fileName; + String? pk1Value; + String? pk2Value; + String? pk3Value; + String? pk4Value; + String? pk5Value; + int? seqNum; + + GetEitAttachmentList({ + this.attachedDocumentId, + this.categoryId, + this.datatypeId, + this.documentId, + this.entityName, + this.fileContentType, + this.fileData, + this.fileId, + this.fileName, + this.pk1Value, + this.pk2Value, + this.pk3Value, + this.pk4Value, + this.pk5Value, + this.seqNum, + }); + + factory GetEitAttachmentList.fromRawJson(String str) => GetEitAttachmentList.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetEitAttachmentList.fromJson(Map json) => GetEitAttachmentList( + attachedDocumentId: json["ATTACHED_DOCUMENT_ID"], + categoryId: json["CATEGORY_ID"], + datatypeId: json["DATATYPE_ID"], + documentId: json["DOCUMENT_ID"], + entityName: json["ENTITY_NAME"], + fileContentType: json["FILE_CONTENT_TYPE"], + fileData: json["FILE_DATA"], + fileId: json["FILE_ID"], + fileName: json["FILE_NAME"], + pk1Value: json["PK1_VALUE"], + pk2Value: json["PK2_VALUE"], + pk3Value: json["PK3_VALUE"], + pk4Value: json["PK4_VALUE"], + pk5Value: json["PK5_VALUE"], + seqNum: json["SEQ_NUM"], + ); + + Map toJson() => { + "ATTACHED_DOCUMENT_ID": attachedDocumentId, + "CATEGORY_ID": categoryId, + "DATATYPE_ID": datatypeId, + "DOCUMENT_ID": documentId, + "ENTITY_NAME": entityName, + "FILE_CONTENT_TYPE": fileContentType, + "FILE_DATA": fileData, + "FILE_ID": fileId, + "FILE_NAME": fileName, + "PK1_VALUE": pk1Value, + "PK2_VALUE": pk2Value, + "PK3_VALUE": pk3Value, + "PK4_VALUE": pk4Value, + "PK5_VALUE": pk5Value, + "SEQ_NUM": seqNum, + }; +} diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 05c9ebb..bdd60c7 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -20,6 +20,7 @@ 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/eit_attachment_ticket_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'; @@ -376,6 +377,23 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } + Future getTicketEitPDFDownload({String? peiExtraInfoId}) async { + try { + GetEitAttachmentTicket? res = await DashboardApiClient().getTicketEitPDFDownload(peiExtraInfoId: peiExtraInfoId!); + if (res?.getEitAttachmentList != null && res?.getEitAttachmentList!.length! != 0 && res!.getEitAttachmentList!.first.fileData != null) { + return res; + } else { + return null; + } + } catch (ex) { + logger.wtf(ex); + isEventLoadingLoading = false; + notifyListeners(); + Utils.handleException(ex, null, null); + return null; // Ensure a return value in case of an exception + } + } + List parseMenus(List getMenuEntriesList) { List menus = []; for (int i = 0; i < getMenuEntriesList.length; i++) { diff --git a/lib/ui/landing/widget/menus_widget.dart b/lib/ui/landing/widget/menus_widget.dart index be04937..72df91c 100644 --- a/lib/ui/landing/widget/menus_widget.dart +++ b/lib/ui/landing/widget/menus_widget.dart @@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/eit/get_eit_transaction_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'; diff --git a/lib/ui/screens/ticket/ticket_detailed_screen.dart b/lib/ui/screens/ticket/ticket_detailed_screen.dart index d406153..3e8d0b1 100644 --- a/lib/ui/screens/ticket/ticket_detailed_screen.dart +++ b/lib/ui/screens/ticket/ticket_detailed_screen.dart @@ -5,11 +5,14 @@ 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/file_process.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/models/eit/get_eit_transaction_model.dart'; +import 'package:mohem_flutter_app/models/eit_attachment_ticket_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'; @@ -125,8 +128,8 @@ class _TicketDetailedScreenState extends State { shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (BuildContext cxt, int cardIndex) { - var transactionDetails = dashboardProviderModel!.ticketHistoryTransactionList![cardIndex]; - const allowedSegmentNames = { + List transactionDetails = dashboardProviderModel!.ticketHistoryTransactionList![cardIndex]; + const Set allowedSegmentNames = { "TICKETS_ROUTE", "TRAVELER_NAME", "TICKETS_EFFECTIVE_DATE", @@ -135,11 +138,22 @@ class _TicketDetailedScreenState extends State { "TICKET_COMP_SHARE", "TICKET_EMP_SHARE", }; - var uniqueDetails = + // Get items for display + List uniqueDetails = transactionDetails - .where((item) => item.dISPLAYFLAG != 'N' && item.sEGMENTPROMPT != null && item.sEGMENTPROMPT!.isNotEmpty && allowedSegmentNames.contains(item.sEGMENTNAME)) + .where( + (CollectionTransaction item) => + item.dISPLAYFLAG != 'N' && item.sEGMENTPROMPT != null && item.sEGMENTPROMPT!.isNotEmpty && allowedSegmentNames.contains(item.sEGMENTNAME), + ) .toList(); + // Get PEI_EXTRA_INFO_ID value for View PDF + CollectionTransaction? peiExtraInfoItem = transactionDetails.firstWhere( + (CollectionTransaction item) => item.aPPLICATIONCOLUMNNAME == "PEI_EXTRA_INFO_ID", + orElse: () => CollectionTransaction(), + ); + num? peiExtraInfoId = peiExtraInfoItem.nUMBERVALUE; + return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, @@ -148,15 +162,15 @@ class _TicketDetailedScreenState extends State { physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: (uniqueDetails.length / 2).ceil(), - itemBuilder: (context, rowIndex) { + itemBuilder: (BuildContext context, int 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() ?? ""); + CollectionTransaction item1 = uniqueDetails[firstIndex]; + ItemDetailViewCol child1 = ItemDetailViewCol(item1.sEGMENTPROMPT!, item1.vARCHAR2VALUE ?? item1.nUMBERVALUE?.toString() ?? ""); Widget child2; if (secondIndex != null) { - var item2 = uniqueDetails[secondIndex]; + CollectionTransaction item2 = uniqueDetails[secondIndex]; child2 = ItemDetailViewCol(item2.sEGMENTPROMPT!, item2.vARCHAR2VALUE ?? item2.nUMBERVALUE?.toString() ?? ""); } else { child2 = const SizedBox(); // Empty widget if there is no second item @@ -164,6 +178,40 @@ class _TicketDetailedScreenState extends State { return ItemDetailGrid(child1, child2, isItLast: isLastRow); }, ), + // View PDF link at the bottom + if (peiExtraInfoId != null) ...[ + const SizedBox(height: 5), + Align( + alignment: Alignment.centerRight, + child: GestureDetector( + onTap: () async { + Utils.showLoading(context); + try { + GetEitAttachmentTicket? result = await dashboardProviderModel!.getTicketEitPDFDownload(peiExtraInfoId: peiExtraInfoId.toString()); + if (result != null && result.getEitAttachmentList != null && result.getEitAttachmentList!.isNotEmpty) { + String? base64Data = result.getEitAttachmentList!.first.fileData; + if (base64Data != null && base64Data.isNotEmpty) { + String fileName = result.getEitAttachmentList!.first.fileName!; + await FileProcess.downloadFile(base64Data, fileName); + Utils.hideLoading(context); + FileProcess.openFile(fileName); + } else { + Utils.hideLoading(context); + Utils.showToast("PDF data not available"); + } + } else { + Utils.hideLoading(context); + Utils.showToast("No attachment found"); + } + } catch (e) { + Utils.hideLoading(context); + Utils.showToast("Something Went Wrong"); + } + }, + child: Padding(padding: const EdgeInsets.only(top: 8.0, left: 0.0, bottom: 8.0), child: "View PDF".toText14(isUnderLine: true, isBold: true)), + ), + ), + ], ], ).objectContainerView(); }, From ba8908d4eb187703b7bdfbe45fae01e01674c275 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Sun, 1 Mar 2026 12:01:46 +0300 Subject: [PATCH 03/17] Greeting Card --- lib/api/dashboard_api_client.dart | 15 + lib/models/greetings/greeting_card_model.dart | 105 ++ lib/provider/dashboard_provider_model.dart | 25 + lib/ui/landing/dashboard_screen.dart | 1280 +++++++++-------- 4 files changed, 851 insertions(+), 574 deletions(-) create mode 100644 lib/models/greetings/greeting_card_model.dart diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 6f7288c..3265774 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -17,6 +17,7 @@ import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart'; import 'package:mohem_flutter_app/models/dashboard/list_menu.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/get_employee_parking_details_model.dart'; +import 'package:mohem_flutter_app/models/greetings/greeting_card_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/sso_auth_model.dart'; @@ -429,4 +430,18 @@ class DashboardApiClient { postParams, ); } + + Future getGreetingCards() async { + String url = "${ApiConsts.erpRest}Get_GreetingCards"; + Map postParams = {}; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject( + (json) { + GetGreetingCardsModelResponse responseData = GetGreetingCardsModelResponse.fromJson(json); + return responseData; + }, + url, + postParams, + ); + } } diff --git a/lib/models/greetings/greeting_card_model.dart b/lib/models/greetings/greeting_card_model.dart new file mode 100644 index 0000000..99b93ed --- /dev/null +++ b/lib/models/greetings/greeting_card_model.dart @@ -0,0 +1,105 @@ +import 'dart:convert'; + +class GetGreetingCardsModelResponse { + List? getGreetingCardsModelResponse; + + GetGreetingCardsModelResponse({ + this.getGreetingCardsModelResponse, + }); + + factory GetGreetingCardsModelResponse.fromRawJson(String str) => GetGreetingCardsModelResponse.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetGreetingCardsModelResponse.fromJson(Map json) => GetGreetingCardsModelResponse( + getGreetingCardsModelResponse: json["Get_GreetingCardsModel_Response"] == null ? [] : List.from(json["Get_GreetingCardsModel_Response"]!.map((x) => GetGreetingCardsModelResponseElement.fromJson(x))), + ); + + Map toJson() => { + "Get_GreetingCardsModel_Response": getGreetingCardsModelResponse == null ? [] : List.from(getGreetingCardsModelResponse!.map((x) => x.toJson())), + }; +} + +class GetGreetingCardsModelResponseElement { + int? id; + dynamic titleEn; + String? titleAr; + String? descriptionEn; + String? descriptionAr; + String? startDate; + String? endDate; + String? urlEn; + String? urlAr; + String? backgroundImageUrlEn; + String? backgroundImageUrlAr; + int? channel; + int? categoryId; + String? categoryNameAr; + String? categoryNameEn; + String? createdOn; + bool? isActive; + + GetGreetingCardsModelResponseElement({ + this.id, + this.titleEn, + this.titleAr, + this.descriptionEn, + this.descriptionAr, + this.startDate, + this.endDate, + this.urlEn, + this.urlAr, + this.backgroundImageUrlEn, + this.backgroundImageUrlAr, + this.channel, + this.categoryId, + this.categoryNameAr, + this.categoryNameEn, + this.createdOn, + this.isActive, + }); + + factory GetGreetingCardsModelResponseElement.fromRawJson(String str) => GetGreetingCardsModelResponseElement.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory GetGreetingCardsModelResponseElement.fromJson(Map json) => GetGreetingCardsModelResponseElement( + id: json["ID"], + titleEn: json["TitleEn"], + titleAr: json["TitleAr"], + descriptionEn: json["DescriptionEn"], + descriptionAr: json["DescriptionAr"], + startDate: json["StartDate"], + endDate: json["EndDate"], + urlEn: json["UrlEn"], + urlAr: json["UrlAr"], + backgroundImageUrlEn: json["BackgroundImageUrlEn"], + backgroundImageUrlAr: json["BackgroundImageUrlAr"], + channel: json["Channel"], + categoryId: json["CategoryID"], + categoryNameAr: json["CategoryNameAr"], + categoryNameEn: json["CategoryNameEn"], + createdOn: json["CreatedOn"], + isActive: json["IsActive"], + ); + + Map toJson() => { + "ID": id, + "TitleEn": titleEn, + "TitleAr": titleAr, + "DescriptionEn": descriptionEn, + "DescriptionAr": descriptionAr, + "StartDate": startDate, + "EndDate": endDate, + "UrlEn": urlEn, + "UrlAr": urlAr, + "BackgroundImageUrlEn": backgroundImageUrlEn, + "BackgroundImageUrlAr": backgroundImageUrlAr, + "Channel": channel, + "CategoryID": categoryId, + "CategoryNameAr": categoryNameAr, + "CategoryNameEn": categoryNameEn, + "CreatedOn": createdOn, + "IsActive": isActive, + }; +} diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index dd1472b..09c347e 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -21,6 +21,7 @@ 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/greetings/greeting_card_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'; import 'package:mohem_flutter_app/models/sso_auth_model.dart'; @@ -67,6 +68,9 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool isOffersLoading = true; List getOffersList = []; + bool isDisplayEidGreetings = false; + List? greetingCardsList; + //Attendance Tracking API's & Methods Future fetchAttendanceTracking(context) async { try { @@ -307,6 +311,27 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } + void fetchGreetingCards() async { + try { + GetGreetingCardsModelResponse? response = await DashboardApiClient().getGreetingCards(); + greetingCardsList = response?.getGreetingCardsModelResponse ?? []; + + // Check if there are any active greeting cards + if (greetingCardsList != null && greetingCardsList!.isNotEmpty) { + isDisplayEidGreetings = greetingCardsList!.any((card) => card.isActive == true); + } else { + isDisplayEidGreetings = false; + } + + notifyListeners(); + } catch (ex) { + logger.wtf(ex); + isDisplayEidGreetings = false; + greetingCardsList = []; + notifyListeners(); + } + } + Future fetchTicketBooking() async { try { GenericResponseModel? genericResponseModel = await DashboardApiClient().getTicketBookingRedirection(); diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 3122d17..aca7aba 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -155,6 +155,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchMenuEntries(); data.fetchEventActivity(); + data.fetchGreetingCards(); data.getCategoryOffersListAPI(context); marathonProvider.getMarathonDetailsFromApi(); marathonProvider.getMarathonTutorial(); @@ -253,585 +254,716 @@ class _DashboardScreenState extends State with WidgetsBindingOb child: Scaffold( key: _scaffoldState, body: Column( - 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(); - }); - }, - ), - Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28).expanded, - 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), - controller: _refreshController, - onRefresh: () { - _onRefresh(false); - }, - child: SingleChildScrollView( - child: Column( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color), - (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true), - 16.height, - Row( - children: [ - Expanded( - child: AspectRatio( - aspectRatio: 159 / 159, - child: Consumer( - builder: (BuildContext context, DashboardProviderModel model, Widget? child) { - 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], - ), - ), - 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( - 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: const Color(0xff259EA4), - borderRadius: BorderRadius.only( - bottomRight: AppState().isArabic(context) ? const Radius.circular(0) : const Radius.circular(15), - bottomLeft: AppState().isArabic(context) ? const Radius.circular(15) : const 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()), - ], - ), - ], - ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), - eventActivityWidget(context), - - if (isDisplayMazaya) ...[ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Directionality( - textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - gradient: const LinearGradient(colors: [Color(0xFF91C481), Color(0xFF7CCED7)], begin: Alignment.centerLeft, end: Alignment.centerRight), - ), - child: Padding( - padding: const EdgeInsets.all(3.0), // This creates the border width - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(17), // Slightly less than outer radius - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 4, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - flex: 2, - child: RichText( - text: - AppState().isArabic(context) - ? TextSpan( - children: [ - TextSpan( - text: 'اطلع على مميزات', - style: TextStyle( - fontSize: 16, - letterSpacing: -0.2, - fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - fontWeight: FontWeight.w700, - height: 24 / 16, - color: Color(0xFF5D5E5E), - ), - ), - TextSpan( - text: ' مزايا', - style: TextStyle( - fontSize: 16, - fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - fontWeight: FontWeight.w700, - letterSpacing: -0.2, - height: 24 / 16, - color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed - ), - ), - ], - ) - : TextSpan( - children: [ - TextSpan( - text: LocaleKeys.explore.tr() + ' ', - style: const TextStyle( - fontSize: 16, - letterSpacing: -0.2, - fontFamily: 'Poppins', - fontWeight: FontWeight.w700, - height: 24 / 16, - color: Color(0xFF5D5E5E), - ), - ), - TextSpan( - text: LocaleKeys.mazaya.tr(), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - fontFamily: 'Poppins', - letterSpacing: -0.2, - height: 24 / 16, - color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed - ), - ), - TextSpan( - text: ' ' + LocaleKeys.benefits.tr(), - style: const TextStyle( - fontSize: 16, - letterSpacing: -0.2, - fontFamily: 'Poppins', - fontWeight: FontWeight.w700, - height: 24 / 16, - color: Color(0xFF5D5E5E), - ), - ), - ], - ), - ), - ), - const Expanded(flex: 1, child: SizedBox()), - ], - ), - const SizedBox(height: 8), - LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), - ], - ), - ), - Expanded( - flex: 2, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), - const SizedBox(height: 28), - LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { - Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); - }), - ], - ), - ), - ], - ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), - ), - ), - ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), - ), - ], - ), - ], + 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(); + }); + }, + ), + Image + .asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28) + .expanded, + 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), + controller: _refreshController, + onRefresh: () { + _onRefresh(false); + }, + child: SingleChildScrollView( + child: Column( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color), + (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true), + 16.height, + Row( + children: [ + Expanded( + child: AspectRatio( + aspectRatio: 159 / 159, + child: Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + 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], + ), + ), + 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( + 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: const Color(0xff259EA4), + borderRadius: BorderRadius.only( + bottomRight: AppState().isArabic(context) ? const Radius.circular(0) : const Radius.circular(15), + bottomLeft: AppState().isArabic(context) ? const Radius.circular(15) : const 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()), + ], + ), + ], + ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), + if (data.isDisplayEidGreetings) ...[ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Directionality( + textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + gradient: const LinearGradient(colors: [Color(0xFFE7E7E7), Color(0xFFE7E7E7)], begin: Alignment.centerLeft, end: Alignment.centerRight), + ), + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Container( + height: 120, + decoration: BoxDecoration(color: const Color(0xFFFAF4E7),borderRadius: BorderRadius.circular(17), image: DecorationImage(image: NetworkImage(AppState().isArabic(context) ? data.greetingCardsList!.first.backgroundImageUrlAr ?? "" : data.greetingCardsList!.first.backgroundImageUrlEn ?? ""), fit: BoxFit.cover)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Expanded( + // flex: 4, + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // Row( + // children: [ + // Expanded( + // flex: 2, + // child: RichText( + // text: + // AppState().isArabic(context) + // ? TextSpan( + // children: [ + // TextSpan( + // text: 'اطلع على مميزات', + // style: TextStyle( + // fontSize: 16, + // letterSpacing: -0.2, + // fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + // fontWeight: FontWeight.w700, + // height: 24 / 16, + // color: const Color(0xFF5D5E5E), + // ), + // ), + // TextSpan( + // text: ' مزايا', + // style: TextStyle( + // fontSize: 16, + // fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + // fontWeight: FontWeight.w700, + // letterSpacing: -0.2, + // height: 24 / 16, + // color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + // ), + // ), + // ], + // ) + // : TextSpan( + // children: [ + // TextSpan( + // text: LocaleKeys.explore.tr() + ' ', + // style: const TextStyle( + // fontSize: 16, + // letterSpacing: -0.2, + // fontFamily: 'Poppins', + // fontWeight: FontWeight.w700, + // height: 24 / 16, + // color: Color(0xFF5D5E5E), + // ), + // ), + // TextSpan( + // text: LocaleKeys.mazaya.tr(), + // style: const TextStyle( + // fontSize: 16, + // fontWeight: FontWeight.w700, + // fontFamily: 'Poppins', + // letterSpacing: -0.2, + // height: 24 / 16, + // color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + // ), + // ), + // TextSpan( + // text: ' ' + LocaleKeys.benefits.tr(), + // style: const TextStyle( + // fontSize: 16, + // letterSpacing: -0.2, + // fontFamily: 'Poppins', + // fontWeight: FontWeight.w700, + // height: 24 / 16, + // color: Color(0xFF5D5E5E), + // ), + // ), + // ], + // ), + // ), + // ), + // const Expanded(flex: 1, child: SizedBox()), + // ], + // ), + // const SizedBox(height: 8), + // LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), + // ], + // ), + // ), + // Expanded( + // flex: 2, + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.end, + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), + // const SizedBox(height: 28), + // LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { + // Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + // }), + // ], + // ), + // ), + ], + ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), + ), + ), + ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), + ), + ], + ), + ], + eventActivityWidget(context), + if (isDisplayMazaya) ...[ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Directionality( + textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + gradient: const LinearGradient(colors: [Color(0xFF91C481), Color(0xFF7CCED7)], begin: Alignment.centerLeft, end: Alignment.centerRight), + ), + child: Padding( + padding: const EdgeInsets.all(3.0), // This creates the border width + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(17), // Slightly less than outer radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + flex: 2, + child: RichText( + text: + AppState().isArabic(context) + ? TextSpan( + children: [ + TextSpan( + text: 'اطلع على مميزات', + style: TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: const Color(0xFF5D5E5E), + ), + ), + TextSpan( + text: ' مزايا', + style: TextStyle( + fontSize: 16, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + letterSpacing: -0.2, + height: 24 / 16, + color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + ), + ), + ], + ) + : TextSpan( + children: [ + TextSpan( + text: LocaleKeys.explore.tr() + ' ', + style: const TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + TextSpan( + text: LocaleKeys.mazaya.tr(), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Poppins', + letterSpacing: -0.2, + height: 24 / 16, + color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + ), + ), + TextSpan( + text: ' ' + LocaleKeys.benefits.tr(), + style: const TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + ], + ), + ), + ), + const Expanded(flex: 1, child: SizedBox()), + ], + ), + const SizedBox(height: 8), + LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), + ], + ), + ), + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), + const SizedBox(height: 28), + LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + }), + ], + ), + ), + ], + ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), + ), + ), + ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), + ), + ], + ), + ], - 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)), - ], - ), - ], - ), - ), - 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), - scrollDirection: Axis.horizontal, - itemBuilder: (BuildContext cxt, int index) { - 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, - ), - ), - ), - ), - 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), - ); - }, - ), - ], - ), + 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), + ), + ], + ), + ], + ), + ), + 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), + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext cxt, int index) { + 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), + ), + ), + ), + 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, + ), + ); + }, + ), + ], + ), - Container( - width: double.infinity, - padding: const EdgeInsets.only(top: 31), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.only(topRight: Radius.circular(50), topLeft: Radius.circular(50)), - border: Border.all(color: MyColors.lightGreyEDColor, width: 1), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ServicesWidget(), - context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 8, top: 8), - // context.watch().isTutorialLoading - // ? const MarathonBannerShimmer().paddingAll(20) - // : Container( - // padding: EdgeInsets.only(bottom: 12, top: 12), - // margin: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 8), - // width: double.infinity, - // alignment: Alignment.center, - // decoration: BoxDecoration( - // color: MyColors.backgroundBlackColor, - // borderRadius: BorderRadius.circular(20), - // border: Border.all(color: MyColors.lightGreyEDColor, width: 1), - // ), - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisSize: MainAxisSize.min, - // children: [ - // Text( - // "Tutorial:", - // style: TextStyle( - // fontSize: 11, - // fontStyle: FontStyle.italic, - // fontWeight: FontWeight.w600, - // color: MyColors.white.withOpacity(0.83), - // letterSpacing: -0.4, - // ), - // ), - // Text( - // context.read().tutorial?.tutorialName ?? "", - // overflow: TextOverflow.ellipsis, - // style: TextStyle( - // fontStyle: FontStyle.italic, - // fontSize: 19, - // fontWeight: FontWeight.bold, - // color: MyColors.white, - // height: 32 / 22, - // ), - // ), - // ], - // ), - // ).onPress(() { - // checkERMChannel(); - // // Navigator.pushNamed(context, AppRoutes.marathonTutorialScreen); - // }), - ], - ), - ), - ], - ), - ), - ), - ), - ], - ), - drawer: 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/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), - Consumer( - builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { - if (data.workListCounter == 0) { - return const SizedBox(); - } - return Positioned( - right: 0, - top: 0, - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - alignment: Alignment.center, - decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), - child: data.workListCounter.toString().toText10(color: Colors.white), - ), - ); - }, - ), - ], - ), - label: LocaleKeys.workList.tr(), - ), - BottomNavigationBarItem( - icon: SvgPicture.asset("assets/icons/item_for_sale.svg", color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), - label: LocaleKeys.itemsForSale.tr(), - ), - BottomNavigationBarItem( - icon: Stack( - alignment: Alignment.centerLeft, - children: [ - SvgPicture.asset( - "assets/icons/chat/chat.svg", - color: - !checkIfPrivilegedForChat() - ? MyColors.lightGreyE3Color - : currentIndex == 4 - ? MyColors.grey3AColor - : cProvider.disbaleChatForThisUser - ? 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), - ), - ); - }, - ), - ], - ), - label: LocaleKeys.chat.tr(), - ), - ], - currentIndex: currentIndex, - selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600), - unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600), - type: BottomNavigationBarType.fixed, - selectedItemColor: MyColors.grey3AColor, - backgroundColor: MyColors.backgroundColor, - selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28), - unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28), - onTap: (int index) { - if (index == 1) { - Navigator.pushNamed(context, AppRoutes.mowadhafhi); - } else if (index == 2) { - Navigator.pushNamed(context, AppRoutes.workList); - } else if (index == 3) { - Navigator.pushNamed(context, AppRoutes.itemsForSale); - } else if (index == 4) { - if (!cProvider.disbaleChatForThisUser && checkIfPrivilegedForChat()) { - Navigator.pushNamed(context, AppRoutes.chat); - } - } - }, - ), - ), - ), + Container( + width: double.infinity, + padding: const EdgeInsets.only(top: 31), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.only(topRight: Radius.circular(50), topLeft: Radius.circular(50)), + border: Border.all(color: MyColors.lightGreyEDColor, width: 1), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ServicesWidget(), + context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 8, top: 8), + // context.watch().isTutorialLoading + // ? const MarathonBannerShimmer().paddingAll(20) + // : Container( + // padding: EdgeInsets.only(bottom: 12, top: 12), + // margin: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 8), + // width: double.infinity, + // alignment: Alignment.center, + // decoration: BoxDecoration( + // color: MyColors.backgroundBlackColor, + // borderRadius: BorderRadius.circular(20), + // border: Border.all(color: MyColors.lightGreyEDColor, width: 1), + // ), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisSize: MainAxisSize.min, + // children: [ + // Text( + // "Tutorial:", + // style: TextStyle( + // fontSize: 11, + // fontStyle: FontStyle.italic, + // fontWeight: FontWeight.w600, + // color: MyColors.white.withOpacity(0.83), + // letterSpacing: -0.4, + // ), + // ), + // Text( + // context.read().tutorial?.tutorialName ?? "", + // overflow: TextOverflow.ellipsis, + // style: TextStyle( + // fontStyle: FontStyle.italic, + // fontSize: 19, + // fontWeight: FontWeight.bold, + // color: MyColors.white, + // height: 32 / 22, + // ), + // ), + // ], + // ), + // ).onPress(() { + // checkERMChannel(); + // // Navigator.pushNamed(context, AppRoutes.marathonTutorialScreen); + // }), + ], + ), + ), + ], + ), + ), + ), + ), + ], + ), + drawer: 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/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), + Consumer( + builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { + if (data.workListCounter == 0) { + return const SizedBox(); + } + return Positioned( + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.workListCounter.toString().toText10(color: Colors.white), + ), ); - } + }, + ), + ], + ), + label: LocaleKeys.workList.tr(), + ), + BottomNavigationBarItem( + icon: SvgPicture.asset("assets/icons/item_for_sale.svg", color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), + label: LocaleKeys.itemsForSale.tr(), + ), + BottomNavigationBarItem( + icon: Stack( + alignment: Alignment.centerLeft, + children: [ + SvgPicture.asset( + "assets/icons/chat/chat.svg", + color: + !checkIfPrivilegedForChat() + ? MyColors.lightGreyE3Color + : currentIndex == 4 + ? MyColors.grey3AColor + : cProvider.disbaleChatForThisUser + ? 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), + ), + ); + }, + ), + ], + ), + label: LocaleKeys.chat.tr(), + ), + ], + currentIndex: currentIndex, + selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600), + unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600), + type: BottomNavigationBarType.fixed, + selectedItemColor: MyColors.grey3AColor, + backgroundColor: MyColors.backgroundColor, + selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28), + unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28), + onTap: (int index) { + if (index == 1) { + Navigator.pushNamed(context, AppRoutes.mowadhafhi); + } else if (index == 2) { + Navigator.pushNamed(context, AppRoutes.workList); + } else if (index == 3) { + Navigator.pushNamed(context, AppRoutes.itemsForSale); + } else if (index == 4) { + if (!cProvider.disbaleChatForThisUser && checkIfPrivilegedForChat()) { + Navigator.pushNamed(context, AppRoutes.chat); + } + } + }, + ), + ), + ), + ); + } Widget eventActivityWidget(BuildContext context) { - return (context.watch().isEventLoadingLoading) + return (context + .watch() + .isEventLoadingLoading) ? const MarathonBannerShimmer().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) - : (context.watch().eventActivity != null && context.watch().eventActivity!.isActive == true) + : (context + .watch() + .eventActivity != null && context + .watch() + .eventActivity! + .isActive == true) ? const EventActivityBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) : const SizedBox(); } @@ -864,4 +996,4 @@ class _DashboardScreenState extends State with WidgetsBindingOb } return false; } -} \ No newline at end of file +} From a958257ce93ef35dd4757bf311b5c536e1ba0f07 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Mon, 2 Mar 2026 14:20:11 +0300 Subject: [PATCH 04/17] Greeting --- assets/images/greeting.svg | 605 ++++++++ assets/langs/ar-SA.json | 43 +- assets/langs/en-US.json | 45 +- lib/generated/codegen_loader.g.dart | 6 +- lib/generated/locale_keys.g.dart | 1 + lib/provider/dashboard_provider_model.dart | 10 +- lib/ui/landing/dashboard_screen.dart | 1363 ++++++++--------- lib/ui/landing/widget/services_widget.dart | 5 +- .../shimmer/dashboard_shimmer_widget.dart | 78 + 9 files changed, 1400 insertions(+), 756 deletions(-) create mode 100644 assets/images/greeting.svg diff --git a/assets/images/greeting.svg b/assets/images/greeting.svg new file mode 100644 index 0000000..0682c60 --- /dev/null +++ b/assets/images/greeting.svg @@ -0,0 +1,605 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index a78c83f..c34661b 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -531,7 +531,7 @@ "noWinner": "حزين! لم يفز أحد اليوم.", "myTeam": "فريقي", "youCanPlayDemo": "لكن يمكنك لعب العرض", - "group" : "مجموعة", + "group": "مجموعة", "searchGroup": "مجموعة البحث", "connectHmgWifi": "قم بتوصيل HMG WIFI", "connectedHmgWifi": "اتصال HMG WIFI", @@ -575,20 +575,20 @@ "versionStatus": "حالة الإصدار", "supplierNo": "رقم المورد", "general": "عام", - "requesterOperatingUnit":"وحدة تشغيل مقدم الطلب", - "prepareEmpNum":"إعداد رقم الموظف", - "supplierInfo" : "معلومات المورد", + "requesterOperatingUnit": "وحدة تشغيل مقدم الطلب", + "prepareEmpNum": "إعداد رقم الموظف", + "supplierInfo": "معلومات المورد", "supplierAcNo": "رقم حساب المورد", "supplierAcName": "اسم حساب المورد", - "supplierIBAN" : "رقم IBAN للمورد", - "supplierCRNo" :"رقم السجل التجاري", - "suppliedAcNo" : "رقم الحساب المقدم", - "patientRefundInvoice" : "فاتورة استرداد الأموال للمريض", - "patientNumber" : "رقم المريض", - "patientName" : "اسم المريض", - "invoiceDate" : "تاريخ الفاتورة", - "refundInvoice" :"فاتورة الاسترجاع", - "hospitalClinic" : "عيادة المستشفى", + "supplierIBAN": "رقم IBAN للمورد", + "supplierCRNo": "رقم السجل التجاري", + "suppliedAcNo": "رقم الحساب المقدم", + "patientRefundInvoice": "فاتورة استرداد الأموال للمريض", + "patientNumber": "رقم المريض", + "patientName": "اسم المريض", + "invoiceDate": "تاريخ الفاتورة", + "refundInvoice": "فاتورة الاسترجاع", + "hospitalClinic": "عيادة المستشفى", "graphicalAnalysis": "التحليل الرسومي", "itemHistoryAnalysis": "تحليل تاريخ العنصر", "pOno": "امر شراء #", @@ -614,23 +614,23 @@ "members": "الأعضاء", "searchByUserName": "البحث بواسطة اسم المستخدم", "shareScreen": "مشاركة الشاشة", - "start":"يبدأ", - "about":"عن", + "start": "يبدأ", + "about": "عن", "explore": "يستكشف", "mazaya": "مازيا", "benefits": "فوائد", "mazayaDesc": "اكتشف الخصومات والعروض الخاصة المتاحة للموظفين", - "viewallofferMazaya" : "أعرض كل المزايا", + "viewallofferMazaya": "أعرض كل المزايا", "buyerName": "اسم المشتري", "buyerNumber": "رقم المشتري", "highestBidder": "أعلى مزايد", "remarks": "ملاحظات", "faHeader": "تفاصيل رأس الصفحة FA", - "bookTypeCode": "رمز نوع الكتاب", + "bookTypeCode": "رمز نوع الكتاب", "categoryCode": "رمز الفئة", "categoryGroup": "مجموعة الفئات", - "faLINES": "تفاصيل الأصول", - "assetNumber": "رقم الأصول", + "faLINES": "تفاصيل الأصول", + "assetNumber": "رقم الأصول", "assetDescription": "وصف الأصول", "barCodeNumber": "رقم الباركود", "datePlaceInService": "تاريخ وضعه في الخدمة", @@ -638,10 +638,11 @@ "disposedDate": "تاريخ التخلص", "netBookValue": "القيمة الدفترية الصافية", "purchasedPrice": "سعر الشراء", - "usefulLife": "العمر الإنتاجي", + "usefulLife": "العمر الإنتاجي", "yearsUsed": "سنوات الاستخدام", "faRequest": "طلب التخلص من FA", "showMore": "عرض المزيد", "buyerDetails": "تفاصيل المشتري", - "parkingQr": "وقوف السيارات QR" + "parkingQr": "وقوف السيارات QR", + "startNow": "ابدأ الآن" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 5b49d24..af3251e 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -565,7 +565,7 @@ "addAtLeastOneAttachment": "Please add at least one attachment.", "pleaseClickButtonToJoinMarathon": "Press the button below to join the Marathon.", "youCannotJoinTheMarathon": "You cannot join the Marathon because you have exceeded the time limit.", - "requesterOperatingUnit":"Requester Operating Unit", + "requesterOperatingUnit": "Requester Operating Unit", "generate": "Generate", "paymentRequest": "Pay Request", "paymentDetails": "Payment Details", @@ -591,19 +591,19 @@ "versionStatus": "Version Status", "supplierNo": "Supplier No", "general": "General", - "prepareEmpNum":"Prepare Employee Num", - "supplierInfo" : "Supplier Information", + "prepareEmpNum": "Prepare Employee Num", + "supplierInfo": "Supplier Information", "supplierAcNo": "Supplier Account No", - "supplierAcName":"Supplier Account Name", - "supplierIBAN" : "Supplier IBAN", - "supplierCRNo" : "CR Number", - "suppliedAcNo" : "Supplied Account No.", - "patientRefundInvoice" : "Patient Refund Invoice", - "patientNumber" : "Patient Number", - "patientName" : "Patient Name", - "invoiceDate" : "Invoice Date", - "refundInvoice" :"Refund Invoice", - "hospitalClinic" : "Hospital Clinic", + "supplierAcName": "Supplier Account Name", + "supplierIBAN": "Supplier IBAN", + "supplierCRNo": "CR Number", + "suppliedAcNo": "Supplied Account No.", + "patientRefundInvoice": "Patient Refund Invoice", + "patientNumber": "Patient Number", + "patientName": "Patient Name", + "invoiceDate": "Invoice Date", + "refundInvoice": "Refund Invoice", + "hospitalClinic": "Hospital Clinic", "graphicalAnalysis": "Graphical Analysis", "itemHistoryAnalysis": "Item History Analysis", "pOno": "P.O #", @@ -612,23 +612,23 @@ "qtyReceived": "Qty. Received", "bonusQty": "Bonus Qty.", "balQty": "Bal. Qty.", - "start":"Start", - "about":"About", + "start": "Start", + "about": "About", "explore": "Explore", "mazaya": "MAZAYA", "benefits": "Benefits", "mazayaDesc": "Discover special Discounts and offers available to Employees", - "viewallofferMazaya" : "View All Offers", + "viewallofferMazaya": "View All Offers", "buyerName": "Buyer Name", "buyerNumber": "Buyer Number", "highestBidder": "Highest Bidder", "remarks": "Remarks", "faHeader": "FA Header Details", - "bookTypeCode": "Book Type Code", + "bookTypeCode": "Book Type Code", "categoryCode": "Category Code", "categoryGroup": "Category Group", - "faLINES": "Asset Details", - "assetNumber": "Asset Number", + "faLINES": "Asset Details", + "assetNumber": "Asset Number", "assetDescription": "Asset Description", "barCodeNumber": "BarCode Number", "datePlaceInService": "Date place In Service", @@ -636,10 +636,11 @@ "disposedDate": "Disposed Date", "netBookValue": "Net Book Value", "purchasedPrice": "Purchased Price", - "usefulLife": "Useful Life", + "usefulLife": "Useful Life", "yearsUsed": "Years Used", - "faRequest":"FA Disposal Request", + "faRequest": "FA Disposal Request", "showMore": "Show More", "buyerDetails": "Buyer Details", - "parkingQr": "Parking QR" + "parkingQr": "Parking QR", + "startNow": "Start Now" } \ No newline at end of file diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 62bbce6..3b24423 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -656,7 +656,8 @@ class CodegenLoader extends AssetLoader{ "faRequest": "طلب التخلص من FA", "showMore": "عرض المزيد", "buyerDetails": "تفاصيل المشتري", - "parkingQr": "وقوف السيارات QR" + "parkingQr": "وقوف السيارات QR", + "startNow": "ابدأ الآن" }; static const Map _en_US = { "mohemm": "Mohemm", @@ -1300,7 +1301,8 @@ static const Map _en_US = { "faRequest": "FA Disposal Request", "showMore": "Show More", "buyerDetails": "Buyer Details", - "parkingQr": "Parking QR" + "parkingQr": "Parking QR", + "startNow": "Start Now" }; static const Map> mapLocales = {"ar_SA": _ar_SA, "en_US": _en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 683c8c4..9cf563a 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -629,5 +629,6 @@ abstract class LocaleKeys { static const showMore = 'showMore'; static const buyerDetails = 'buyerDetails'; static const parkingQr = 'parkingQr'; + static const startNow = 'startNow'; } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 09c347e..169eb28 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -68,6 +68,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool isOffersLoading = true; List getOffersList = []; + bool isGreetingCardsLoading = true; bool isDisplayEidGreetings = false; List? greetingCardsList; @@ -119,6 +120,8 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { getMenuEntriesList = null; isOffersLoading = true; getOffersList = []; + isGreetingCardsLoading = true; + isDisplayEidGreetings = false; drawerMenuItemList = [ DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile), @@ -312,22 +315,23 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void fetchGreetingCards() async { + isGreetingCardsLoading = true; + notifyListeners(); try { GetGreetingCardsModelResponse? response = await DashboardApiClient().getGreetingCards(); greetingCardsList = response?.getGreetingCardsModelResponse ?? []; - - // Check if there are any active greeting cards if (greetingCardsList != null && greetingCardsList!.isNotEmpty) { isDisplayEidGreetings = greetingCardsList!.any((card) => card.isActive == true); } else { isDisplayEidGreetings = false; } - + isGreetingCardsLoading = false; notifyListeners(); } catch (ex) { logger.wtf(ex); isDisplayEidGreetings = false; greetingCardsList = []; + isGreetingCardsLoading = false; notifyListeners(); } } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index aca7aba..e067666 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; @@ -254,716 +253,670 @@ class _DashboardScreenState extends State with WidgetsBindingOb child: Scaffold( key: _scaffoldState, body: Column( - 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(); - }); - }, - ), - Image - .asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28) - .expanded, - 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), - controller: _refreshController, - onRefresh: () { - _onRefresh(false); - }, - child: SingleChildScrollView( - child: Column( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color), - (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true), - 16.height, - Row( - children: [ - Expanded( - child: AspectRatio( - aspectRatio: 159 / 159, - child: Consumer( - builder: (BuildContext context, DashboardProviderModel model, Widget? child) { - 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], - ), - ), - 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( - 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: const Color(0xff259EA4), - borderRadius: BorderRadius.only( - bottomRight: AppState().isArabic(context) ? const Radius.circular(0) : const Radius.circular(15), - bottomLeft: AppState().isArabic(context) ? const Radius.circular(15) : const 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()), - ], - ), - ], - ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), - if (data.isDisplayEidGreetings) ...[ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Directionality( - textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - gradient: const LinearGradient(colors: [Color(0xFFE7E7E7), Color(0xFFE7E7E7)], begin: Alignment.centerLeft, end: Alignment.centerRight), - ), - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Container( - height: 120, - decoration: BoxDecoration(color: const Color(0xFFFAF4E7),borderRadius: BorderRadius.circular(17), image: DecorationImage(image: NetworkImage(AppState().isArabic(context) ? data.greetingCardsList!.first.backgroundImageUrlAr ?? "" : data.greetingCardsList!.first.backgroundImageUrlEn ?? ""), fit: BoxFit.cover)), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Expanded( - // flex: 4, - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisAlignment: MainAxisAlignment.start, - // children: [ - // Row( - // children: [ - // Expanded( - // flex: 2, - // child: RichText( - // text: - // AppState().isArabic(context) - // ? TextSpan( - // children: [ - // TextSpan( - // text: 'اطلع على مميزات', - // style: TextStyle( - // fontSize: 16, - // letterSpacing: -0.2, - // fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - // fontWeight: FontWeight.w700, - // height: 24 / 16, - // color: const Color(0xFF5D5E5E), - // ), - // ), - // TextSpan( - // text: ' مزايا', - // style: TextStyle( - // fontSize: 16, - // fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - // fontWeight: FontWeight.w700, - // letterSpacing: -0.2, - // height: 24 / 16, - // color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed - // ), - // ), - // ], - // ) - // : TextSpan( - // children: [ - // TextSpan( - // text: LocaleKeys.explore.tr() + ' ', - // style: const TextStyle( - // fontSize: 16, - // letterSpacing: -0.2, - // fontFamily: 'Poppins', - // fontWeight: FontWeight.w700, - // height: 24 / 16, - // color: Color(0xFF5D5E5E), - // ), - // ), - // TextSpan( - // text: LocaleKeys.mazaya.tr(), - // style: const TextStyle( - // fontSize: 16, - // fontWeight: FontWeight.w700, - // fontFamily: 'Poppins', - // letterSpacing: -0.2, - // height: 24 / 16, - // color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed - // ), - // ), - // TextSpan( - // text: ' ' + LocaleKeys.benefits.tr(), - // style: const TextStyle( - // fontSize: 16, - // letterSpacing: -0.2, - // fontFamily: 'Poppins', - // fontWeight: FontWeight.w700, - // height: 24 / 16, - // color: Color(0xFF5D5E5E), - // ), - // ), - // ], - // ), - // ), - // ), - // const Expanded(flex: 1, child: SizedBox()), - // ], - // ), - // const SizedBox(height: 8), - // LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), - // ], - // ), - // ), - // Expanded( - // flex: 2, - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.end, - // mainAxisAlignment: MainAxisAlignment.end, - // children: [ - // SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), - // const SizedBox(height: 28), - // LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { - // Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); - // }), - // ], - // ), - // ), - ], - ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), - ), - ), - ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), - ), - ], - ), - ], - eventActivityWidget(context), - if (isDisplayMazaya) ...[ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Directionality( - textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - gradient: const LinearGradient(colors: [Color(0xFF91C481), Color(0xFF7CCED7)], begin: Alignment.centerLeft, end: Alignment.centerRight), - ), - child: Padding( - padding: const EdgeInsets.all(3.0), // This creates the border width - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(17), // Slightly less than outer radius - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 4, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - flex: 2, - child: RichText( - text: - AppState().isArabic(context) - ? TextSpan( - children: [ - TextSpan( - text: 'اطلع على مميزات', - style: TextStyle( - fontSize: 16, - letterSpacing: -0.2, - fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - fontWeight: FontWeight.w700, - height: 24 / 16, - color: const Color(0xFF5D5E5E), - ), - ), - TextSpan( - text: ' مزايا', - style: TextStyle( - fontSize: 16, - fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - fontWeight: FontWeight.w700, - letterSpacing: -0.2, - height: 24 / 16, - color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed - ), - ), - ], - ) - : TextSpan( - children: [ - TextSpan( - text: LocaleKeys.explore.tr() + ' ', - style: const TextStyle( - fontSize: 16, - letterSpacing: -0.2, - fontFamily: 'Poppins', - fontWeight: FontWeight.w700, - height: 24 / 16, - color: Color(0xFF5D5E5E), - ), - ), - TextSpan( - text: LocaleKeys.mazaya.tr(), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - fontFamily: 'Poppins', - letterSpacing: -0.2, - height: 24 / 16, - color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed - ), - ), - TextSpan( - text: ' ' + LocaleKeys.benefits.tr(), - style: const TextStyle( - fontSize: 16, - letterSpacing: -0.2, - fontFamily: 'Poppins', - fontWeight: FontWeight.w700, - height: 24 / 16, - color: Color(0xFF5D5E5E), - ), - ), - ], - ), - ), - ), - const Expanded(flex: 1, child: SizedBox()), - ], - ), - const SizedBox(height: 8), - LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), - ], - ), - ), - Expanded( - flex: 2, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), - const SizedBox(height: 28), - LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { - Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); - }), - ], - ), - ), - ], - ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), - ), - ), - ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), - ), - ], - ), - ], + 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(); + }); + }, + ), + Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28).expanded, + 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), + controller: _refreshController, + onRefresh: () { + _onRefresh(false); + }, + child: SingleChildScrollView( + child: Column( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color), + (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true), + 16.height, + Row( + children: [ + Expanded( + child: AspectRatio( + aspectRatio: 159 / 159, + child: Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + 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], + ), + ), + 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( + 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: const Color(0xff259EA4), + borderRadius: BorderRadius.only( + bottomRight: AppState().isArabic(context) ? const Radius.circular(0) : const Radius.circular(15), + bottomLeft: AppState().isArabic(context) ? const Radius.circular(15) : const 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()), + ], + ), + ], + ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), + Consumer( + builder: (BuildContext context, DashboardProviderModel model, Widget? child) { + if (model.isGreetingCardsLoading) { + return const GreetingCardShimmer(); + } else if (model.isDisplayEidGreetings) { + return Column( + children: [ + Directionality( + textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, + child: Container( + height: 100, + decoration: BoxDecoration( + color: const Color(0xFFFAF4E7), + border: Border.all(width: 2, color: const Color(0xFFE7E7E7)), + borderRadius: BorderRadius.circular(20), + image: const DecorationImage( + image: NetworkImage( + "https://dummyimage.com/1200X600/faf4e7/faf4e7.jpg&text=0", + // AppState().isArabic(context) ? model.greetingCardsList!.first.backgroundImageUrlAr ?? "" : model.greetingCardsList!.first.backgroundImageUrlEn ?? "", + ), + fit: BoxFit.cover, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset("assets/images/greeting.svg", width: 65, height: 81), + const SizedBox(width: 10), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Text( + AppState().isArabic(context) ? model.greetingCardsList!.first.descriptionAr ?? '' : model.greetingCardsList!.first.descriptionEn ?? '', + style: TextStyle( + fontSize: AppState().isArabic(context) ? 18 : 16, + letterSpacing: -0.2, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: const Color(0xFF3B3E4F), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppState().isArabic(context) ? model.greetingCardsList!.first.titleAr ?? '' : model.greetingCardsList!.first.titleEn ?? '', + style: TextStyle( + fontSize: AppState().isArabic(context) ? 18 : 16, + letterSpacing: -0.2, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: const Color(0xFF3B3E4F), + ), + ), + ], + ), + ], + ), + ], + ).paddingOnly(top: 10, bottom: 10).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + LocaleKeys.startNow.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + }), + ], + ), + ], + ).paddingOnly(left: 8, right: 8, top: 6, bottom: 12), + ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), + ), + ], + ); + } else { + return const SizedBox(); + } + }, + ), - 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), - ), - ], - ), - ], - ), - ), - 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), - scrollDirection: Axis.horizontal, - itemBuilder: (BuildContext cxt, int index) { - 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), - ), - ), - ), - 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, - ), - ); - }, - ), - ], - ), + eventActivityWidget(context), + if (isDisplayMazaya) ...[ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Directionality( + textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + gradient: const LinearGradient(colors: [Color(0xFF91C481), Color(0xFF7CCED7)], begin: Alignment.centerLeft, end: Alignment.centerRight), + ), + child: Padding( + padding: const EdgeInsets.all(3.0), // This creates the border width + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(17), // Slightly less than outer radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + flex: 2, + child: RichText( + text: + AppState().isArabic(context) + ? TextSpan( + children: [ + TextSpan( + text: 'اطلع على مميزات', + style: TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: const Color(0xFF5D5E5E), + ), + ), + TextSpan( + text: ' مزايا', + style: TextStyle( + fontSize: 16, + fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', + fontWeight: FontWeight.w700, + letterSpacing: -0.2, + height: 24 / 16, + color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + ), + ), + ], + ) + : TextSpan( + children: [ + TextSpan( + text: LocaleKeys.explore.tr() + ' ', + style: const TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + TextSpan( + text: LocaleKeys.mazaya.tr(), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Poppins', + letterSpacing: -0.2, + height: 24 / 16, + color: MyColors.mazayaRedColor, // Use your MAZAYA red color here if defined, e.g. MyColors.mazayaRed + ), + ), + TextSpan( + text: ' ' + LocaleKeys.benefits.tr(), + style: const TextStyle( + fontSize: 16, + letterSpacing: -0.2, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + height: 24 / 16, + color: Color(0xFF5D5E5E), + ), + ), + ], + ), + ), + ), + const Expanded(flex: 1, child: SizedBox()), + ], + ), + const SizedBox(height: 8), + LocaleKeys.mazayaDesc.tr().toText11(color: const Color(0xFF5D5E5E)), + ], + ), + ), + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SvgPicture.asset("assets/icons/mazaya_brand.svg", width: 90, height: 47), + const SizedBox(height: 28), + LocaleKeys.viewallofferMazaya.tr().toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); + }), + ], + ), + ), + ], + ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14), + ), + ), + ).paddingOnly(left: 21, right: 21, top: 0, bottom: 21), + ), + ], + ), + ], - Container( - width: double.infinity, - padding: const EdgeInsets.only(top: 31), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.only(topRight: Radius.circular(50), topLeft: Radius.circular(50)), - border: Border.all(color: MyColors.lightGreyEDColor, width: 1), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ServicesWidget(), - context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 8, top: 8), - // context.watch().isTutorialLoading - // ? const MarathonBannerShimmer().paddingAll(20) - // : Container( - // padding: EdgeInsets.only(bottom: 12, top: 12), - // margin: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 8), - // width: double.infinity, - // alignment: Alignment.center, - // decoration: BoxDecoration( - // color: MyColors.backgroundBlackColor, - // borderRadius: BorderRadius.circular(20), - // border: Border.all(color: MyColors.lightGreyEDColor, width: 1), - // ), - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisSize: MainAxisSize.min, - // children: [ - // Text( - // "Tutorial:", - // style: TextStyle( - // fontSize: 11, - // fontStyle: FontStyle.italic, - // fontWeight: FontWeight.w600, - // color: MyColors.white.withOpacity(0.83), - // letterSpacing: -0.4, - // ), - // ), - // Text( - // context.read().tutorial?.tutorialName ?? "", - // overflow: TextOverflow.ellipsis, - // style: TextStyle( - // fontStyle: FontStyle.italic, - // fontSize: 19, - // fontWeight: FontWeight.bold, - // color: MyColors.white, - // height: 32 / 22, - // ), - // ), - // ], - // ), - // ).onPress(() { - // checkERMChannel(); - // // Navigator.pushNamed(context, AppRoutes.marathonTutorialScreen); - // }), - ], - ), - ), - ], - ), - ), - ), - ), - ], - ), - drawer: 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/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), - Consumer( - builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { - if (data.workListCounter == 0) { - return const SizedBox(); - } - return Positioned( - right: 0, - top: 0, - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - alignment: Alignment.center, - decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), - child: data.workListCounter.toString().toText10(color: Colors.white), - ), - ); - }, - ), - ], - ), - label: LocaleKeys.workList.tr(), - ), - BottomNavigationBarItem( - icon: SvgPicture.asset("assets/icons/item_for_sale.svg", color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), - label: LocaleKeys.itemsForSale.tr(), - ), - BottomNavigationBarItem( - icon: Stack( - alignment: Alignment.centerLeft, - children: [ - SvgPicture.asset( - "assets/icons/chat/chat.svg", - color: - !checkIfPrivilegedForChat() - ? MyColors.lightGreyE3Color - : currentIndex == 4 - ? MyColors.grey3AColor - : cProvider.disbaleChatForThisUser - ? 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), - ), - ); - }, - ), - ], - ), - label: LocaleKeys.chat.tr(), - ), - ], - currentIndex: currentIndex, - selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600), - unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600), - type: BottomNavigationBarType.fixed, - selectedItemColor: MyColors.grey3AColor, - backgroundColor: MyColors.backgroundColor, - selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28), - unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28), - onTap: (int index) { - if (index == 1) { - Navigator.pushNamed(context, AppRoutes.mowadhafhi); - } else if (index == 2) { - Navigator.pushNamed(context, AppRoutes.workList); - } else if (index == 3) { - Navigator.pushNamed(context, AppRoutes.itemsForSale); - } else if (index == 4) { - if (!cProvider.disbaleChatForThisUser && checkIfPrivilegedForChat()) { - Navigator.pushNamed(context, AppRoutes.chat); - } - } - }, - ), - ), - ), + 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), + ), + ], + ), + ], + ), + ), + 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), + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext cxt, int index) { + 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), + ), + ), + ), + 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, + ), + ); + }, + ), + ], + ), + + Container( + width: double.infinity, + padding: const EdgeInsets.only(top: 31), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.only(topRight: Radius.circular(50), topLeft: Radius.circular(50)), + border: Border.all(color: MyColors.lightGreyEDColor, width: 1), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ServicesWidget(), + context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 8, top: 8), + // context.watch().isTutorialLoading + // ? const MarathonBannerShimmer().paddingAll(20) + // : Container( + // padding: EdgeInsets.only(bottom: 12, top: 12), + // margin: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 8), + // width: double.infinity, + // alignment: Alignment.center, + // decoration: BoxDecoration( + // color: MyColors.backgroundBlackColor, + // borderRadius: BorderRadius.circular(20), + // border: Border.all(color: MyColors.lightGreyEDColor, width: 1), + // ), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisSize: MainAxisSize.min, + // children: [ + // Text( + // "Tutorial:", + // style: TextStyle( + // fontSize: 11, + // fontStyle: FontStyle.italic, + // fontWeight: FontWeight.w600, + // color: MyColors.white.withOpacity(0.83), + // letterSpacing: -0.4, + // ), + // ), + // Text( + // context.read().tutorial?.tutorialName ?? "", + // overflow: TextOverflow.ellipsis, + // style: TextStyle( + // fontStyle: FontStyle.italic, + // fontSize: 19, + // fontWeight: FontWeight.bold, + // color: MyColors.white, + // height: 32 / 22, + // ), + // ), + // ], + // ), + // ).onPress(() { + // checkERMChannel(); + // // Navigator.pushNamed(context, AppRoutes.marathonTutorialScreen); + // }), + ], + ), + ), + ], + ), + ), + ), + ), + ], + ), + drawer: 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/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), + Consumer( + builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { + if (data.workListCounter == 0) { + return const SizedBox(); + } + return Positioned( + right: 0, + top: 0, + child: Container( + padding: const EdgeInsets.only(left: 4, right: 4), + alignment: Alignment.center, + decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.workListCounter.toString().toText10(color: Colors.white), + ), + ); + }, + ), + ], + ), + label: LocaleKeys.workList.tr(), + ), + BottomNavigationBarItem( + icon: SvgPicture.asset("assets/icons/item_for_sale.svg", color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color).paddingAll(4), + label: LocaleKeys.itemsForSale.tr(), + ), + BottomNavigationBarItem( + icon: Stack( + alignment: Alignment.centerLeft, + children: [ + SvgPicture.asset( + "assets/icons/chat/chat.svg", + color: + !checkIfPrivilegedForChat() + ? MyColors.lightGreyE3Color + : currentIndex == 4 + ? MyColors.grey3AColor + : cProvider.disbaleChatForThisUser + ? 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), + ), + ); + }, + ), + ], + ), + label: LocaleKeys.chat.tr(), + ), + ], + currentIndex: currentIndex, + selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600), + unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600), + type: BottomNavigationBarType.fixed, + selectedItemColor: MyColors.grey3AColor, + backgroundColor: MyColors.backgroundColor, + selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28), + unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28), + onTap: (int index) { + if (index == 1) { + Navigator.pushNamed(context, AppRoutes.mowadhafhi); + } else if (index == 2) { + Navigator.pushNamed(context, AppRoutes.workList); + } else if (index == 3) { + Navigator.pushNamed(context, AppRoutes.itemsForSale); + } else if (index == 4) { + if (!cProvider.disbaleChatForThisUser && checkIfPrivilegedForChat()) { + Navigator.pushNamed(context, AppRoutes.chat); + } + } + }, + ), + ), + ), ); - } + } Widget eventActivityWidget(BuildContext context) { - return (context - .watch() - .isEventLoadingLoading) + return (context.watch().isEventLoadingLoading) ? const MarathonBannerShimmer().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) - : (context - .watch() - .eventActivity != null && context - .watch() - .eventActivity! - .isActive == true) + : (context.watch().eventActivity != null && context.watch().eventActivity!.isActive == true) ? const EventActivityBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) : const SizedBox(); } diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index 879173b..0a30857 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -92,7 +92,7 @@ class ServicesWidget extends StatelessWidget { aspectRatio: 105 / 105, child: data.isServicesMenusLoading - ? ServicesMenuShimmer() + ? const ServicesMenuShimmer() : Container( decoration: BoxDecoration( color: Colors.white, @@ -266,7 +266,6 @@ class ServicesWidget extends StatelessWidget { 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))); @@ -311,7 +310,7 @@ class ServicesWidget extends StatelessWidget { padding: const EdgeInsets.only(left: 21, right: 21, top: 13, bottom: 13), scrollDirection: Axis.horizontal, itemBuilder: (cxt, index) { - return AspectRatio(aspectRatio: 105 / 105, child: ServicesMenuShimmer()); + return AspectRatio(aspectRatio: 105 / 105, child: const ServicesMenuShimmer()); }, separatorBuilder: (cxt, index) => 9.width, itemCount: 4, diff --git a/lib/widgets/shimmer/dashboard_shimmer_widget.dart b/lib/widgets/shimmer/dashboard_shimmer_widget.dart index c11cf16..7d59899 100644 --- a/lib/widgets/shimmer/dashboard_shimmer_widget.dart +++ b/lib/widgets/shimmer/dashboard_shimmer_widget.dart @@ -8,6 +8,8 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:shimmer/shimmer.dart'; class GetAttendanceTrackingShimmer extends StatelessWidget { + const GetAttendanceTrackingShimmer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Container( @@ -85,6 +87,8 @@ class GetAttendanceTrackingShimmer extends StatelessWidget { } class MenuShimmer extends StatelessWidget { + const MenuShimmer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Container( @@ -122,6 +126,8 @@ class MenuShimmer extends StatelessWidget { } class ServicesHeaderShimmer extends StatelessWidget { + const ServicesHeaderShimmer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Row( @@ -145,6 +151,8 @@ class ServicesHeaderShimmer extends StatelessWidget { } class ServicesMenuShimmer extends StatelessWidget { + const ServicesMenuShimmer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Container( @@ -188,6 +196,75 @@ class ServicesMenuShimmer extends StatelessWidget { } } +class GreetingCardShimmer extends StatelessWidget { + const GreetingCardShimmer({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 100, + decoration: BoxDecoration( + color: const Color(0xFFFAF4E7), + border: Border.all(width: 2, color: const Color(0xFFE7E7E7)), + borderRadius: BorderRadius.circular(20), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 65, + height: 81, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(10), + ), + ).toShimmer(), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 150, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ).toShimmer(), + const SizedBox(height: 8), + Container( + width: 120, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ).toShimmer(), + ], + ).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + width: 60, + height: 12, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ).toShimmer(), + ], + ), + ], + ).paddingOnly(left: 8, right: 8, top: 6, bottom: 12), + ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14); + } +} + + class MarathonBannerShimmer extends StatelessWidget { const MarathonBannerShimmer({Key? key}) : super(key: key); @@ -305,3 +382,4 @@ class ChatHomeShimmer extends StatelessWidget { )); } } + From bdaccf133c2273324b5f5c398ebc2712658e9dfd Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 15 Mar 2026 16:04:06 +0300 Subject: [PATCH 05/17] updates --- assets/images/eid_banner.svg | 606 +++++++++++++++++++++ lib/provider/dashboard_provider_model.dart | 2 +- lib/ui/landing/dashboard_screen.dart | 6 +- 3 files changed, 610 insertions(+), 4 deletions(-) create mode 100644 assets/images/eid_banner.svg diff --git a/assets/images/eid_banner.svg b/assets/images/eid_banner.svg new file mode 100644 index 0000000..f8e4adb --- /dev/null +++ b/assets/images/eid_banner.svg @@ -0,0 +1,606 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index e9c6678..2b7a2bb 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -137,7 +137,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.keen.tr(), AppRoutes.etqanOvr), // DrawerMenuItem("assets/images/drawer/car_parking_icon.svg", LocaleKeys.parkingQr.tr(), AppRoutes.parkingQr), DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions), - DrawerMenuItem("assets/images/drawer/courses.svg", "courses".tr(), AppRoutes.courses), + // DrawerMenuItem("assets/images/drawer/courses.svg", "courses".tr(), AppRoutes.courses), // DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen), DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword), ]; diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 0ff22ae..eac7890 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -450,8 +450,8 @@ class _DashboardScreenState extends State with WidgetsBindingOb flipX: !AppState().isArabic(context), child: SvgPicture.network( AppState().isArabic(context) - ? (card.backgroundImageUrlAr ?? "http://meena-health-care-1.s3.eu-north-1.amazonaws.com/eid_banner.svg") - : (card.backgroundImageUrlEn ?? "http://meena-health-care-1.s3.eu-north-1.amazonaws.com/eid_banner.svg"), + ? (card.backgroundImageUrlAr ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg") + : (card.backgroundImageUrlEn ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg"), fit: BoxFit.contain, placeholderBuilder: (context) => ClipRRect(borderRadius: BorderRadius.circular(18), child: Container(height: 80, color: Colors.white).toShimmer()), ), @@ -460,7 +460,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox(width: AppState().isArabic(context) ? 10 : 40), + SizedBox(width: AppState().isArabic(context) ? 20 : 50), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, From 057e71e3c0fc811118fdd67cd4fdfec387bb3c85 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Mon, 16 Mar 2026 01:47:39 +0300 Subject: [PATCH 06/17] Etqan fixes, Update to Stores VersionID 9.6 --- lib/app_state/app_state.dart | 2 +- lib/classes/consts.dart | 4 ++-- lib/ui/etqan_ovr/etqan_create_request.dart | 11 ++++++++--- pubspec.yaml | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 799bcb5..703a8b0 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -90,7 +90,7 @@ class AppState { String get getHuaweiPushToken => _huaweiPushToken; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 9.5, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 9.6, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index d8efe5d..88ebf73 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -4,12 +4,12 @@ class ApiConsts { // static String baseUrl = "http://10.200.204.11"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver + // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver // static String baseUrl = "http://10.201.204.101:2024"; // static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://hmgwebservices.com"; // Live server - // static String baseUrl = "https://mohemm.hmg.com"; // New Live server + static String baseUrl = "https://mohemm.hmg.com"; // New Live server // // static String baseUrl = "http://10.20.200.111:1010/"; diff --git a/lib/ui/etqan_ovr/etqan_create_request.dart b/lib/ui/etqan_ovr/etqan_create_request.dart index a1d64af..ba3c504 100644 --- a/lib/ui/etqan_ovr/etqan_create_request.dart +++ b/lib/ui/etqan_ovr/etqan_create_request.dart @@ -110,15 +110,20 @@ class _EtqanOvrCreateRequestState extends State { if (ticketInfo != null) { String ticketNumber = ticketInfo['ticketNumber'] ?? ''; String ticketId = ticketInfo['id'] ?? ''; - String successMessage = '${LocaleKeys.requestCreatedSuccessfully.tr()}\n\n${LocaleKeys.ticketNumber.tr()}: $ticketNumber\n${LocaleKeys.ticketId.tr()}: $ticketId'; + // String successMessage = '${LocaleKeys.requestCreatedSuccessfully.tr()}\n\n${LocaleKeys.ticketNumber.tr()}: $ticketNumber\n${LocaleKeys.ticketId.tr()}: $ticketId'; + String successMessage = '${LocaleKeys.requestCreatedSuccessfully.tr()}\n\n${LocaleKeys.ticketNumber.tr()}: $ticketNumber'; Utils.showErrorDialog( context: context, message: successMessage, onOkTapped: () { - Navigator.popAndPushNamed(context, AppRoutes.etqanOvr); + Navigator.pop(context); + Navigator.pop(context); + // Navigator.popAndPushNamed(context, AppRoutes.etqanOvr); }, onCloseTap: () { - Navigator.popAndPushNamed(context, AppRoutes.etqanOvr); + Navigator.pop(context); + Navigator.pop(context); + // Navigator.popAndPushNamed(context, AppRoutes.etqanOvr); }, ); } diff --git a/pubspec.yaml b/pubspec.yaml index 49dec60..7e5a29a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 3.7.1+300081 +version: 3.7.2+300082 #version: 3.9.3+1 environment: From 3391cf49ef304d3e5b6e6b7e5743a58f82197634 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Mon, 16 Mar 2026 14:56:04 +0300 Subject: [PATCH 07/17] updates --- lib/ui/landing/dashboard_screen.dart | 89 ++++------------------------ 1 file changed, 13 insertions(+), 76 deletions(-) diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index eac7890..793712c 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -431,86 +431,24 @@ class _DashboardScreenState extends State with WidgetsBindingOb return const GreetingCardShimmer(); } else if (model.isDisplayEidGreetings && model.greetingCardsList != null && model.greetingCardsList!.isNotEmpty) { return SizedBox( - height: 120, + height: 140, child: ListView.separated( shrinkWrap: true, scrollDirection: Axis.horizontal, - padding: const EdgeInsets.symmetric(horizontal: 21), + padding: const EdgeInsets.symmetric(horizontal: 24), itemCount: model.greetingCardsList!.length, - separatorBuilder: (context, index) => const SizedBox(width: 12), + separatorBuilder: (context, index) => const SizedBox(width: 24), itemBuilder: (context, index) { var card = model.greetingCardsList![index]; - return SizedBox( - width: MediaQuery.of(context).size.width - 42, - child: Directionality( - textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr, - child: Stack( - children: [ - Transform.flip( - flipX: !AppState().isArabic(context), - child: SvgPicture.network( - AppState().isArabic(context) - ? (card.backgroundImageUrlAr ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg") - : (card.backgroundImageUrlEn ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg"), - fit: BoxFit.contain, - placeholderBuilder: (context) => ClipRRect(borderRadius: BorderRadius.circular(18), child: Container(height: 80, color: Colors.white).toShimmer()), - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(width: AppState().isArabic(context) ? 20 : 50), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - AppState().isArabic(context) ? card.titleAr ?? '' : card.titleEn ?? '', - style: TextStyle( - fontSize: AppState().isArabic(context) ? 20 : 18, - letterSpacing: -0.2, - fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - fontWeight: FontWeight.w700, - height: 24 / 16, - color: const Color(0xFF3B3E4F), - ), - ), - const SizedBox(height: 4), - Text( - AppState().isArabic(context) ? card.descriptionAr ?? '' : card.descriptionEn ?? '', - style: TextStyle( - fontSize: AppState().isArabic(context) ? 16 : 14, - letterSpacing: -0.2, - fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', - fontWeight: FontWeight.w500, - color: const Color(0xFF3B3E4F), - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - (AppState().isArabic(context) - ? card.buttonTextN!.toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)) - : card.buttonText!.toText12(isUnderLine: true, color: const Color(0xFF3B3D4A))) - .onPress(() { - launchUrl(Uri.parse(AppState().isArabic(context) ? card.urlAr! : card.urlEn!)); - }), - ], - ).paddingOnly(bottom: 10, right: 15, left: 15), - ], - ).paddingOnly(left: AppState().isArabic(context) ? 10 : 36, right: AppState().isArabic(context) ? 66 : 10, top: 6, bottom: 40), - ], - ), - ), - ); + return SvgPicture.network( + AppState().isArabic(context) + ? (card.backgroundImageUrlAr ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg") + : (card.backgroundImageUrlEn ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg"), + fit: BoxFit.fill, + placeholderBuilder: (context) => ClipRRect(borderRadius: BorderRadius.circular(18), child: Container(height: 80, color: Colors.white).toShimmer()), + ).onPress(() { + launchUrl(Uri.parse(AppState().isArabic(context) ? card.urlAr! : card.urlEn!)); + }); }, ), ).paddingOnly(bottom: 0); @@ -518,8 +456,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb return const SizedBox(); } }, - ), - + ).paddingOnly(bottom: 24), // eventActivityWidget(context), if (isDisplayMazaya) ...[ Column( From 5ad012d60245501c702ec4ef2e4912c53e2a9e69 Mon Sep 17 00:00:00 2001 From: Haroon Amjad <> Date: Thu, 19 Mar 2026 17:09:37 -0400 Subject: [PATCH 08/17] Banner updates, VersionID 9.7 sent to stores --- assets/images/EID_ARABIC_3.svg | 9 +++++++++ assets/images/EID_Englsih_04.svg | 4 ++++ assets/images/asddasd.svg | 14 ++++++++++++++ lib/app_state/app_state.dart | 2 +- lib/ui/landing/dashboard_screen.dart | 4 ++-- 5 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 assets/images/EID_ARABIC_3.svg create mode 100644 assets/images/EID_Englsih_04.svg create mode 100644 assets/images/asddasd.svg diff --git a/assets/images/EID_ARABIC_3.svg b/assets/images/EID_ARABIC_3.svg new file mode 100644 index 0000000..483a836 --- /dev/null +++ b/assets/images/EID_ARABIC_3.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/EID_Englsih_04.svg b/assets/images/EID_Englsih_04.svg new file mode 100644 index 0000000..c2a75b5 --- /dev/null +++ b/assets/images/EID_Englsih_04.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/images/asddasd.svg b/assets/images/asddasd.svg new file mode 100644 index 0000000..b91a675 --- /dev/null +++ b/assets/images/asddasd.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 703a8b0..5ce6861 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -90,7 +90,7 @@ class AppState { String get getHuaweiPushToken => _huaweiPushToken; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 9.6, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 9.7, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 793712c..a89c7f6 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -435,7 +435,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb child: ListView.separated( shrinkWrap: true, scrollDirection: Axis.horizontal, - padding: const EdgeInsets.symmetric(horizontal: 24), + padding: const EdgeInsets.symmetric(horizontal: 0), itemCount: model.greetingCardsList!.length, separatorBuilder: (context, index) => const SizedBox(width: 24), itemBuilder: (context, index) { @@ -444,7 +444,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb AppState().isArabic(context) ? (card.backgroundImageUrlAr ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg") : (card.backgroundImageUrlEn ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg"), - fit: BoxFit.fill, + fit: BoxFit.contain, placeholderBuilder: (context) => ClipRRect(borderRadius: BorderRadius.circular(18), child: Container(height: 80, color: Colors.white).toShimmer()), ).onPress(() { launchUrl(Uri.parse(AppState().isArabic(context) ? card.urlAr! : card.urlEn!)); From deffeda0155456a679b947ae57b3c744361a4fd1 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Mon, 30 Mar 2026 15:44:31 +0300 Subject: [PATCH 09/17] Alma --- lib/api/dashboard_api_client.dart | 3 ++- lib/classes/consts.dart | 8 +++++--- lib/provider/dashboard_provider_model.dart | 3 ++- lib/widgets/sso_webview_widget.dart | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index f04080c..de71e7f 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -250,7 +250,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"; - http.MultipartRequest request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG')); + http.MultipartRequest request = http.MultipartRequest('POST', Uri.parse('https://www.paxes.com/sso/hmg')); + // http.MultipartRequest request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG')); request.fields.addAll({'JWTToken': token}); http.StreamedResponse response = await request.send(); if (response.statusCode == 302) { diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index e1ad116..5e30acc 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -9,9 +9,10 @@ class ApiConsts { // static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://hmgwebservices.com"; // Live server - // static String baseUrl = "https://mohemm.hmg.com"; // New Live server + static String baseUrl = "https://mohemm.hmg.com"; // New Live server + static String ssoBaseUrl = "https://sso.hmg.com"; // New Live server // - static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver + // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver // static String baseUrl = "http://10.20.200.111:1010/"; // static String baseUrl = "https://webservices.hmg.com"; // PreProd @@ -27,7 +28,8 @@ class ApiConsts { static String user = baseUrlServices + "api/User/"; static String cocRest = baseUrlServices + "COCWS.svc/REST/"; - static String ssoAuthRedirection = "https://sso-uat.hmg.com/api/auth/connect"; + // static String ssoAuthRedirection = "https://sso-uat.hmg.com/api/auth/connect"; + static String ssoAuthRedirection = ssoBaseUrl + "/api/auth/connect"; //Chat static String chatServerBaseUrl = "https://apiderichat.hmg.com/"; diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index bdd60c7..4a8ec61 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -311,6 +311,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { try { GenericResponseModel? genericResponseModel = await DashboardApiClient().getTicketBookingRedirection(); if (genericResponseModel?.portalDirectionData?.pRedirection!.toLowerCase() == "alma") { + // ticketBookingResponse = TicketBookingResult(true, "a9f4d1a0596d4aea8f830992ec4bdac1"); ticketBookingResponse = TicketBookingResult(true, genericResponseModel?.portalDirectionData?.clientID); return; } @@ -320,7 +321,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isEventLoadingLoading = false; notifyListeners(); Utils.handleException(ex, null, null); - ticketBookingResponse = TicketBookingResult(false, null); // Ensure a return value in case of an exception + ticketBookingResponse = TicketBookingResult(false, null); } } diff --git a/lib/widgets/sso_webview_widget.dart b/lib/widgets/sso_webview_widget.dart index 070f270..02ed5eb 100644 --- a/lib/widgets/sso_webview_widget.dart +++ b/lib/widgets/sso_webview_widget.dart @@ -46,7 +46,7 @@ class _SsoLoginWebViewState extends State { -
+

Redirecting...

@@ -54,6 +54,7 @@ class _SsoLoginWebViewState extends State { '''); } + ////
@override Widget build(BuildContext context) { return Scaffold(appBar: AppBar(title: Text('Logging in...')), body: WebViewWidget(controller: _controller)); From 9f4e9943cf994933f8d80927b0e3816e3c5f53ed Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Tue, 31 Mar 2026 14:43:40 +0300 Subject: [PATCH 10/17] VHR-279 --- lib/classes/consts.dart | 4 +-- .../mowadhafhi/mowadhafhi_hr_request.dart | 31 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 88ebf73..d8efe5d 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -4,12 +4,12 @@ class ApiConsts { // static String baseUrl = "http://10.200.204.11"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver + static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver // static String baseUrl = "http://10.201.204.101:2024"; // static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://hmgwebservices.com"; // Live server - static String baseUrl = "https://mohemm.hmg.com"; // New Live server + // static String baseUrl = "https://mohemm.hmg.com"; // New Live server // // static String baseUrl = "http://10.20.200.111:1010/"; diff --git a/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart b/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart index e7d2fde..ec12c51 100644 --- a/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart +++ b/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart @@ -194,8 +194,35 @@ class _MowadhafhiHRRequestState extends State { SimpleButton(LocaleKeys.add.tr(), () async { FilePickerResult? result = await FilePicker.platform.pickFiles(allowMultiple: true); if (result != null) { - attachmentFiles = attachmentFiles + result.paths.map((path) => File(path!)).toList(); - attachmentFiles = attachmentFiles.toSet().toList(); + // Maximum file size: 2 MB (in bytes) + const int maxFileSizeInBytes = 2 * 1024 * 1024; // 2 MB + List newFiles = []; + List oversizedFiles = []; + + for (String? path in result.paths) { + if (path != null) { + File file = File(path); + int fileSize = await file.length(); + + if (fileSize <= maxFileSizeInBytes) { + newFiles.add(file); + } else { + String fileName = path.split('/').last; + oversizedFiles.add(fileName); + } + } + } + + if (newFiles.isNotEmpty) { + attachmentFiles = attachmentFiles + newFiles; + attachmentFiles = attachmentFiles.toSet().toList(); + } + + if (oversizedFiles.isNotEmpty) { + // String fileList = oversizedFiles.join(', '); + Utils.showToast('File exceeds 2 MB limit'); + } + setState(() {}); } }, fontSize: 14), From a131179c7108d0cc23e88e31b7347a4535bfd1b8 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Wed, 1 Apr 2026 14:33:16 +0300 Subject: [PATCH 11/17] VHR-279 --- .../mowadhafhi/mowadhafhi_hr_request.dart | 63 +++++++++++++++---- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart b/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart index ec12c51..b358843 100644 --- a/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart +++ b/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart @@ -192,35 +192,76 @@ class _MowadhafhiHRRequestState extends State { title.toText16().expanded, 6.width, SimpleButton(LocaleKeys.add.tr(), () async { - FilePickerResult? result = await FilePicker.platform.pickFiles(allowMultiple: true); + FilePickerResult? result = await FilePicker.platform.pickFiles( + allowMultiple: true, + ); if (result != null) { // Maximum file size: 2 MB (in bytes) - const int maxFileSizeInBytes = 2 * 1024 * 1024; // 2 MB + const int maxFileSizeInBytes = 2 * 1024 * 1024; // 2 MB = 2097152 bytes List newFiles = []; List oversizedFiles = []; - for (String? path in result.paths) { - if (path != null) { - File file = File(path); - int fileSize = await file.length(); + for (PlatformFile platformFile in result.files) { + if (platformFile.path != null) { + File file = File(platformFile.path!); - if (fileSize <= maxFileSizeInBytes) { + // Get file size - check multiple sources for iOS compatibility + int fileSize = 0; + + // Method 1: Check platformFile.size first + if (platformFile.size > 0) { + fileSize = platformFile.size; + debugPrint('Using platformFile.size: $fileSize bytes'); + } + + // Method 2: Always verify with file.length() as well + try { + int fileLengthSize = await file.length(); + debugPrint('Using file.length(): $fileLengthSize bytes'); + // Use the maximum of both to ensure we catch the real size + if (fileLengthSize > fileSize) { + fileSize = fileLengthSize; + debugPrint('Using larger value from file.length()'); + } + } catch (e) { + debugPrint('Error getting file.length(): $e'); + // If file.length() fails, rely on platformFile.size + if (fileSize == 0) { + debugPrint('Cannot determine file size, rejecting file: ${platformFile.name}'); + oversizedFiles.add('${platformFile.name} (unknown size)'); + continue; + } + } + + double fileSizeMB = fileSize / (1024 * 1024); + debugPrint('Final file size - ${platformFile.name}: $fileSize bytes (${fileSizeMB.toStringAsFixed(2)} MB)'); + + // STRICT validation: Only accept files that are 2 MB or less + if (fileSize > 0 && fileSize <= maxFileSizeInBytes) { + debugPrint('✓ File accepted: ${platformFile.name}'); newFiles.add(file); + } else if (fileSize > maxFileSizeInBytes) { + debugPrint('✗ File REJECTED (too large): ${platformFile.name} - ${fileSizeMB.toStringAsFixed(2)} MB'); + oversizedFiles.add('${platformFile.name} (${fileSizeMB.toStringAsFixed(2)} MB)'); } else { - String fileName = path.split('/').last; - oversizedFiles.add(fileName); + debugPrint('✗ File REJECTED (invalid size): ${platformFile.name}'); + oversizedFiles.add('${platformFile.name} (invalid)'); } } } + // Only add valid files if (newFiles.isNotEmpty) { attachmentFiles = attachmentFiles + newFiles; attachmentFiles = attachmentFiles.toSet().toList(); + debugPrint('Total files attached: ${attachmentFiles.length}'); } + // Show error message for rejected files if (oversizedFiles.isNotEmpty) { - // String fileList = oversizedFiles.join(', '); - Utils.showToast('File exceeds 2 MB limit'); + String fileList = oversizedFiles.join('\n'); + Utils.showToast('Max 2MB File allowed.'); + debugPrint('Total rejected files: ${oversizedFiles.length}'); } setState(() {}); From 8ea831c2c4059a6016d26f8c0ad4b404ccd4f623 Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Thu, 2 Apr 2026 09:23:00 +0300 Subject: [PATCH 12/17] color coding changes on the monthly leave calendar and prod e-learning URL added. --- lib/api/dashboard_api_client.dart | 2 +- lib/classes/consts.dart | 8 ++-- ...get_day_hours_type_details_list_model.dart | 8 ++++ .../attendance/monthly_attendance_screen.dart | 48 +++++++++++++++++-- 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 87025f2..e4c63c0 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -435,7 +435,7 @@ class DashboardApiClient { //Fetch All Courses Status Future fetchAllCoursesStatus() async { - String url = "https://elearning.hmg.com/moodle_dev/api/Fetch_All_Courses_Status.php"; + String url = ApiConsts.eLearningBaseUrl +"Fetch_All_Courses_Status.php"; Map headers = { 'x-api-key': 'bLi@mbXJeXTHd/)h&LFh%25+%25(Nbnaq6hBg%7d%5dyQbthY%7bv6ew6-5UT\$NASwucn%7d,_PSJpuwNCCen2%7djj%7b00HR2T-%5b,k7W%7d-0yepK?%258', diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index d8efe5d..7fc3540 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -4,13 +4,13 @@ class ApiConsts { // static String baseUrl = "http://10.200.204.11"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver + // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver // static String baseUrl = "http://10.201.204.101:2024"; // static String baseUrl = "https://webservices.hmg.com"; // PreProd - // static String baseUrl = "https://hmgwebservices.com"; // Live server - // static String baseUrl = "https://mohemm.hmg.com"; // New Live server - // + static String baseUrl = "https://mohemm.hmg.com"; // New Live server + //static String eLearningBaseUrl = "https://elearning.hmg.com/moodle_dev/api/"; // Elearning server UAT + static String eLearningBaseUrl = "https://elearning.hmg.com/moodle/api/"; // Elearning server live // static String baseUrl = "http://10.20.200.111:1010/"; diff --git a/lib/models/get_day_hours_type_details_list_model.dart b/lib/models/get_day_hours_type_details_list_model.dart index e4eef25..0a0c8b0 100644 --- a/lib/models/get_day_hours_type_details_list_model.dart +++ b/lib/models/get_day_hours_type_details_list_model.dart @@ -22,6 +22,8 @@ class GetDayHoursTypeDetailsList { dynamic? fROMROWNUM; String? lATEINFLAG; String? lATEINHRS; + String? lEAVEDESCRIPTION; + String? lEAVETYPECODE; String? mISSINGSWIPEFLAG; String? nONSCHEDULEDFLAG; dynamic? nOOFROWS; @@ -66,6 +68,8 @@ class GetDayHoursTypeDetailsList { this.fROMROWNUM, this.lATEINFLAG, this.lATEINHRS, + this.lEAVEDESCRIPTION, + this.lEAVETYPECODE, this.mISSINGSWIPEFLAG, this.nONSCHEDULEDFLAG, this.nOOFROWS, @@ -110,6 +114,8 @@ class GetDayHoursTypeDetailsList { fROMROWNUM = json['FROM_ROW_NUM']; lATEINFLAG = json['LATE_IN_FLAG']; lATEINHRS = json['LATE_IN_HRS']; + lEAVEDESCRIPTION = json['LEAVE_DESCRIPTION']; + lEAVETYPECODE = json['LEAVE_TYPE_CODE']; mISSINGSWIPEFLAG = json['MISSING_SWIPE_FLAG']; nONSCHEDULEDFLAG = json['NON_SCHEDULED_FLAG']; nOOFROWS = json['NO_OF_ROWS']; @@ -156,6 +162,8 @@ class GetDayHoursTypeDetailsList { data['FROM_ROW_NUM'] = this.fROMROWNUM; data['LATE_IN_FLAG'] = this.lATEINFLAG; data['LATE_IN_HRS'] = this.lATEINHRS; + data['LEAVE_DESCRIPTION'] = this.lEAVEDESCRIPTION; + data['LEAVE_TYPE_CODE'] = this.lEAVETYPECODE; data['MISSING_SWIPE_FLAG'] = this.mISSINGSWIPEFLAG; data['NON_SCHEDULED_FLAG'] = this.nONSCHEDULEDFLAG; data['NO_OF_ROWS'] = this.nOOFROWS; diff --git a/lib/ui/attendance/monthly_attendance_screen.dart b/lib/ui/attendance/monthly_attendance_screen.dart index cce9d3b..5fbd585 100644 --- a/lib/ui/attendance/monthly_attendance_screen.dart +++ b/lib/ui/attendance/monthly_attendance_screen.dart @@ -315,6 +315,26 @@ class _MonthlyAttendanceScreenState extends State { bool isDayIsPresent = getDayHoursTypeDetailsList[index].aTTENDEDFLAG == 'Y'; bool isDayIsAbsent = getDayHoursTypeDetailsList[index].aTTENDEDFLAG == 'N' && getDayHoursTypeDetailsList[index].aBSENTFLAG == 'Y'; + // Get leave type code and corresponding color + String? leaveTypeCode = getDayHoursTypeDetailsList[index].lEAVETYPECODE; + Color? leaveTypeColor; + bool useGradient = false; + + // Determine color based on leave type code + if (leaveTypeCode != null && leaveTypeCode.isNotEmpty) { + leaveTypeColor = leaveTypeColors[leaveTypeCode]; + } + + // If no leave type color found, use default colors based on attendance status + if (leaveTypeColor == null) { + if (isDayIsPresent) { + leaveTypeColor = leaveTypeColors['Present']; + useGradient = true; // Use gradient for present days without leave type + } else if (isDayIsAbsent) { + leaveTypeColor = leaveTypeColors['Absent']; + } + } + if (isDayIsOff) { return Container( margin: const EdgeInsets.all(4), @@ -331,12 +351,13 @@ class _MonthlyAttendanceScreenState extends State { return Container( margin: const EdgeInsets.all(4), decoration: BoxDecoration( - gradient: const LinearGradient( + gradient: useGradient && leaveTypeColor != null ? LinearGradient( transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [MyColors.gradiantEndColor, MyColors.gradiantStartColor], - ), + ) : null, + color: !useGradient && leaveTypeColor != null ? leaveTypeColor : null, shape: BoxShape.circle, boxShadow: [ BoxShadow( @@ -358,7 +379,7 @@ class _MonthlyAttendanceScreenState extends State { return Container( margin: const EdgeInsets.all(4), decoration: BoxDecoration( - color: MyColors.backgroundBlackColor, + color: leaveTypeColor ?? MyColors.backgroundBlackColor, shape: BoxShape.circle, boxShadow: [ BoxShadow( @@ -751,3 +772,24 @@ class Meeting { Color background; bool isAllDay; } +const Map leaveTypeColors = { + 'Present': Color(0xFF00ad62), + 'Absent': Color(0xFFcb3232), + 'HOLIDAY': Color(0xFFF26B0F), + 'BUS_TRIP': Color(0xFF001A6E), + 'WFH': Color(0xFF5DB996), + 'ANNUAL': Color(0xFFf39c12), + 'EMERGENCY': Color(0xFFFF2929), + 'EXAM': Color(0xFFCB6040), + 'HAJJ': Color(0xFF798645), + 'HALF': Color(0xFFE8B86D), + 'LWOP': Color(0xFFCD5C08), + 'LWOP_MATUNPAID': Color(0xFFE73879), + 'LWOP_UNAUUNPAID': Color(0xFFA02334), + 'MATPAID': Color(0xFFE73879), + 'MRGE': Color(0xFF0D7C66), + 'PAT': Color(0xFFC96868), + 'PROF': Color(0xFF6256CA), + 'SICK': Color(0xFFA5B68D), +}; + From e1f2819fe62781808f5c721e0cee5e9799d3cbae Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Thu, 2 Apr 2026 15:41:28 +0300 Subject: [PATCH 13/17] Ticket --- lib/api/eit_api_client.dart | 11 +++++++++-- lib/ui/screens/ticket/ticket_detailed_screen.dart | 10 +++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/api/eit_api_client.dart b/lib/api/eit_api_client.dart index d473aaf..67f155a 100644 --- a/lib/api/eit_api_client.dart +++ b/lib/api/eit_api_client.dart @@ -25,16 +25,23 @@ class EITApiClient { postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject( (json) { + // Check if GetEITTransactionList exists and is not empty + if (json['GetEITTransactionList'] == null || (json['GetEITTransactionList'] is List && json['GetEITTransactionList'].isEmpty)) { + return isCompleteList ? >[] : []; + } + if (isCompleteList) { List> responseData = []; json['GetEITTransactionList'].forEach((element) { var transactionList = GetEitTransactionsModel.fromJson(element).collectionTransaction; - if (transactionList != null) responseData.add(transactionList); + if (transactionList != null && transactionList.isNotEmpty) { + responseData.add(transactionList); + } }); return responseData; } else { List? responseData = GetEitTransactionsModel.fromJson(json['GetEITTransactionList'][0]).collectionTransaction; - return responseData; + return responseData ?? []; } }, url, diff --git a/lib/ui/screens/ticket/ticket_detailed_screen.dart b/lib/ui/screens/ticket/ticket_detailed_screen.dart index 3e8d0b1..f5b3583 100644 --- a/lib/ui/screens/ticket/ticket_detailed_screen.dart +++ b/lib/ui/screens/ticket/ticket_detailed_screen.dart @@ -115,13 +115,12 @@ class _TicketDetailedScreenState extends State { ), ), const SizedBox(height: 21), - dashboardProviderModel == null && dashboardProviderModel!.ticketHistoryTransactionList == null - ? const SizedBox() - : ListView( + (dashboardProviderModel != null && dashboardProviderModel!.ticketHistoryTransactionList != null && dashboardProviderModel!.ticketHistoryTransactionList!.isNotEmpty) + ? ListView( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), children: [ - "Tickets History".toText20().expanded, + "Tickets History".toText20(), 12.height, ListView.separated( physics: const NeverScrollableScrollPhysics(), @@ -219,7 +218,8 @@ class _TicketDetailedScreenState extends State { itemCount: dashboardProviderModel!.ticketHistoryTransactionList!.length, ), ], - ), + ) + : const SizedBox(), ], ], ).expanded, From ecc0869a2383090bbb6af346edb8316395d0772b Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Thu, 2 Apr 2026 15:48:26 +0300 Subject: [PATCH 14/17] Ticket --- lib/api/dashboard_api_client.dart | 1 + lib/ui/screens/ticket/ticket_detailed_screen.dart | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index acdf413..df81621 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -5,6 +5,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:http/http.dart' as http; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:mobile_device_identifier/mobile_device_identifier.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; diff --git a/lib/ui/screens/ticket/ticket_detailed_screen.dart b/lib/ui/screens/ticket/ticket_detailed_screen.dart index aa2a301..7959f39 100644 --- a/lib/ui/screens/ticket/ticket_detailed_screen.dart +++ b/lib/ui/screens/ticket/ticket_detailed_screen.dart @@ -16,7 +16,6 @@ import 'package:mohem_flutter_app/models/eit/get_eit_transaction_model.dart'; import 'package:mohem_flutter_app/models/eit_attachment_ticket_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'; From de3f091ef1bbdb454399ebeafc76435888cb79f5 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Thu, 2 Apr 2026 16:27:13 +0300 Subject: [PATCH 15/17] dashboard --- lib/ui/landing/dashboard_screen.dart | 34 +-- .../shimmer/dashboard_shimmer_widget.dart | 221 +++++------------- 2 files changed, 72 insertions(+), 183 deletions(-) diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 0aafcef..ea0d8d2 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -431,32 +431,22 @@ class _DashboardScreenState extends State with WidgetsBindingOb return const GreetingCardShimmer(); } else if (model.isDisplayEidGreetings && model.greetingCardsList != null && model.greetingCardsList!.isNotEmpty) { return SizedBox( - height: 140, - child: ListView.separated( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.symmetric(horizontal: 0), - itemCount: model.greetingCardsList!.length, - separatorBuilder: (context, index) => const SizedBox(width: 24), - itemBuilder: (context, index) { - var card = model.greetingCardsList![index]; - return SvgPicture.network( - AppState().isArabic(context) - ? (card.backgroundImageUrlAr ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg") - : (card.backgroundImageUrlEn ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg"), - fit: BoxFit.contain, - placeholderBuilder: (context) => ClipRRect(borderRadius: BorderRadius.circular(18), child: Container(height: 80, color: Colors.white).toShimmer()), - ).onPress(() { - launchUrl(Uri.parse(AppState().isArabic(context) ? card.urlAr! : card.urlEn!)); - }); - }, - ), - ).paddingOnly(bottom: 0); + width: double.infinity, + child: SvgPicture.network( + AppState().isArabic(context) + ? (model.greetingCardsList!.first.backgroundImageUrlAr ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg") + : (model.greetingCardsList!.first.backgroundImageUrlEn ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg"), + fit: BoxFit.cover, + placeholderBuilder: (context) => ClipRRect(borderRadius: BorderRadius.circular(18), child: Container(height: 80, color: Colors.white).toShimmer()), + ).onPress(() { + launchUrl(Uri.parse(AppState().isArabic(context) ? model.greetingCardsList!.first.urlAr! : model.greetingCardsList!.first.urlEn!)); + }), + ); } else { return const SizedBox(); } }, - ).paddingOnly(bottom: 24), + ).paddingOnly(bottom: 24, left: 24, right: 24), // eventActivityWidget(context), if (isDisplayMazaya) ...[ Column( diff --git a/lib/widgets/shimmer/dashboard_shimmer_widget.dart b/lib/widgets/shimmer/dashboard_shimmer_widget.dart index 7d59899..4da9751 100644 --- a/lib/widgets/shimmer/dashboard_shimmer_widget.dart +++ b/lib/widgets/shimmer/dashboard_shimmer_widget.dart @@ -19,13 +19,7 @@ class GetAttendanceTrackingShimmer extends StatelessWidget { decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], + boxShadow: [BoxShadow(color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3))], ), child: Stack( alignment: Alignment.center, @@ -46,15 +40,8 @@ class GetAttendanceTrackingShimmer extends StatelessWidget { LocaleKeys.timeLeftToday.tr().toText10(color: Colors.white).toShimmer(), 9.height, const ClipRRect( - borderRadius: BorderRadius.all( - Radius.circular(20), - ), - child: LinearProgressIndicator( - value: 0.7, - minHeight: 8, - valueColor: const AlwaysStoppedAnimation(Colors.white), - backgroundColor: const Color(0xff196D73), - ), + borderRadius: BorderRadius.all(Radius.circular(20)), + child: LinearProgressIndicator(value: 0.7, minHeight: 8, valueColor: const AlwaysStoppedAnimation(Colors.white), backgroundColor: const Color(0xff196D73)), ).toShimmer(), ], ).paddingOnly(top: 12, right: 15, left: 12), @@ -65,9 +52,7 @@ class GetAttendanceTrackingShimmer extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.checkIn.tr().toText12(color: Colors.white).toShimmer(), - ], + children: [LocaleKeys.checkIn.tr().toText12(color: Colors.white).toShimmer()], ).paddingOnly(left: 12), ), Container( @@ -96,13 +81,7 @@ class MenuShimmer extends StatelessWidget { decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], + boxShadow: [BoxShadow(color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3))], ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -111,14 +90,11 @@ class MenuShimmer extends StatelessWidget { LocaleKeys.workList.tr().toText12(color: Colors.white).toShimmer(), Row( children: [ - Expanded( - flex: 3, - child: 123.toString().toText10(color: Colors.white, isBold: true).toShimmer(), - ), + Expanded(flex: 3, child: 123.toString().toText10(color: Colors.white, isBold: true).toShimmer()), 12.width, - SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white).toShimmer() + SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white).toShimmer(), ], - ) + ), ], ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), ); @@ -137,11 +113,7 @@ class ServicesHeaderShimmer extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, - children: [ - LocaleKeys.otherCharges.tr().toText10().toShimmer(), - 6.height, - LocaleKeys.services.tr().toText12(isBold: true).toShimmer(), - ], + children: [LocaleKeys.otherCharges.tr().toText10().toShimmer(), 6.height, LocaleKeys.services.tr().toText12(isBold: true).toShimmer()], ), ), LocaleKeys.viewAllServices.tr().toText12(isUnderLine: true).toShimmer(), @@ -159,13 +131,7 @@ class ServicesMenuShimmer extends StatelessWidget { decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], + boxShadow: [BoxShadow(color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3))], ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -181,15 +147,13 @@ class ServicesMenuShimmer extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - Expanded( - child: LocaleKeys.attendance.tr().toText11(isBold: false).toShimmer(), - ), + Expanded(child: LocaleKeys.attendance.tr().toText11(isBold: false).toShimmer()), 6.width, - SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4).toShimmer() + SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4).toShimmer(), ], ), ], - ) + ), ], ).paddingOnly(left: 10, right: 10, bottom: 10, top: 12), ); @@ -202,69 +166,35 @@ class GreetingCardShimmer extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - height: 100, - decoration: BoxDecoration( - color: const Color(0xFFFAF4E7), - border: Border.all(width: 2, color: const Color(0xFFE7E7E7)), - borderRadius: BorderRadius.circular(20), - ), + height: 140, + decoration: BoxDecoration(color: const Color(0xFFFAF4E7), border: Border.all(width: 2, color: const Color(0xFFE7E7E7)), borderRadius: BorderRadius.circular(20)), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - width: 65, - height: 81, - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(10), - ), - ).toShimmer(), + const SizedBox(width: 10), + Container(width: 65, height: 100, decoration: BoxDecoration(color: Colors.grey[300], borderRadius: BorderRadius.circular(10))).toShimmer().paddingOnly(top: 10), const SizedBox(width: 10), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Container( - width: 150, - height: 16, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(4), - ), - ).toShimmer(), + Container(width: 150, height: 16, decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(4))).toShimmer(), const SizedBox(height: 8), - Container( - width: 120, - height: 16, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(4), - ), - ).toShimmer(), + Container(width: 120, height: 16, decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(4))).toShimmer(), ], ).expanded, Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, - children: [ - Container( - width: 60, - height: 12, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(4), - ), - ).toShimmer(), - ], + children: [Container(width: 60, height: 12, decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(4))).toShimmer()], ), ], ).paddingOnly(left: 8, right: 8, top: 6, bottom: 12), - ).paddingOnly(left: 21, right: 21, top: 14, bottom: 14); + ).paddingOnly( top: 14, bottom: 14); } } - class MarathonBannerShimmer extends StatelessWidget { const MarathonBannerShimmer({Key? key}) : super(key: key); @@ -274,13 +204,7 @@ class MarathonBannerShimmer extends StatelessWidget { decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], + boxShadow: [BoxShadow(color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3))], ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -296,15 +220,13 @@ class MarathonBannerShimmer extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - Expanded( - child: LocaleKeys.attendance.tr().toText11(isBold: false).toShimmer(), - ), + Expanded(child: LocaleKeys.attendance.tr().toText11(isBold: false).toShimmer()), 6.width, - SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4).toShimmer() + SvgPicture.asset("assets/images/arrow_next.svg").paddingOnly(bottom: 4).toShimmer(), ], ), ], - ) + ), ], ).paddingOnly(left: 10, right: 10, bottom: 10, top: 12), ); @@ -320,66 +242,43 @@ class ChatHomeShimmer extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - width: double.infinity, - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0), - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Shimmer.fromColors( - baseColor: Colors.white, - highlightColor: Colors.grey.shade100, - child: ListView.builder( - itemBuilder: (_, __) => Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (!isDetailedScreen) - Container( - width: 48.0, - height: 48.0, - decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(40))), - ), - if (!isDetailedScreen) - const Padding( - padding: EdgeInsets.symmetric(horizontal: 8.0), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: double.infinity, - height: 20.0, - color: Colors.white, - ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 2.0), - ), - Container( - width: double.infinity, - height: 15.0, - color: Colors.white, - ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 2.0), - ), - Container( - width: 40.0, - height: 10.0, - color: Colors.white, - ), - ], - ).expanded - ], + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Shimmer.fromColors( + baseColor: Colors.white, + highlightColor: Colors.grey.shade100, + child: ListView.builder( + itemBuilder: + (_, __) => Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (!isDetailedScreen) Container(width: 48.0, height: 48.0, decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(40)))), + if (!isDetailedScreen) const Padding(padding: EdgeInsets.symmetric(horizontal: 8.0)), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container(width: double.infinity, height: 20.0, color: Colors.white), + const Padding(padding: EdgeInsets.symmetric(vertical: 2.0)), + Container(width: double.infinity, height: 15.0, color: Colors.white), + const Padding(padding: EdgeInsets.symmetric(vertical: 2.0)), + Container(width: 40.0, height: 10.0, color: Colors.white), + ], + ).expanded, + ], + ), ), - ), - itemCount: 6, - ), + itemCount: 6, ), ), - ], - )); + ), + ], + ), + ); } } - From 8260a65bddfa83667762c9f7fb969248344a7681 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Thu, 2 Apr 2026 16:30:09 +0300 Subject: [PATCH 16/17] dashboard --- lib/widgets/shimmer/dashboard_shimmer_widget.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/shimmer/dashboard_shimmer_widget.dart b/lib/widgets/shimmer/dashboard_shimmer_widget.dart index 4da9751..05b30fa 100644 --- a/lib/widgets/shimmer/dashboard_shimmer_widget.dart +++ b/lib/widgets/shimmer/dashboard_shimmer_widget.dart @@ -191,7 +191,7 @@ class GreetingCardShimmer extends StatelessWidget { ), ], ).paddingOnly(left: 8, right: 8, top: 6, bottom: 12), - ).paddingOnly( top: 14, bottom: 14); + ).paddingOnly(top: 14, bottom: 14); } } From 598ce5d7fe2ffba166789e8231a151dc6184df65 Mon Sep 17 00:00:00 2001 From: Aamir Saleem Ahmad Date: Sat, 11 Apr 2026 18:46:05 +0300 Subject: [PATCH 17/17] ticket enable --- lib/ui/landing/dashboard_screen.dart | 2 +- lib/ui/landing/widget/menus_widget.dart | 42 ++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index ea0d8d2..43552ca 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -165,7 +165,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon(); _refreshController.refreshCompleted(); - // await data.fetchTicketBooking(); + await data.fetchTicketBooking(); // if (data.ticketBookingResponse != null && !data.ticketBookingResponse!.success) { // data.fetchTicketBalance(); diff --git a/lib/ui/landing/widget/menus_widget.dart b/lib/ui/landing/widget/menus_widget.dart index 6abfb35..0526bb9 100644 --- a/lib/ui/landing/widget/menus_widget.dart +++ b/lib/ui/landing/widget/menus_widget.dart @@ -123,28 +123,28 @@ class MenusWidget extends StatelessWidget { ], ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), ).onPress(() async { - Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); + // Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); - // var pro = Provider.of(context, listen: false); - // - // // if (menuEntry.menuName == "HMG_TICKET_REQUESTS") { - // 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 { - // Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); - // } + var pro = Provider.of(context, listen: false); + + // if (menuEntry.menuName == "HMG_TICKET_REQUESTS") { + 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 { + Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); + } }), ], );