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'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/landing/event_activity_banner.dart'; import 'package:mohem_flutter_app/ui/landing/widget/app_drawer.dart'; import 'package:mohem_flutter_app/ui/landing/widget/menus_widget.dart'; import 'package:mohem_flutter_app/ui/landing/widget/services_widget.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_banner.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/mark_attendance_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:signalr_netcore/signalr_client.dart'; late HubConnection chatHubConnection; class DashboardScreen extends StatefulWidget { DashboardScreen({Key? key}) : super(key: key); @override _DashboardScreenState createState() { return _DashboardScreenState(); } } class _DashboardScreenState extends State with WidgetsBindingObserver { late DashboardProviderModel data; late MarathonProvider marathonProvider; late ChatProviderModel cProvider; final GlobalKey _scaffoldState = GlobalKey(); final RefreshController _refreshController = RefreshController(initialRefresh: false); int currentIndex = 0; @override void initState() { WidgetsBinding.instance.addObserver(this); super.initState(); cProvider = Provider.of(context, listen: false); scheduleMicrotask(() { data = Provider.of(context, listen: false); marathonProvider = Provider.of(context, listen: false); if (checkIfPrivilegedForChat()) { _bHubCon(); } _onRefresh(true); }); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { checkSession(); } } void checkSession() async { try { await DashboardApiClient().getOpenMissingSwipes(); } catch (ex) { Utils.handleException(ex, context, null); } } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); if (!cProvider.disbaleChatForThisUser) { chatHubConnection.stop(); } } void _bHubCon() { cProvider.getUserAutoLoginToken().whenComplete(() async { if (!cProvider.disbaleChatForThisUser) { String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); if (isAppOpendByChat != "null" && isAppOpendByChat == "true") { Utils.showLoading(context); cProvider.buildHubConnection(); Future.delayed(const Duration(seconds: 2), () async { cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!); gotoChat(context); }); } else { cProvider.buildHubConnection(); Future.delayed(const Duration(seconds: 2), () { cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!); }); } } }); } Future checkHubCon() async { // chatHubConnection = await context.read().getHubConnection(); if (chatHubConnection.state == HubConnectionState.Connected) { await chatHubConnection.stop(); await chatHubConnection.start(); } else if (chatHubConnection.state != HubConnectionState.Connected) { await chatHubConnection.start(); } } void gotoChat(BuildContext context) async { if (chatHubConnection.state == HubConnectionState.Connected) { Utils.hideLoading(context); Navigator.pushNamed(context, AppRoutes.chat); String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat"); if (isAppOpendByChat != "null" || isAppOpendByChat == "true") { Utils.saveStringFromPrefs("isAppOpendByChat", "false"); Utils.saveStringFromPrefs("notificationData", "null"); } } } void _onRefresh(bool isFromInit) async { data.initProvider(); // data.getITGNotification().then((value) { // print("--------------------detail_1-----------------"); // print(value!.result!.data!.notificationMasterId); // print(value.result!.data!.notificationTitle); // }); data.fetchListMenu(); data.fetchAttendanceTracking(context); data.fetchWorkListCounter(context); data.fetchMissingSwipe(context); data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchMenuEntries(); data.fetchEventActivity(); // data.getCategoryOffersListAPI(context); marathonProvider.getMarathonDetailsFromApi(); marathonProvider.getMarathonTutorial(); if (isFromInit) { checkERMChannel(); } if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon(); _refreshController.refreshCompleted(); await data.fetchTicketBooking(); // if (data.ticketBookingResponse != null && !data.ticketBookingResponse!.success) { // // data.fetchTicketBalance(); // } //continue here } int ermIndex = 0; void handleErmChannel(List list) async { try { if (ermIndex == list.length) { return; } // Utils.showLoading(context); ItgMainRes? response = await DashboardApiClient().getAdvertisementDetail(list[ermIndex].notificationMasterId ?? ""); // Utils.hideLoading(context); if (response!.mohemmItgResponseItem!.result!.data != null) { if (list[ermIndex].notificationType == "Survey") { await Navigator.pushNamed(context, AppRoutes.survey, arguments: response.mohemmItgResponseItem!.result!.data!.first); } else { await Navigator.pushNamed( context, AppRoutes.advertisement, arguments: {"masterId": list[ermIndex].notificationMasterId, "advertisement": response.mohemmItgResponseItem!.result!.data!.first.advertisement}, ); } } ermIndex++; handleErmChannel(list); } catch (ex) { print(ex); // Utils.hideLoading(context); // Utils.handleException(ex, context, null); return; } } void checkERMChannel() { data.getITGNotification().then((val) async { if (val!.result!.data != null) { ermIndex = 0; val.result?.data?.removeWhere((element) => element.notificationType == "Announcement"); handleErmChannel(val.result?.data ?? []); { // if (ERMvalue.notificationType == "Survey") { // await DashboardApiClient().getAdvertisementDetail(val.result!.data!.first.notificationMasterId ?? "").then( // (value) async { // if (value!.mohemmItgResponseItem!.statusCode == 200) { // if (value.mohemmItgResponseItem!.result!.data != null) { // // Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data); // await Navigator.pushNamed(context, AppRoutes.survey, arguments: value.mohemmItgResponseItem!.result!.data!.first); // // Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { // // "masterId": val.result!.data!.notificationMasterId, // // "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement, // // }); // } // } // }, // ); // } else { // print("------------------------------------------- Ads --------------------"); // await DashboardApiClient().getAdvertisementDetail(ERMvalue.notificationMasterId ?? "").then( // (value) async { // if (value!.mohemmItgResponseItem!.statusCode == 200) { // if (value.mohemmItgResponseItem!.result!.data != null) { // await Navigator.pushNamed(context, AppRoutes.advertisement, arguments: { // "masterId": val.result!.data!.first.notificationMasterId, // "advertisement": value.mohemmItgResponseItem!.result!.data!.first.advertisement, // }); // } // } // }, // ); // } } } }); } @override Widget build(BuildContext context) { return SafeArea( bottom: Platform.isAndroid ? true : false, top: false, 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), 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), ), ], ), 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) ? const MarathonBannerShimmer().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) : (context.watch().eventActivity != null && context.watch().eventActivity!.isActive == true) ? const EventActivityBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 0) : const SizedBox(); } void navigateToDetails(OffersListModel offersListModelObj) { List getOffersDetailList = []; getOffersDetailList.clear(); int counter = 1; getOffersDetailList.add(offersListModelObj); data.getOffersList.forEach((OffersListModel element) { if (counter <= 4) { if (element.offersDiscountId != offersListModelObj.offersDiscountId) { getOffersDetailList.add(element); counter++; } } }); Navigator.pushNamed(context, AppRoutes.offersAndDiscountsDetails, arguments: getOffersDetailList); } bool checkIfPrivilegedForChat() { for (PrivilegeListModel element in AppState().privilegeListModel!) { if (element.serviceName?.toLowerCase() == "chat") { if (element.previlege != null) { return element.previlege!; } } } return false; } }