From 82afd0ae61dc61a1c2d438ac573d42a30dc82aee Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 24 Oct 2022 11:02:43 +0300 Subject: [PATCH 01/31] Chat Fixes --- lib/api/chat/chat_provider_model.dart | 11 +++++++++++ .../bottom_sheets/search_employee_bottom_sheet.dart | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index ea6ea13..708096b 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -224,6 +224,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (chatMessage == null || chatMessage.isEmpty) { return; } + + var contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); + if (contain.isEmpty) { + searchedChats!.add( + ChatUser( + id: targetUserId, + userName: targetUserName, + ), + ); + } + String chatData = '{"contant":"$chatMessage","contantNo":"8a129295-36d7-7185-5d34-cc4eec7bcba4","chatEventId":1,"fileTypeId":null,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"conversationId":"715f8b13-96ee-cd36-cb07-5a982a219982"}'; await hubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index face11b..e7db4e2 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -230,7 +230,7 @@ class _SearchEmployeeBottomSheetState extends State { }, ); }, - separatorBuilder: (cxt, index) => Container( + separatorBuilder: (BuildContext cxt, int index) => Container( height: 1, color: MyColors.borderE3Color, ), From 912ac8070712117d810236ed0b09ba3d7f92a0ba Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 24 Oct 2022 11:29:28 +0300 Subject: [PATCH 02/31] Chat Fixes --- assets/langs/ar-SA.json | 3 ++- assets/langs/en-US.json | 3 ++- lib/generated/locale_keys.g.dart | 1 + lib/ui/chat/chat_detailed_screen.dart | 4 +++- lib/ui/chat/chat_home.dart | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index f5d9495..e6628b8 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -467,5 +467,6 @@ "fromUserName": "من", "sentDate": "تاريخ الإرسال", "itemTypeDisplayName": "اسم العرض", - "none": "بدون" + "none": "بدون", + "typeheretoreply": "اكتب هنا للرد" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 640afdb..3527ed4 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -467,5 +467,6 @@ "fromUserName": "From User Name", "sentDate": "Sent Date", "itemTypeDisplayName": "Item Type Display Name", - "none": "None" + "none": "None", + "typeheretoreply": "Type here to reply" } \ No newline at end of file diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index d2fae58..b351236 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -454,5 +454,6 @@ abstract class LocaleKeys { static const sentDate = 'sentDate'; static const itemTypeDisplayName = 'itemTypeDisplayName'; static const none = 'none'; + static const typeheretoreply = 'typeheretoreply'; } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index b647a38..654b026 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,11 +1,13 @@ import 'dart:async'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/chat/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; @@ -56,7 +58,7 @@ class ChatDetailScreen extends StatelessWidget { child: TextField( controller: m.message, decoration: InputDecoration( - hintText: 'Type here to reply', + hintText: LocaleKeys.typeheretoreply.tr(), hintStyle: const TextStyle(color: MyColors.grey98Color), border: InputBorder.none, focusedBorder: InputBorder.none, diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index ef984a3..5d6d065 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -45,7 +45,7 @@ class _ChatHomeScreenState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, - appBar: AppBarWidget(context, title: "My Chats", showHomeButton: false), + appBar: AppBarWidget(context, title: LocaleKeys.mychats.tr(), showHomeButton: false), body: Consumer(builder: (BuildContext context, ChatProviderModel m, Widget? child) { return m.isLoading ? ChatHomeShimmer() From cf9f84f38bc61f31f52e52eeb5228857fa84ee0d Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 26 Oct 2022 16:47:13 +0300 Subject: [PATCH 03/31] PO fixes --- lib/models/get_item_creation_ntf_body_list_model.dart | 2 +- lib/models/get_po_Item_history_list_model.dart | 4 ++-- lib/models/get_po_notification_body_list_model.dart | 2 +- lib/models/get_quotation_analysis_list_model.dart | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/models/get_item_creation_ntf_body_list_model.dart b/lib/models/get_item_creation_ntf_body_list_model.dart index e4c22e7..6f98ebb 100644 --- a/lib/models/get_item_creation_ntf_body_list_model.dart +++ b/lib/models/get_item_creation_ntf_body_list_model.dart @@ -168,7 +168,7 @@ class ItemCreationLines { int? tOROWNUM; int? tRANSACTIONHEADERID; int? tRANSACTIONLINEID; - int? uNITPRICE; + num? uNITPRICE; String? uSERMANUFACTURERNAME; String? uSERMFGPARTNUM; diff --git a/lib/models/get_po_Item_history_list_model.dart b/lib/models/get_po_Item_history_list_model.dart index 656457d..35e81d6 100644 --- a/lib/models/get_po_Item_history_list_model.dart +++ b/lib/models/get_po_Item_history_list_model.dart @@ -7,11 +7,11 @@ class GetPoItemHistoryList { int? dISCOUNTPERCENTAGE; int? fROMROWNUM; int? iTEMID; - int? nETPRICE; + num? nETPRICE; int? nOOFROWS; String? oUNAME; String? pONUMBER; - int? pURCHASEPRICE; + num? pURCHASEPRICE; int? qUANTITYORDERED; int? qUANTITYRECEIVED; int? rEVISIONNUM; diff --git a/lib/models/get_po_notification_body_list_model.dart b/lib/models/get_po_notification_body_list_model.dart index 3bc92a0..e1dfbdf 100644 --- a/lib/models/get_po_notification_body_list_model.dart +++ b/lib/models/get_po_notification_body_list_model.dart @@ -164,7 +164,7 @@ class POLines { String? rEQUESTOR; int? rOWNUM; int? tOROWNUM; - int? uNITPRICE; + num? uNITPRICE; String? uOM; POLines( diff --git a/lib/models/get_quotation_analysis_list_model.dart b/lib/models/get_quotation_analysis_list_model.dart index 4ceaa96..e041f95 100644 --- a/lib/models/get_quotation_analysis_list_model.dart +++ b/lib/models/get_quotation_analysis_list_model.dart @@ -8,8 +8,8 @@ class GetQuotationAnalysisList { int? qUOTLINETOTAL; String? qUOTMFGPARTNUM; String? qUOTNUM; - int? qUOTQTY; - int? qUOTUNITPRICE; + num? qUOTQTY; + num? qUOTUNITPRICE; String? qUOTUOM; String? rFQNUM; int? rFQQTY; From f0129399e6751f94b222babbb0aad25406caa00b Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Thu, 27 Oct 2022 12:38:52 +0300 Subject: [PATCH 04/31] Resolved issue in Release mode --- lib/provider/dashboard_provider_model.dart | 1 + lib/ui/login/login_screen.dart | 2 +- lib/ui/marathon/marathon_intro_screen.dart | 74 +++++++++++----------- lib/ui/marathon/marathon_provider.dart | 15 +++-- lib/ui/marathon/marathon_screen.dart | 2 +- lib/ui/marathon/widgets/question_card.dart | 30 ++++----- 6 files changed, 61 insertions(+), 63 deletions(-) diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 26060ea..964dab8 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -123,6 +123,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List? getOpenNotificationsList; MohemmITGPendingTaskResponseItem? cocCount; int cocFinalCount = 0; + //Work List API's & Methods Future fetchWorkListCounter(context, {bool showLoading = false}) async { try { diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 8cd93e4..4a7b659 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -140,7 +140,7 @@ class _LoginScreenState extends State { Widget build(BuildContext context) { if (isAppOpenBySystem == null) { isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool; - if (kDebugMode) { + if (kReleaseMode) { // username.text = "15444"; // Maha User username.text = "15153"; // Tamer User password.text = "Abcd@12345"; diff --git a/lib/ui/marathon/marathon_intro_screen.dart b/lib/ui/marathon/marathon_intro_screen.dart index 4a1a2b6..9ccf5b0 100644 --- a/lib/ui/marathon/marathon_intro_screen.dart +++ b/lib/ui/marathon/marathon_intro_screen.dart @@ -178,47 +178,45 @@ class MarathonFooter extends StatelessWidget { }) : super(key: key); Widget buildNoteForDemo() { - return Flexible( - child: RichText( - text: TextSpan( - children: [ - TextSpan( - text: LocaleKeys.note.tr(), - style: const TextStyle( - color: MyColors.darkTextColor, - fontSize: 17, - letterSpacing: -0.64, - fontWeight: FontWeight.bold, - ), + return RichText( + text: TextSpan( + children: [ + TextSpan( + text: LocaleKeys.note.tr(), + style: const TextStyle( + color: MyColors.darkTextColor, + fontSize: 17, + letterSpacing: -0.64, + fontWeight: FontWeight.bold, ), - TextSpan( - text: " " + LocaleKeys.demoMarathonNoteP1.tr(), - style: const TextStyle( - color: MyColors.grey77Color, - fontSize: 17, - letterSpacing: -0.64, - fontWeight: FontWeight.w500, - ), + ), + TextSpan( + text: " " + LocaleKeys.demoMarathonNoteP1.tr(), + style: const TextStyle( + color: MyColors.grey77Color, + fontSize: 17, + letterSpacing: -0.64, + fontWeight: FontWeight.w500, ), - TextSpan( - text: " " + LocaleKeys.demoMarathonNoteP2.tr(), - style: const TextStyle( - color: MyColors.darkTextColor, - fontSize: 17, - fontWeight: FontWeight.bold, - ), + ), + TextSpan( + text: " " + LocaleKeys.demoMarathonNoteP2.tr(), + style: const TextStyle( + color: MyColors.darkTextColor, + fontSize: 17, + fontWeight: FontWeight.bold, ), - TextSpan( - text: " " + LocaleKeys.demoMarathonNoteP3.tr(), - style: const TextStyle( - color: MyColors.grey77Color, - fontSize: 17, - letterSpacing: -0.64, - fontWeight: FontWeight.w500, - ), - ) - ], - ), + ), + TextSpan( + text: " " + LocaleKeys.demoMarathonNoteP3.tr(), + style: const TextStyle( + color: MyColors.grey77Color, + fontSize: 17, + letterSpacing: -0.64, + fontWeight: FontWeight.w500, + ), + ) + ], ), ).paddingOnly(right: 21, left: 21, top: 11, bottom: 0); } diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index 50a7bd2..39958c2 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -55,11 +55,13 @@ class MarathonProvider extends ChangeNotifier { timer.cancel(); cancelTimer(); isMarathonCompleted = true; - await Future.delayed(const Duration(seconds: 3)); - Navigator.pushReplacementNamed( - context, - AppRoutes.marathonWinnerSelection, + await Future.delayed(const Duration(seconds: 3)).whenComplete( + () => Navigator.pushReplacementNamed( + context, + AppRoutes.marathonWinnerSelection, + ), ); + resetValues(); return; @@ -77,8 +79,9 @@ class MarathonProvider extends ChangeNotifier { void resetValues() { timerU.cancel(); - isMarathonCompleted = false; - currentQuestionNumber = 1; + _isMarathonCompleted = false; + _currentQuestionNumber = 1; + notifyListeners(); } void cancelTimer() { diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index 2d7acee..445d72a 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -29,7 +29,7 @@ class MarathonScreen extends StatelessWidget { child: Column( children: [ const MarathonHeader(), - 20.height, + 20.height, MarathonProgressContainer(provider: provider) .paddingOnly(left: 21, right: 21), if (provider.isMarathonCompleted) diff --git a/lib/ui/marathon/widgets/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index 08c9e3b..45fa6cc 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -135,9 +135,7 @@ class AnswerContent extends StatelessWidget { final DummyQuestionModel question; final MarathonProvider provider; - const AnswerContent( - {Key? key, required this.question, required this.provider}) - : super(key: key); + const AnswerContent({Key? key, required this.question, required this.provider}) : super(key: key); @override Widget build(BuildContext context) { @@ -170,20 +168,18 @@ class AnswerContent extends StatelessWidget { provider.startTimer(context); provider.swipeCardLeft(); }, - child: Flexible( - child: Container( - height: 60, - width: MediaQuery.of(context).size.width - 75, - alignment: Alignment.centerLeft, - decoration: MyDecorations.answerContainerDecoration, - child: Center( - child: Text( - question.opt1!, - style: const TextStyle( - color: MyColors.darkTextColor, - fontWeight: FontWeight.w600, - fontSize: 16, - ), + child: Container( + height: 60, + width: MediaQuery.of(context).size.width - 75, + alignment: Alignment.centerLeft, + decoration: MyDecorations.answerContainerDecoration, + child: Center( + child: Text( + question.opt1!, + style: const TextStyle( + color: MyColors.darkTextColor, + fontWeight: FontWeight.w600, + fontSize: 16, ), ), ), From 1cd7cd4d7653f1451da220c5d2d2be8307a54035 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 27 Oct 2022 15:54:52 +0300 Subject: [PATCH 05/31] issues fixed. --- lib/generated/codegen_loader.g.dart | 2 +- lib/ui/marathon/marathon_screen.dart | 32 ++++++------------- lib/ui/work_list/itg_detail_screen.dart | 1 + lib/ui/work_list/sheets/delegate_sheet.dart | 6 ++++ lib/ui/work_list/work_list_screen.dart | 29 +++++++++++------ lib/ui/work_list/worklist_detail_screen.dart | 29 +++++++++++------ .../worklist_fragments/actions_fragment.dart | 5 +-- 7 files changed, 61 insertions(+), 43 deletions(-) diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 5da5ba1..6e35b8d 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -932,7 +932,7 @@ static const Map en_US = { "updateMember": "Are You Sure You Want to Update this Member?", "fieldIsEmpty": "'{data}' Field is empty. Please select", "pleaseEnterComments": "Please enter comments", - "skip": "skip", + "skip": "Skip", "typeCurrentPasswordBelow": "Type Your Current password below", "currentPassword": "Current password", "profile": { diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index 445d72a..d8f1b97 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -30,8 +30,7 @@ class MarathonScreen extends StatelessWidget { children: [ const MarathonHeader(), 20.height, - MarathonProgressContainer(provider: provider) - .paddingOnly(left: 21, right: 21), + MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21), if (provider.isMarathonCompleted) InkWell( onTap: () { @@ -58,17 +57,12 @@ class MarathonScreen extends StatelessWidget { subTitle: Text( LocaleKeys.allQuestionsCorrect.tr(), textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: MyColors.darkTextColor, - letterSpacing: -1.08), + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -1.08), ), ).paddingOnly(top: 12, left: 21, right: 21), ) else - QuestionCard(provider: provider) - .paddingOnly(top: 12, left: 21, right: 21), + QuestionCard(provider: provider).paddingOnly(top: 12, left: 21, right: 21), ], ), ), @@ -79,12 +73,10 @@ class MarathonScreen extends StatelessWidget { class MarathonProgressContainer extends StatefulWidget { final MarathonProvider provider; - const MarathonProgressContainer({Key? key, required this.provider}) - : super(key: key); + const MarathonProgressContainer({Key? key, required this.provider}) : super(key: key); @override - State createState() => - _MarathonProgressContainerState(); + State createState() => _MarathonProgressContainerState(); } class _MarathonProgressContainerState extends State { @@ -107,7 +99,7 @@ class _MarathonProgressContainerState extends State { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20), + padding: const EdgeInsets.all(21), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -120,18 +112,15 @@ class _MarathonProgressContainerState extends State { borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8), - child: - "${widget.provider.currentQuestionNumber.toString()} / ${widget.provider.totalQuestions.toString()} ${LocaleKeys.question.tr()}" - .toText12(color: MyColors.white), + child: "${widget.provider.currentQuestionNumber.toString()} / ${widget.provider.totalQuestions.toString()} ${LocaleKeys.question.tr()}".toText12(color: MyColors.white), ), "23 ${LocaleKeys.marathoners.tr()}".toText14(), - "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}" - .toText18(), + "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}".toText18(), ], ), 15.height, StepsIndicator( - lineLength: 23, + lineLength: 21, nbSteps: 10, selectedStep: widget.provider.currentQuestionNumber, doneLineColor: MyColors.greenColor, @@ -152,8 +141,7 @@ class _MarathonProgressContainerState extends State { 12.height, Row( children: [ - "${widget.provider.currentQuestionNumber * 10}% ${LocaleKeys.completed.tr()}" - .toText14(isBold: true), + "${widget.provider.currentQuestionNumber * 10}% ${LocaleKeys.completed.tr()}".toText14(isBold: true), ], ), ], diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index 0a74500..e306750 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -210,6 +210,7 @@ class _ItgDetailScreenState extends State { AppState().itgWorkListIndex = AppState().itgWorkListIndex! + 1; requestDetails = null; itgRequest = null; + tabIndex = 0; showFabOptions = false; getDataFromState(); } else if (AppState().requestAllList!.length - 1 == AppState().itgWorkListIndex!) { diff --git a/lib/ui/work_list/sheets/delegate_sheet.dart b/lib/ui/work_list/sheets/delegate_sheet.dart index 7417c30..4075332 100644 --- a/lib/ui/work_list/sheets/delegate_sheet.dart +++ b/lib/ui/work_list/sheets/delegate_sheet.dart @@ -54,6 +54,12 @@ class _DelegateSheetState extends State { var ids = widget.wFHistory!.map((e) => e.employeeID).toSet(); widget.wFHistory!.retainWhere((x) => ids.remove(x.employeeID)); } + + if (widget.actionHistoryList != null) { + widget.actionHistoryList = widget.actionHistoryList!.reversed.toList(); + var ids = widget.actionHistoryList!.map((e) => e.uSERNAME).toSet(); + widget.actionHistoryList!.retainWhere((x) => ids.remove(x.uSERNAME)); + } } @override diff --git a/lib/ui/work_list/work_list_screen.dart b/lib/ui/work_list/work_list_screen.dart index 7def350..9719030 100644 --- a/lib/ui/work_list/work_list_screen.dart +++ b/lib/ui/work_list/work_list_screen.dart @@ -131,16 +131,27 @@ class _WorkListScreenState extends State { } else if (workListElement.key == "COC") { workListElement.value = providerData.cocFinalCount; } else { - var tempList = providerData.getOpenNotificationsList?.where((notificationElement) { - return (notificationElement.itemType == workListItemTypes[workListItemIndex].key) && notificationElement.itemType == workListElement.key; - }).toList(); - if (tempList!.isNotEmpty) { - if ((AppState().workList?.length ?? 0) != (tempList.first.openNtfNumber ?? 0)) { - workListElement.value = AppState().workList?.length ?? 0; - providerData.workListCounter = providerData.workListCounter - ((tempList.first.openNtfNumber ?? 0) - (AppState().workList?.length ?? 0)); - providerData.notify(); + providerData.getOpenNotificationsList?.forEach((element) { + if ((element.itemType == workListItemTypes[workListItemIndex].key) && element.itemType == workListElement.key) { + if ((AppState().workList?.length ?? 0) != (element.openNtfNumber ?? 0)) { + workListElement.value = AppState().workList?.length ?? 0; + providerData.workListCounter = providerData.workListCounter - ((element.openNtfNumber ?? 0) - (AppState().workList?.length ?? 0)); + element.openNtfNumber = workListElement.value; + providerData.notify(); + } } - } + }); + + // var tempList = providerData.getOpenNotificationsList?.where((notificationElement) { + // return (notificationElement.itemType == workListItemTypes[workListItemIndex].key) && notificationElement.itemType == workListElement.key; + // }).toList(); + // if (tempList!.isNotEmpty) { + // if ((AppState().workList?.length ?? 0) != (tempList.first.openNtfNumber ?? 0)) { + // workListElement.value = AppState().workList?.length ?? 0; + // providerData.workListCounter = providerData.workListCounter - ((tempList.first.openNtfNumber ?? 0) - (AppState().workList?.length ?? 0)); + // providerData.notify(); + // } + // } } }); } diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 6e4dcb2..03c9081 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -312,6 +312,7 @@ class _WorkListDetailScreenState extends State { AppState().setWorkListIndex = AppState().workListIndex! + 1; workListData = null; showFabOptions = false; + tabIndex = 0; getDataFromState(); } else if (AppState().workList!.length - 1 == AppState().workListIndex!) { Navigator.pop(context); @@ -354,26 +355,35 @@ class _WorkListDetailScreenState extends State { if (notificationButtonsList[i].bUTTONACTION! == "REJECTED" || notificationButtonsList[i].bUTTONACTION! == "APPROVED" || notificationButtonsList[i].bUTTONACTION! == "CLOSE") { continue; } - fabs.add(myFab(notificationButtonsList[i].bUTTONLABEL!, notificationButtonsList[i].bUTTONACTION == "DELEGATE" ? "assets/images/delegate.svg" : notificationButtonsList[i].bUTTONICON ?? "", - isIconAsset: notificationButtonsList[i].bUTTONACTION == "DELEGATE" ? true : false,) - .paddingOnly(bottom: 12) - .onPress(() => handleFabAction(notificationButtonsList[i]))); + fabs.add(myFab( + notificationButtonsList[i].bUTTONLABEL!, + notificationButtonsList[i].bUTTONACTION == "DELEGATE" ? "assets/images/delegate.svg" : notificationButtonsList[i].bUTTONICON ?? "", + isIconAsset: notificationButtonsList[i].bUTTONACTION == "DELEGATE" ? true : false, + ).paddingOnly(bottom: 12).onPress(() => handleFabAction(notificationButtonsList[i]))); } return fabs; } void handleFabAction(GetNotificationButtonsList notificationButton) { + print("notificationButton:${notificationButton.bUTTONACTION}"); switch (notificationButton.bUTTONACTION) { case "DELEGATE": showMyBottomSheet(context, child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); - break; case "REQUEST_INFO": // do something else showMyBottomSheet(context, child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); break; + case "TRANSFER_INFO": + // do something else + showMyBottomSheet(context, + child: DelegateSheet(title: notificationButton.bUTTONLABEL!, apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + break; + case "ANSWER_INFO": + performAction(notificationButton.bUTTONACTION!,title: notificationButton.bUTTONLABEL); + break; case "RFC": // do something else break; @@ -384,10 +394,10 @@ class _WorkListDetailScreenState extends State { // do something else case "APPROVE_AND_FORWARD": showMyBottomSheet(context, - child: DelegateSheet(title: "Approve and Forward", apiMode: "APPROVE_AND_FORWARD", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: "Approve and Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); break; case "FORWARD": - showMyBottomSheet(context, child: DelegateSheet(title: "Forward", apiMode: "FORWARD", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + showMyBottomSheet(context, child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); break; case "REJECT": performNetworkCall(context, email: "", userId: ""); @@ -480,12 +490,13 @@ class _WorkListDetailScreenState extends State { ); } - void performAction(String actionMode) { + void performAction(String actionMode,{String? title}) { TextEditingController textEditingController = TextEditingController(); showDialog( context: context, builder: (cxt) => AcceptRejectInputDialog( - message: LocaleKeys.requestedItems.tr(), + message: title !=null ? null:LocaleKeys.requestedItems.tr(), + title: title, notificationGetRespond: notificationNoteInput, onTap: (note) { Map payload = { diff --git a/lib/ui/work_list/worklist_fragments/actions_fragment.dart b/lib/ui/work_list/worklist_fragments/actions_fragment.dart index c00f521..d5e1f89 100644 --- a/lib/ui/work_list/worklist_fragments/actions_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/actions_fragment.dart @@ -124,6 +124,7 @@ class ActionsFragment extends StatelessWidget { } Color getStatusColor(String code) { + print("code:$code"); if (code == "SUBMIT") { return const Color(0xff2E303A); } else if (code == "REJECTED") { @@ -134,10 +135,10 @@ class ActionsFragment extends StatelessWidget { return MyColors.orange; } else if (code == "APPROVED" || code == "APPROVE") { return const Color(0xff1FA269); - } else if (code != "SUBMIT" && code != "REJECT" && code != "PENDING") { - return MyColors.orange; } else if (code == "REQUEST_INFO") { return const Color(0xff2E303A); + } else if (code != "SUBMIT" && code != "REJECT" && code != "PENDING") { + return MyColors.orange; } else { return const Color(0xff2E303A); } From 937c4c18b5c2d293c48d89fd404b1dfe4ccf9cb3 Mon Sep 17 00:00:00 2001 From: devmirza121 Date: Sun, 30 Oct 2022 12:31:23 +0300 Subject: [PATCH 06/31] Mark Attandence success animation and font settings --- assets/lottie/lt_success.json | 1 + lib/api/dashboard_api_client.dart | 76 +++- lib/config/routes.dart | 2 +- lib/extensions/string_extensions.dart | 158 +++---- lib/models/itg/advertisement.dart | 99 +++++ lib/models/itg/itg_main_response.dart | 195 +++++++++ lib/models/itg/itg_response_model.dart | 159 ++++++++ lib/provider/dashboard_provider_model.dart | 8 + lib/ui/dialogs/success_dialog.dart | 33 ++ lib/ui/landing/dashboard_screen.dart | 429 ++++++-------------- lib/ui/landing/{ => itg}/survey_screen.dart | 74 +++- lib/ui/landing/itg/video_page.dart | 96 +++++ lib/ui/landing/today_attendance_screen.dart | 55 +-- lib/ui/login/login_screen.dart | 2 +- lib/widgets/dialogs/dialogs.dart | 5 +- lib/widgets/mark_attendance_widget.dart | 23 +- pubspec.yaml | 2 + 17 files changed, 956 insertions(+), 461 deletions(-) create mode 100644 assets/lottie/lt_success.json create mode 100644 lib/models/itg/advertisement.dart create mode 100644 lib/models/itg/itg_main_response.dart create mode 100644 lib/models/itg/itg_response_model.dart create mode 100644 lib/ui/dialogs/success_dialog.dart rename lib/ui/landing/{ => itg}/survey_screen.dart (62%) create mode 100644 lib/ui/landing/itg/video_page.dart diff --git a/assets/lottie/lt_success.json b/assets/lottie/lt_success.json new file mode 100644 index 0000000..e20ec96 --- /dev/null +++ b/assets/lottie/lt_success.json @@ -0,0 +1 @@ +{"v":"5.7.12","fr":24,"ip":0,"op":63,"w":520,"h":520,"nm":"Checklist 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Checklist","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[100]},{"t":62,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[259.587,260.119,0],"ix":2,"l":2},"a":{"a":0,"k":[297.587,298.119,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[54.754,-36.121],[-17.487,36.12],[-54.754,-1.147]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":23,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[294.971,298.679],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[100]},{"t":36,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":720,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Cricle","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[100]},{"t":62,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[260,260,0],"ix":2,"l":2},"a":{"a":0,"k":[-7.627,-7.691,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":18,"s":[124.222,124.222,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[134.222,134.222,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":22,"s":[114.222,114.222,100]},{"t":24,"s":[124.222,124.222,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[178.46,178.46],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.239],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":24,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.16862745098039217,0.7215686274509804,0.6509803921568628,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.16862745098039217,0.7215686274509804,0.6509803921568628,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":22,"s":[0]},{"t":24,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-7.627,-7.691],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":720,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Line","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":39,"s":[100]},{"t":50,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[260,260,0],"ix":2,"l":2},"a":{"a":0,"k":[298,298,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":28,"s":[46,46,100]},{"t":50,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-120.208,0],[0,-120.208],[120.207,0],[0,120.208]],"o":[[120.207,0],[0,120.208],[-120.208,0],[0,-120.208]],"v":[[0,-217.655],[217.655,0],[0,217.655],[-217.655,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.7607843137254902,0.9725490196078431,0.9490196078431372,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[297.587,298.119],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":28,"op":720,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shadow","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":22,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":33,"s":[100]},{"t":44,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[260,260,0],"ix":2,"l":2},"a":{"a":0,"k":[298,298,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":22,"s":[60,60,100]},{"t":44,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-94.797,0],[0,-94.797],[94.797,0],[0,94.798]],"o":[[94.797,0],[0,94.798],[-94.797,0],[0,-94.797]],"v":[[0,-171.646],[171.646,0],[0,171.646],[-171.646,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.8941176470588236,1,0.9882352941176471,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[297.587,298.119],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":22,"op":720,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index dd3f182..cce2207 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; @@ -9,8 +10,12 @@ import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_ 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/itg/itg_main_response.dart'; +import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; + import 'package:uuid/uuid.dart'; + class DashboardApiClient { static final DashboardApiClient _instance = DashboardApiClient._internal(); @@ -40,10 +45,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) { @@ -62,8 +64,7 @@ class DashboardApiClient { }, url, postParams); } - Future> getAccrualBalances( - String effectiveDate) async { + Future> getAccrualBalances(String effectiveDate) async { String url = "${ApiConsts.erpRest}GET_ACCRUAL_BALANCES"; Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; postParams.addAll(AppState().postParamsJson); @@ -97,10 +98,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) { GenericResponseModel responseData = GenericResponseModel.fromJson(json); @@ -109,13 +107,7 @@ class DashboardApiClient { } //Mark Attendance - Future markAttendance( - {String lat = "0", - String? long = "0", - required int pointType, - String nfcValue = "", - bool isGpsRequired = false, - String QRValue = ""}) async { + Future markAttendance({String lat = "0", String? long = "0", required int pointType, String nfcValue = "", bool isGpsRequired = false, String QRValue = ""}) async { String url = "${ApiConsts.swpRest}AuthenticateAndSwipeUserSupportNFC"; var uuid = Uuid(); // Generate a v4 (random) id @@ -136,4 +128,54 @@ class DashboardApiClient { return responseData; }, url, postParams); } + + //Check ITG Type + Future getITGPageNotification() async { + String url = "${ApiConsts.cocRest}Mohemm_ITG_GetPageNotification"; + + Map postParams = { + "EmployeeNumber": AppState().getUserName, + "ItgEnableAt": "After Service Submission", //Mobile Id + "ItgServiceName": "Login" + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + MohemmItgResponseItem res = MohemmItgResponseItem.fromJson(jsonDecode(responseData.mohemmITGResponseItem ?? "")); + // var jsonDecodedData = jsonDecode(jsonDecode(responseData.mohemmITGResponseItem!)['result']['data']); + return res; + }, url, postParams); + } + + //Submit ITG + 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 = { + "EmployeeNumber": AppState().getUserName, + "ItgComments": comment, + "ItgNotificationMasterId": masterId, + "ItgQuestionResponses": itgList, + "ItgSurveyId": serviceId + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + ItgMainRes responseData = ItgMainRes.fromJson(json); + return responseData; + }, url, postParams); + } + + Future getAdvertisementDetail(String masterID) async { + String url = "${ApiConsts.cocRest}Mohemm_ITG_GetPageNotificationDetails"; + + Map postParams = { + "EmployeeNumber": AppState().getUserName, + "ItgNotificationMasterId": masterID, //Mobile Id + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + ItgMainRes responseData = ItgMainRes.fromJson(json); + return responseData; + }, url, postParams); + } } diff --git a/lib/config/routes.dart b/lib/config/routes.dart index c647953..9823082 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -6,7 +6,7 @@ import 'package:mohem_flutter_app/ui/bottom_sheets/attendence_details_bottom_she import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_home.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; -import 'package:mohem_flutter_app/ui/landing/survey_screen.dart'; +import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart'; import 'package:mohem_flutter_app/ui/leave_balance/add_leave_balance_screen.dart'; import 'package:mohem_flutter_app/ui/leave_balance/leave_balance_screen.dart'; diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 9ee4546..9bcc984 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -10,36 +10,19 @@ extension CapExtension on String { String get allInCaps => this.toUpperCase(); - String get capitalizeFirstofEach => this.trim().length > 0 - ? this.trim().toLowerCase().split(" ").map((str) => str.inCaps).join(" ") - : ""; + String get capitalizeFirstofEach => this.trim().length > 0 ? this.trim().toLowerCase().split(" ").map((str) => str.inCaps).join(" ") : ""; } extension EmailValidator on String { Widget get toWidget => Text(this); - Widget toText10( - {Color? color, - bool isBold = false, - int? maxlines, - FontStyle? fontStyle}) => - Text( + Widget toText10({Color? color, bool isBold = false, int? maxlines, FontStyle? fontStyle}) => Text( this, //maxLines: maxlines, - style: TextStyle( - fontSize: 10, - fontStyle: fontStyle ?? FontStyle.normal, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600, - color: color ?? MyColors.darkTextColor, - letterSpacing: -0.4), + style: TextStyle(fontSize: 10, fontStyle: fontStyle ?? FontStyle.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4), ); - Widget toText11( - {Color? color, - FontWeight? weight, - bool isUnderLine = false, - bool isBold = false}) => - Text( + Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isBold = false}) => Text( this, style: TextStyle( fontSize: 11, @@ -50,13 +33,7 @@ extension EmailValidator on String { ), ); - Widget toText12( - {Color? color, - bool isUnderLine = false, - bool isBold = false, - bool isCenter = false, - int maxLine = 0}) => - Text( + Widget toText12({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0}) => Text( this, textAlign: isCenter ? TextAlign.center : null, maxLines: (maxLine > 0) ? maxLine : null, @@ -69,13 +46,7 @@ extension EmailValidator on String { ), ); - Widget toText12Auto( - {Color? color, - bool isUnderLine = false, - bool isBold = false, - bool isCenter = false, - int maxLine = 0}) => - AutoSizeText( + Widget toText12Auto({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0}) => AutoSizeText( this, textAlign: isCenter ? TextAlign.center : null, maxLines: (maxLine > 0) ? maxLine : null, @@ -89,28 +60,47 @@ extension EmailValidator on String { ), ); - Widget toText13({Color? color, bool isUnderLine = false}) => Text( + Widget toTextAuto({ + Color? color, + bool isUnderLine = false, + bool isBold = false, + bool isCenter = false, + int maxLine = 0, + double fontSize = 12, + double letterSpacing = -0.72, + double height = 1, + }) => + AutoSizeText( this, + textAlign: isCenter ? TextAlign.center : null, + maxLines: (maxLine > 0) ? maxLine : null, + minFontSize: 8, style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w600, - color: color ?? MyColors.darkTextColor, - letterSpacing: -0.52, - decoration: isUnderLine ? TextDecoration.underline : null), + fontSize: fontSize, + fontWeight: isBold ? FontWeight.bold : FontWeight.w600, + color: color ?? MyColors.darkTextColor, + letterSpacing: letterSpacing, + decoration: isUnderLine ? TextDecoration.underline : null, + ), + ); + + Widget toText13({Color? color, bool isUnderLine = false}) => Text( + this, + style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.52, decoration: isUnderLine ? TextDecoration.underline : null), ); Widget toText14({Color? color, bool isUnderLine = false, bool isBold = false, FontWeight? weight, int? maxlines}) => Text( this, maxLines: maxlines, - style: TextStyle(color: color ?? MyColors.darkTextColor, fontSize: 14, letterSpacing: -0.48, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600), decoration: isUnderLine ? TextDecoration.underline : null), + style: TextStyle( + color: color ?? MyColors.darkTextColor, + fontSize: 14, + letterSpacing: -0.48, + fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600), + decoration: isUnderLine ? TextDecoration.underline : null), ); - Widget toText16( - {Color? color, - bool isUnderLine = false, - bool isBold = false, - int? maxlines}) => - Text( + Widget toText16({Color? color, bool isUnderLine = false, bool isBold = false, int? maxlines}) => Text( this, maxLines: maxlines, style: TextStyle( @@ -124,97 +114,51 @@ extension EmailValidator on String { Widget toText17({Color? color, bool isBold = false}) => Text( this, - style: TextStyle( - color: color ?? MyColors.darkTextColor, - fontSize: 17, - letterSpacing: -0.68, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600), + style: TextStyle(color: color ?? MyColors.darkTextColor, fontSize: 17, letterSpacing: -0.68, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); Widget toText18({Color? color, bool isBold = false}) => Text( this, - style: TextStyle( - fontSize: 18, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600, - color: color ?? MyColors.darkTextColor, - letterSpacing: -1.08), + style: TextStyle(fontSize: 18, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -1.08), ); Widget toText19({Color? color, bool isBold = false}) => Text( this, - style: TextStyle( - fontSize: 19, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600, - color: color ?? MyColors.darkTextColor, - letterSpacing: -1.14), + style: TextStyle(fontSize: 19, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -1.14), ); Widget toText20({Color? color, bool isBold = false}) => Text( this, - style: TextStyle( - fontSize: 20, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600, - color: color ?? MyColors.darkTextColor, - letterSpacing: -0.4), + style: TextStyle(fontSize: 20, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4), ); - Widget toText21( - {Color? color, - bool isBold = false, - FontWeight? weight, - int? maxlines}) => - Text( + Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text( this, maxLines: maxlines, - style: TextStyle( - color: color ?? MyColors.grey3AColor, - fontSize: 21, - letterSpacing: -0.31, - fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600)), + style: TextStyle(color: color ?? MyColors.grey3AColor, fontSize: 21, letterSpacing: -0.31, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600)), ); Widget toText22({Color? color, bool isBold = false}) => Text( this, - style: TextStyle( - height: 1, - color: color ?? MyColors.darkTextColor, - fontSize: 22, - letterSpacing: -1.44, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600), + style: TextStyle(height: 1, color: color ?? MyColors.darkTextColor, fontSize: 22, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); Widget toText24({Color? color, bool isBold = false}) => Text( this, - style: TextStyle( - height: 23 / 24, - color: color ?? MyColors.darkTextColor, - fontSize: 24, - letterSpacing: -1.44, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600), + style: TextStyle(height: 23 / 24, color: color ?? MyColors.darkTextColor, fontSize: 24, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); Widget toText32({Color? color, bool isBold = false}) => Text( this, - style: TextStyle( - height: 32 / 32, - color: color ?? MyColors.darkTextColor, - fontSize: 32, - letterSpacing: -1.92, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600), + style: TextStyle(height: 32 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.92, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); Widget toText44({Color? color, bool isBold = false}) => Text( this, - style: TextStyle( - height: 32 / 32, - color: color ?? MyColors.darkTextColor, - fontSize: 44, - letterSpacing: -2.64, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600), + style: TextStyle(height: 32 / 32, color: color ?? MyColors.darkTextColor, fontSize: 44, letterSpacing: -2.64, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); - Widget toSectionHeading( - {String upperHeading = "", String lowerHeading = ""}) { + Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) { String upper = ""; String lower = ""; String heading = this; @@ -247,9 +191,7 @@ extension EmailValidator on String { } bool isValidEmail() { - return RegExp( - r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$') - .hasMatch(this); + return RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(this); } String toFormattedDate() { diff --git a/lib/models/itg/advertisement.dart b/lib/models/itg/advertisement.dart new file mode 100644 index 0000000..598a248 --- /dev/null +++ b/lib/models/itg/advertisement.dart @@ -0,0 +1,99 @@ +class Advertisement { + Advertisement({ + this.advertisementId, + this.advertisementTitle, + this.durationInSeconds, + this.showDelete, + this.acknowledgment, + this.viewAttachFileColl, + this.isActive, + this.pageSize, + this.pageNo, + this.languageId, + }); + + final int? advertisementId; + final String? advertisementTitle; + final int? durationInSeconds; + final bool? showDelete; + final dynamic acknowledgment; + final List? viewAttachFileColl; + final bool? isActive; + final dynamic pageSize; + final dynamic pageNo; + final dynamic languageId; + + factory Advertisement.fromJson(Map json) => Advertisement( + advertisementId: json["advertisementId"] == null ? null : json["advertisementId"], + advertisementTitle: json["advertisementTitle"] == null ? null : json["advertisementTitle"], + durationInSeconds: json["durationInSeconds"] == null ? null : json["durationInSeconds"], + showDelete: json["showDelete"] == null ? null : json["showDelete"], + acknowledgment: json["acknowledgment"], + viewAttachFileColl: json["viewAttachFileColl"] == null ? null : List.from(json["viewAttachFileColl"].map((x) => ViewAttachFileColl.fromJson(x))), + isActive: json["isActive"] == null ? null : json["isActive"], + pageSize: json["pageSize"], + pageNo: json["pageNo"], + languageId: json["languageId"], + ); + + Map toJson() => { + "advertisementId": advertisementId == null ? null : advertisementId, + "advertisementTitle": advertisementTitle == null ? null : advertisementTitle, + "durationInSeconds": durationInSeconds == null ? null : durationInSeconds, + "showDelete": showDelete == null ? null : showDelete, + "acknowledgment": acknowledgment, + "viewAttachFileColl": viewAttachFileColl == null ? null : List.from(viewAttachFileColl!.map((x) => x.toJson())), + "isActive": isActive == null ? null : isActive, + "pageSize": pageSize, + "pageNo": pageNo, + "languageId": languageId, + }; +} + +class ViewAttachFileColl { + ViewAttachFileColl({ + this.attachmentId, + this.fileName, + this.contentType, + this.attachFileStream, + this.base64String, + this.isActive, + this.referenceItemId, + this.content, + this.filePath, + }); + + final dynamic attachmentId; + final String? fileName; + final String? contentType; + final dynamic attachFileStream; + final String? base64String; + final dynamic isActive; + final dynamic referenceItemId; + final dynamic content; + final dynamic filePath; + + factory ViewAttachFileColl.fromJson(Map json) => ViewAttachFileColl( + attachmentId: json["attachmentId"], + fileName: json["fileName"] == null ? null : json["fileName"], + contentType: json["contentType"] == null ? null : json["contentType"], + attachFileStream: json["attachFileStream"], + base64String: json["base64String"] == null ? null : json["base64String"], + isActive: json["isActive"], + referenceItemId: json["referenceItemId"], + content: json["content"], + filePath: json["filePath"], + ); + + Map toJson() => { + "attachmentId": attachmentId, + "fileName": fileName == null ? null : fileName, + "contentType": contentType == null ? null : contentType, + "attachFileStream": attachFileStream, + "base64String": base64String == null ? null : base64String, + "isActive": isActive, + "referenceItemId": referenceItemId, + "content": content, + "filePath": filePath, + }; +} diff --git a/lib/models/itg/itg_main_response.dart b/lib/models/itg/itg_main_response.dart new file mode 100644 index 0000000..93ea9c8 --- /dev/null +++ b/lib/models/itg/itg_main_response.dart @@ -0,0 +1,195 @@ +// To parse this JSON data, do +// +// final itgRes = itgResFromJson(jsonString); + +import 'dart:convert'; + +import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; + +ItgMainRes itgResFromJson(String str) => ItgMainRes.fromJson(json.decode(str)); + +String itgResToJson(ItgMainRes data) => json.encode(data.toJson()); + +class ItgMainRes { + ItgMainRes({ + this.date, + this.languageId, + this.serviceName, + this.time, + this.androidLink, + this.authenticationTokenId, + this.data, + this.dataw, + this.dietType, + this.dietTypeId, + this.errorCode, + this.errorEndUserMessage, + this.errorEndUserMessageN, + this.errorMessage, + this.errorType, + this.foodCategory, + this.iosLink, + this.isAuthenticated, + this.mealOrderStatus, + this.mealType, + this.messageStatus, + this.numberOfResultRecords, + this.patientBlodType, + this.successMsg, + this.successMsgN, + this.vidaUpdatedResponse, + this.itgRequest, + this.itgFormAttachmentsList, + this.message, + this.mohemmItgDepartmentSectionsList, + this.mohemmItgPendingTaskResponseItem, + this.mohemmItgProjectDepartmentsList, + this.mohemmItgResponseItem, + this.mohemmItgSectionTopicsList, + this.mohemmItgTicketDetailsList, + this.mohemmItgTicketTransactionsList, + this.mohemmItgTicketsByEmployeeList, + this.mohemmItgProjectsList, + this.mohemmItgTicketTypesList, + this.referenceNumber, + this.requestType, + this.totalCount, + this.statuseCode, + }); + + final dynamic date; + final int? languageId; + final int? serviceName; + final dynamic time; + final dynamic androidLink; + final dynamic authenticationTokenId; + final dynamic data; + final bool? dataw; + final int? dietType; + final int? dietTypeId; + final dynamic errorCode; + final dynamic errorEndUserMessage; + final dynamic errorEndUserMessageN; + final dynamic errorMessage; + final int? errorType; + final int? foodCategory; + final dynamic iosLink; + final bool? isAuthenticated; + final int? mealOrderStatus; + final int? mealType; + final int? messageStatus; + final int? numberOfResultRecords; + final dynamic patientBlodType; + final dynamic successMsg; + final dynamic successMsgN; + final dynamic vidaUpdatedResponse; + final dynamic itgRequest; + final dynamic itgFormAttachmentsList; + final dynamic message; + final dynamic mohemmItgDepartmentSectionsList; + final dynamic mohemmItgPendingTaskResponseItem; + final dynamic mohemmItgProjectDepartmentsList; + final MohemmItgResponseItem? mohemmItgResponseItem; + final dynamic mohemmItgSectionTopicsList; + final dynamic mohemmItgTicketDetailsList; + final dynamic mohemmItgTicketTransactionsList; + final dynamic mohemmItgTicketsByEmployeeList; + final dynamic mohemmItgProjectsList; + final dynamic mohemmItgTicketTypesList; + final dynamic referenceNumber; + final dynamic requestType; + final int? totalCount; + final int? statuseCode; + + factory ItgMainRes.fromJson(Map json) => ItgMainRes( + date: json["Date"], + languageId: json["LanguageID"] == null ? null : json["LanguageID"], + serviceName: json["ServiceName"] == null ? null : json["ServiceName"], + time: json["Time"], + androidLink: json["AndroidLink"], + authenticationTokenId: json["AuthenticationTokenID"], + data: json["Data"], + dataw: json["Dataw"] == null ? null : json["Dataw"], + dietType: json["DietType"] == null ? null : json["DietType"], + dietTypeId: json["DietTypeID"] == null ? null : json["DietTypeID"], + errorCode: json["ErrorCode"], + errorEndUserMessage: json["ErrorEndUserMessage"], + errorEndUserMessageN: json["ErrorEndUserMessageN"], + errorMessage: json["ErrorMessage"], + errorType: json["ErrorType"] == null ? null : json["ErrorType"], + foodCategory: json["FoodCategory"] == null ? null : json["FoodCategory"], + iosLink: json["IOSLink"], + isAuthenticated: json["IsAuthenticated"] == null ? null : json["IsAuthenticated"], + mealOrderStatus: json["MealOrderStatus"] == null ? null : json["MealOrderStatus"], + mealType: json["MealType"] == null ? null : json["MealType"], + messageStatus: json["MessageStatus"] == null ? null : json["MessageStatus"], + numberOfResultRecords: json["NumberOfResultRecords"] == null ? null : json["NumberOfResultRecords"], + patientBlodType: json["PatientBlodType"], + successMsg: json["SuccessMsg"], + successMsgN: json["SuccessMsgN"], + vidaUpdatedResponse: json["VidaUpdatedResponse"], + itgRequest: json["ITGRequest"], + itgFormAttachmentsList: json["Itg_FormAttachmentsList"], + message: json["Message"], + mohemmItgDepartmentSectionsList: json["Mohemm_ITG_DepartmentSectionsList"], + mohemmItgPendingTaskResponseItem: json["Mohemm_ITG_Pending_Task_ResponseItem"], + mohemmItgProjectDepartmentsList: json["Mohemm_ITG_ProjectDepartmentsList"], + mohemmItgResponseItem: json["Mohemm_ITG_ResponseItem"] ==null ? null : MohemmItgResponseItem.fromJson(jsonDecode(json["Mohemm_ITG_ResponseItem"])), + mohemmItgSectionTopicsList: json["Mohemm_ITG_SectionTopicsList"], + mohemmItgTicketDetailsList: json["Mohemm_ITG_TicketDetailsList"], + mohemmItgTicketTransactionsList: json["Mohemm_ITG_TicketTransactionsList"], + mohemmItgTicketsByEmployeeList: json["Mohemm_ITG_TicketsByEmployeeList"], + mohemmItgProjectsList: json["Mohemm_Itg_ProjectsList"], + mohemmItgTicketTypesList: json["Mohemm_Itg_TicketTypesList"], + referenceNumber: json["ReferenceNumber"], + requestType: json["RequestType"], + totalCount: json["TotalCount"] == null ? null : json["TotalCount"], + statuseCode: json["statuseCode"] == null ? null : json["statuseCode"], + ); + + Map toJson() => { + "Date": date, + "LanguageID": languageId == null ? null : languageId, + "ServiceName": serviceName == null ? null : serviceName, + "Time": time, + "AndroidLink": androidLink, + "AuthenticationTokenID": authenticationTokenId, + "Data": data, + "Dataw": dataw == null ? null : dataw, + "DietType": dietType == null ? null : dietType, + "DietTypeID": dietTypeId == null ? null : dietTypeId, + "ErrorCode": errorCode, + "ErrorEndUserMessage": errorEndUserMessage, + "ErrorEndUserMessageN": errorEndUserMessageN, + "ErrorMessage": errorMessage, + "ErrorType": errorType == null ? null : errorType, + "FoodCategory": foodCategory == null ? null : foodCategory, + "IOSLink": iosLink, + "IsAuthenticated": isAuthenticated == null ? null : isAuthenticated, + "MealOrderStatus": mealOrderStatus == null ? null : mealOrderStatus, + "MealType": mealType == null ? null : mealType, + "MessageStatus": messageStatus == null ? null : messageStatus, + "NumberOfResultRecords": numberOfResultRecords == null ? null : numberOfResultRecords, + "PatientBlodType": patientBlodType, + "SuccessMsg": successMsg, + "SuccessMsgN": successMsgN, + "VidaUpdatedResponse": vidaUpdatedResponse, + "ITGRequest": itgRequest, + "Itg_FormAttachmentsList": itgFormAttachmentsList, + "Message": message, + "Mohemm_ITG_DepartmentSectionsList": mohemmItgDepartmentSectionsList, + "Mohemm_ITG_Pending_Task_ResponseItem": mohemmItgPendingTaskResponseItem, + "Mohemm_ITG_ProjectDepartmentsList": mohemmItgProjectDepartmentsList, + "Mohemm_ITG_ResponseItem": mohemmItgResponseItem == null ? null : mohemmItgResponseItem, + "Mohemm_ITG_SectionTopicsList": mohemmItgSectionTopicsList, + "Mohemm_ITG_TicketDetailsList": mohemmItgTicketDetailsList, + "Mohemm_ITG_TicketTransactionsList": mohemmItgTicketTransactionsList, + "Mohemm_ITG_TicketsByEmployeeList": mohemmItgTicketsByEmployeeList, + "Mohemm_Itg_ProjectsList": mohemmItgProjectsList, + "Mohemm_Itg_TicketTypesList": mohemmItgTicketTypesList, + "ReferenceNumber": referenceNumber, + "RequestType": requestType, + "TotalCount": totalCount == null ? null : totalCount, + "statuseCode": statuseCode == null ? null : statuseCode, + }; +} diff --git a/lib/models/itg/itg_response_model.dart b/lib/models/itg/itg_response_model.dart new file mode 100644 index 0000000..4dff106 --- /dev/null +++ b/lib/models/itg/itg_response_model.dart @@ -0,0 +1,159 @@ +// To parse this JSON data, do +// +// final mohemmItgResponseItem = mohemmItgResponseItemFromJson(jsonString); + +import 'dart:convert'; + +import 'package:mohem_flutter_app/models/itg/advertisement.dart'; + +MohemmItgResponseItem mohemmItgResponseItemFromJson(String str) => MohemmItgResponseItem.fromJson(json.decode(str)); + +String mohemmItgResponseItemToJson(MohemmItgResponseItem data) => json.encode(data.toJson()); + +class MohemmItgResponseItem { + MohemmItgResponseItem({ + this.statusCode, + this.message, + this.originalErrMsg, + this.result, + }); + + final int? statusCode; + final dynamic? message; + final dynamic? originalErrMsg; + final ItgResponseResult? result; + + factory MohemmItgResponseItem.fromJson(Map json) => MohemmItgResponseItem( + statusCode: json["statusCode"] == null ? null : json["statusCode"], + message: json["message"], + originalErrMsg: json["originalErrMsg"], + result: json["result"] == null ? null : ItgResponseResult.fromJson(json["result"]), + ); + + Map toJson() => { + "statusCode": statusCode == null ? null : statusCode, + "message": message, + "originalErrMsg": originalErrMsg, + "result": result == null ? null : result!.toJson(), + }; +} + +class ItgResponseResult { + ItgResponseResult({ + this.totalItemsCount, + this.data, + this.errormsg, + }); + + final dynamic totalItemsCount; + final ItgResponseData? data; + final dynamic errormsg; + + factory ItgResponseResult.fromJson(Map json) => ItgResponseResult( + totalItemsCount: json["totalItemsCount"], + data: json["data"] == null ? null : ItgResponseData.fromJson(json["data"]), + errormsg: json["errormsg"], + ); + + Map toJson() => { + "totalItemsCount": totalItemsCount, + "data": data == null ? null : data!.toJson(), + "errormsg": errormsg, + }; +} + +class ItgResponseData { + ItgResponseData({ + this.notificationMasterId, + this.notificationType, + this.referenceItemId, + this.notificationTitle, + this.enableAt, + this.applicationItemId, + this.startDate, + this.endDate, + this.isRepeat, + this.channelId, + this.serviceId, + this.channelName, + this.serviceName, + this.isDeleted, + this.showDelete, + this.advertisement, + this.survey, + this.isActive, + this.pageSize, + this.pageNo, + this.languageId, + }); + + final String? notificationMasterId; + final String? notificationType; + final int? referenceItemId; + final String? notificationTitle; + final String? enableAt; + final dynamic applicationItemId; + final dynamic startDate; + final dynamic endDate; + final bool? isRepeat; + final int? channelId; + final int? serviceId; + final String? channelName; + final String? serviceName; + final bool? isDeleted; + final bool? showDelete; + final Advertisement? advertisement; + final dynamic survey; + final dynamic isActive; + final dynamic pageSize; + final dynamic pageNo; + final dynamic languageId; + + factory ItgResponseData.fromJson(Map json) => ItgResponseData( + notificationMasterId: json["notificationMasterId"] == null ? null : json["notificationMasterId"], + notificationType: json["notificationType"] == null ? null : json["notificationType"], + referenceItemId: json["referenceItemId"] == null ? null : json["referenceItemId"], + notificationTitle: json["notificationTitle"] == null ? null : json["notificationTitle"], + enableAt: json["enableAt"] == null ? null : json["enableAt"], + applicationItemId: json["applicationItemId"], + startDate: json["startDate"], + endDate: json["endDate"], + isRepeat: json["isRepeat"] == null ? null : json["isRepeat"], + channelId: json["channelId"] == null ? null : json["channelId"], + serviceId: json["serviceId"] == null ? null : json["serviceId"], + channelName: json["channelName"] == null ? null : json["channelName"], + serviceName: json["serviceName"] == null ? null : json["serviceName"], + isDeleted: json["isDeleted"] == null ? null : json["isDeleted"], + showDelete: json["showDelete"] == null ? null : json["showDelete"], + advertisement: json["advertisement"] == null ? null : Advertisement.fromJson(json["advertisement"]), + survey: json["survey"], + isActive: json["isActive"], + pageSize: json["pageSize"], + pageNo: json["pageNo"], + languageId: json["languageId"], + ); + + Map toJson() => { + "notificationMasterId": notificationMasterId == null ? null : notificationMasterId, + "notificationType": notificationType == null ? null : notificationType, + "referenceItemId": referenceItemId == null ? null : referenceItemId, + "notificationTitle": notificationTitle == null ? null : notificationTitle, + "enableAt": enableAt == null ? null : enableAt, + "applicationItemId": applicationItemId, + "startDate": startDate, + "endDate": endDate, + "isRepeat": isRepeat == null ? null : isRepeat, + "channelId": channelId == null ? null : channelId, + "serviceId": serviceId == null ? null : serviceId, + "channelName": channelName == null ? null : channelName, + "serviceName": serviceName == null ? null : serviceName, + "isDeleted": isDeleted == null ? null : isDeleted, + "showDelete": showDelete == null ? null : showDelete, + "advertisement": advertisement, + "survey": survey, + "isActive": isActive, + "pageSize": pageSize, + "pageNo": pageNo, + "languageId": languageId, + }; +} diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 964dab8..4e53242 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -17,6 +17,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/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'; /// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool @@ -248,6 +249,13 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return menus; } + Future getITGNotification() async { + MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification(); + return res; + } + + + void notify() { notifyListeners(); } diff --git a/lib/ui/dialogs/success_dialog.dart b/lib/ui/dialogs/success_dialog.dart new file mode 100644 index 0000000..8e1de54 --- /dev/null +++ b/lib/ui/dialogs/success_dialog.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:lottie/lottie.dart'; + +class SuccessDialog extends StatelessWidget { + bool isFromDashboard; + + SuccessDialog(this.isFromDashboard); + + @override + Widget build(BuildContext context) { + double size = MediaQuery.of(context).size.width / 1.8; + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: size, + height: size, + child: Card( + child: Lottie.asset('assets/lottie/lt_success.json', repeat: false, reverse: false, onLoaded: (v) { + print("calling_lottie " + v.seconds.toString()); + Future.delayed(Duration(seconds: 2)).then((value) { + Navigator.pop(context); + if (isFromDashboard) Navigator.pop(context); + }); + }), + ), + ), + ], + ); + } +} diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index c99d2e7..c09c16d 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -4,6 +4,7 @@ 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'; @@ -12,13 +13,17 @@ 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_response_model.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/dialogs/success_dialog.dart'; +import 'package:mohem_flutter_app/ui/landing/itg/video_page.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/widgets/marathon_banner.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/dialogs.dart'; import 'package:mohem_flutter_app/widgets/mark_attendance_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart'; @@ -38,8 +43,7 @@ class _DashboardScreenState extends State { late DashboardProviderModel data; final GlobalKey _scaffoldState = GlobalKey(); - final RefreshController _refreshController = - RefreshController(initialRefresh: false); + final RefreshController _refreshController = RefreshController(initialRefresh: false); int currentIndex = 0; @@ -59,6 +63,11 @@ class _DashboardScreenState extends State { void _onRefresh() 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); @@ -73,6 +82,44 @@ class _DashboardScreenState extends State { Widget build(BuildContext context) { return Scaffold( key: _scaffoldState, + // appBar: AppBar( + // actions: [ + // IconButton( + // onPressed: () { + // data.getITGNotification().then((value) { + // print("--------------------detail_1-----------------"); + // if (value!.result!.data != null) { + // print(value.result!.data!.notificationMasterId); + // print(value.result!.data!.notificationType); + // if (value.result!.data!.notificationType == "Survey") { + // Navigator.pushNamed(context, AppRoutes.survey, arguments: value.result!.data); + // } else { + // DashboardApiClient().getAdvertisementDetail(value.result!.data!.notificationMasterId ?? "").then( + // (value) { + // if (value!.mohemmItgResponseItem!.statusCode == 200) { + // if (value.mohemmItgResponseItem!.result!.data != null) { + // String? image64 = value.mohemmItgResponseItem!.result!.data!.advertisement!.viewAttachFileColl!.first.base64String; + // print(image64); + // var sp = image64!.split("base64,"); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => MovieTheaterBody( + // encodedBytes: sp[1], + // ), + // ), + // ); + // } + // } + // }, + // ); + // } + // } + // }); + // }, + // icon: Icon(Icons.add)) + // ], + // ), body: Column( children: [ Row( @@ -85,8 +132,7 @@ class _DashboardScreenState extends State { Utils.dataFromBase64String( AppState().memberInformationList!.eMPLOYEEIMAGE ?? "", ), - errorBuilder: (BuildContext context, Object error, - StackTrace? stackTrace) { + errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { return SvgPicture.asset( "assets/images/user.svg", height: 34, @@ -109,9 +155,7 @@ class _DashboardScreenState extends State { _scaffoldState.currentState!.openDrawer(); }); }), - Image.asset("assets/images/logos/main_mohemm_logo.png", - width: 134, height: 28) - .expanded, + Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28).expanded, SvgPicture.asset( "assets/images/announcements.svg", ).onPress(() async { @@ -134,11 +178,8 @@ class _DashboardScreenState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.goodMorning - .tr() - .toText14(color: MyColors.grey77Color), - (AppState().memberInformationList!.eMPLOYEENAME ?? "") - .toText24(isBold: true), + LocaleKeys.goodMorning.tr().toText14(color: MyColors.grey77Color), + (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true), 16.height, Row( children: [ @@ -146,223 +187,92 @@ class _DashboardScreenState extends State { child: AspectRatio( aspectRatio: 159 / 159, child: Consumer( - builder: (BuildContext context, - DashboardProviderModel model, - Widget? child) { + 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, - ]), + 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"), + if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"), Column( - crossAxisAlignment: - CrossAxisAlignment - .start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( - mainAxisSize: - MainAxisSize - .min, - crossAxisAlignment: - CrossAxisAlignment - .start, + 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) + 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, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ 9.height, 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), + 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), + 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), + 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), + ).paddingOnly(top: 12, right: 15, left: 12), ), Row( children: [ Expanded( child: Column( - mainAxisSize: - MainAxisSize - .min, - crossAxisAlignment: - CrossAxisAlignment - .start, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys - .checkIn - .tr() - .toText12( - color: - Colors.white), - (model.attendanceTracking!.pSwipeIn == - null - ? "--:--" - : model - .attendanceTracking! - .pSwipeIn) + LocaleKeys.checkIn.tr().toText12(color: Colors.white), + (model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn) .toString() - .toText14( - color: Colors - .white, - isBold: - true), + .toText14(color: Colors.white, isBold: true), 4.height, ], - ).paddingOnly( - left: 12, - right: 12), + ).paddingOnly(left: 12, right: 12), ), Container( - margin: EdgeInsets.only( - top: AppState() - .isArabic( - context) - ? 6 - : 0), + margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0), width: 45, height: 45, - padding: - const EdgeInsets - .only( - left: 14, - right: - 14), - decoration: - BoxDecoration( - color: Color( - 0xff259EA4), - borderRadius: - BorderRadius - .only( - bottomRight: AppState() - .isArabic( - context) - ? Radius - .circular( - 0) - : Radius - .circular( - 15), - bottomLeft: AppState() - .isArabic( - context) - ? Radius - .circular( - 15) - : Radius - .circular( - 0), + padding: const EdgeInsets.only(left: 14, right: 14), + decoration: BoxDecoration( + color: Color(0xff259EA4), + borderRadius: BorderRadius.only( + bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15), + bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), ), ), - child: SvgPicture.asset( - model.isTimeRemainingInSeconds == - 0 - ? "assets/images/play.svg" - : "assets/images/stop.svg"), + child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/play.svg" : "assets/images/stop.svg"), ).onPress(() { showMyBottomSheet( - context, - child: - MarkAttendanceWidget( - model)); + context, + child: MarkAttendanceWidget(model, isFromDashboard: true), + ); }), ], ), @@ -372,10 +282,7 @@ class _DashboardScreenState extends State { ), ).onPress( () { - Navigator.pushNamed( - context, - AppRoutes - .todayAttendance); + Navigator.pushNamed(context, AppRoutes.todayAttendance); }, )) .animatedSwither(); @@ -399,11 +306,8 @@ class _DashboardScreenState extends State { 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), + 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, @@ -420,32 +324,22 @@ class _DashboardScreenState extends State { LocaleKeys.offers.tr().toText12(), Row( children: [ - LocaleKeys.discounts - .tr() - .toText24(isBold: true), + LocaleKeys.discounts.tr().toText24(isBold: true), 6.width, Container( - padding: const EdgeInsets.only( - left: 8, right: 8), + padding: const EdgeInsets.only(left: 8, right: 8), decoration: BoxDecoration( color: MyColors.yellowColor, - borderRadius: - BorderRadius.circular(10), + borderRadius: BorderRadius.circular(10), ), - child: LocaleKeys.newString - .tr() - .toText10(isBold: true)), + child: LocaleKeys.newString.tr().toText10(isBold: true)), ], ), ], ), ), - LocaleKeys.viewAllOffers - .tr() - .toText12(isUnderLine: true) - .onPress(() { - Navigator.pushNamed( - context, AppRoutes.offersAndDiscounts); + LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { + Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); }) ], ).paddingOnly(left: 21, right: 21), @@ -456,56 +350,38 @@ class _DashboardScreenState extends State { child: ListView.separated( shrinkWrap: true, physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.only( - left: 21, right: 21, top: 13), + 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]); + navigateToDetails(data.getOffersList[index]); }, child: SizedBox( width: 73, child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( width: 73, height: 73, decoration: BoxDecoration( - borderRadius: - const BorderRadius - .all( + borderRadius: const BorderRadius.all( Radius.circular(100), ), - border: Border.all( - color: MyColors - .lightGreyE3Color, - width: 1), + border: Border.all(color: MyColors.lightGreyE3Color, width: 1), ), child: ClipRRect( - borderRadius: - const BorderRadius - .all( + borderRadius: const BorderRadius.all( Radius.circular(50), ), child: Hero( - tag: "ItemImage" + - data - .getOffersList[ - index] - .rowID!, - transitionOnUserGestures: - true, + tag: "ItemImage" + data.getOffersList[index].rowID!, + transitionOnUserGestures: true, child: Image.network( - data - .getOffersList[ - index] - .bannerImage!, + data.getOffersList[index].bannerImage!, fit: BoxFit.contain, ), ), @@ -513,33 +389,16 @@ class _DashboardScreenState extends State { ), 4.height, Expanded( - child: AppState() - .isArabic(context) - ? data - .getOffersList[ - index] - .titleAR! - .toText12( - isCenter: - true, - maxLine: 1) - : data - .getOffersList[ - index] - .title! - .toText12( - isCenter: - true, - maxLine: 1), + child: AppState().isArabic(context) + ? data.getOffersList[index].titleAR!.toText12(isCenter: true, maxLine: 1) + : data.getOffersList[index].title!.toText12(isCenter: true, maxLine: 1), ), ], ), ), ); }, - separatorBuilder: - (BuildContext cxt, int index) => - 8.width, + separatorBuilder: (BuildContext cxt, int index) => 8.width, itemCount: 6), ); }, @@ -564,18 +423,14 @@ class _DashboardScreenState extends State { BottomNavigationBarItem( icon: SvgPicture.asset( "assets/icons/home.svg", - color: currentIndex == 0 - ? MyColors.grey3AColor - : MyColors.grey98Color, + 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, + color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color, ).paddingAll(4), label: LocaleKeys.createRequest.tr(), ), @@ -585,13 +440,10 @@ class _DashboardScreenState extends State { children: [ SvgPicture.asset( "assets/icons/work_list.svg", - color: currentIndex == 2 - ? MyColors.grey3AColor - : MyColors.grey98Color, + color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color, ).paddingAll(4), Consumer( - builder: (BuildContext cxt, DashboardProviderModel data, - Widget? child) { + builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { if (data.workListCounter == 0) { return const SizedBox(); } @@ -601,12 +453,8 @@ class _DashboardScreenState extends State { 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), + decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)), + child: data.workListCounter.toString().toText10(color: Colors.white), ), ); }, @@ -618,38 +466,26 @@ class _DashboardScreenState extends State { BottomNavigationBarItem( icon: SvgPicture.asset( "assets/icons/item_for_sale.svg", - color: currentIndex == 3 - ? MyColors.grey3AColor - : MyColors.grey98Color, + color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color, ).paddingAll(4), label: LocaleKeys.itemsForSale.tr(), ), BottomNavigationBarItem( icon: SvgPicture.asset( "assets/icons/chat/chat.svg", - color: currentIndex == 4 - ? MyColors.grey3AColor - : MyColors.grey98Color, + color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color, ).paddingAll(4), 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), + 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), + 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); @@ -682,7 +518,6 @@ class _DashboardScreenState extends State { } }); - Navigator.pushNamed(context, AppRoutes.offersAndDiscountsDetails, - arguments: getOffersDetailList); + Navigator.pushNamed(context, AppRoutes.offersAndDiscountsDetails, arguments: getOffersDetailList); } } diff --git a/lib/ui/landing/survey_screen.dart b/lib/ui/landing/itg/survey_screen.dart similarity index 62% rename from lib/ui/landing/survey_screen.dart rename to lib/ui/landing/itg/survey_screen.dart index a23733a..ec79d0f 100644 --- a/lib/ui/landing/survey_screen.dart +++ b/lib/ui/landing/itg/survey_screen.dart @@ -1,13 +1,19 @@ +import 'dart:convert'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; +import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; @@ -20,10 +26,14 @@ class SurveyScreen extends StatefulWidget { class _SurveyScreenState extends State { String reviewText = ""; - int _selectedIndex = -1; + double starRating = 1; + int _selectedIndex = 5; + + ItgResponseData? itgResponseData; @override Widget build(BuildContext context) { + if (itgResponseData == null) itgResponseData = ModalRoute.of(context)!.settings.arguments as ItgResponseData; return Scaffold( backgroundColor: MyColors.backgroundColor, body: Column( @@ -41,19 +51,23 @@ class _SurveyScreenState extends State { LocaleKeys.rateUI.tr().toText16(), 22.height, Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ RatingBar.builder( initialRating: 3, - minRating: 1, + minRating: starRating, direction: Axis.horizontal, - allowHalfRating: true, + allowHalfRating: false, itemCount: 5, - itemPadding: EdgeInsets.symmetric(horizontal: 12), + itemPadding: EdgeInsets.symmetric(horizontal: 8), itemBuilder: (context, _) => Icon( Icons.star, color: Colors.amber, ), - onRatingUpdate: (rating) {}, + onRatingUpdate: (rating) { + starRating = rating; + }, ) ], ).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true), @@ -66,11 +80,11 @@ class _SurveyScreenState extends State { padding: const EdgeInsets.only(top: 0), shrinkWrap: true, children: [ - optionUI("poor.svg", 0), - optionUI("bad.svg", 1), - optionUI("normal.svg", 2), - optionUI("good.svg", 3), - optionUI("xcellent.svg", 4), + optionUI("poor.svg", 1), + optionUI("bad.svg", 2), + optionUI("normal.svg", 3), + optionUI("good.svg", 4), + optionUI("xcellent.svg", 5), ], ), 27.height, @@ -78,13 +92,21 @@ class _SurveyScreenState extends State { LocaleKeys.description.tr(), LocaleKeys.typeHere.tr(), lines: 3, + onChange: (v) { + reviewText = v; + }, ), 150.height ], ).paddingOnly(left: 21, right: 21), ], )), - DefaultButton(LocaleKeys.submitSurvey.tr(), () async {}).insideContainer, + DefaultButton( + LocaleKeys.submitSurvey.tr(), + () { + performAPI(); + }, + ).insideContainer, ], )); } @@ -108,4 +130,34 @@ class _SurveyScreenState extends State { setState(() {}); }); } + + void performAPI() async { + Utils.showLoading(context); + try { + ItgMainRes? res= await DashboardApiClient().submitItgForm( + comment: reviewText, + masterId: itgResponseData!.notificationMasterId ?? "", + itgList: [ + {"questionId": "1", "optionId": null, "starRating": starRating}, + {"questionId": "2", "optionId": "4", "starRating": _selectedIndex} + ], + serviceId: itgResponseData!.serviceId ?? 0); + Utils.hideLoading(context); + + + + if(res!.mohemmItgResponseItem!.statusCode==200){ + Utils.showToast("Survey has been submitted successfully"); + Navigator.pop(context); + }else{ + Utils.showToast(res.mohemmItgResponseItem!.message.toString()); + } + + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, (msg) { + Utils.confirmDialog(context, msg); + }); + } + } } diff --git a/lib/ui/landing/itg/video_page.dart b/lib/ui/landing/itg/video_page.dart new file mode 100644 index 0000000..657d714 --- /dev/null +++ b/lib/ui/landing/itg/video_page.dart @@ -0,0 +1,96 @@ +import 'dart:convert'; +import 'dart:io' as Io; + +import 'package:flutter/material.dart'; +import 'package:video_player/video_player.dart'; + +class MovieTheaterBody extends StatefulWidget { + final String encodedBytes; + + const MovieTheaterBody({required this.encodedBytes}); + + @override + _MovieTheaterBodyState createState() => _MovieTheaterBodyState(); +} + +class _MovieTheaterBodyState extends State { + late Future _futureController; + late VideoPlayerController _controller; + + Future createVideoPlayer() async { + try { + var decodedBytes = base64Decode(widget.encodedBytes); + + var file = Io.File("decodedBezkoder.mp4"); + file.writeAsBytesSync(decodedBytes); + + VideoPlayerController controller = VideoPlayerController.file(file); + await controller.initialize(); + await controller.setLooping(true); + return controller; + } catch (e) { + print("object0000000"); + print(e); + return new VideoPlayerController.asset("dataSource"); + } + } + + @override + void initState() { + _futureController = createVideoPlayer(); + super.initState(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Expanded( + child: FutureBuilder( + future: _futureController, + builder: (context, snapshot) { + //UST: 05/2021 - MovieTheaterBody - id:11 - 2pts - Criação + if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) { + _controller = snapshot.data as VideoPlayerController; + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AspectRatio( + aspectRatio: _controller.value.aspectRatio, + child: VideoPlayer(_controller), + ), + const SizedBox( + height: 50, + ), + FloatingActionButton( + onPressed: () { + setState(() { + if (_controller.value.isPlaying) { + _controller.pause(); + } else { + // If the video is paused, play it. + _controller.play(); + } + }); + }, + backgroundColor: Colors.green[700], + child: Icon( + _controller.value.isPlaying ? Icons.pause : Icons.play_arrow, + ), + ) + ], + ); + } else { + return const Center(child: CircularProgressIndicator()); + } + }, + ), + ), + ); + } +} diff --git a/lib/ui/landing/today_attendance_screen.dart b/lib/ui/landing/today_attendance_screen.dart index cde099d..54c08e7 100644 --- a/lib/ui/landing/today_attendance_screen.dart +++ b/lib/ui/landing/today_attendance_screen.dart @@ -1,3 +1,4 @@ +import 'package:auto_size_text/auto_size_text.dart'; import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; @@ -107,29 +108,37 @@ class _TodayAttendanceScreenState extends State { child: AspectRatio( aspectRatio: 265 / 265, child: CircularStepProgressBar( - totalSteps: 16 * 4, - currentStep: (model.progress * 100).toInt(), - //width: 216, - // height: 216, - selectedColor: MyColors.gradiantEndColor, - unselectedColor: MyColors.grey70Color, - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - CountdownTimer( - endTime: model.endTime, - onEnd: null, - endWidget: "00:00:00".toText32(color: Colors.white, isBold: true), - textStyle: TextStyle(color: Colors.white, fontSize: 32, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), - ), - 19.height, - LocaleKeys.shiftTime.tr().tr().toText12(color: MyColors.greyACColor), - (model.attendanceTracking!.pShtName ?? "00:00:00").toString().toText22(color: Colors.white, isBold: true), - ], - ), - ), - ), + totalSteps: 16 * 4, + currentStep: (model.progress * 100).toInt(), + //width: 216, + // height: 216, + selectedColor: MyColors.gradiantEndColor, + unselectedColor: MyColors.grey70Color, + child: Padding( + padding: const EdgeInsets.all(21.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CountdownTimer( + endTime: model.endTime, + widgetBuilder: (context, v) { + return AutoSizeText( + v!.hours.toString() + " : " + v.min.toString() + " : " + v.sec.toString(), + style: TextStyle(color: Colors.white, fontSize: 42, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), + ); + }, + onEnd: null, + endWidget: "00:00:00".toTextAuto(color: Colors.white, isBold: true, fontSize: 30, letterSpacing: -1.92), + textStyle: TextStyle(color: Colors.white, fontSize: 30, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), + ), + 19.height, + LocaleKeys.shiftTime.tr().tr().toTextAuto(color: MyColors.greyACColor, fontSize: 18), + (model.attendanceTracking!.pShtName ?? "00:00:00").toString().toTextAuto(color: Colors.white, isBold: true, fontSize: 26), + ], + ), + )), ).paddingAll(21), ).expanded, ], diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 4a7b659..0e9b454 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -140,7 +140,7 @@ class _LoginScreenState extends State { Widget build(BuildContext context) { if (isAppOpenBySystem == null) { isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool; - if (kReleaseMode) { + if (!kReleaseMode) { // username.text = "15444"; // Maha User username.text = "15153"; // Tamer User password.text = "Abcd@12345"; diff --git a/lib/widgets/dialogs/dialogs.dart b/lib/widgets/dialogs/dialogs.dart index 8c65a20..debb147 100644 --- a/lib/widgets/dialogs/dialogs.dart +++ b/lib/widgets/dialogs/dialogs.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; -void showMDialog(context, {Widget? child}) async { +void showMDialog(context, {Widget? child,Color? backgroundColor,bool isDismissable=true}) async { return showDialog( context: context, - barrierDismissible: true, + barrierDismissible: isDismissable, builder: (context) { return Dialog( + backgroundColor: backgroundColor, child: child, ); }, diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 90c57e3..1780d68 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -13,6 +13,8 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/ui/dialogs/success_dialog.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/dialogs.dart'; import 'package:mohem_flutter_app/widgets/location/Location.dart'; import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart'; import 'package:mohem_flutter_app/widgets/qr_scanner_dialog.dart'; @@ -22,8 +24,9 @@ import 'package:wifi_iot/wifi_iot.dart'; class MarkAttendanceWidget extends StatefulWidget { DashboardProviderModel model; double topPadding; + bool isFromDashboard; - MarkAttendanceWidget(this.model, {Key? key, this.topPadding = 0}) : super(key: key); + MarkAttendanceWidget(this.model, {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key); @override _MarkAttendanceWidgetState createState() { @@ -141,6 +144,12 @@ class _MarkAttendanceWidgetState extends State { GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); bool status = await model.fetchAttendanceTracking(context); Utils.hideLoading(context); + showMDialog( + context, + backgroundColor: Colors.transparent, + isDismissable: false, + child: SuccessDialog(widget.isFromDashboard), + ); } catch (ex) { print(ex); Utils.hideLoading(context); @@ -175,6 +184,12 @@ class _MarkAttendanceWidgetState extends State { if (Platform.isAndroid) { await closeWifiRequest(); } + showMDialog( + context, + backgroundColor: Colors.transparent, + isDismissable: false, + child: SuccessDialog(widget.isFromDashboard), + ); } catch (ex) { print("performWifiAttendance: " + ex.toString()); await closeWifiRequest(); @@ -208,6 +223,12 @@ class _MarkAttendanceWidgetState extends State { GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 1, isGpsRequired: isQrLocationEnabled, lat: lat, long: lng, QRValue: qrCodeValue); bool status = await model.fetchAttendanceTracking(context); Utils.hideLoading(context); + showMDialog( + context, + backgroundColor: Colors.transparent, + isDismissable: false, + child: SuccessDialog(widget.isFromDashboard), + ); } catch (ex) { print(ex); Utils.hideLoading(context); diff --git a/pubspec.yaml b/pubspec.yaml index e621c50..f66fe24 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -91,6 +91,8 @@ dependencies: + video_player: ^2.4.7 + dev_dependencies: flutter_test: sdk: flutter From 09d2d9936b38379f405f731d8684a93c257d8ee5 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 30 Oct 2022 14:27:58 +0300 Subject: [PATCH 07/31] Jira Fixes --- lib/ui/landing/dashboard_screen.dart | 1 + lib/ui/leave_balance/add_leave_balance_screen.dart | 12 ++++++------ lib/ui/work_list/work_list_screen.dart | 2 +- lib/ui/work_list/worklist_detail_screen.dart | 2 ++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index c99d2e7..c8b5091 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -114,6 +114,7 @@ class _DashboardScreenState extends State { .expanded, SvgPicture.asset( "assets/images/announcements.svg", + matchTextDirection: true, ).onPress(() async { await Navigator.pushNamed(context, AppRoutes.announcements); }) diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index e1c58c2..e600800 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -92,7 +92,7 @@ class _AddLeaveBalanceScreenState extends State { } void validateAbsenceTransaction() async { - try { + // try { Utils.showLoading(context); Map dffDataMap = {}; for (int i = 1; i <= 20; i++) { @@ -100,7 +100,7 @@ class _AddLeaveBalanceScreenState extends State { for (int dffIndex = 0; dffIndex < getabsenceDffStructureList.length; dffIndex++) { if ("ATTRIBUTE$i" == getabsenceDffStructureList[dffIndex].aPPLICATIONCOLUMNNAME) { if (getabsenceDffStructureList[dffIndex].fORMATTYPE == "X") { - dffDataMap["P_ATTRIBUTE$i"] = Utils.formatDate(getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME!); + dffDataMap["P_ATTRIBUTE$i"] = getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME != null ? Utils.formatDate(getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME!) : ""; } else { dffDataMap["P_ATTRIBUTE$i"] = getabsenceDffStructureList[dffIndex].eSERVICESDV?.pIDCOLUMNNAME; } @@ -129,10 +129,10 @@ class _AddLeaveBalanceScreenState extends State { // Utils.showLoading(context); await LeaveBalanceApiClient().cancelHrTransaction(submit.pTRANSACTIONID!); // Utils.hideLoading(context); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - } + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // } } @override diff --git a/lib/ui/work_list/work_list_screen.dart b/lib/ui/work_list/work_list_screen.dart index 9719030..2e362a9 100644 --- a/lib/ui/work_list/work_list_screen.dart +++ b/lib/ui/work_list/work_list_screen.dart @@ -432,7 +432,7 @@ class _WorkListScreenState extends State { child: WorkListAdvanceSearch((selectedViewID, selectedItemTypeID, searchByInput, searchByDate) async { itgRequestTypeIndex = null; pNotificationType = selectedViewID; - int index = -1; + int index = 0; for (int i = 0; i < workListItemTypes.length; i++) { if (workListItemTypes[i].key == selectedItemTypeID) { index = i; diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 03c9081..8f43b8d 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -136,6 +136,8 @@ class _WorkListDetailScreenState extends State { getPRNotification(); } + controller.jumpToPage(0); + // List dataToFetch = await Future.wait([ // // WorkListApiClient().getActionHistory(workListData!.nOTIFICATIONID!), From db174035cabb33e2282f9bb5d8ab1970f68f9b91 Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Sun, 30 Oct 2022 15:13:15 +0300 Subject: [PATCH 08/31] Icons updated --- assets/images/drawer/drawer_marathon.svg | 3 + assets/images/winner_ribbon.svg | 10 ++ lib/provider/dashboard_provider_model.dart | 2 +- lib/ui/login/login_screen.dart | 2 +- lib/ui/marathon/widgets/countdown_timer.dart | 43 +++----- lib/ui/marathon/widgets/marathon_banner.dart | 105 +++++++++++-------- lib/ui/marathon/winner_screen.dart | 31 ++++-- 7 files changed, 116 insertions(+), 80 deletions(-) create mode 100644 assets/images/drawer/drawer_marathon.svg create mode 100644 assets/images/winner_ribbon.svg diff --git a/assets/images/drawer/drawer_marathon.svg b/assets/images/drawer/drawer_marathon.svg new file mode 100644 index 0000000..33b6c02 --- /dev/null +++ b/assets/images/drawer/drawer_marathon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/winner_ribbon.svg b/assets/images/winner_ribbon.svg new file mode 100644 index 0000000..7a6fbd7 --- /dev/null +++ b/assets/images/winner_ribbon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 964dab8..b0fa94b 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -101,7 +101,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation), DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi), DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions), - DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen), + 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/login/login_screen.dart b/lib/ui/login/login_screen.dart index 4a7b659..8cd93e4 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -140,7 +140,7 @@ class _LoginScreenState extends State { Widget build(BuildContext context) { if (isAppOpenBySystem == null) { isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool; - if (kReleaseMode) { + if (kDebugMode) { // username.text = "15444"; // Maha User username.text = "15153"; // Tamer User password.text = "Abcd@12345"; diff --git a/lib/ui/marathon/widgets/countdown_timer.dart b/lib/ui/marathon/widgets/countdown_timer.dart index 3c4f790..557cfd3 100644 --- a/lib/ui/marathon/widgets/countdown_timer.dart +++ b/lib/ui/marathon/widgets/countdown_timer.dart @@ -33,8 +33,9 @@ class BuildCountdownTimer extends StatelessWidget { color: MyColors.white, fontSize: 24, fontStyle: FontStyle.italic, + fontFamily: "Poppins", letterSpacing: -1.44, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.bold, ); final TextStyle styleTextMarathon = const TextStyle( @@ -141,15 +142,11 @@ class BuildCountdownTimer extends StatelessWidget { time.days == null ? Text( "00", - style: - screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ) : Text( - time.days! < 10 - ? "0${time.days.toString()}" - : time.days.toString(), - style: - screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + time.days! < 10 ? "0${time.days.toString()}" : time.days.toString(), + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), Text( LocaleKeys.days.tr(), @@ -163,15 +160,11 @@ class BuildCountdownTimer extends StatelessWidget { time.hours == null ? Text( "00", - style: - screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ) : Text( - time.hours! < 10 - ? "0${time.hours.toString()}" - : time.hours.toString(), - style: - screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + time.hours! < 10 ? "0${time.hours.toString()}" : time.hours.toString(), + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), Text( LocaleKeys.hours.tr(), @@ -185,15 +178,11 @@ class BuildCountdownTimer extends StatelessWidget { time.min == null ? Text( "00", - style: - screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ) : Text( - time.min! < 10 - ? "0${time.min.toString()}" - : time.min.toString(), - style: - screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + time.min! < 10 ? "0${time.min.toString()}" : time.min.toString(), + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), Text( LocaleKeys.minutes.tr(), @@ -207,15 +196,11 @@ class BuildCountdownTimer extends StatelessWidget { time.sec == null ? Text( "00", - style: - screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ) : Text( - time.sec! < 10 - ? "0${time.sec.toString()}" - : time.sec.toString(), - style: - screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + time.sec! < 10 ? "0${time.sec.toString()}" : time.sec.toString(), + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), Text( LocaleKeys.seconds.tr(), diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index 44bca40..be06e35 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -1,3 +1,4 @@ +import 'package:auto_size_text/auto_size_text.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -22,6 +23,7 @@ class MarathonBanner extends StatelessWidget { MarathonProvider provider = context.read(); return Container( decoration: MyDecorations.shadowDecoration, + height: 90, child: Stack( children: [ Transform( @@ -35,50 +37,69 @@ class MarathonBanner extends StatelessWidget { width: MediaQuery.of(context).size.width - 40, ), ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - AppState().isArabic(context) ? 0.height : 5.height, - Flexible( - child: Text( - LocaleKeys.getReadyForContest.tr(), - style: const TextStyle( - fontStyle: FontStyle.italic, - fontSize: 12, - fontWeight: FontWeight.w600, - color: MyColors.lightGreyEFColor, - letterSpacing: -0.4, - ), - ), + SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( + children: [ + const Expanded( + flex: 3, + child: SizedBox( + width: double.infinity, + height: double.infinity, ), - const Flexible( - child: Text( - "Saudi Arabia", - style: TextStyle( - fontStyle: FontStyle.italic, - fontSize: 19, - fontWeight: FontWeight.bold, - color: MyColors.lightGreyEFColor, - height: 32 / 22, - ), - ), + ), + Expanded( + flex: 5, + child: SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + AppState().isArabic(context) ? 0.height : 5.height, + AutoSizeText( + LocaleKeys.getReadyForContest.tr(), + style: const TextStyle( + fontStyle: FontStyle.italic, + fontSize: 12, + fontWeight: FontWeight.w600, + color: MyColors.lightGreyEFColor, + letterSpacing: -0.4, + ), + ), + const AutoSizeText( + "Saudi Arabia", + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: 19, + fontWeight: FontWeight.bold, + color: MyColors.lightGreyEFColor, + height: 32 / 22, + ), + ), + 3.height, + BuildCountdownTimer( + timeToMarathon: dummyEndTime, + provider: provider, + screenFlag: 0, + ), + ], + ).paddingOnly( + left: AppState().isArabic(context) ? 12 : 0, + right: AppState().isArabic(context) ? 0 : 12, + ) + ], + ).paddingOnly(right: 20), ), - 3.height, - BuildCountdownTimer( - timeToMarathon: dummyEndTime, - provider: provider, - screenFlag: 0, - ), - ], - ).paddingOnly( - left: AppState().isArabic(context) ? 12 : 0, - right: AppState().isArabic(context) ? 0 : 12, - ) - ], + ), + ], + ), ), ], ).onPress( diff --git a/lib/ui/marathon/winner_screen.dart b/lib/ui/marathon/winner_screen.dart index cdd3df0..2e9b16b 100644 --- a/lib/ui/marathon/winner_screen.dart +++ b/lib/ui/marathon/winner_screen.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:lottie/lottie.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; @@ -43,18 +44,34 @@ class WinnerScreen extends StatelessWidget { ], ), ), - 50.height, + 26.height, + SizedBox( + height: 50, + child: Stack( + children: [ + Align( + alignment: Alignment.center, + child: SvgPicture.asset( + "assets/images/winner_ribbon.svg", + height: 50, + ), + ), + Align( + alignment: Alignment.center, + child: "WINNER".toText32(color: MyColors.white, isBold: true).paddingOnly(top: 07), + ) + ], + ), + ), + 12.height, "Muhammad Shrouff".toText22(color: MyColors.grey3AColor), "837436".toText22(color: MyColors.grey57Color), - 90.height, + 80.height, Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - LocaleKeys.sponsoredBy - .tr() - .toText14(color: MyColors.grey77Color), - " Extra".toText14( - color: MyColors.darkTextColor, isBold: true), + LocaleKeys.sponsoredBy.tr().toText14(color: MyColors.grey77Color), + " Extra".toText14(color: MyColors.darkTextColor, isBold: true), ], ), 5.height, From 528b0930c20962b6668823ddeb95188a9f0abf67 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 30 Oct 2022 17:23:08 +0300 Subject: [PATCH 09/31] mark attendance counter 1.0 --- ios/Runner.xcodeproj/project.pbxproj | 22 ++++--- .../xcshareddata/xcschemes/Runner.xcscheme | 8 +-- lib/ui/landing/today_attendance_screen.dart | 66 ++++++++++--------- lib/ui/login/login_screen.dart | 7 +- pubspec.yaml | 6 +- 5 files changed, 58 insertions(+), 51 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 2646e3b..9daee21 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -345,6 +345,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -363,7 +364,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -382,11 +383,11 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 99Z3UD3LJM; + DEVELOPMENT_TEAM = 3A359E86ZF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -423,6 +424,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -447,7 +449,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -478,6 +480,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -496,10 +499,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -516,11 +520,11 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 99Z3UD3LJM; + DEVELOPMENT_TEAM = 3A359E86ZF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -545,11 +549,11 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 99Z3UD3LJM; + DEVELOPMENT_TEAM = 3A359E86ZF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Mohemm; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 3db53b6..c87d15a 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -27,8 +27,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + + - - { : Column( children: [ Container( + width: double.infinity, color: MyColors.backgroundBlackColor, padding: EdgeInsets.only(top: 4, left: 21, right: 21, bottom: 21), child: Column( @@ -108,39 +109,32 @@ class _TodayAttendanceScreenState extends State { child: AspectRatio( aspectRatio: 265 / 265, child: CircularStepProgressBar( - totalSteps: 16 * 4, - currentStep: (model.progress * 100).toInt(), - //width: 216, - // height: 216, - selectedColor: MyColors.gradiantEndColor, - unselectedColor: MyColors.grey70Color, - child: Padding( - padding: const EdgeInsets.all(21.0), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CountdownTimer( - endTime: model.endTime, - widgetBuilder: (context, v) { - return AutoSizeText( - v!.hours.toString() + " : " + v.min.toString() + " : " + v.sec.toString(), - style: TextStyle(color: Colors.white, fontSize: 42, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), - ); - }, - onEnd: null, - endWidget: "00:00:00".toTextAuto(color: Colors.white, isBold: true, fontSize: 30, letterSpacing: -1.92), - textStyle: TextStyle(color: Colors.white, fontSize: 30, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), - ), - 19.height, - LocaleKeys.shiftTime.tr().tr().toTextAuto(color: MyColors.greyACColor, fontSize: 18), - (model.attendanceTracking!.pShtName ?? "00:00:00").toString().toTextAuto(color: Colors.white, isBold: true, fontSize: 26), - ], - ), - )), + totalSteps: 16 * 4, + currentStep: (model.progress * 100).toInt(), + //width: 216, + // height: 216, + selectedColor: MyColors.gradiantEndColor, + unselectedColor: MyColors.grey70Color, + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CountdownTimer( + endTime: model.endTime, + onEnd: null, + endWidget: "00:00:00".toText32(color: Colors.white, isBold: true), + textStyle: TextStyle(color: Colors.white, fontSize: 32, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), + ), + 19.height, + LocaleKeys.shiftTime.tr().tr().toText12(color: MyColors.greyACColor), + (model.attendanceTracking!.pShtName ?? "00:00:00").toString().toText22(color: Colors.white, isBold: true), + ], + ), + ), + ), ).paddingAll(21), ).expanded, + ], ), ).expanded, @@ -325,6 +319,16 @@ class _TodayAttendanceScreenState extends State { // } // } + String getValue(int? v) { + if (v == null) { + return "00"; + } else if (v.toString().length == 1) { + return "0" + v.toString(); + } else { + return v.toString(); + } + } + Future closeWifiRequest() async { await WiFiForIoTPlugin.forceWifiUsage(false); bool v = await WiFiForIoTPlugin.disconnect(); diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 0e9b454..0c4e268 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -142,8 +142,11 @@ class _LoginScreenState extends State { isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool; if (!kReleaseMode) { // username.text = "15444"; // Maha User - username.text = "15153"; // Tamer User - password.text = "Abcd@12345"; + // username.text = "15153"; // Tamer User + // password.text = "Abcd@12345"; + + username.text = "210038"; // Hashim User + password.text = "123"; } if (isAppOpenBySystem!) checkFirebaseToken(); } diff --git a/pubspec.yaml b/pubspec.yaml index f66fe24..633edd7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ description: A new Flutter application. publish_to: 'none' # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 +# A version number is three numbers separated by dots, like 1.2.43v # followed by an optional build number separated by a +. # Both the version and the builder number may be overridden in flutter # build by specifying --build-name and --build-number, respectively. @@ -53,7 +53,7 @@ dependencies: shimmer: ^2.0.0 logger: ^1.1.0 flutter_countdown_timer: ^4.1.0 - nfc_manager: ^3.1.1 + nfc_manager: ^3.2.0 uuid: ^3.0.6 image_picker: ^0.8.5+3 file_picker: ^4.6.1 @@ -78,7 +78,7 @@ dependencies: auto_size_text: ^3.0.0 pull_to_refresh: ^2.0.0 # lottie json animations - lottie: ^1.4.3 + lottie: any # Steps Progress steps_indicator: ^1.3.0 # Marathon Card Swipe From c87a00df6ab5b6a86da6af1121271e9cc930289e Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 30 Oct 2022 17:26:39 +0300 Subject: [PATCH 10/31] Jira fixes --- lib/api/profile_api_client.dart | 2 +- lib/classes/utils.dart | 4 +++- lib/ui/landing/dashboard_screen.dart | 8 ++------ .../dynamic_screens/dynamic_input_screen.dart | 2 +- .../dynamic_screens/dynamic_input_address_screen.dart | 11 +++++++++-- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/api/profile_api_client.dart b/lib/api/profile_api_client.dart index 832b6d8..d7ceba0 100644 --- a/lib/api/profile_api_client.dart +++ b/lib/api/profile_api_client.dart @@ -97,7 +97,7 @@ class ProfileApiClient { Future getDffStructure(String pFunctionName, String uRL, String requestType) async { String url = ApiConsts.erpRest + uRL; - Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E", "P_REQUEST_TYPE": pFunctionName, "P_COUNTRY_CODE": "SA"}; + Map postParams = {"P_SELECTED_RESP_ID": -999, "P_MENU_TYPE": "E", "P_REQUEST_TYPE": pFunctionName, "P_FUNCTION_NAME": pFunctionName, "P_COUNTRY_CODE": "SA"}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index af9e340..8f9df26 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -287,7 +287,9 @@ class Utils { String formattedDate; if (date.isNotEmpty) { formattedDate = date.split('T')[0]; - formattedDate = formattedDate + ' 00:00:00'; + if(!formattedDate.contains("00:00:00")) { + formattedDate = formattedDate + ' 00:00:00'; + } } else { formattedDate = date; } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index f5f1d7f..bb4ee43 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -1,10 +1,10 @@ import 'dart:async'; import 'dart:io'; + 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'; @@ -13,17 +13,13 @@ 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_response_model.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; -import 'package:mohem_flutter_app/ui/dialogs/success_dialog.dart'; -import 'package:mohem_flutter_app/ui/landing/itg/video_page.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/widgets/marathon_banner.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; -import 'package:mohem_flutter_app/widgets/dialogs/dialogs.dart'; import 'package:mohem_flutter_app/widgets/mark_attendance_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart'; @@ -268,7 +264,7 @@ class _DashboardScreenState extends State { bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0), ), ), - child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/play.svg" : "assets/images/stop.svg"), + child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/attendance.svg" : "assets/images/attendance.svg"), ).onPress(() { showMyBottomSheet( context, diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 1c97b28..0a6c9d4 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -260,7 +260,7 @@ class _DynamicInputScreenState extends State { for (int i = 0; i < parentsList.length; i++) { for (int j = 0; j < (getEitDffStructureList?.length ?? 0); j++) { - if (getEitDffStructureList![j].sEGMENTNAME == parentsList[i].opt1) { + if (getEitDffStructureList![j].sEGMENTNAME == parentsList[i].name) { if (getEitDffStructureList![j].dISPLAYFLAG != "N") { if (getEitDffStructureList![j].vALIDATIONTYPE == "N") { String? idColName; diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart index 5c54b6d..cc8e861 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart @@ -283,10 +283,17 @@ class _DynamicInputScreenState extends State { tempVar = e.getEmployeeAddressList!.sEGMENTVALUEDSP ?? ""; } - return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: tempVar.toString()).toJson(); + return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 0, vARCHAR2VALUE: tempVar.toString()).toJson(); }).toList(); - submitPhoneNumbers = await ProfileApiClient().submitAddressTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, dynamicParams!.correctOrNew, countryCode, effectiveDate); + submitPhoneNumbers = await ProfileApiClient().submitAddressTransaction( + dESCFLEXCONTEXTCODE, + dynamicParams!.dynamicId, + values, + dynamicParams!.correctOrNew, + countryCode, + effectiveDate.isEmpty ? DateFormat('dd-MMM-yyy').format(DateTime.now().add(Duration(days: 35))) : effectiveDate, + ); print(values); Utils.hideLoading(context); From 40b9cb95767e4096d19c1a735f1cd050791175c1 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 31 Oct 2022 08:45:03 +0300 Subject: [PATCH 11/31] Chat Fixes --- lib/ui/chat/chat_detailed_screen.dart | 100 +++++++++++++++----------- 1 file changed, 59 insertions(+), 41 deletions(-) diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 654b026..1a9cf7d 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -1,5 +1,4 @@ import 'dart:async'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -21,7 +20,10 @@ class ChatDetailScreen extends StatelessWidget { @override Widget build(BuildContext context) { - userDetails = ModalRoute.of(context)!.settings.arguments; + userDetails = ModalRoute + .of(context)! + .settings + .arguments; data = Provider.of(context, listen: false); data.getSingleUserChatHistory(senderUID: AppState().chatDetails!.response!.id.toString(), receiverUID: userDetails["targetUser"].id, pagination: "0"); Timer(const Duration(seconds: 1), () => data.scrollDown()); @@ -33,56 +35,72 @@ class ChatDetailScreen extends StatelessWidget { return (m.isLoading ? ChatHomeShimmer() : Column( - children: [ - Expanded( - child: ListView.builder( - controller: m.scrollController, - shrinkWrap: true, - itemCount: m.userChatHistory.length, - padding: const EdgeInsets.symmetric(vertical: 10), - itemBuilder: (BuildContext context, int i) { - return ChatBubble( - text: m.userChatHistory[i].contant.toString(), - isSeen: m.userChatHistory[i].isSeen == true ? true : false, - isCurrentUser: m.userChatHistory[i].currentUserId == 42062 ? true : false, - isDelivered: m.userChatHistory[i].currentUserId == 42062 && m.userChatHistory[i].isDelivered == true ? true : false, - dateTime: m.userChatHistory[i].createdDate.toString(), - ); - }, - ), - ), - Card( - margin: EdgeInsets.zero, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: TextField( - controller: m.message, - decoration: InputDecoration( - hintText: LocaleKeys.typeheretoreply.tr(), - hintStyle: const TextStyle(color: MyColors.grey98Color), - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), - suffixIcon: IconButton( + children: [ + Expanded( + child: ListView.builder( + controller: m.scrollController, + shrinkWrap: true, + itemCount: m.userChatHistory.length, + padding: const EdgeInsets.symmetric(vertical: 10), + itemBuilder: (BuildContext context, int i) { + return ChatBubble( + text: m.userChatHistory[i].contant.toString(), + isSeen: m.userChatHistory[i].isSeen == true ? true : false, + isCurrentUser: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id ? true : false, + isDelivered: m.userChatHistory[i].currentUserId == AppState().chatDetails!.response!.id && m.userChatHistory[i].isDelivered == true ? true : false, + dateTime: m.userChatHistory[i].createdDate.toString(), + ); + }, + ), + ), + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: TextField( + controller: m.message, + decoration: InputDecoration( + hintText: LocaleKeys.typeheretoreply.tr(), + hintStyle: const TextStyle(color: MyColors.grey98Color), + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), + suffixIcon: SizedBox( + width: 100, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton( + icon: const Icon( + Icons.attach_file_rounded, + size: 27, + color: MyColors.lightGreenColor, + ), + onPressed: () {}, + ), + IconButton( icon: SvgPicture.asset( "assets/icons/chat/chat_send_icon.svg", height: 26, width: 35, ), onPressed: () { - // m.logger.d(userDetails); - m.sendChatMessage(m.message.text, userDetails["targetUser"].id, userDetails["targetUser"].userName); + m.sendChatMessage(m.message.text, userDetails["targetUser"].id, userDetails["targetUser"].userName); }, ), - ), + ], ), ), ), - ], - )); + ), + ), + ), + ], + )); }, ), ); From 39240b734ebe557b4a816b82a1bd34153450f934 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 31 Oct 2022 15:01:45 +0300 Subject: [PATCH 12/31] mark attendance counter & ios nfc fixed --- lib/classes/utils.dart | 21 ++ lib/config/routes.dart | 3 +- lib/extensions/string_extensions.dart | 2 +- lib/extensions/widget_extensions.dart | 33 +-- lib/ui/landing/today_attendance_screen.dart | 288 ++++---------------- lib/widgets/mark_attendance_widget.dart | 82 ++++-- 6 files changed, 146 insertions(+), 283 deletions(-) diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index af9e340..2bb9135 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -17,6 +17,8 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.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'; +import 'package:nfc_manager/platform_tags.dart'; import 'package:shared_preferences/shared_preferences.dart'; // ignore_for_file: avoid_annotating_with_dynamic @@ -321,4 +323,23 @@ class Utils { } return selectedDate; } + + static void readNFc({required Function(String) onRead}) { + var instance = NfcManager.instance; + + NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async { + print(tag.data); + var f; + if (Platform.isAndroid) { + f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + } else { + f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + } + String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); + NfcManager.instance.stopSession(); + onRead(identifier); + }).catchError((err) { + print(err); + }); + } } diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 9823082..1fcbf2e 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/ui/chat/chat_home.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart'; +import 'package:mohem_flutter_app/ui/landing/today_attendance_screen2.dart'; import 'package:mohem_flutter_app/ui/leave_balance/add_leave_balance_screen.dart'; import 'package:mohem_flutter_app/ui/leave_balance/leave_balance_screen.dart'; import 'package:mohem_flutter_app/ui/login/change_password_screen.dart'; @@ -193,7 +194,7 @@ class AppRoutes { subMenuScreen: (BuildContext context) => SubMenuScreen(), newPassword: (BuildContext context) => NewPasswordScreen(), forgotPassword: (BuildContext context) => ForgotPasswordScreen(), - todayAttendance: (BuildContext context) => TodayAttendanceScreen(), + todayAttendance: (BuildContext context) => TodayAttendanceScreen2(), //eit addEitScreen: (BuildContext context) => AddEITScreen(), diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 9bcc984..37f41ae 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -74,7 +74,7 @@ extension EmailValidator on String { this, textAlign: isCenter ? TextAlign.center : null, maxLines: (maxLine > 0) ? maxLine : null, - minFontSize: 8, + minFontSize: 5, style: TextStyle( fontSize: fontSize, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index ad41cfb..64aaae8 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -12,21 +12,14 @@ extension WidgetExtensions on Widget { Widget get center => Center(child: this); - Widget circle(double _value) => - ClipRRect(borderRadius: BorderRadius.circular(_value), child: this); + Widget circle(double _value) => ClipRRect(borderRadius: BorderRadius.circular(_value), child: this); - Widget paddingAll(double _value) => - Padding(padding: EdgeInsets.all(_value), child: this); + Widget paddingAll(double _value) => Padding(padding: EdgeInsets.all(_value), child: this); - Widget paddingOnly( - {double left = 0.0, - double right = 0.0, - double top = 0.0, - double bottom = 0.0}) => - Padding( - padding: EdgeInsets.only( - left: left, right: right, top: top, bottom: bottom), - child: this); + Widget paddingOnly({double left = 0.0, double right = 0.0, double top = 0.0, double bottom = 0.0}) => + Padding(padding: EdgeInsets.only(left: left, right: right, top: top, bottom: bottom), child: this); + + Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); Widget toShimmer({bool isShow = true}) => isShow ? Shimmer.fromColors( @@ -51,15 +44,9 @@ extension WidgetExtensions on Widget { child: this, ); - Widget objectContainerView( - {String title = "", - String note = "", - bool disablePadding = false, - double radius = 15}) { + Widget objectContainerView({String title = "", String note = "", bool disablePadding = false, double radius = 15}) { return Container( - padding: disablePadding - ? EdgeInsets.zero - : const EdgeInsets.only(top: 15, bottom: 15, left: 14, right: 14), + padding: disablePadding ? EdgeInsets.zero : const EdgeInsets.only(top: 15, bottom: 15, left: 14, right: 14), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(radius), @@ -95,9 +82,7 @@ extension WidgetExtensions on Widget { bool disableWidth = false, bool isAlignment = false}) { return Container( - padding: disablePadding - ? EdgeInsets.zero - : const EdgeInsets.only(top: 15, bottom: 15, left: 14, right: 14), + padding: disablePadding ? EdgeInsets.zero : const EdgeInsets.only(top: 15, bottom: 15, left: 14, right: 14), decoration: BoxDecoration( borderRadius: BorderRadius.circular(radius), color: color, diff --git a/lib/ui/landing/today_attendance_screen.dart b/lib/ui/landing/today_attendance_screen.dart index 22c4df9..d23fa10 100644 --- a/lib/ui/landing/today_attendance_screen.dart +++ b/lib/ui/landing/today_attendance_screen.dart @@ -95,64 +95,76 @@ class _TodayAttendanceScreenState extends State { ? Center(child: CircularProgressIndicator()) : Column( children: [ - Container( - width: double.infinity, - color: MyColors.backgroundBlackColor, - padding: EdgeInsets.only(top: 4, left: 21, right: 21, bottom: 21), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - DateUtil.getWeekDayMonthDayYearDateFormatted(DateTime.now(), "en").toText24(isBold: true, color: Colors.white), - LocaleKeys.timeLeftToday.tr().toText16(color: Color(0xffACACAC)), - //21.height, - Center( - child: AspectRatio( - aspectRatio: 265 / 265, - child: CircularStepProgressBar( - totalSteps: 16 * 4, - currentStep: (model.progress * 100).toInt(), - //width: 216, - // height: 216, - selectedColor: MyColors.gradiantEndColor, - unselectedColor: MyColors.grey70Color, - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - CountdownTimer( - endTime: model.endTime, - onEnd: null, - endWidget: "00:00:00".toText32(color: Colors.white, isBold: true), - textStyle: TextStyle(color: Colors.white, fontSize: 32, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), + Expanded( + flex: 2, + child: Container( + width: double.infinity, + color: MyColors.backgroundBlackColor, + padding: EdgeInsets.only(top: 4, left: 21, right: 21, bottom: 21), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + DateUtil.getWeekDayMonthDayYearDateFormatted(DateTime.now(), "en").toText24(isBold: true, color: Colors.white), + LocaleKeys.timeLeftToday.tr().toText16(color: Color(0xffACACAC)), + Center( + child: AspectRatio( + aspectRatio: 265 / 265, + child: CircularStepProgressBar( + totalSteps: 16 * 4, + currentStep: (model.progress * 100).toInt(), + selectedColor: MyColors.gradiantEndColor, + unselectedColor: MyColors.grey70Color, + child: Center( + child: Padding( + padding: const EdgeInsets.all(21.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CountdownTimer( + endTime: model.endTime, + widgetBuilder: (context, v) { + return AutoSizeText( + getValue(v?.hours) + " : " + getValue(v?.min) + " : " + getValue(v?.sec), + maxLines: 1, + style: TextStyle(color: Colors.white, fontSize: 42, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), + ); + }, + onEnd: null, + endWidget: "00:00:00".toTextAuto(color: Colors.white, isBold: true, fontSize: 30, letterSpacing: -1.92), + textStyle: TextStyle(color: Colors.white, fontSize: 30, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), + ).center.expanded, + LocaleKeys.shiftTime.tr().tr().toTextAuto(color: MyColors.greyACColor, fontSize: 18, maxLine: 1), + (model.attendanceTracking!.pShtName ?? "00:00:00").toString().toTextAuto(color: Colors.white, isBold: true, fontSize: 26, maxLine: 1), + ], ), - 19.height, - LocaleKeys.shiftTime.tr().tr().toText12(color: MyColors.greyACColor), - (model.attendanceTracking!.pShtName ?? "00:00:00").toString().toText22(color: Colors.white, isBold: true), - ], + ), ), ), - ), - ).paddingAll(21), - ).expanded, - - ], + ).paddingAll(12), + ).expanded, + ], + ), ), - ).expanded, + ), Center( child: Container( - // color: MyColors.backgroundBlackColor, decoration: const BoxDecoration( borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), - gradient: LinearGradient(transform: GradientRotation(.64), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ - MyColors.gradiantEndColor, - MyColors.gradiantStartColor, - ]), + gradient: LinearGradient( + transform: GradientRotation(.64), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), ), child: Column( children: [ Container( //height: 187, - padding: const EdgeInsets.only(left: 31, right: 31, top: 31, bottom: 16), + padding: const EdgeInsets.only(left: 21, right: 21, top: 21, bottom: 16), decoration: const BoxDecoration( borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), gradient: LinearGradient(transform: GradientRotation(.64), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ @@ -179,80 +191,7 @@ class _TodayAttendanceScreenState extends State { ), ), //.expanded, - MarkAttendanceWidget(model, topPadding: 24), - // Container( - // width: double.infinity, - // decoration: BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white), - // // margin: EdgeInsets.only(top: 187 - 31), - // padding: EdgeInsets.only(left: 21, right: 21, top: 24, bottom: 24), - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisSize: MainAxisSize.min, - // children: [ - // LocaleKeys.markAttendance.tr().toSectionHeading(), - // LocaleKeys.selectMethodOfAttendance.tr().tr().toText11(color: Color(0xff535353)), - // 24.height, - // GridView( - // physics: const NeverScrollableScrollPhysics(), - // shrinkWrap: true, - // padding: EdgeInsets.zero, - // gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8), - // children: [ - // if (isNfcEnabled) - // attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () { - // if (isNfcLocationEnabled) { - // Location.getCurrentLocation((LatLng? latlng) { - // performNfcAttendance(model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); - // }); - // } else { - // performNfcAttendance(model); - // } - // }), - // if (isWifiEnabled) - // attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () { - // if (isWifiLocationEnabled) { - // Location.getCurrentLocation((LatLng? latlng) { - // performWifiAttendance(model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); - // }); - // } else { - // performWifiAttendance(model); - // } - // // connectWifi(); - // }), - // if (isQrEnabled) - // attendanceMethod("QR", "assets/images/ic_qr.svg", isQrEnabled, () async { - // if (isQrLocationEnabled) { - // Location.getCurrentLocation((LatLng? latlng) { - // performQrCodeAttendance(model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); - // }); - // } else { - // performQrCodeAttendance(model); - // } - // // performQrCodeAttendance(model); - // }), - // ], - // ) - // ], - // ), - // ), - // Positioned( - // top: 187 - 21, - // child: Container( - // padding: EdgeInsets.only(left: 31, right: 31, top: 31, bottom: 16), - // decoration: BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white), - // child: Column( - // children: [ - // Row( - // children: [commonStatusView("Check In", "09:27"), commonStatusView("Check Out", "- - : - -")], - // ), - // 21.height, - // Row( - // children: [commonStatusView("Late In", "00:27"), commonStatusView("Regular", "08:00")], - // ), - // ], - // ), - // ), - // ), + MarkAttendanceWidget(model, topPadding: 21), ], ), ), @@ -265,60 +204,6 @@ class _TodayAttendanceScreenState extends State { ); } - // Future performNfcAttendance(DashboardProviderModel model, {String lat = "0", String lng = "0"}) async { - // if (isNfcLocationEnabled) { - // print("nfc location enabled"); - // } else { - // print("nfc not location enabled"); - // } - // - // showNfcReader(context, onNcfScan: (String? nfcId) async { - // print(nfcId); - // Utils.showLoading(context); - // try { - // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); - // bool status = await model.fetchAttendanceTracking(context); - // Utils.hideLoading(context); - // } catch (ex) { - // print(ex); - // Utils.hideLoading(context); - // Utils.handleException(ex, context, (msg) { - // Utils.confirmDialog(context, msg); - // }); - // } - // }); - // } - // - // Future performWifiAttendance(DashboardProviderModel model, {String lat = "0", String lng = "0"}) async { - // if (isWifiLocationEnabled) { - // print("wifi location enabled"); - // } else { - // print("wifi not location enabled"); - // } - // - // bool v = await WiFiForIoTPlugin.connect(AppState().mohemmWifiSSID ?? "", password: AppState().mohemmWifiPassword ?? "", joinOnce: true, security: NetworkSecurity.WPA, withInternet: false); - // if (v) { - // await WiFiForIoTPlugin.forceWifiUsage(true); - // print("connected"); - // Utils.showLoading(context); - // try { - // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 3, nfcValue: "", isGpsRequired: isWifiLocationEnabled, lat: lat, long: lng); - // bool status = await model.fetchAttendanceTracking(context); - // Utils.hideLoading(context); - // await closeWifiRequest(); - // } catch (ex) { - // print(ex); - // await closeWifiRequest(); - // Utils.hideLoading(context); - // Utils.handleException(ex, context, (msg) { - // Utils.confirmDialog(context, msg); - // }); - // } - // } else { - // Utils.confirmDialog(context, LocaleKeys.comeNearHMGWifi.tr()); - // } - // } - String getValue(int? v) { if (v == null) { return "00"; @@ -335,63 +220,6 @@ class _TodayAttendanceScreenState extends State { return v; } - // Future performQrCodeAttendance(DashboardProviderModel model, {String lat = "0", String lng = "0"}) async { - // var qrCodeValue = await Navigator.of(context).push( - // MaterialPageRoute( - // builder: (context) => QrScannerDialog(), - // ), - // ); - // if (qrCodeValue != null) { - // print("qrCode: " + qrCodeValue); - // Utils.showLoading(context); - // try { - // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 1, isGpsRequired: isQrLocationEnabled, lat: lat, long: lng, QRValue: qrCodeValue); - // bool status = await model.fetchAttendanceTracking(context); - // Utils.hideLoading(context); - // } catch (ex) { - // print(ex); - // Utils.hideLoading(context); - // Utils.handleException(ex, context, (msg) { - // Utils.confirmDialog(context, msg); - // }); - // } - // } - // } - // - // Widget attendanceMethod(String title, String image, bool isEnabled, VoidCallback onPress) => Container( - // decoration: BoxDecoration( - // borderRadius: BorderRadius.circular(15), - // gradient: const LinearGradient(transform: GradientRotation(.64), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ - // MyColors.gradiantEndColor, - // MyColors.gradiantStartColor, - // ]), - // ), - // clipBehavior: Clip.antiAlias, - // child: Stack( - // children: [ - // Container( - // padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14), - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // SvgPicture.asset( - // image, - // color: Colors.white, - // ).expanded, - // title.toText17(isBold: true, color: Colors.white), - // ], - // ), - // ), - // if (!isEnabled) - // Container( - // width: double.infinity, - // height: double.infinity, - // color: Colors.grey.withOpacity(0.7), - // ) - // ], - // ), - // ).onPress(onPress); - Widget commonStatusView(String title, String time) => Expanded( child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ title.toText12(color: Colors.white.withOpacity(.69)), diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 1780d68..6a5b4d8 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -75,21 +75,23 @@ class _MarkAttendanceWidgetState extends State { @override Widget build(BuildContext context) { + print(MediaQuery.of(context).size.width); return Container( padding: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: widget.topPadding), decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white), width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ LocaleKeys.markAttendance.tr().toSectionHeading(), LocaleKeys.selectMethodOfAttendance.tr().tr().toText11(color: const Color(0xff535353)), GridView( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, - padding: const EdgeInsets.only(bottom: 14, top: 21), + padding: const EdgeInsets.only(bottom: 0, top: 21), gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 400) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8), + SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8), children: [ // if (isNfcEnabled) attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () { @@ -137,27 +139,50 @@ class _MarkAttendanceWidgetState extends State { print("nfc not location enabled"); } - showNfcReader(context, onNcfScan: (String? nfcId) async { - print(nfcId); - Utils.showLoading(context); - try { - GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); - bool status = await model.fetchAttendanceTracking(context); - Utils.hideLoading(context); - showMDialog( - context, - backgroundColor: Colors.transparent, - isDismissable: false, - child: SuccessDialog(widget.isFromDashboard), - ); - } catch (ex) { - print(ex); - Utils.hideLoading(context); - Utils.handleException(ex, context, (msg) { - Utils.confirmDialog(context, msg); - }); - } - }); + if (Platform.isIOS) { + Utils.readNFc(onRead: (String nfcId) async { + Utils.showLoading(context); + try { + GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); + bool status = await model.fetchAttendanceTracking(context); + Utils.hideLoading(context); + showMDialog( + context, + backgroundColor: Colors.transparent, + isDismissable: false, + child: SuccessDialog(widget.isFromDashboard), + ); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, context, (msg) { + Utils.confirmDialog(context, msg); + }); + } + }); + } else { + showNfcReader(context, onNcfScan: (String? nfcId) async { + print(nfcId); + Utils.showLoading(context); + try { + GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); + bool status = await model.fetchAttendanceTracking(context); + Utils.hideLoading(context); + showMDialog( + context, + backgroundColor: Colors.transparent, + isDismissable: false, + child: SuccessDialog(widget.isFromDashboard), + ); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, context, (msg) { + Utils.confirmDialog(context, msg); + }); + } + }); + } } Future performWifiAttendance(DashboardProviderModel model, {String lat = "0", String lng = "0"}) async { @@ -199,6 +224,7 @@ class _MarkAttendanceWidgetState extends State { }); } } else { + Utils.hideLoading(context); Utils.confirmDialog(context, LocaleKeys.comeNearHMGWifi.tr()); } } @@ -264,8 +290,10 @@ class _MarkAttendanceWidgetState extends State { title.toText17(isBold: true, color: Colors.white), ], ), - ).onPress(() { - if (!isEnabled) return; - onPress(); - }); + ).onPress( + () { + if (!isEnabled) return; + onPress(); + }, + ); } From 69ded3dc43361a2fbc8cd2c556c18e5ea42a4701 Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Mon, 31 Oct 2022 15:17:24 +0300 Subject: [PATCH 13/31] fix my request --- assets/langs/ar-SA.json | 1 + assets/langs/en-US.json | 1 + lib/api/my_requests_api_client.dart | 35 +++++++++++++++ lib/generated/codegen_loader.g.dart | 6 +++ lib/generated/locale_keys.g.dart | 1 + lib/models/generic_response_model.dart | 13 ++++-- .../get_ccp_transations_list_model.dart | 24 ++++++++++ lib/ui/profile/add_update_family_member.dart | 10 ++--- lib/ui/screens/my_requests/my_requests.dart | 2 +- lib/ui/screens/my_requests/new_request.dart | 45 +++++++++++++++++-- 10 files changed, 126 insertions(+), 12 deletions(-) create mode 100644 lib/models/my_requests/get_ccp_transations_list_model.dart diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 6eae388..752200a 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -423,6 +423,7 @@ "skip": "يتخطى", "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", "currentPassword": "كلمة المرور الحاليه", + "concurrentReports": "التقارير المتزامنه", "profile": { "reset_password": { "label": "Reset Password", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 2a7945c..c176c5d 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -423,6 +423,7 @@ "skip": "skip", "typeCurrentPasswordBelow": "Type Your Current password below", "currentPassword": "Current password", + "concurrentReports": "Concurrent Reports", "profile": { "reset_password": { "label": "Reset Password", diff --git a/lib/api/my_requests_api_client.dart b/lib/api/my_requests_api_client.dart index 391e297..c9507b9 100644 --- a/lib/api/my_requests_api_client.dart +++ b/lib/api/my_requests_api_client.dart @@ -6,6 +6,7 @@ import 'package:mohem_flutter_app/models/get_eit_dff_structure_list_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_ccp_dff_structure_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_ccp_output_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_ccp_transactions_model.dart'; +import 'package:mohem_flutter_app/models/my_requests/get_ccp_transations_list_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_concurrent_programs_model.dart'; class MyRequestsApiClient { @@ -59,4 +60,38 @@ class MyRequestsApiClient { }, url, postParams); } + Future getSubmitNewRequest(List> list) async + { + String url = "${ApiConsts.erpRest}SUBMIT_CCP_TRANSACTION"; + Map postParams = { + "P_MENU_TYPE": "E", + "P_SELECTED_RESP_ID": -999, + "P_DESC_FLEX_NAME": "HMG_EMP_BUS_TRIP_SET_SS", + }; + + postParams.addAll(AppState().postParamsJson); + postParams["EITTransactionTBL"] = list; + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + return responseData.submitCcpTransactionList; + }, url, postParams); + } + + Future> getCcpTransactions(List> list) async + { + String url = "${ApiConsts.erpRest}GET_CCP_TRANSACTIONS"; + Map postParams = { + "P_MENU_TYPE": "E", + "P_SELECTED_RESP_ID": -999, + "P_DESC_FLEX_NAME": "HMG_EMP_BUS_TRIP_SET_SS", + }; + + postParams.addAll(AppState().postParamsJson); + postParams["EITTransactionTBL"] = list; + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + return responseData.getCCPTransactionsModel ?? []; + }, url, postParams); + } + } diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 5824fe1..e9aeff4 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -435,8 +435,11 @@ class CodegenLoader extends AssetLoader{ "adult": "بالغ", "updateMember": "هل انت متأكد تريد تحديث بيانات هذا العضو؟", "fieldIsEmpty": "'{data}' الحقل فارغ. الرجاء التحديد", + "pleaseEnterComments": "الرجاء إدخال التعليقات", + "skip": "يتخطى", "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", "currentPassword": "كلمة المرور الحاليه", + "concurrentReports": "التقارير المتزامنه", "profile": { "reset_password": { "label": "Reset Password", @@ -906,8 +909,11 @@ static const Map en_US = { "adult": "Adult", "updateMember": "Are You Sure You Want to Update this Member?", "fieldIsEmpty": "'{data}' Field is empty. Please select", + "pleaseEnterComments": "Please enter comments", + "skip": "skip", "typeCurrentPasswordBelow": "Type Your Current password below", "currentPassword": "Current password", + "concurrentReports": "Concurrent Reports", "profile": { "reset_password": { "label": "Reset Password", diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 8e45025..4ca2275 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -424,6 +424,7 @@ abstract class LocaleKeys { static const skip = 'skip'; static const typeCurrentPasswordBelow = 'typeCurrentPasswordBelow'; static const currentPassword = 'currentPassword'; + static const concurrentReports = 'concurrentReports'; static const profile_reset_password_label = 'profile.reset_password.label'; static const profile_reset_password_username = 'profile.reset_password.username'; static const profile_reset_password_password = 'profile.reset_password.password'; diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 2374fbc..753d2c2 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -61,6 +61,7 @@ import 'package:mohem_flutter_app/models/mowadhafhi/get_tickets_list.dart'; import 'package:mohem_flutter_app/models/my_requests/get_ccp_dff_structure_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_ccp_output_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_ccp_transactions_model.dart'; +import 'package:mohem_flutter_app/models/my_requests/get_ccp_transations_list_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_concurrent_programs_model.dart'; import 'package:mohem_flutter_app/models/my_team/get_employee_subordinates_list.dart'; import 'package:mohem_flutter_app/models/my_team/get_subordinates_leaves_total_vacations_list_model.dart'; @@ -342,7 +343,7 @@ class GenericResponseModel { SubmitAddressTransaction? submitAddressTransactionList; SubmitBasicDetailsTransactionList? submitBasicDetTransactionList; String? submitCEITransactionList; - String? submitCcpTransactionList; + SubmitCcpTransactionList? submitCcpTransactionList; SubmitContactTransactionList? submitContactTransactionList; SubmitEITTransactionList? submitEITTransactionList; String? submitHrTransactionList; @@ -1298,7 +1299,10 @@ class GenericResponseModel { submitAddressTransactionList = json['SubmitAddressTransactionList'] != null ? SubmitAddressTransaction.fromJson(json['SubmitAddressTransactionList']) : null; submitBasicDetTransactionList = json['SubmitBasicDetTransactionList'] != null ? SubmitBasicDetailsTransactionList.fromJson(json['SubmitBasicDetTransactionList']) : null; submitCEITransactionList = json['SubmitCEITransactionList']; - submitCcpTransactionList = json['SubmitCcpTransactionList']; + submitCcpTransactionList = json['SubmitCcpTransactionList'] != null + ? new SubmitCcpTransactionList.fromJson( + json['SubmitCcpTransactionList']) + : null; submitContactTransactionList = json['SubmitContactTransactionList'] != null ? SubmitContactTransactionList.fromJson(json['SubmitContactTransactionList']) : null; submitEITTransactionList = json['SubmitEITTransactionList'] != null ? SubmitEITTransactionList.fromJson(json['SubmitEITTransactionList']) : null; @@ -1753,7 +1757,10 @@ class GenericResponseModel { } data['SubmitCEITransactionList'] = this.submitCEITransactionList; - data['SubmitCcpTransactionList'] = this.submitCcpTransactionList; + if (this.submitCcpTransactionList != null) { + data['SubmitCcpTransactionList'] = + this.submitCcpTransactionList!.toJson(); + } data['SubmitContactTransactionList'] = this.submitContactTransactionList; if (this.submitEITTransactionList != null) { diff --git a/lib/models/my_requests/get_ccp_transations_list_model.dart b/lib/models/my_requests/get_ccp_transations_list_model.dart new file mode 100644 index 0000000..2e5191b --- /dev/null +++ b/lib/models/my_requests/get_ccp_transations_list_model.dart @@ -0,0 +1,24 @@ + + +class SubmitCcpTransactionList { + int? pREQUESTID; + String? pRETURNMSG; + String? pRETURNSTATUS; + + SubmitCcpTransactionList( + {this.pREQUESTID, this.pRETURNMSG, this.pRETURNSTATUS}); + + SubmitCcpTransactionList.fromJson(Map json) { + pREQUESTID = json['P_REQUEST_ID']; + pRETURNMSG = json['P_RETURN_MSG']; + pRETURNSTATUS = json['P_RETURN_STATUS']; + } + + Map toJson() { + Map data = new Map(); + data['P_REQUEST_ID'] = this.pREQUESTID; + data['P_RETURN_MSG'] = this.pRETURNMSG; + data['P_RETURN_STATUS'] = this.pRETURNSTATUS; + return data; + } +} \ No newline at end of file diff --git a/lib/ui/profile/add_update_family_member.dart b/lib/ui/profile/add_update_family_member.dart index 00ad7fc..61b6639 100644 --- a/lib/ui/profile/add_update_family_member.dart +++ b/lib/ui/profile/add_update_family_member.dart @@ -392,7 +392,7 @@ class _AddUpdateFamilyMemberState extends State { } void submitUpdateForm() async { - // try { + try { List> values1 = getBasicDetDffStructureList!.map((e) { String? dateVal = ''; String? vatcherVal = ''; @@ -463,9 +463,9 @@ class _AddUpdateFamilyMemberState extends State { Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, arguments: RequestSubmitScreenParams(LocaleKeys.profile_familyDetails.tr(), transactionId!.toInt(), itemKey.toString(), 'family_member')); setState(() {}); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } } diff --git a/lib/ui/screens/my_requests/my_requests.dart b/lib/ui/screens/my_requests/my_requests.dart index 65aa534..f9d8d39 100644 --- a/lib/ui/screens/my_requests/my_requests.dart +++ b/lib/ui/screens/my_requests/my_requests.dart @@ -47,7 +47,7 @@ class _MyRequestsState extends State { backgroundColor: Colors.white, appBar: AppBarWidget( context, - title: "Concurrent Reports", + title: LocaleKeys.concurrentReports, ), body: Column( children: [ diff --git a/lib/ui/screens/my_requests/new_request.dart b/lib/ui/screens/my_requests/new_request.dart index b476ecc..d04382d 100644 --- a/lib/ui/screens/my_requests/new_request.dart +++ b/lib/ui/screens/my_requests/new_request.dart @@ -5,11 +5,15 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/my_requests_api_client.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/dyanmic_forms/validate_eit_transaction_model.dart'; import 'package:mohem_flutter_app/models/get_eit_dff_structure_list_model.dart'; +import 'package:mohem_flutter_app/models/my_requests/get_ccp_transactions_model.dart'; +import 'package:mohem_flutter_app/models/my_requests/get_ccp_transations_list_model.dart'; import 'package:mohem_flutter_app/models/my_requests/get_concurrent_programs_model.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; @@ -25,7 +29,8 @@ class NewRequest extends StatefulWidget { class _NewRequestState extends State { List getConcurrentProgramsList = []; GetConcurrentProgramsModel? selectedConcurrentProgramList; - + SubmitCcpTransactionList? submitCcpTransactionList; + List getCCPTransactionsList = []; List? getCCPDFFStructureModelList; DateTime selectedDate = DateTime.now(); @@ -42,7 +47,7 @@ class _NewRequestState extends State { backgroundColor: Colors.white, appBar: AppBarWidget( context, - title: "Concurrent Reports", + title: LocaleKeys.concurrentReports, ), body: Column( children: [ @@ -84,7 +89,7 @@ class _NewRequestState extends State { 1.divider, DefaultButton(LocaleKeys.submit.tr(), () { // todo need to add submit method - // openNewRequest(); + openNewRequest(); }) .insideContainer, ], @@ -92,6 +97,40 @@ class _NewRequestState extends State { ); } + + void openNewRequest() async { + try { + List> values = getCCPDFFStructureModelList!.map((e) { + String? dateVal = ''; + String? vatcherVal = ''; + int? numberVal; + if (e!.fORMATTYPE == 'N') { + dateVal = null; + vatcherVal = e.eSERVICESDV!.pIDCOLUMNNAME; + numberVal = null; + } else if (e.fORMATTYPE == 'X') { + dateVal = null; + vatcherVal = e.eSERVICESDV!.pIDCOLUMNNAME; + numberVal = null; + } else { + dateVal = null; + numberVal = null; + vatcherVal = null; + } + return ValidateEitTransactionModel(dATEVALUE: dateVal, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: numberVal, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: vatcherVal.toString()).toJson(); + }).toList(); + Utils.showLoading(context); + submitCcpTransactionList = await MyRequestsApiClient().getSubmitNewRequest(values); + getCCPTransactionsList = await MyRequestsApiClient().getCcpTransactions(values); + Utils.hideLoading(context); + Navigator.pushNamed(context, AppRoutes.myRequests,); + setState(() {}); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + void getConcurrentPrograms() async { try { Utils.showLoading(context); From 6e409c77a0590c194321566b111a18058fad7f52 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 31 Oct 2022 15:50:33 +0300 Subject: [PATCH 14/31] mark attendance counter & ios nfc fixed 1.0 --- lib/classes/utils.dart | 1 - lib/main.dart | 10 +++------- lib/widgets/mark_attendance_widget.dart | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 2bb9135..f28cd2e 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -325,7 +325,6 @@ class Utils { } static void readNFc({required Function(String) onRead}) { - var instance = NfcManager.instance; NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async { print(tag.data); diff --git a/lib/main.dart b/lib/main.dart index 9a1ac05..adca4aa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -28,9 +28,7 @@ Logger logger = Logger( class MyHttpOverrides extends HttpOverrides { @override HttpClient createHttpClient(SecurityContext? context) { - return super.createHttpClient(context) - ..badCertificateCallback = - (X509Certificate cert, String host, int port) => true; + return super.createHttpClient(context)..badCertificateCallback = (X509Certificate cert, String host, int port) => true; } } @@ -86,11 +84,9 @@ class MyApp extends StatelessWidget { DeviceType deviceType, ) { PostParamsModel? obj = AppState().postParamsObject; - obj?.languageID = - EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2; + obj?.languageID = EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2; AppState().setPostParamsModel(obj!); - List> delegates = - context.localizationDelegates; + List> delegates = context.localizationDelegates; // delegates.add(GlobalMaterialLocalizations.delegate); delegates.add( MonthYearPickerLocalizations.delegate, diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 6a5b4d8..c41b89c 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -143,7 +143,7 @@ class _MarkAttendanceWidgetState extends State { Utils.readNFc(onRead: (String nfcId) async { Utils.showLoading(context); try { - GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); + GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId, isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); bool status = await model.fetchAttendanceTracking(context); Utils.hideLoading(context); showMDialog( From 11e4da6478343dc37f292df21b051cc514059f9a Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Mon, 31 Oct 2022 17:25:26 +0300 Subject: [PATCH 15/31] Added Answer Selected Status --- lib/classes/decorations_helper.dart | 13 +- lib/ui/marathon/marathon_intro_screen.dart | 49 +++----- lib/ui/marathon/marathon_provider.dart | 16 ++- lib/ui/marathon/marathon_screen.dart | 34 ++---- .../marathon/marathon_winner_selection.dart | 20 ++- lib/ui/marathon/widgets/question_card.dart | 115 +++++++++++------- lib/ui/marathon/winner_screen.dart | 14 +-- 7 files changed, 135 insertions(+), 126 deletions(-) diff --git a/lib/classes/decorations_helper.dart b/lib/classes/decorations_helper.dart index 67139b8..77ea4a4 100644 --- a/lib/classes/decorations_helper.dart +++ b/lib/classes/decorations_helper.dart @@ -14,9 +14,12 @@ class MyDecorations { ], ); - static Decoration answerContainerDecoration = BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: MyColors.greyF7Color, - border: Border.all(width: 1, color: MyColors.lightGreyEFColor), - ); + static Decoration getContainersDecoration(Color color) { + Decoration answerContainerDecoration = BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: color, + border: Border.all(width: 1, color: MyColors.lightGreyEFColor), + ); + return answerContainerDecoration; + } } diff --git a/lib/ui/marathon/marathon_intro_screen.dart b/lib/ui/marathon/marathon_intro_screen.dart index 9ccf5b0..f836229 100644 --- a/lib/ui/marathon/marathon_intro_screen.dart +++ b/lib/ui/marathon/marathon_intro_screen.dart @@ -11,7 +11,7 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart'; -import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_header.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:provider/provider.dart'; @@ -24,18 +24,20 @@ class MarathonIntroScreen extends StatelessWidget { Widget build(BuildContext context) { MarathonProvider provider = context.watch(); return Scaffold( + appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()), body: Stack( children: [ SingleChildScrollView( child: Column( children: [ - const MarathonHeader(), MarathonDetailsCard(provider: provider).paddingAll(15), MarathonTimerCard( provider: provider, timeToMarathon: dummyEndTime, ).paddingOnly(left: 15, right: 15, bottom: 15), - const SizedBox(height: 100,), + const SizedBox( + height: 100, + ), ], ), ), @@ -52,8 +54,7 @@ class MarathonIntroScreen extends StatelessWidget { class MarathonDetailsCard extends StatelessWidget { final MarathonProvider provider; - const MarathonDetailsCard({Key? key, required this.provider}) - : super(key: key); + const MarathonDetailsCard({Key? key, required this.provider}) : super(key: key); @override Widget build(BuildContext context) { @@ -68,17 +69,12 @@ class MarathonDetailsCard extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.contestTopicAbout - .tr() - .toText16(color: MyColors.grey77Color), - "Saudi Arabia" - .toText20(color: MyColors.textMixColor, isBold: true), + LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey77Color), + "Saudi Arabia".toText20(color: MyColors.textMixColor, isBold: true), Row( children: [ Flexible( - child: - "Nam suscipit turpis in pharetra euismsdef. Duis rutrum at nulla id aliquam" - .toText14(color: MyColors.grey77Color), + child: "Nam suscipit turpis in pharetra euismsdef. Duis rutrum at nulla id aliquam".toText14(color: MyColors.grey77Color), ) ], ), @@ -86,31 +82,25 @@ class MarathonDetailsCard extends StatelessWidget { 5.height, Row( children: [ - LocaleKeys.prize - .tr() - .toText16(color: MyColors.grey77Color, isBold: true), - " LED 55\" Android TV" - .toText16(color: MyColors.greenColor, isBold: true), + LocaleKeys.prize.tr().toText16(color: MyColors.grey77Color, isBold: true), + " LED 55\" Android TV".toText16(color: MyColors.greenColor, isBold: true), ], ), Row( children: [ - LocaleKeys.sponsoredBy - .tr() - .toText16(color: MyColors.grey77Color), - " Extra" - .toText16(color: MyColors.darkTextColor, isBold: true), + LocaleKeys.sponsoredBy.tr().toText16(color: MyColors.grey77Color), + " Extra".toText16(color: MyColors.darkTextColor, isBold: true), ], ), 10.height, Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.network( - "https://cdn.pixabay.com/photo/2014/08/27/07/53/blog-428950_1280.jpg", - height: 50, + Image.asset( + "assets/images/logos/main_mohemm_logo.png", + height: 40, fit: BoxFit.fill, - width: 120, + width: 150, ) ], ), @@ -144,8 +134,7 @@ class MarathonTimerCard extends StatelessWidget { Row( children: [ LocaleKeys.gameDate.tr().toText16(color: MyColors.grey77Color), - " 10 Oct, 2022" - .toText16(color: MyColors.darkTextColor, isBold: true), + " 10 Oct, 2022".toText16(color: MyColors.darkTextColor, isBold: true), ], ), Row( @@ -156,7 +145,7 @@ class MarathonTimerCard extends StatelessWidget { ), Lottie.asset( MyLottieConsts.hourGlassLottie, - height: 140, + height: 200, ), BuildCountdownTimer( timeToMarathon: timeToMarathon, diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index 39958c2..5a03b74 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -2,7 +2,9 @@ import 'dart:async'; import 'package:appinio_swiper/appinio_swiper.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/config/routes.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; class MarathonProvider extends ChangeNotifier { final AppinioSwiperController swiperController = AppinioSwiperController(); @@ -41,11 +43,18 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); } + void resetAll() { + isSelectedOptions[0] = false; + isSelectedOptions[1] = false; + isSelectedOptions[2] = false; + isSelectedOptions[3] = false; + } + Timer timerU = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); - int start = 5; + int start = 8; void startTimer(BuildContext context) { - start = 5; + start = 8; const Duration oneSec = Duration(seconds: 1); timerU = Timer.periodic( oneSec, @@ -66,9 +75,10 @@ class MarathonProvider extends ChangeNotifier { return; } - swipeCardLeft(); + resetAll(); timer.cancel(); cancelTimer(); + swipeCardLeft(); } else { start--; } diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index 445d72a..93e4913 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -13,8 +13,8 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/custom_status_widget.dart'; -import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_header.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:provider/provider.dart'; import 'package:steps_indicator/steps_indicator.dart'; @@ -25,13 +25,12 @@ class MarathonScreen extends StatelessWidget { Widget build(BuildContext context) { MarathonProvider provider = context.watch(); return Scaffold( + appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()), body: SingleChildScrollView( child: Column( children: [ - const MarathonHeader(), - 20.height, - MarathonProgressContainer(provider: provider) - .paddingOnly(left: 21, right: 21), + 20.height, + MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21), if (provider.isMarathonCompleted) InkWell( onTap: () { @@ -58,17 +57,12 @@ class MarathonScreen extends StatelessWidget { subTitle: Text( LocaleKeys.allQuestionsCorrect.tr(), textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: MyColors.darkTextColor, - letterSpacing: -1.08), + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -1.08), ), ).paddingOnly(top: 12, left: 21, right: 21), ) else - QuestionCard(provider: provider) - .paddingOnly(top: 12, left: 21, right: 21), + QuestionCard(provider: provider).paddingOnly(top: 12, left: 21, right: 21), ], ), ), @@ -79,12 +73,10 @@ class MarathonScreen extends StatelessWidget { class MarathonProgressContainer extends StatefulWidget { final MarathonProvider provider; - const MarathonProgressContainer({Key? key, required this.provider}) - : super(key: key); + const MarathonProgressContainer({Key? key, required this.provider}) : super(key: key); @override - State createState() => - _MarathonProgressContainerState(); + State createState() => _MarathonProgressContainerState(); } class _MarathonProgressContainerState extends State { @@ -120,13 +112,10 @@ class _MarathonProgressContainerState extends State { borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8), - child: - "${widget.provider.currentQuestionNumber.toString()} / ${widget.provider.totalQuestions.toString()} ${LocaleKeys.question.tr()}" - .toText12(color: MyColors.white), + child: "${widget.provider.currentQuestionNumber.toString()} / ${widget.provider.totalQuestions.toString()} ${LocaleKeys.question.tr()}".toText12(color: MyColors.white), ), "23 ${LocaleKeys.marathoners.tr()}".toText14(), - "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}" - .toText18(), + "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}".toText18(), ], ), 15.height, @@ -152,8 +141,7 @@ class _MarathonProgressContainerState extends State { 12.height, Row( children: [ - "${widget.provider.currentQuestionNumber * 10}% ${LocaleKeys.completed.tr()}" - .toText14(isBold: true), + "${widget.provider.currentQuestionNumber * 10}% ${LocaleKeys.completed.tr()}".toText14(isBold: true), ], ), ], diff --git a/lib/ui/marathon/marathon_winner_selection.dart b/lib/ui/marathon/marathon_winner_selection.dart index c69f54f..8462ab4 100644 --- a/lib/ui/marathon/marathon_winner_selection.dart +++ b/lib/ui/marathon/marathon_winner_selection.dart @@ -13,7 +13,7 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/custom_status_widget.dart'; -import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_header.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:provider/provider.dart'; class MarathonWinnerSelection extends StatelessWidget { @@ -23,13 +23,12 @@ class MarathonWinnerSelection extends StatelessWidget { Widget build(BuildContext context) { MarathonProvider provider = context.read(); return Scaffold( + appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()), body: SingleChildScrollView( child: Column( children: [ - const MarathonHeader(), 20.height, - QualifiersContainer(provider: provider) - .paddingOnly(left: 21, right: 21), + QualifiersContainer(provider: provider).paddingOnly(left: 21, right: 21), 20.height, InkWell( onTap: () { @@ -53,8 +52,7 @@ class MarathonWinnerSelection extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - "Muhammad Shrouff" - .toText18(isBold: true, color: MyColors.white), + "Muhammad Shrouff".toText18(isBold: true, color: MyColors.white), "837436".toText18(isBold: true, color: MyColors.white), ], ), @@ -96,8 +94,7 @@ class MarathonWinnerSelection extends StatelessWidget { class QualifiersContainer extends StatefulWidget { final MarathonProvider provider; - const QualifiersContainer({Key? key, required this.provider}) - : super(key: key); + const QualifiersContainer({Key? key, required this.provider}) : super(key: key); @override State createState() => _QualifiersContainerState(); @@ -134,11 +131,8 @@ class _QualifiersContainerState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - LocaleKeys.winnerSelection - .tr() - .toText18(isBold: true, color: MyColors.grey3AColor), - "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}" - .toText18(isBold: true, color: MyColors.redColor), + LocaleKeys.winnerSelection.tr().toText18(isBold: true, color: MyColors.grey3AColor), + "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}".toText18(isBold: true, color: MyColors.redColor), ], ), 10.height, diff --git a/lib/ui/marathon/widgets/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index 45fa6cc..d5f6bce 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -8,6 +8,13 @@ import 'package:mohem_flutter_app/models/marathon_question_model.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:provider/provider.dart'; +List isSelectedOptions = [ + false, + false, + false, + false, +]; + class QuestionCard extends StatefulWidget { final MarathonProvider provider; @@ -18,7 +25,7 @@ class QuestionCard extends StatefulWidget { } class _QuestionCardState extends State { - final List questionCards = []; + final List questionCards = []; @override void initState() { @@ -29,7 +36,7 @@ class _QuestionCardState extends State { void _loadCards() { for (DummyQuestionModel question in questions) { questionCards.add( - QuestionContent( + CardContent( question: question, provider: widget.provider, ), @@ -64,11 +71,11 @@ class _QuestionCardState extends State { } } -class QuestionContent extends StatelessWidget { +class CardContent extends StatelessWidget { final DummyQuestionModel question; final MarathonProvider provider; - const QuestionContent({ + const CardContent({ Key? key, required this.question, required this.provider, @@ -131,12 +138,38 @@ class QuestionContent extends StatelessWidget { } } -class AnswerContent extends StatelessWidget { +class AnswerContent extends StatefulWidget { final DummyQuestionModel question; final MarathonProvider provider; const AnswerContent({Key? key, required this.question, required this.provider}) : super(key: key); + @override + State createState() => _AnswerContentState(); +} + +class _AnswerContentState extends State { + void updateOption(int index, bool value) { + isSelectedOptions[0] = false; + isSelectedOptions[1] = false; + isSelectedOptions[2] = false; + isSelectedOptions[3] = false; + isSelectedOptions[index] = value; + setState(() {}); + } + + Decoration getContainerColor(int index) { + if (!isSelectedOptions[index]) { + return MyDecorations.getContainersDecoration(MyColors.greyF7Color); + } + if (isSelectedOptions[index] && context.watch().start > 0) { + return MyDecorations.getContainersDecoration(MyColors.yellowColorII); + } + return MyDecorations.getContainersDecoration( + isSelectedOptions[index] ? MyColors.greenColor : MyColors.greyF7Color, + ); + } + @override Widget build(BuildContext context) { return Container( @@ -155,29 +188,27 @@ class AnswerContent extends StatelessWidget { children: [ InkWell( onTap: () { - if (provider.currentQuestionNumber == 9) { - provider.cancelTimer(); - provider.resetValues(); + if (widget.provider.currentQuestionNumber == 9) { + widget.provider.cancelTimer(); + widget.provider.resetValues(); Navigator.pushReplacementNamed( context, AppRoutes.marathonWinnerSelection, ); return; } - provider.cancelTimer(); - provider.startTimer(context); - provider.swipeCardLeft(); + updateOption(0, true); }, child: Container( height: 60, width: MediaQuery.of(context).size.width - 75, alignment: Alignment.centerLeft, - decoration: MyDecorations.answerContainerDecoration, + decoration: getContainerColor(0), child: Center( child: Text( - question.opt1!, - style: const TextStyle( - color: MyColors.darkTextColor, + widget.question.opt1!, + style: TextStyle( + color: isSelectedOptions[0] ? MyColors.white : MyColors.darkTextColor, fontWeight: FontWeight.w600, fontSize: 16, ), @@ -188,29 +219,27 @@ class AnswerContent extends StatelessWidget { const SizedBox(height: 15), InkWell( onTap: () { - if (provider.currentQuestionNumber == 9) { - provider.cancelTimer(); - provider.resetValues(); + if (widget.provider.currentQuestionNumber == 9) { + widget.provider.cancelTimer(); + widget.provider.resetValues(); Navigator.pushReplacementNamed( context, AppRoutes.marathonWinnerSelection, ); return; } - provider.cancelTimer(); - provider.startTimer(context); - provider.swipeCardLeft(); + updateOption(1, true); }, child: Container( height: 60, width: MediaQuery.of(context).size.width - 75, alignment: Alignment.centerLeft, - decoration: MyDecorations.answerContainerDecoration, + decoration: getContainerColor(1), child: Center( child: Text( - question.opt2!, - style: const TextStyle( - color: MyColors.darkTextColor, + widget.question.opt2!, + style: TextStyle( + color: isSelectedOptions[1] ? MyColors.white : MyColors.darkTextColor, fontWeight: FontWeight.w600, fontSize: 16, ), @@ -221,29 +250,27 @@ class AnswerContent extends StatelessWidget { const SizedBox(height: 15), InkWell( onTap: () { - if (provider.currentQuestionNumber == 9) { - provider.cancelTimer(); - provider.resetValues(); + if (widget.provider.currentQuestionNumber == 9) { + widget.provider.cancelTimer(); + widget.provider.resetValues(); Navigator.pushReplacementNamed( context, AppRoutes.marathonWinnerSelection, ); return; } - provider.cancelTimer(); - provider.startTimer(context); - provider.swipeCardLeft(); + updateOption(2, true); }, child: Container( height: 60, width: MediaQuery.of(context).size.width - 75, alignment: Alignment.centerLeft, - decoration: MyDecorations.answerContainerDecoration, + decoration: getContainerColor(2), child: Center( child: Text( - question.opt3!, - style: const TextStyle( - color: MyColors.darkTextColor, + widget.question.opt3!, + style: TextStyle( + color: isSelectedOptions[2] ? MyColors.white : MyColors.darkTextColor, fontWeight: FontWeight.w600, fontSize: 16, ), @@ -254,29 +281,27 @@ class AnswerContent extends StatelessWidget { const SizedBox(height: 15), InkWell( onTap: () { - if (provider.currentQuestionNumber == 9) { - provider.cancelTimer(); - provider.resetValues(); + if (widget.provider.currentQuestionNumber == 9) { + widget.provider.cancelTimer(); + widget.provider.resetValues(); Navigator.pushReplacementNamed( context, AppRoutes.marathonWinnerSelection, ); return; } - provider.cancelTimer(); - provider.startTimer(context); - provider.swipeCardLeft(); + updateOption(3, true); }, child: Container( height: 60, width: MediaQuery.of(context).size.width - 75, alignment: Alignment.centerLeft, - decoration: MyDecorations.answerContainerDecoration, + decoration: getContainerColor(3), child: Center( child: Text( - question.opt3!, - style: const TextStyle( - color: MyColors.darkTextColor, + widget.question.opt3!, + style: TextStyle( + color: isSelectedOptions[3] ? MyColors.white : MyColors.darkTextColor, fontWeight: FontWeight.w600, fontSize: 16, ), diff --git a/lib/ui/marathon/winner_screen.dart b/lib/ui/marathon/winner_screen.dart index 2e9b16b..8d6d171 100644 --- a/lib/ui/marathon/winner_screen.dart +++ b/lib/ui/marathon/winner_screen.dart @@ -9,7 +9,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/ui/marathon/widgets/marathon_header.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; class WinnerScreen extends StatelessWidget { const WinnerScreen({Key? key}) : super(key: key); @@ -18,10 +18,10 @@ class WinnerScreen extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( backgroundColor: MyColors.backgroundColor, + appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()), body: SingleChildScrollView( child: Column( children: [ - const MarathonHeader(), 60.height, Container( width: double.infinity, @@ -75,12 +75,12 @@ class WinnerScreen extends StatelessWidget { ], ), 5.height, - Image.network( - "https://cdn.pixabay.com/photo/2014/08/27/07/53/blog-428950_1280.jpg", - height: 50, + Image.asset( + "assets/images/logos/main_mohemm_logo.png", + height: 40, fit: BoxFit.fill, - width: 120, - ), + width: 150, + ) ], ), ).paddingOnly(left: 21, right: 21), From c0ee98b06ec80eee36bfbe24a63df01d0087e654 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 1 Nov 2022 09:16:55 +0300 Subject: [PATCH 16/31] Merge branch 'master' into development_aamir # Conflicts: # assets/langs/ar-SA.json # assets/langs/en-US.json # lib/generated/locale_keys.g.dart --- assets/langs/ar-SA.json | 4 +--- assets/langs/en-US.json | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 88f0b75..bfcaa1c 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -492,8 +492,6 @@ "winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.", "fingersCrossed": "تشابك الاصابع!!!", "congrats": "مبروك !!!", - "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح." - - "none": "بدون", + "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح.", "typeheretoreply": "اكتب هنا للرد" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 0c7434a..7e9b42a 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -492,7 +492,6 @@ "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", "fingersCrossed": "Fingers Crossed!!!", "congrats": "Congratulations!!!", - "allQuestionsCorrect": "You have answered all questions correct" - "none": "None", + "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply" } \ No newline at end of file From d77f9a33628cbc6d9644c98a19a55450d7bb88db Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 1 Nov 2022 09:22:30 +0300 Subject: [PATCH 17/31] Worklist fixes --- assets/lottie/loading.json | 1 + .../get_po_notification_body_list_model.dart | 2 +- .../itg_worklist_table_model.dart | 21 ++++++ lib/provider/dashboard_provider_model.dart | 14 +++- .../attendance/add_vacation_rule_screen.dart | 1 + lib/ui/chat/chat_home.dart | 1 + lib/ui/landing/dashboard_screen.dart | 1 + .../add_leave_balance_screen.dart | 1 + lib/ui/profile/profile_screen.dart | 2 +- lib/ui/work_list/itg_detail_screen.dart | 23 ++++++- .../approval_level_fragment.dart | 20 ++++-- .../request_detail_fragment.dart | 2 + lib/ui/work_list/sheets/delegate_sheet.dart | 5 ++ .../work_list/sheets/selected_item_sheet.dart | 8 +-- lib/ui/work_list/work_list_screen.dart | 1 + lib/ui/work_list/worklist_detail_screen.dart | 69 ++++++++++++++++--- .../worklist_fragments/actions_fragment.dart | 16 +++-- lib/widgets/bottom_sheet.dart | 12 +++- lib/widgets/circular_avatar.dart | 2 +- .../dialogs/accept_reject_input_dialog.dart | 19 +++-- lib/widgets/dialogs/itg_comments_dialog.dart | 27 +++++--- lib/widgets/image_picker.dart | 1 + lib/widgets/item_detail_view_widget.dart | 19 ++++- 23 files changed, 216 insertions(+), 52 deletions(-) create mode 100644 assets/lottie/loading.json create mode 100644 lib/models/itg_forms_models/itg_worklist_table_model.dart diff --git a/assets/lottie/loading.json b/assets/lottie/loading.json new file mode 100644 index 0000000..8190459 --- /dev/null +++ b/assets/lottie/loading.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":30,"ip":0,"op":60,"w":300,"h":300,"nm":"loading_6","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[360]}],"ix":10},"p":{"a":0,"k":[150.00000000000003,150.00000000000003,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[30.000000000000004,30.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.12941176470588237,0.7411764705882353,0.7764705882352941,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":60,"s":[99]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[1]},{"t":50,"s":[100]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[3]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":30,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150.00000000000003,150.00000000000003,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[30.000000000000004,30.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.7450980392156863,0.9254901960784314,0.9372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/lib/models/get_po_notification_body_list_model.dart b/lib/models/get_po_notification_body_list_model.dart index e1dfbdf..d0473dc 100644 --- a/lib/models/get_po_notification_body_list_model.dart +++ b/lib/models/get_po_notification_body_list_model.dart @@ -160,7 +160,7 @@ class POLines { int? pOHEADERID; String? pROMISEDDATE; String? pRNUM; - int? qUANTITY; + num? qUANTITY; String? rEQUESTOR; int? rOWNUM; int? tOROWNUM; diff --git a/lib/models/itg_forms_models/itg_worklist_table_model.dart b/lib/models/itg_forms_models/itg_worklist_table_model.dart new file mode 100644 index 0000000..e1212ba --- /dev/null +++ b/lib/models/itg_forms_models/itg_worklist_table_model.dart @@ -0,0 +1,21 @@ +class ITGWorkListTableModel { + String? label; + String? isTable; + String? textvalue; + + ITGWorkListTableModel({this.label, this.isTable, this.textvalue}); + + ITGWorkListTableModel.fromJson(Map json) { + label = json['label']; + isTable = json['isTable']; + textvalue = json['textvalue']; + } + + Map toJson() { + Map data = new Map(); + data['label'] = this.label; + data['isTable'] = this.isTable; + data['textvalue'] = this.textvalue; + return data; + } +} diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 4e53242..9396704 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -19,6 +19,7 @@ import 'package:mohem_flutter_app/models/dashboard/mohemm_itg_pending_task_respo 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'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; /// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool // ignore: prefer_mixin @@ -151,7 +152,18 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { logger.wtf(ex); if (showLoading) Utils.hideLoading(context); notifyListeners(); - Utils.handleException(ex, context, null); + Utils.handleException(ex, context, (err) { + Utils.hideLoading(context); + showDialog( + context: context, + builder: (cxt) => ConfirmDialog( + message: err, + onTap: () { + Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route route) => false); + }, + ), + ); + }); } } diff --git a/lib/ui/attendance/add_vacation_rule_screen.dart b/lib/ui/attendance/add_vacation_rule_screen.dart index aa48696..a698adc 100644 --- a/lib/ui/attendance/add_vacation_rule_screen.dart +++ b/lib/ui/attendance/add_vacation_rule_screen.dart @@ -430,6 +430,7 @@ class _AddVacationRuleScreenState extends State { onTap: () { showMyBottomSheet( context, + callBackFunc: (){}, child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index ef984a3..b8f7514 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -160,6 +160,7 @@ class _ChatHomeScreenState extends State { // .getChatMemberFromSearch("aamir.muhammad", 36239); showMyBottomSheet( context, + callBackFunc: (){}, child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index bb4ee43..d342072 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -268,6 +268,7 @@ class _DashboardScreenState extends State { ).onPress(() { showMyBottomSheet( context, + callBackFunc: (){}, child: MarkAttendanceWidget(model, isFromDashboard: true), ); }), diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index e600800..864a507 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -221,6 +221,7 @@ class _AddLeaveBalanceScreenState extends State { onTap: () { showMyBottomSheet( context, + callBackFunc: (){}, child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), diff --git a/lib/ui/profile/profile_screen.dart b/lib/ui/profile/profile_screen.dart index c071d3f..0bf007e 100644 --- a/lib/ui/profile/profile_screen.dart +++ b/lib/ui/profile/profile_screen.dart @@ -112,7 +112,7 @@ class _ProfileScreenState extends State { } void startImageSheet() { - showMyBottomSheet(context, + showMyBottomSheet(context, callBackFunc: (){}, child: Column( children: [ Container( diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index e306750..0f45648 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -125,7 +125,7 @@ class _ItgDetailScreenState extends State { }, children: [ RequestDetailFragment(fields: itgRequest?.fieldGoups?[1].fields ?? []), - ApprovalLevelfragment(wFHistory: itgRequest?.wFHistory ?? []), + ApprovalLevelfragment(wFHistory: itgRequest?.wFHistory ?? [], voidCallback: reloadITG,), RequestDetailFragment(fields: itgRequest?.fieldGoups?[0].fields ?? []), ], ).expanded, @@ -263,12 +263,12 @@ class _ItgDetailScreenState extends State { print(action.toJson()); switch (action.action) { case "Delegate": - showMyBottomSheet(context, + showMyBottomSheet(context, callBackFunc: reloadITG, child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [])); break; case "RequestInformation": - showMyBottomSheet(context, + showMyBottomSheet(context, callBackFunc: reloadITG, child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [])); break; @@ -342,10 +342,12 @@ class _ItgDetailScreenState extends State { } void performAction(String actionMode) { + print(actionMode); showDialog( context: context, builder: (cxt) => ITGCommentsDialog( message: LocaleKeys.writeComment.tr(), + actionMode: actionMode, onTap: (note) { if (actionMode == "APPROVED") { performApproveAction(requestDetails!.requestType!, requestDetails!.iD!, requestDetails!.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", note); @@ -404,4 +406,19 @@ class _ItgDetailScreenState extends State { Utils.handleException(ex, context, null); } } + + void reloadITG() { + AppState().requestAllList!.removeAt(AppState().itgWorkListIndex!); + if (AppState().requestAllList!.isEmpty) { + Navigator.pop(context, "delegate_reload"); + } else { + if (AppState().requestAllList!.length <= AppState().itgWorkListIndex!) { + Navigator.pop(context, "delegate_reload"); + } else { + requestDetails = null; + getDataFromState(); + } + } + } + } diff --git a/lib/ui/work_list/itg_fragments/approval_level_fragment.dart b/lib/ui/work_list/itg_fragments/approval_level_fragment.dart index 1d77f2a..eb478af 100644 --- a/lib/ui/work_list/itg_fragments/approval_level_fragment.dart +++ b/lib/ui/work_list/itg_fragments/approval_level_fragment.dart @@ -12,8 +12,9 @@ import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; class ApprovalLevelfragment extends StatelessWidget { List wFHistory; + VoidCallback voidCallback; - ApprovalLevelfragment({Key? key, this.wFHistory = const []}) : super(key: key); + ApprovalLevelfragment({Key? key, this.wFHistory = const [], required this.voidCallback}) : super(key: key); @override Widget build(BuildContext context) { @@ -98,6 +99,7 @@ class ApprovalLevelfragment extends StatelessWidget { LocaleKeys.request_info.tr().toText12(color: MyColors.grey67Color).center.paddingOnly(top: 6, bottom: 6).onPress(() { showMyBottomSheet( context, + callBackFunc: voidCallback, child: SelectedItgItemSheet( LocaleKeys.comments.tr(), wfHistory: history, @@ -109,6 +111,7 @@ class ApprovalLevelfragment extends StatelessWidget { LocaleKeys.delegate.tr().toText12(color: MyColors.gradiantEndColor).center.paddingOnly(top: 6, bottom: 6).onPress(() { showMyBottomSheet( context, + callBackFunc: voidCallback, child: SelectedItgItemSheet( LocaleKeys.comments.tr(), wfHistory: history, @@ -126,18 +129,21 @@ class ApprovalLevelfragment extends StatelessWidget { } Color getStatusColor(String code) { - if (code == "Submit") { + if (code.toLowerCase() == "submit") { return MyColors.grey3AColor; - } else if (code == "Pending") { + } else if (code.toLowerCase() == "pending") { return MyColors.yellowColor; - } else if (code == "Not Doable" || code == "Rejected") { + } else if (code.toLowerCase() == "not doable" || code.toLowerCase() == "rejected") { return MyColors.redColor; - } else if (code == "APPROVED") { + } else if (code.toLowerCase() == "approved" || + code.toLowerCase() == "auto-approve" || + code.toLowerCase() == "auto-approved" || + code.toLowerCase() == "doable") { return MyColors.greenColor; - } else if (code == "Requested Information") { + } else if (code.toLowerCase() == "requested information" || code.toLowerCase() == "assign" || code.toLowerCase() == "reassign") { return MyColors.orange; } else { - return MyColors.yellowColor; + return MyColors.whiteColor; } } } diff --git a/lib/ui/work_list/itg_fragments/request_detail_fragment.dart b/lib/ui/work_list/itg_fragments/request_detail_fragment.dart index 6092bef..72b20d4 100644 --- a/lib/ui/work_list/itg_fragments/request_detail_fragment.dart +++ b/lib/ui/work_list/itg_fragments/request_detail_fragment.dart @@ -51,6 +51,7 @@ class RequestDetailFragment extends StatelessWidget { ? true : false : false, + type: fields[index].type, ); } return ItemDetailViewGridItem( @@ -62,6 +63,7 @@ class RequestDetailFragment extends StatelessWidget { ? true : false : false, + type: fields[index].type, ); }, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( diff --git a/lib/ui/work_list/sheets/delegate_sheet.dart b/lib/ui/work_list/sheets/delegate_sheet.dart index 4075332..28a90e6 100644 --- a/lib/ui/work_list/sheets/delegate_sheet.dart +++ b/lib/ui/work_list/sheets/delegate_sheet.dart @@ -194,6 +194,7 @@ class _DelegateSheetState extends State { ).onPress(() { showMyBottomSheet( context, + callBackFunc: (){}, child: SearchOptionsSheet( selectedType, onSelection: (String value) { @@ -392,6 +393,7 @@ class _DelegateSheetState extends State { return InkWell( onTap: () { showMyBottomSheet(context, + callBackFunc: (){}, child: SelectedItemSheet( "Comment", apiMode: widget.apiMode, @@ -437,6 +439,7 @@ class _DelegateSheetState extends State { return InkWell( onTap: () { showMyBottomSheet(context, + callBackFunc: (){}, child: SelectedItgItemSheet( "Comment", apiMode: widget.apiMode, @@ -461,6 +464,7 @@ class _DelegateSheetState extends State { return InkWell( onTap: () { showMyBottomSheet(context, + callBackFunc: (){}, child: SelectedItemSheet( "Comment", apiMode: widget.apiMode, @@ -506,6 +510,7 @@ class _DelegateSheetState extends State { return InkWell( onTap: () { showMyBottomSheet(context, + callBackFunc: (){}, child: SelectedItemSheet( LocaleKeys.comments.tr(), apiMode: widget.apiMode, diff --git a/lib/ui/work_list/sheets/selected_item_sheet.dart b/lib/ui/work_list/sheets/selected_item_sheet.dart index f3f8f0d..e053218 100644 --- a/lib/ui/work_list/sheets/selected_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_item_sheet.dart @@ -71,7 +71,7 @@ class SelectedItemSheet extends StatelessWidget { child: DefaultButton( LocaleKeys.cancel.tr(), () { - Navigator.pop(context); + Navigator.pop(context, "cancel"); }, textColor: Colors.black, colors: [ @@ -120,8 +120,8 @@ class SelectedItemSheet extends StatelessWidget { try { await WorkListApiClient().submitComment(comment: comment, email: email, userId: userId, notificationId: notificationID, apiMode: apiMode); Utils.hideLoading(context); - Navigator.pop(context); - Navigator.pop(context); + // Navigator.pop(context); + // Navigator.pop(context); Navigator.pop(context, "delegate_reload"); } catch (ex) { Utils.hideLoading(context); @@ -142,7 +142,7 @@ class SelectedItemSheet extends StatelessWidget { padding: EdgeInsets.only(top: 16, bottom: 16, left: 21, right: 21), child: Row( children: [ - actionHistoryList != null + (actionHistoryList != null && actionHistoryList!.eMPLOYEEIMAGE != null) ? CircularAvatar( height: 30, width: 30, diff --git a/lib/ui/work_list/work_list_screen.dart b/lib/ui/work_list/work_list_screen.dart index 2e362a9..9471568 100644 --- a/lib/ui/work_list/work_list_screen.dart +++ b/lib/ui/work_list/work_list_screen.dart @@ -429,6 +429,7 @@ class _WorkListScreenState extends State { void openBottomSheet(BuildContext context) { showMyBottomSheet( context, + callBackFunc: (){}, child: WorkListAdvanceSearch((selectedViewID, selectedItemTypeID, searchByInput, searchByDate) async { itgRequestTypeIndex = null; pNotificationType = selectedViewID; diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 8f43b8d..ec02631 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:lottie/lottie.dart'; import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -82,6 +83,9 @@ class _WorkListDetailScreenState extends State { bool isApproveAvailable = false; bool isRejectAvailable = false; + bool isAttachmentLoaded = false; + bool isActionHistoryLoaded = false; + @override void initState() { super.initState(); @@ -241,8 +245,20 @@ class _WorkListDetailScreenState extends State { itemCreationLines: getItemCreationNtfBody?.itemCreationLines ?? [], prLinesList: getPrNotificationBody?.pRLines ?? [], ), - actionHistoryList.isEmpty ? Utils.getNoDataWidget(context) : ActionsFragment(workListData!.nOTIFICATIONID, actionHistoryList), - getAttachmentList.isEmpty ? Utils.getNoDataWidget(context) : AttachmentsFragment(getAttachmentList), + isActionHistoryLoaded + ? actionHistoryList.isEmpty + ? Utils.getNoDataWidget(context) + : ActionsFragment( + workListData!.nOTIFICATIONID, + actionHistoryList, + voidCallback: reloadWorkList, + ) + : showLoadingAnimation(), + isAttachmentLoaded + ? getAttachmentList.isEmpty + ? Utils.getNoDataWidget(context) + : AttachmentsFragment(getAttachmentList) + : showLoadingAnimation(), ], ).expanded, if (isApproveAvailable || isRejectAvailable || isCloseAvailable) @@ -371,20 +387,24 @@ class _WorkListDetailScreenState extends State { switch (notificationButton.bUTTONACTION) { case "DELEGATE": showMyBottomSheet(context, + callBackFunc: reloadWorkList, child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); break; case "REQUEST_INFO": // do something else showMyBottomSheet(context, + callBackFunc: reloadWorkList, child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); break; case "TRANSFER_INFO": // do something else showMyBottomSheet(context, - child: DelegateSheet(title: notificationButton.bUTTONLABEL!, apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + callBackFunc: reloadWorkList, + child: + DelegateSheet(title: notificationButton.bUTTONLABEL!, apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); break; case "ANSWER_INFO": - performAction(notificationButton.bUTTONACTION!,title: notificationButton.bUTTONLABEL); + performAction(notificationButton.bUTTONACTION!, title: notificationButton.bUTTONLABEL); break; case "RFC": // do something else @@ -396,10 +416,13 @@ class _WorkListDetailScreenState extends State { // do something else case "APPROVE_AND_FORWARD": showMyBottomSheet(context, + callBackFunc: reloadWorkList, child: DelegateSheet(title: "Approve and Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); break; case "FORWARD": - showMyBottomSheet(context, child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + showMyBottomSheet(context, + callBackFunc: reloadWorkList, + child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); break; case "REJECT": performNetworkCall(context, email: "", userId: ""); @@ -492,14 +515,15 @@ class _WorkListDetailScreenState extends State { ); } - void performAction(String actionMode,{String? title}) { + void performAction(String actionMode, {String? title}) { TextEditingController textEditingController = TextEditingController(); showDialog( context: context, builder: (cxt) => AcceptRejectInputDialog( - message: title !=null ? null:LocaleKeys.requestedItems.tr(), + message: title != null ? null : LocaleKeys.requestedItems.tr(), title: title, notificationGetRespond: notificationNoteInput, + actionMode: actionMode, onTap: (note) { Map payload = { "P_ACTION_MODE": actionMode, @@ -550,6 +574,20 @@ class _WorkListDetailScreenState extends State { } } + void reloadWorkList() { + AppState().workList!.removeAt(AppState().workListIndex!); + if (AppState().workList!.isEmpty) { + Navigator.pop(context, "delegate_reload"); + } else { + if (AppState().workList!.length <= AppState().workListIndex!) { + Navigator.pop(context, "delegate_reload"); + } else { + workListData = null; + getDataFromState(); + } + } + } + void getEitNotificationBody() async { try { if (apiCallCount == 0) Utils.showLoading(context); @@ -791,7 +829,9 @@ class _WorkListDetailScreenState extends State { // apiCallCount--; // if (apiCallCount == 0) { // Utils.hideLoading(context); - setState(() {}); + setState(() { + isActionHistoryLoaded = true; + }); // } } catch (ex) { // apiCallCount--; @@ -808,7 +848,9 @@ class _WorkListDetailScreenState extends State { // apiCallCount--; // if (apiCallCount == 0) { // Utils.hideLoading(context); - setState(() {}); + setState(() { + isAttachmentLoaded = true; + }); // } } catch (ex) { // apiCallCount--; @@ -816,4 +858,13 @@ class _WorkListDetailScreenState extends State { Utils.handleException(ex, context, null); } } + + Widget showLoadingAnimation() { + return Lottie.asset( + 'assets/lottie/loading.json', + repeat: true, + reverse: false, + fit: BoxFit.contain, + ); + } } diff --git a/lib/ui/work_list/worklist_fragments/actions_fragment.dart b/lib/ui/work_list/worklist_fragments/actions_fragment.dart index d5e1f89..8a69599 100644 --- a/lib/ui/work_list/worklist_fragments/actions_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/actions_fragment.dart @@ -7,7 +7,6 @@ import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/get_action_history_list_model.dart'; -import 'package:mohem_flutter_app/ui/work_list/sheets/delegate_sheet.dart'; import 'package:mohem_flutter_app/ui/work_list/sheets/selected_item_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; @@ -15,8 +14,9 @@ import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; class ActionsFragment extends StatelessWidget { int? notificationID; List actionHistoryList; + VoidCallback voidCallback; - ActionsFragment(this.notificationID, this.actionHistoryList, {Key? key}) : super(key: key); + ActionsFragment(this.notificationID, this.actionHistoryList, {Key? key, required this.voidCallback}) : super(key: key); @override Widget build(BuildContext context) { @@ -99,13 +99,17 @@ class ActionsFragment extends StatelessWidget { Row( children: [ LocaleKeys.request_info.tr().toText12(color: MyColors.grey67Color).center.paddingOnly(top: 6, bottom: 6).onPress(() { - showMyBottomSheet(context, - child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: notificationID, actionHistoryList: actionHistoryList)); + showMyBottomSheet( + context, + callBackFunc: voidCallback, + child: SelectedItemSheet(LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: notificationID, actionHistoryList: actionHistory), + ); }).expanded, Container(width: 1, height: 30, color: MyColors.lightGreyEFColor), LocaleKeys.delegate.tr().toText12(color: MyColors.gradiantEndColor).center.paddingOnly(top: 6, bottom: 6).onPress(() { showMyBottomSheet( context, + callBackFunc: voidCallback, child: SelectedItemSheet( LocaleKeys.comments.tr(), apiMode: "DELEGATE", @@ -133,9 +137,9 @@ class ActionsFragment extends StatelessWidget { return MyColors.redColor; } else if (code == "PENDING") { return MyColors.orange; - } else if (code == "APPROVED" || code == "APPROVE") { + } else if (code == "APPROVED" || code == "APPROVE" || code == "ANSWER_INFO") { return const Color(0xff1FA269); - } else if (code == "REQUEST_INFO") { + } else if (code == "REQUEST_INFO"|| code == "FORWARD") { return const Color(0xff2E303A); } else if (code != "SUBMIT" && code != "REJECT" && code != "PENDING") { return MyColors.orange; diff --git a/lib/widgets/bottom_sheet.dart b/lib/widgets/bottom_sheet.dart index 206d017..a15fc3b 100644 --- a/lib/widgets/bottom_sheet.dart +++ b/lib/widgets/bottom_sheet.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; -void showMyBottomSheet(BuildContext context, {required Widget child}) { - showModalBottomSheet( +void showMyBottomSheet(BuildContext context, {required Widget child, required VoidCallback callBackFunc}) { + showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, @@ -37,7 +37,13 @@ void showMyBottomSheet(BuildContext context, {required Widget child}) { ), ); }, - ); + ).then((value) { + // print("BACK FROM DELEGATE!!!!"); + // print("value: $value"); + if (value == "delegate_reload") { + callBackFunc(); + } + }); } class BottomSheetItem extends StatelessWidget { diff --git a/lib/widgets/circular_avatar.dart b/lib/widgets/circular_avatar.dart index ad94052..a18cf03 100644 --- a/lib/widgets/circular_avatar.dart +++ b/lib/widgets/circular_avatar.dart @@ -25,7 +25,7 @@ class CircularAvatar extends StatelessWidget { image: NetworkImage(url ?? "https://cdn4.iconfinder.com/data/icons/professions-2-2/151/89-512.png"), ), ), - child: isImageBase64 ? imageFromBase64String(url!) : null, + child: (isImageBase64 && url != null) ? imageFromBase64String(url!) : Container(), ); } diff --git a/lib/widgets/dialogs/accept_reject_input_dialog.dart b/lib/widgets/dialogs/accept_reject_input_dialog.dart index ef2cfaa..a0faf2c 100644 --- a/lib/widgets/dialogs/accept_reject_input_dialog.dart +++ b/lib/widgets/dialogs/accept_reject_input_dialog.dart @@ -13,11 +13,13 @@ class AcceptRejectInputDialog extends StatelessWidget { final String? title; final String? message; final String? okTitle; + final String? actionMode; final NotificationGetRespondAttributesList? notificationGetRespond; final Function(String) onTap; + // final TextEditingController textEditingController; - AcceptRejectInputDialog({Key? key, this.title, @required this.message, this.okTitle, required this.onTap, this.notificationGetRespond}) : super(key: key); + AcceptRejectInputDialog({Key? key, this.title, @required this.message, this.okTitle, required this.onTap, this.notificationGetRespond, this.actionMode}) : super(key: key); String note = ""; @@ -85,15 +87,20 @@ class AcceptRejectInputDialog extends StatelessWidget { ).expanded, 10.width, DefaultButton( - LocaleKeys.ok.tr(), + actionMode == "REJECTED" ? LocaleKeys.reject.tr() : LocaleKeys.ok.tr(), () { Navigator.pop(context); onTap(note); }, - colors: const [ - Color(0xff28C884), - Color(0xff1BB271), - ], + colors: actionMode == "REJECTED" + ? const [ + Color(0xffE47A7E), + Color(0xffE47A7E), + ] + : const [ + Color(0xff28C884), + Color(0xff1BB271), + ], ).expanded, ], ), diff --git a/lib/widgets/dialogs/itg_comments_dialog.dart b/lib/widgets/dialogs/itg_comments_dialog.dart index b984851..34199ba 100644 --- a/lib/widgets/dialogs/itg_comments_dialog.dart +++ b/lib/widgets/dialogs/itg_comments_dialog.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; @@ -12,9 +13,10 @@ class ITGCommentsDialog extends StatelessWidget { final String? title; final String? message; final String? okTitle; + final String? actionMode; final Function(String) onTap; - ITGCommentsDialog({Key? key, this.title, @required this.message, this.okTitle, required this.onTap}) : super(key: key); + ITGCommentsDialog({Key? key, this.title, @required this.message, this.okTitle, required this.onTap, this.actionMode}) : super(key: key); String note = ""; @@ -82,15 +84,24 @@ class ITGCommentsDialog extends StatelessWidget { ).expanded, 10.width, DefaultButton( - LocaleKeys.ok.tr(), + actionMode == "REJECTED" ? LocaleKeys.reject.tr() : LocaleKeys.approve.tr(), () { - Navigator.pop(context); - onTap(note); + if (actionMode == "REJECTED" && note.isEmpty) { + Utils.showToast(LocaleKeys.pleaseEnterComments.tr()); + } else { + Navigator.pop(context); + onTap(note); + } }, - colors: const [ - Color(0xff28C884), - Color(0xff1BB271), - ], + colors: actionMode == "REJECTED" + ? const [ + Color(0xffE47A7E), + Color(0xffE47A7E), + ] + : const [ + Color(0xff28C884), + Color(0xff1BB271), + ], ).expanded, ], ), diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index 4a99577..5e5ac01 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -13,6 +13,7 @@ class ImageOptions { static void showImageOptionsNew(BuildContext context, bool showFilesOption, Function(String, File) image) { showMyBottomSheet( context, + callBackFunc: (){}, child: AttachmentOptions( showFilesOption: showFilesOption, onCameraTap: () async { diff --git a/lib/widgets/item_detail_view_widget.dart b/lib/widgets/item_detail_view_widget.dart index 34b2eb3..05495e9 100644 --- a/lib/widgets/item_detail_view_widget.dart +++ b/lib/widgets/item_detail_view_widget.dart @@ -1,8 +1,11 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/classes/colors.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/itg_forms_models/itg_worklist_table_model.dart'; class ItemDetailView extends StatelessWidget { final String title; @@ -46,9 +49,10 @@ class ItemDetailViewGridItem extends StatelessWidget { int index; final String? title; final String? value; + final String? type; final bool isNeedToShowEmptyDivider; - ItemDetailViewGridItem(this.index, this.title, this.value, {Key? key, this.isNeedToShowEmptyDivider = false}) : super(key: key); + ItemDetailViewGridItem(this.index, this.title, this.value, {Key? key, this.isNeedToShowEmptyDivider = false, this.type = ""}) : super(key: key); @override Widget build(BuildContext context) { @@ -78,7 +82,7 @@ class ItemDetailViewGridItem extends StatelessWidget { children: [ Flexible(child: "$title:".toText12Auto(isBold: true, color: const Color(0xff2BB8A6))), 4.width, - Flexible(child: (value!.isEmpty ? "--" : value).toString().toText12Auto(color: MyColors.normalTextColor)), + type!.toLowerCase() == "table" ? getStringFromJSON(value!) : Flexible(child: (value!.isEmpty ? "--" : value).toString().toText12Auto(color: MyColors.normalTextColor)), ], ), ); @@ -129,3 +133,14 @@ class ItemDetailGrid extends StatelessWidget { ); } } + +Widget getStringFromJSON(String jsonString) { + var body = json.decode(jsonString); + ITGWorkListTableModel itgWorkListTableModel = ITGWorkListTableModel(); + if (body.length != 0) { + itgWorkListTableModel = ITGWorkListTableModel.fromJson(body[0][0]); + return Flexible(child: (itgWorkListTableModel.textvalue).toString().toText12Auto(color: MyColors.normalTextColor)); + } else { + return Flexible(child: ("-").toString().toText12Auto(color: MyColors.normalTextColor)); + } +} From e4737f403ecd03e93bd3d4ae0f183057af1866ad Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 1 Nov 2022 09:36:08 +0300 Subject: [PATCH 18/31] attendance file fixed --- lib/ui/landing/today_attendance_screen2.dart | 214 +++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 lib/ui/landing/today_attendance_screen2.dart diff --git a/lib/ui/landing/today_attendance_screen2.dart b/lib/ui/landing/today_attendance_screen2.dart new file mode 100644 index 0000000..17bb03a --- /dev/null +++ b/lib/ui/landing/today_attendance_screen2.dart @@ -0,0 +1,214 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:easy_localization/src/public_ext.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.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/provider/dashboard_provider_model.dart'; +import 'package:mohem_flutter_app/widgets/circular_step_progress_bar.dart'; +import 'package:mohem_flutter_app/widgets/mark_attendance_widget.dart'; +import 'package:nfc_manager/nfc_manager.dart'; +import 'package:provider/provider.dart'; +import 'package:wifi_iot/wifi_iot.dart'; + +class TodayAttendanceScreen2 extends StatefulWidget { + TodayAttendanceScreen2({Key? key}) : super(key: key); + + @override + _TodayAttendanceScreenState createState() { + return _TodayAttendanceScreenState(); + } +} + +class _TodayAttendanceScreenState extends State { + ValueNotifier result = ValueNotifier(null); + late DashboardProviderModel data; + + @override + void initState() { + super.initState(); + data = Provider.of(context, listen: false); + } + + @override + void dispose() { + super.dispose(); + // Stop Session + NfcManager.instance.stopSession(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: MyColors.backgroundBlackColor, + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios, color: Colors.white), + onPressed: () => Navigator.pop(context), + ), + actions: [ + IconButton( + onPressed: () { + data.fetchAttendanceTracking(context); + }, + icon: const Icon( + Icons.ac_unit, + color: Colors.white, + ), + ) + ], + ), + backgroundColor: MyColors.backgroundBlackColor, + body: Consumer( + builder: (context, model, child) { + return (model.isAttendanceTrackingLoading + ? Center(child: CircularProgressIndicator()) + : Column( + children: [ + Container( + width: double.infinity, + color: MyColors.backgroundBlackColor, + padding: EdgeInsets.only(top: 1, left: 21, right: 21, bottom: 21), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + DateUtil.getWeekDayMonthDayYearDateFormatted(DateTime.now(), "en").toText24(isBold: true, color: Colors.white), + LocaleKeys.timeLeftToday.tr().toText16(color: Color(0xffACACAC)), + Center( + child: Container( + margin: EdgeInsets.only(left: 21, right: 21, top: 18), + child: AspectRatio( + aspectRatio: 1, + child: CircularStepProgressBar( + totalSteps: 16 * 4, + currentStep: (model.progress * 100).toInt(), + selectedColor: MyColors.gradiantEndColor, + unselectedColor: MyColors.grey70Color, + child: Center( + child: Padding( + padding: const EdgeInsets.all(21.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: 1, + child: CountdownTimer( + endTime: model.endTime, + widgetBuilder: (context, v) { + return AutoSizeText( + getValue(v?.hours) + " : " + getValue(v?.min) + " : " + getValue(v?.sec), + maxLines: 1, + style: const TextStyle(color: Colors.white, fontSize: 42, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), + ); + }, + onEnd: null, + endWidget: "00:00:00".toTextAuto(color: Colors.white, isBold: true, fontSize: 30, letterSpacing: -1.92), + textStyle: const TextStyle(color: Colors.white, fontSize: 30, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1), + ).center, + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + LocaleKeys.shiftTime.tr().tr().toTextAuto(color: MyColors.greyACColor, fontSize: 18, maxLine: 1).paddingOnly(left: 21,right: 21), + (model.attendanceTracking!.pShtName ?? "00:00:00").toString().toTextAuto(color: Colors.white, isBold: true, fontSize: 26, maxLine: 1), + ], + ), + ) + ], + ), + ), + ), + ), + ), + ), + ).expanded, + ], + ), + ).toExpanded(flex: 2), + Center( + child: Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), + gradient: LinearGradient( + transform: GradientRotation(.64), + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ], + ), + ), + child: Column( + children: [ + Container( + padding: const EdgeInsets.only(left: 21, right: 21, top: 21, bottom: 16), + decoration: const BoxDecoration( + borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), + gradient: LinearGradient(transform: GradientRotation(.64), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ + MyColors.gradiantEndColor, + MyColors.gradiantStartColor, + ]), + ), + child: Column( + children: [ + Row( + children: [ + commonStatusView(LocaleKeys.checkIn.tr(), (model.attendanceTracking!.pSwipeIn) ?? "- - : - -"), + commonStatusView(LocaleKeys.checkOut.tr(), (model.attendanceTracking!.pSwipeOut) ?? "- - : - -") + ], + ), + 21.height, + Row( + children: [ + commonStatusView(LocaleKeys.lateIn.tr(), (model.attendanceTracking!.pLateInHours) ?? "- - : - -"), + commonStatusView(LocaleKeys.regular.tr(), (model.attendanceTracking!.pScheduledHours) ?? "- - : - -") + ], + ), + ], + ), + ), //.expanded, + + MarkAttendanceWidget(model, topPadding: 21), + ], + ), + ), + ) + ], + )) + .animatedSwither(); + }, + ), + ); + } + + String getValue(int? v) { + if (v == null) { + return "00"; + } else if (v.toString().length == 1) { + return "0" + v.toString(); + } else { + return v.toString(); + } + } + + Future closeWifiRequest() async { + await WiFiForIoTPlugin.forceWifiUsage(false); + bool v = await WiFiForIoTPlugin.disconnect(); + return v; + } + + Widget commonStatusView(String title, String time) => Expanded( + child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ + title.toText12(color: Colors.white.withOpacity(.69)), + time.toText22(color: Colors.white, isBold: true), + ]), + ); +} From 7408e242457f04d76853c4d1436f40115f1aac33 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 1 Nov 2022 11:35:18 +0300 Subject: [PATCH 19/31] Chat Delivered&Seen Event Added. --- lib/api/chat/chat_provider_model.dart | 42 ++++++++++++++++++++------- lib/classes/consts.dart | 4 +-- lib/ui/chat/chat_detailed_screen.dart | 1 + lib/ui/chat/chat_home.dart | 2 +- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/lib/api/chat/chat_provider_model.dart b/lib/api/chat/chat_provider_model.dart index d5abd79..bcb748c 100644 --- a/lib/api/chat/chat_provider_model.dart +++ b/lib/api/chat/chat_provider_model.dart @@ -91,18 +91,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { .build(); hubConnection.onclose( ({Exception? error}) { - logger.d(error); + // logger.d(error); }, ); hubConnection.onreconnecting( ({Exception? error}) { - logger.d(error); - logger.d("Reconnecting"); + // logger.d(error); + // logger.d("Reconnecting"); }, ); hubConnection.onreconnected( ({String? connectionId}) { - logger.d("Reconnected"); + // logger.d("Reconnected"); }, ); if (hubConnection.state != HubConnectionState.Connected) { @@ -110,23 +110,39 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - // hubConnection.on("OnUserTypingAsync", onUserTyping); + hubConnection.on("OnUserTypingAsync", onUserTyping); // hubConnection.on("OnUserCountAsync", userCountAsync); // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); // hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); + hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); } else { hubConnection.on("OnUpdateUserStatusAsync", changeStatus); hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); - // hubConnection.on("OnUserTypingAsync", onUserTyping); + hubConnection.on("OnUserTypingAsync", onUserTyping); // hubConnection.on("OnUserCountAsync", userCountAsync); // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); // hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); + hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus); } isLoading = false; notifyListeners(); } + void updateUserChatStatus(List? args) { + dynamic items = args!.toList(); + for (dynamic cItem in items[0]) { + for (SingleUserChatModel chat in userChatHistory) { + if (chat.userChatHistoryId.toString() == cItem["userChatHistoryId"].toString()) { + logger.d(jsonEncode(chat)); + chat.isSeen = cItem["isSeen"]; + chat.isDelivered = cItem["isDelivered"]; + notifyListeners(); + } + } + } + } + void userCountAsync(List? args) { List items = args!.toList(); print("---------------------------------User Count Async -------------------------------------"); @@ -166,7 +182,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void changeStatus(List? args) { // print("================= Status Online // Offline ===================="); List items = args!.toList(); - logger.d(items); + // logger.d(items); for (ChatUser user in searchedChats!) { if (user.id == items.first["id"]) { user.userStatus = items.first["userStatus"]; @@ -192,9 +208,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future onMsgReceived(List? parameters) async { List data = []; + List temp = []; for (dynamic msg in parameters!) { data = getSingleUserChatModel(jsonEncode(msg)); - logger.d(msg); + temp = getSingleUserChatModel(jsonEncode(msg)); + data.first.targetUserId = temp.first.currentUserId; + data.first.targetUserName = temp.first.currentUserName; + data.first.currentUserId = temp.first.targetUserId; + data.first.currentUserName = temp.first.targetUserName; } userChatHistory.add(data.first); notifyListeners(); @@ -207,11 +228,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUser user in searchedChats!) { if (user.id == parameters![1] && parameters[0] == true) { user.isTyping = parameters[0] as bool?; - } else { + Future.delayed( - const Duration(milliseconds: 500), + const Duration(seconds: 2), () { user.isTyping = false; + notifyListeners(); }, ); } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index e82c30a..3fd992f 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server - static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server - // static String baseUrl = "https://hmgwebservices.com"; // Live server + //static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server + static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 1a9cf7d..5f2fa97 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -43,6 +43,7 @@ class ChatDetailScreen extends StatelessWidget { itemCount: m.userChatHistory.length, padding: const EdgeInsets.symmetric(vertical: 10), itemBuilder: (BuildContext context, int i) { + i == 0 ? m.logger.d(m.userChatHistory.length) : ""; return ChatBubble( text: m.userChatHistory[i].contant.toString(), isSeen: m.userChatHistory[i].isSeen == true ? true : false, diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 5d6d065..b8696ae 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -110,7 +110,7 @@ class _ChatHomeScreenState extends State { ], ), title: (m.searchedChats![index].userName ?? "").toText14(color: MyColors.darkTextColor), - subtitle: (m.searchedChats![index].isTyping == true ? "Something is Typing" : "Last message text").toText11(color: MyColors.normalTextColor), + subtitle: (m.searchedChats![index].isTyping == true ? "Typing ..." : "").toText11(color: MyColors.normalTextColor), trailing: ("Today").toText10(color: MyColors.lightTextColor), minVerticalPadding: 0, onTap: () { From 96e1be782353ddce3c0bf35017fcee294e1d39d1 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 1 Nov 2022 11:50:51 +0300 Subject: [PATCH 20/31] Chat Delivered&Seen Event Added. --- lib/classes/consts.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 3fd992f..e82c30a 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server - //static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server - static String baseUrl = "https://hmgwebservices.com"; // Live server + static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server + // static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; From f0d2c78f8348affc00853be23f60977922f5a852 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 1 Nov 2022 14:51:51 +0300 Subject: [PATCH 21/31] Chat Delivered&Seen Event Added. --- lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index e7db4e2..1904a48 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -217,7 +217,7 @@ class _SearchEmployeeBottomSheetState extends State { ], ), title: (chatUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), - subtitle: (chatUsersList![index].isTyping == true ? "Something is Typing" : "Last message text").toText11(color: MyColors.normalTextColor), + // subtitle: (chatUsersList![index].isTyping == true ? "Something is Typing" : "Last message text").toText11(color: MyColors.normalTextColor), trailing: ("Today").toText10(color: MyColors.lightTextColor), minVerticalPadding: 0, onTap: () { From 77a56759dc3c4f6f1b484f1ecc442f78603d2637 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 1 Nov 2022 15:03:38 +0300 Subject: [PATCH 22/31] Chat Delivered&Seen Event Added. --- lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index 1904a48..16942c5 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -218,7 +218,7 @@ class _SearchEmployeeBottomSheetState extends State { ), title: (chatUsersList![index].userName ?? "").toText14(color: MyColors.darkTextColor), // subtitle: (chatUsersList![index].isTyping == true ? "Something is Typing" : "Last message text").toText11(color: MyColors.normalTextColor), - trailing: ("Today").toText10(color: MyColors.lightTextColor), + // trailing: ("Today").toText10(color: MyColors.lightTextColor), minVerticalPadding: 0, onTap: () { Navigator.pop(context); From f06238a93fdac1feee2c21d1a967136e405e973e Mon Sep 17 00:00:00 2001 From: devmirza121 Date: Wed, 2 Nov 2022 11:22:27 +0300 Subject: [PATCH 23/31] OTP dialog new design --- assets/icons/ic_alarm.png | Bin 0 -> 875 bytes assets/langs/ar-SA.json | 6 +- assets/langs/en-US.json | 6 +- lib/classes/colors.dart | 1 + lib/dialogs/otp_dialog.dart | 117 +++++++++------ lib/generated/codegen_loader.g.dart | 12 +- lib/generated/locale_keys.g.dart | 4 + lib/ui/login/forgot_password_screen.dart | 5 +- lib/ui/login/verify_last_login_screen.dart | 158 ++++++--------------- lib/ui/login/verify_login_screen.dart | 16 +-- 10 files changed, 153 insertions(+), 172 deletions(-) create mode 100644 assets/icons/ic_alarm.png diff --git a/assets/icons/ic_alarm.png b/assets/icons/ic_alarm.png new file mode 100644 index 0000000000000000000000000000000000000000..5bc71e7f23b3ba503f7432b873fc044249d98564 GIT binary patch literal 875 zcmV-x1C;!UP)nd8+uPmmo0$XWffoW{ zX5RO^+57fp7b1~JBoc}IuXF@lyB8R!{rw&&hqL0BeZV823M|%C1s(!>0{Zg8NnoC( z;Qwk4I1$X9WA+0TnuoXg0}KZ8=!|aQHLb&2O#!QeICaE%(ucRY5X7ki)&t+kUVtCK z#sGfRxkdKyR<{HARb>b1zWAD{3hegoT9FCzhqrp--L(=&kcYQA>e;)PZr~Mq1$YPa zcugSWEPCOs&UsBBU@b6L7ukPNEb1W<~lIn=F<5}HE+%tS1@b!0r;pm-j zp+mOP16Sb>C>yN+_kjDzj?NoN{n=s{vbNVqhwJ7aR-XHL&9fS(l?_feSfix8#wo4v zy}*pJxiZT?p#tzzd5vjcjYa{kD;u*K#oP>a0#_ZaA^x4m4{)eM4H?vAxV0I81W4R09%7TO?4RxJRRq~R?GfoE+HDy^Q@ zJhvq4>+=1WmZI__!vST?>GEu7BauiX5{X3GpTAzciiy*UBJThI002ovPDHLkV1h_x Bj9dT! literal 0 HcmV?d00001 diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index dcd03b5..27eccc8 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -493,6 +493,10 @@ "winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.", "fingersCrossed": "تشابك الاصابع!!!", "congrats": "مبروك !!!", - "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح." + "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح.", + "otp": "OTP", + "verification": "تَحَقّق", + "resend": "إعادة إرسال", + "codeExpire": "انتهت صلاحية رمز التحقق" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 503302b..64a7fed 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -493,5 +493,9 @@ "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", "fingersCrossed": "Fingers Crossed!!!", "congrats": "Congratulations!!!", - "allQuestionsCorrect": "You have answered all questions correct" + "allQuestionsCorrect": "You have answered all questions correct", + "otp": "OTP", + "verification": "Verification", + "resend": "Resend", + "codeExpire": "The verification code has been expired" } \ No newline at end of file diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart index e670bbc..ad91de7 100644 --- a/lib/classes/colors.dart +++ b/lib/classes/colors.dart @@ -29,6 +29,7 @@ class MyColors { static const Color darkWhiteColor = Color(0xffE0E0E0); static const Color redColor = Color(0xffD02127); static const Color pinkColor = Color(0xffEBA9A9); + static const Color pinkDarkColor = Color(0xffe3797d); static const Color yellowColor = Color(0xffF4E31C); static const Color orange = Color(0xFFCC9B14); static const Color yellowFavColor = Color(0xffEAC321); diff --git a/lib/dialogs/otp_dialog.dart b/lib/dialogs/otp_dialog.dart index 23c7c67..3952e70 100644 --- a/lib/dialogs/otp_dialog.dart +++ b/lib/dialogs/otp_dialog.dart @@ -7,7 +7,9 @@ import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/otp_widget.dart'; +import 'package:sizer/sizer.dart'; class OtpDialog { final int type; @@ -15,6 +17,7 @@ class OtpDialog { final Function(String) onSuccess; final Function onFailure; final BuildContext context; + final Function onResendCode; int remainingTime = 120; @@ -24,13 +27,7 @@ class OtpDialog { static bool? _loading; - OtpDialog( - this.context, - this.type, - this.mobileNo, - this.onSuccess, - this.onFailure, - ); + OtpDialog(this.context, this.type, this.mobileNo, this.onSuccess, this.onFailure, {required this.onResendCode}); GlobalKey? verifyAccountForm = GlobalKey(); @@ -69,7 +66,7 @@ class OtpDialog { // projectProvider = Provider.of(context); return Dialog( backgroundColor: Colors.white, - shape: const RoundedRectangleBorder(), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), insetPadding: const EdgeInsets.only(left: 21, right: 21), child: StatefulBuilder(builder: (context, setState) { if (displayTime == '') { @@ -77,37 +74,26 @@ class OtpDialog { } return Container( - padding: EdgeInsets.only(left: 21, right: 18, top: 39, bottom: 59), + padding: EdgeInsets.all(21), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SvgPicture.asset( - type == 1 - ? "assets/images/login/verify_sms.svg" - : type == 2 - ? "assets/images/login/verify_whatsapp.svg" - : type == 3 - ? "assets/images/login/verify_face.svg" - : 'assets/images/login/verify_thumb.svg', - height: 50, - width: 50, - ), - IconButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.close), - constraints: const BoxConstraints(), - onPressed: () { - stopTimer = true; - onFailure(); - }) - ], + SvgPicture.asset( + type == 1 + ? "assets/images/login/verify_sms.svg" + : type == 2 + ? "assets/images/login/verify_whatsapp.svg" + : type == 3 + ? "assets/images/login/verify_face.svg" + : 'assets/images/login/verify_thumb.svg', + height: 50, + width: 50, ), - 22.height, + 12.height, + LocaleKeys.otp.tr().toText14(), + LocaleKeys.verification.tr().toText24(isBold: true), + 6.height, (LocaleKeys.pleaseEnterTheVerificationCodeSentTo.tr() + ' xxxxxxxx' + mobileNo.toString().substring(mobileNo.toString().length - 3)).toText16(), 18.height, Directionality( @@ -132,18 +118,55 @@ class OtpDialog { ), ), ), - 30.height, - RichText( - text: TextSpan( - text: LocaleKeys.theVerificationCodeWillExpireIn.tr() + '\n', - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -0.48), - children: [ - TextSpan( - text: displayTime, - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.textMixColor, letterSpacing: -0.48), + 10.height, + stopTimer + ? Row( + children: [ + Expanded( + child: LocaleKeys.codeExpire.tr().toText16( + color: MyColors.redColor, + ), + ), + 12.width, + Image.asset( + "assets/icons/ic_alarm.png", + width: 20, + height: 20, + color: MyColors.redColor, + ), + ], + ) + : RichText( + text: TextSpan( + text: LocaleKeys.theVerificationCodeWillExpireIn.tr() + '\n', + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -0.48), + children: [ + TextSpan( + text: displayTime, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.textMixColor, letterSpacing: -0.48), + ), + ], + ), ), - ], - ), + 18.height, + DefaultButton( + stopTimer ? LocaleKeys.resend.tr() : LocaleKeys.cancel.tr(), + () async { + if (stopTimer) { + hideSMSBox(context); + onResendCode(); + } else { + stopTimer = true; + // onFailure(); + hideSMSBox(context); + } + }, + colors: stopTimer + ? null + : [ + MyColors.pinkDarkColor, + MyColors.pinkDarkColor, + ], ), ], ), @@ -208,7 +231,9 @@ class OtpDialog { if (remainingTime > 0) { startTimer(setState); } else { - Navigator.pop(context); + setState(() { + stopTimer = true; + }); } }); } diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 6b702f8..66e4f97 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -509,7 +509,11 @@ class CodegenLoader extends AssetLoader{ "winnerSelectedRandomly": "سيتم اختيار الفائز عشوائياً من بين التصفيات.", "fingersCrossed": "تشابك الاصابع!!!", "congrats": "مبروك !!!", - "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح." + "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح.", + "otp": "OTP", + "verification": "تَحَقّق", + "resend": "إعادة إرسال", + "codeExpire": "انتهت صلاحية رمز التحقق" }; static const Map en_US = { "mohemm": "Mohemm", @@ -1006,7 +1010,11 @@ static const Map en_US = { "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", "fingersCrossed": "Fingers Crossed!!!", "congrats": "Congratulations!!!", - "allQuestionsCorrect": "You have answered all questions correct" + "allQuestionsCorrect": "You have answered all questions correct", + "otp": "OTP", + "verification": "Verification", + "resend": "Resend", + "codeExpire": "The verification code has been expired" }; 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 0da7047..835157b 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -480,5 +480,9 @@ abstract class LocaleKeys { static const fingersCrossed = 'fingersCrossed'; static const congrats = 'congrats'; static const allQuestionsCorrect = 'allQuestionsCorrect'; + static const otp = 'otp'; + static const verification = 'verification'; + static const resend = 'resend'; + static const codeExpire = 'codeExpire'; } diff --git a/lib/ui/login/forgot_password_screen.dart b/lib/ui/login/forgot_password_screen.dart index f058d43..6c1868e 100644 --- a/lib/ui/login/forgot_password_screen.dart +++ b/lib/ui/login/forgot_password_screen.dart @@ -65,11 +65,14 @@ class _ForgotPasswordScreenState extends State { () => { Navigator.pop(context), }, + onResendCode: () { + performForgotPassword(); + }, ).displayDialog(context); } catch (ex) { print(ex); Utils.hideLoading(context); - Utils.handleException(ex, context, null); + Utils.handleException(ex, context, null); } } diff --git a/lib/ui/login/verify_last_login_screen.dart b/lib/ui/login/verify_last_login_screen.dart index 4d653ed..6e51e51 100644 --- a/lib/ui/login/verify_last_login_screen.dart +++ b/lib/ui/login/verify_last_login_screen.dart @@ -57,30 +57,21 @@ class _VerifyLastLoginScreenState extends State { @override Widget build(BuildContext context) { - mobileLoginInfoListModel ??= ModalRoute.of(context)!.settings.arguments - as GetMobileLoginInfoListModel; - String empName = AppState().isArabic(context) - ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! - : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; + mobileLoginInfoListModel ??= ModalRoute.of(context)!.settings.arguments as GetMobileLoginInfoListModel; + String empName = AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; return Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, automaticallyImplyLeading: false, title: (mobileLoginInfoListModel?.businessCardPrivilege ?? false) - ? LocaleKeys.viewBusinessCard - .tr() - .toText12(color: MyColors.textMixColor, isUnderLine: true) - .onPress(() { + ? LocaleKeys.viewBusinessCard.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { showMDialog(context, child: BusinessCardDialog()); }) : null, actions: [ Center( - child: LocaleKeys.employeeDigitalID - .tr() - .toText12(color: MyColors.textMixColor, isUnderLine: true) - .onPress(() { + child: LocaleKeys.employeeDigitalID.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { showMDialog(context, child: EmployeeDigitialIdDialog()); })), 21.width @@ -99,12 +90,9 @@ class _VerifyLastLoginScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.welcomeBack.tr().toText12(), - mobileLoginInfoListModel!.employeeName! - .toText24(isBold: true), + mobileLoginInfoListModel!.employeeName!.toText24(isBold: true), 10.height, - LocaleKeys.wouldYouLikeToLoginWithCurrentUsername - .tr() - .toText16(), + LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText16(), Container( height: 72, margin: const EdgeInsets.only(top: 23, bottom: 23), @@ -126,42 +114,26 @@ class _VerifyLastLoginScreenState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ LocaleKeys.lastLoginDetails.tr().toText16(), - DateUtil.formatDateToDate( - DateUtil.convertStringToDate( - mobileLoginInfoListModel!.editedOn!), - false) - .toText12(), + DateUtil.formatDateToDate(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn!), false).toText12(), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - LocaleKeys.verificationType - .tr() - .toText10(color: MyColors.grey57Color), - getVerificationType( - mobileLoginInfoListModel!.loginType!) - .toText12(), + LocaleKeys.verificationType.tr().toText10(color: MyColors.grey57Color), + getVerificationType(mobileLoginInfoListModel!.loginType!).toText12(), Expanded(child: SizedBox()), - DateUtil.formatDateToTime( - DateUtil.convertStringToDate( - mobileLoginInfoListModel!.editedOn!)) - .toText12(), + DateUtil.formatDateToTime(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn!)).toText12(), ], ) ], ), ), LocaleKeys.pleaseVerify.tr().toText16(), - if (isNeedVerifyWithFaceIDAndBiometrics) - LocaleKeys.pleaseVerifyForBio.tr().toText12(), + if (isNeedVerifyWithFaceIDAndBiometrics) LocaleKeys.pleaseVerifyForBio.tr().toText12(), GridView( - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 13, - mainAxisSpacing: 9), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.only(top: 9), shrinkWrap: true, @@ -214,9 +186,7 @@ class _VerifyLastLoginScreenState extends State { DefaultButton( LocaleKeys.useAnotherAccount.tr(), () { - Navigator.pushNamedAndRemoveUntil( - context, AppRoutes.login, (Route route) => false, - arguments: false); + Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: false); }, ).insideContainer, ], @@ -248,19 +218,11 @@ class _VerifyLastLoginScreenState extends State { } Future loginWithFaceIDAndBiometrics() async { - IOSAuthMessages iosStrings = const IOSAuthMessages( - cancelButton: 'cancel', - goToSettingsButton: 'settings', - goToSettingsDescription: 'Please set up your Touch ID.', - lockOut: 'Please reenable your Touch ID'); + IOSAuthMessages iosStrings = + const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); bool authenticated = false; try { - authenticated = await auth.authenticate( - localizedReason: 'Scan your fingerprint to authenticate', - useErrorDialogs: true, - stickyAuth: true, - biometricOnly: true, - iOSAuthStrings: iosStrings); + authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, biometricOnly: true, iOSAuthStrings: iosStrings); } on PlatformException catch (e) { print(e); Utils.hideLoading(context); @@ -269,11 +231,8 @@ class _VerifyLastLoginScreenState extends State { return authenticated; } - Widget _loginOptionButton( - String _title, String _icon, int _flag, int? _loginIndex) { - bool isDisable = ((_flag == 3 && - !checkBiometricIsAvailable(BiometricType.face)) || - (_flag == 4 && !checkBiometricIsAvailable(BiometricType.fingerprint))); + Widget _loginOptionButton(String _title, String _icon, int _flag, int? _loginIndex) { + bool isDisable = ((_flag == 3 && !checkBiometricIsAvailable(BiometricType.face)) || (_flag == 4 && !checkBiometricIsAvailable(BiometricType.fingerprint))); return InkWell( onTap: isDisable ? null @@ -284,21 +243,18 @@ class _VerifyLastLoginScreenState extends State { }); } else { if (_flag == 3 || _flag == 4) { - bool authenticateWithFaceAndTouchID = - await loginWithFaceIDAndBiometrics(); + bool authenticateWithFaceAndTouchID = await loginWithFaceIDAndBiometrics(); if (!authenticateWithFaceAndTouchID) { return; } else { - if (mobileLoginInfoListModel!.loginType == 3 || - mobileLoginInfoListModel!.loginType == 4) { + if (mobileLoginInfoListModel!.loginType == 3 || mobileLoginInfoListModel!.loginType == 4) { // bool authenticateWithFaceAndTouchID = await loginWithFaceIDAndBiometrics(); // if (!authenticateWithFaceAndTouchID) { // return; // } else { // performApiCall(_title, _icon, _flag, isDirectLogin: true); // } - performApiCall(_title, _icon, _flag, _flag, - isDirectLogin: true); + performApiCall(_title, _icon, _flag, _flag, isDirectLogin: true); } else { isNeedVerifyWithFaceIDAndBiometrics = true; selectedFlag = _flag; @@ -316,8 +272,7 @@ class _VerifyLastLoginScreenState extends State { } }, child: Container( - padding: - const EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 28), + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 28), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: isDisable ? Colors.grey.withOpacity(0.3) : Colors.white, @@ -343,23 +298,13 @@ class _VerifyLastLoginScreenState extends State { Widget getButton(int flag) { switch (flag) { case 1: - return _loginOptionButton(LocaleKeys.verifyThroughSMS.tr(), - 'assets/images/login/verify_sms.svg', flag, null); + return _loginOptionButton(LocaleKeys.verifyThroughSMS.tr(), 'assets/images/login/verify_sms.svg', flag, null); case 2: - return _loginOptionButton(LocaleKeys.verifyThroughWhatsapp.tr(), - 'assets/images/login/verify_whatsapp.svg', flag, null); + return _loginOptionButton(LocaleKeys.verifyThroughWhatsapp.tr(), 'assets/images/login/verify_whatsapp.svg', flag, null); case 3: - return _loginOptionButton( - LocaleKeys.verifyThroughFace.tr(), - 'assets/images/login/verify_face.svg', - flag, - BiometricType.face.index); + return _loginOptionButton(LocaleKeys.verifyThroughFace.tr(), 'assets/images/login/verify_face.svg', flag, BiometricType.face.index); case 4: - return _loginOptionButton( - LocaleKeys.verifyThroughFingerprint.tr(), - 'assets/images/login/verify_thumb.svg', - flag, - BiometricType.fingerprint.index); + return _loginOptionButton(LocaleKeys.verifyThroughFingerprint.tr(), 'assets/images/login/verify_thumb.svg', flag, BiometricType.fingerprint.index); default: return const SizedBox(); } @@ -376,9 +321,7 @@ class _VerifyLastLoginScreenState extends State { return isAvailable; } - Future performApiCall( - String _title, String _icon, int _flag, int sendVerificationFlat, - {bool isDirectLogin = false}) async { + Future performApiCall(String _title, String _icon, int _flag, int sendVerificationFlat, {bool isDirectLogin = false}) async { try { if (isDirectLogin) setState(() { @@ -387,16 +330,10 @@ class _VerifyLastLoginScreenState extends State { else Utils.showLoading(context); await LoginApiClient().checkMobileAppVersion(); - await LoginApiClient() - .memberLogin(AppState().getUserName!, AppState().password!); + await LoginApiClient().memberLogin(AppState().getUserName!, AppState().password!); if (!isDirectLogin) BasicMemberInformationModel? memberInformationModel = - await LoginApiClient() - .mohemmSendActivationCodeByOTPNotificationType( - 0, - AppState().memberLoginList?.pMOBILENUMBER, - sendVerificationFlat, - AppState().getUserName); + await LoginApiClient().mohemmSendActivationCodeByOTPNotificationType(0, AppState().memberLoginList?.pMOBILENUMBER, sendVerificationFlat, AppState().getUserName); if (isDirectLogin) performDirectApiCall(_title, _icon, _flag, ""); if (!isDirectLogin) Utils.hideLoading(context); if (!isDirectLogin) @@ -411,6 +348,9 @@ class _VerifyLastLoginScreenState extends State { () => { Navigator.pop(context), }, + onResendCode: () { + performApiCall(_title, _icon, _flag, sendVerificationFlat, isDirectLogin: isDirectLogin); + }, ).displayDialog(context); } catch (ex) { Utils.hideLoading(context); @@ -418,34 +358,26 @@ class _VerifyLastLoginScreenState extends State { } } - Future performDirectApiCall( - String _title, String _icon, int _flag, String value, - {bool isDirectLogin = false}) async { + Future performDirectApiCall(String _title, String _icon, int _flag, String value, {bool isDirectLogin = false}) async { try { - GenericResponseModel? genericResponseModel = await LoginApiClient() - .checkActivationCode(false, AppState().memberLoginList?.pMOBILENUMBER, - value, AppState().getUserName); - GenericResponseModel? genericResponseModel1 = await LoginApiClient() - .insertMobileLoginInfoNEW( - AppState().memberLoginList?.pEMAILADDRESS ?? "", - genericResponseModel?.pSESSIONID ?? 0, - genericResponseModel?.memberInformationList![0].eMPLOYEENAME ?? - "", - _flag, - AppState().memberLoginList?.pMOBILENUMBER ?? "", - AppState().getUserName!, - mobileLoginInfoListModel!.deviceToken!, - Platform.isAndroid ? "android" : "ios"); - AppState().setMemberInformationListModel = - genericResponseModel!.memberInformationList?.first; + GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(false, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); + GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW( + AppState().memberLoginList?.pEMAILADDRESS ?? "", + genericResponseModel?.pSESSIONID ?? 0, + genericResponseModel?.memberInformationList![0].eMPLOYEENAME ?? "", + _flag, + AppState().memberLoginList?.pMOBILENUMBER ?? "", + AppState().getUserName!, + mobileLoginInfoListModel!.deviceToken!, + Platform.isAndroid ? "android" : "ios"); + AppState().setMemberInformationListModel = genericResponseModel!.memberInformationList?.first; if (genericResponseModel?.errorMessage != null) { Utils.showToast(genericResponseModel?.errorMessage ?? ""); // Navigator.pop(context); } Utils.hideLoading(context); Navigator.pop(context); - Navigator.pushNamedAndRemoveUntil( - context, AppRoutes.dashboard, (Route route) => false); + Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboard, (Route route) => false); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); diff --git a/lib/ui/login/verify_login_screen.dart b/lib/ui/login/verify_login_screen.dart index f31311f..8dba16c 100644 --- a/lib/ui/login/verify_login_screen.dart +++ b/lib/ui/login/verify_login_screen.dart @@ -511,7 +511,6 @@ class _VerifyLoginScreenState extends State { // } // - Future loginWithFaceIDAndBiometrics() async { IOSAuthMessages iosStrings = const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); @@ -550,9 +549,9 @@ class _VerifyLoginScreenState extends State { } } else { if (isNeedVerifyWithFaceIDAndBiometrics) - performApiCall(_title, _icon, selectedFlag,_flag); + performApiCall(_title, _icon, selectedFlag, _flag); else - performApiCall(_title, _icon, _flag,_flag); + performApiCall(_title, _icon, _flag, _flag); } } }, @@ -606,13 +605,13 @@ class _VerifyLoginScreenState extends State { return isAvailable; } - Future performApiCall(String _title, String _icon, int _flag,int sendVerificationFlat) async { + Future performApiCall(String _title, String _icon, int _flag, int sendVerificationFlat) async { try { Utils.showLoading(context); await LoginApiClient().checkMobileAppVersion(); await LoginApiClient().memberLogin(AppState().getUserName!, AppState().password!); - BasicMemberInformationModel? memberInformationModel = await LoginApiClient() - .mohemmSendActivationCodeByOTPNotificationType(0, AppState().memberLoginList?.pMOBILENUMBER, sendVerificationFlat, AppState().getUserName); + BasicMemberInformationModel? memberInformationModel = + await LoginApiClient().mohemmSendActivationCodeByOTPNotificationType(0, AppState().memberLoginList?.pMOBILENUMBER, sendVerificationFlat, AppState().getUserName); Utils.hideLoading(context); OtpDialog( context, @@ -633,8 +632,6 @@ class _VerifyLoginScreenState extends State { Platform.isAndroid ? "android" : "ios"); if (genericResponseModel?.errorMessage != null) { Utils.showToast(genericResponseModel?.errorMessage ?? ""); - - } else { AppState().setPrivilegeListModel = genericResponseModel!.privilegeList ?? []; AppState().setMemberInformationListModel = genericResponseModel.memberInformationList?.first; @@ -662,6 +659,9 @@ class _VerifyLoginScreenState extends State { () => { Navigator.pop(context), }, + onResendCode: () { + performApiCall(_title, _icon, _flag, sendVerificationFlat); + }, ).displayDialog(context); } catch (ex) { Utils.hideLoading(context); From 5880e227716e19a8e79bbcf5bf83a9e42bf12ca3 Mon Sep 17 00:00:00 2001 From: "mirza.shafique" Date: Wed, 2 Nov 2022 14:34:55 +0300 Subject: [PATCH 24/31] merge fix --- assets/langs/ar-SA.json | 4 +--- assets/langs/en-US.json | 3 +-- lib/generated/codegen_loader.g.dart | 8 +++++--- lib/generated/locale_keys.g.dart | 1 + 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index bf3c1a8..f72ea36 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -497,8 +497,6 @@ "otp": "OTP", "verification": "تَحَقّق", "resend": "إعادة إرسال", - "codeExpire": "انتهت صلاحية رمز التحقق" - - "allQuestionsCorrect": "لقد أجبت على جميع الأسئلة بشكل صحيح.", + "codeExpire": "انتهت صلاحية رمز التحقق", "typeheretoreply": "اكتب هنا للرد" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 0543013..896a365 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -493,11 +493,10 @@ "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", "fingersCrossed": "Fingers Crossed!!!", "congrats": "Congratulations!!!", - "allQuestionsCorrect": "You have answered all questions correct", "otp": "OTP", "verification": "Verification", "resend": "Resend", - "codeExpire": "The verification code has been expired" + "codeExpire": "The verification code has been expired", "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply" } \ No newline at end of file diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 66e4f97..83910f7 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -513,7 +513,8 @@ class CodegenLoader extends AssetLoader{ "otp": "OTP", "verification": "تَحَقّق", "resend": "إعادة إرسال", - "codeExpire": "انتهت صلاحية رمز التحقق" + "codeExpire": "انتهت صلاحية رمز التحقق", + "typeheretoreply": "اكتب هنا للرد" }; static const Map en_US = { "mohemm": "Mohemm", @@ -1010,11 +1011,12 @@ static const Map en_US = { "winnerSelectedRandomly": "The winner will be selected randomly among the qualifiers.", "fingersCrossed": "Fingers Crossed!!!", "congrats": "Congratulations!!!", - "allQuestionsCorrect": "You have answered all questions correct", "otp": "OTP", "verification": "Verification", "resend": "Resend", - "codeExpire": "The verification code has been expired" + "codeExpire": "The verification code has been expired", + "allQuestionsCorrect": "You have answered all questions correct", + "typeheretoreply": "Type here to reply" }; 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 835157b..f52bb89 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -484,5 +484,6 @@ abstract class LocaleKeys { static const verification = 'verification'; static const resend = 'resend'; static const codeExpire = 'codeExpire'; + static const typeheretoreply = 'typeheretoreply'; } From 7cc110b9a1092a5d23809b4106e32b711b55a372 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 2 Nov 2022 15:03:01 +0300 Subject: [PATCH 25/31] JIRA fixes --- assets/langs/en-US.json | 4 +-- assets/lottie/loading.json | 2 +- lib/classes/consts.dart | 4 +-- lib/generated/codegen_loader.g.dart | 4 +-- .../add_leave_balance_screen.dart | 33 ++++++++++++------- lib/ui/login/login_screen.dart | 4 +-- .../dynamic_screens/dynamic_input_screen.dart | 2 +- .../dynamic_input_address_screen.dart | 4 +-- lib/ui/profile/widgets/profile_panel.dart | 20 ++++++----- lib/ui/work_list/itg_detail_screen.dart | 11 +++++-- lib/ui/work_list/sheets/delegate_sheet.dart | 15 ++++++--- .../sheets/selected_itg_item_sheet.dart | 4 +-- lib/ui/work_list/worklist_detail_screen.dart | 16 +++++---- .../dialogs/accept_reject_input_dialog.dart | 9 +++-- lib/widgets/item_detail_view_widget.dart | 8 +++-- 15 files changed, 88 insertions(+), 52 deletions(-) diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 503302b..a589a82 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -284,7 +284,7 @@ "add": "Add", "edit": "Edit", "myProfile": "My Profile", - "mowadhafhi": "Mowadhafhi", + "mowadhafhi": "Mowadhafi", "searchAnnouncements": "Search Announcements", "announcements": "Announcements", "swipeRequest": "Swipe Request", @@ -296,7 +296,7 @@ "relatedTopic": "Related Topic", "selectTopic": "Select Topic", "supportingDocument": "Supporting Document", - "mowadhafhiRequest": "Mowadhafhi Request", + "mowadhafhiRequest": "Mowadhafi Request", "ticketReference": "Ticket Reference", "section": "Section", "topic": "Topic", diff --git a/assets/lottie/loading.json b/assets/lottie/loading.json index 8190459..ea7bff3 100644 --- a/assets/lottie/loading.json +++ b/assets/lottie/loading.json @@ -1 +1 @@ -{"v":"5.8.1","fr":30,"ip":0,"op":60,"w":300,"h":300,"nm":"loading_6","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[360]}],"ix":10},"p":{"a":0,"k":[150.00000000000003,150.00000000000003,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[30.000000000000004,30.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.12941176470588237,0.7411764705882353,0.7764705882352941,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":60,"s":[99]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[1]},{"t":50,"s":[100]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[3]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":30,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150.00000000000003,150.00000000000003,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[30.000000000000004,30.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.7450980392156863,0.9254901960784314,0.9372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]} \ No newline at end of file +{"v":"5.8.1","fr":30,"ip":0,"op":60,"w":100,"h":100,"nm":"loading_6","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[360]}],"ix":10},"p":{"a":0,"k":[50.00000000000002,50.00000000000002,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10.000000000000004,10.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.12941176470588237,0.7411764705882353,0.7764705882352941,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":60,"s":[99]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[1]},{"t":50,"s":[100]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[3]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":30,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50.00000000000002,50.00000000000002,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10.000000000000004,10.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.7450980392156863,0.9254901960784314,0.9372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index e82c30a..eea2481 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -1,7 +1,7 @@ class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server - static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server - // static String baseUrl = "https://hmgwebservices.com"; // Live server + // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server + static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 6b702f8..8754d9b 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -797,7 +797,7 @@ static const Map en_US = { "add": "Add", "edit": "Edit", "myProfile": "My Profile", - "mowadhafhi": "Mowadhafhi", + "mowadhafhi": "Mowadhafi", "searchAnnouncements": "Search Announcements", "announcements": "Announcements", "swipeRequest": "Swipe Request", @@ -809,7 +809,7 @@ static const Map en_US = { "relatedTopic": "Related Topic", "selectTopic": "Select Topic", "supportingDocument": "Supporting Document", - "mowadhafhiRequest": "Mowadhafhi Request", + "mowadhafhiRequest": "Mowadhafi Request", "ticketReference": "Ticket Reference", "section": "Section", "topic": "Topic", diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index 864a507..85337aa 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -92,7 +92,7 @@ class _AddLeaveBalanceScreenState extends State { } void validateAbsenceTransaction() async { - // try { + try { Utils.showLoading(context); Map dffDataMap = {}; for (int i = 1; i <= 20; i++) { @@ -100,7 +100,8 @@ class _AddLeaveBalanceScreenState extends State { for (int dffIndex = 0; dffIndex < getabsenceDffStructureList.length; dffIndex++) { if ("ATTRIBUTE$i" == getabsenceDffStructureList[dffIndex].aPPLICATIONCOLUMNNAME) { if (getabsenceDffStructureList[dffIndex].fORMATTYPE == "X") { - dffDataMap["P_ATTRIBUTE$i"] = getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME != null ? Utils.formatDate(getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME!) : ""; + dffDataMap["P_ATTRIBUTE$i"] = + getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME != null ? Utils.formatDate(getabsenceDffStructureList[dffIndex].eSERVICESDV!.pIDCOLUMNNAME!) : ""; } else { dffDataMap["P_ATTRIBUTE$i"] = getabsenceDffStructureList[dffIndex].eSERVICESDV?.pIDCOLUMNNAME; } @@ -108,9 +109,17 @@ class _AddLeaveBalanceScreenState extends State { } } } - await LeaveBalanceApiClient().validateAbsenceTransaction(selectedAbsenceType!.dESCFLEXCONTEXTCODE!, "HR_LOA_SS", selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, - selectedReplacementEmployee != null ? selectedReplacementEmployee!.userName! : "", DateUtil.getFormattedDate(startDateTime!, "MM/dd/yyyy"), DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), -999, dffDataMap, - comments: comment); + await LeaveBalanceApiClient() + .validateAbsenceTransaction( + selectedAbsenceType!.dESCFLEXCONTEXTCODE!, + "HR_LOA_SS", + selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, + selectedReplacementEmployee != null ? selectedReplacementEmployee!.userName! : "", + DateUtil.getFormattedDate(startDateTime!, "MM/dd/yyyy"), + DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), + -999, + dffDataMap, + comments: comment); SumbitAbsenceTransactionList submit = await LeaveBalanceApiClient().submitAbsenceTransaction( selectedAbsenceType!.dESCFLEXCONTEXTCODE!, @@ -126,13 +135,13 @@ class _AddLeaveBalanceScreenState extends State { Utils.hideLoading(context); await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submit.pTRANSACTIONID!, "", "add_leave_balance")); - // Utils.showLoading(context); + Utils.showLoading(context); await LeaveBalanceApiClient().cancelHrTransaction(submit.pTRANSACTIONID!); - // Utils.hideLoading(context); - // } catch (ex) { - // Utils.hideLoading(context); - // Utils.handleException(ex, context, null); - // } + Utils.hideLoading(context); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } } @override @@ -221,7 +230,7 @@ class _AddLeaveBalanceScreenState extends State { onTap: () { showMyBottomSheet( context, - callBackFunc: (){}, + callBackFunc: () {}, child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 0c4e268..20fa8bc 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -145,8 +145,8 @@ class _LoginScreenState extends State { // username.text = "15153"; // Tamer User // password.text = "Abcd@12345"; - username.text = "210038"; // Hashim User - password.text = "123"; + // username.text = "206535"; // Hashim User + // password.text = "Namira786"; } if (isAppOpenBySystem!) checkFirebaseToken(); } diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index 0a6c9d4..519bb6c 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -448,7 +448,7 @@ class _DynamicInputScreenState extends State { return DynamicTextFieldWidget( (model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""), model.eSERVICESDV?.pIDCOLUMNNAME ?? "", - isReadOnly: model.rEADONLY == "Y", + // isReadOnly: model.rEADONLY == "Y", isInputTypeNum: true, onChange: (text) { model.fieldAnswer = text; diff --git a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart index cc8e861..6933a28 100644 --- a/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart +++ b/lib/ui/profile/dynamic_screens/dynamic_input_address_screen.dart @@ -269,13 +269,13 @@ class _DynamicInputScreenState extends State { if (tempVar.isNotEmpty) { DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar); - tempVar = DateFormat('dd/MMM/yyy').format(date); + tempVar = DateFormat('dd-MMM-yyy').format(date); if (e.aPPLICATIONCOLUMNNAME == null) { effectiveDate = tempVar; } } } else if (e.eSERVICESVS?.isNotEmpty ?? false) { - tempVar = e.getEmployeeAddressList!.vARCHAR2VALUE!; + e.getEmployeeAddressList!.vARCHAR2VALUE != null ? tempVar = e.getEmployeeAddressList!.vARCHAR2VALUE! : tempVar = ""; if (e.aPPLICATIONCOLUMNNAME == null) { countryCode = tempVar; } diff --git a/lib/ui/profile/widgets/profile_panel.dart b/lib/ui/profile/widgets/profile_panel.dart index 5018171..440fbb3 100644 --- a/lib/ui/profile/widgets/profile_panel.dart +++ b/lib/ui/profile/widgets/profile_panel.dart @@ -44,12 +44,16 @@ class ProfilePanel extends StatelessWidget { Widget profileImage() => memberInformationList.eMPLOYEEIMAGE == null ? SvgPicture.asset( - "assets/images/user.svg", - height: 68, - width: 68,) - : CircleAvatar( - radius: 68, - backgroundImage: MemoryImage(Utils.dataFromBase64String(memberInformationList.eMPLOYEEIMAGE!)), - backgroundColor: Colors.black, - ); + "assets/images/user.svg", + height: 68, + width: 68, + ) + : ClipOval( + child: Image.memory( + Utils.dataFromBase64String(memberInformationList.eMPLOYEEIMAGE!), + width: 75, + height: 75, + fit: BoxFit.fill, + ), + ); } diff --git a/lib/ui/work_list/itg_detail_screen.dart b/lib/ui/work_list/itg_detail_screen.dart index 0f45648..84bd9bd 100644 --- a/lib/ui/work_list/itg_detail_screen.dart +++ b/lib/ui/work_list/itg_detail_screen.dart @@ -66,7 +66,9 @@ class _ItgDetailScreenState extends State { isRejectAvailable = itgRequest!.allowedActions!.any((element) => element.action == "Reject"); } Utils.hideLoading(context); - setState(() {}); + setState(() { + controller.jumpToPage(0); + }); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); @@ -264,12 +266,12 @@ class _ItgDetailScreenState extends State { switch (action.action) { case "Delegate": showMyBottomSheet(context, callBackFunc: reloadITG, - child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [])); + child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [], callBackFunc: reloadITG,)); break; case "RequestInformation": showMyBottomSheet(context, callBackFunc: reloadITG, - child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [])); + child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: action.action!, notificationID: null, actionHistoryList: null, wFHistory: itgRequest?.wFHistory ?? [], callBackFunc: reloadITG,)); break; case "RFC": @@ -279,6 +281,9 @@ class _ItgDetailScreenState extends State { // do something else break; } + setState(() { + showFabOptions = false; + }); } Widget myTab(String title, int index) { diff --git a/lib/ui/work_list/sheets/delegate_sheet.dart b/lib/ui/work_list/sheets/delegate_sheet.dart index 28a90e6..bd3b010 100644 --- a/lib/ui/work_list/sheets/delegate_sheet.dart +++ b/lib/ui/work_list/sheets/delegate_sheet.dart @@ -28,8 +28,9 @@ class DelegateSheet extends StatefulWidget { String title, apiMode; List? actionHistoryList; List? wFHistory; + VoidCallback callBackFunc; - DelegateSheet({required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, this.wFHistory}); + DelegateSheet({required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, this.wFHistory, required this.callBackFunc}); @override State createState() => _DelegateSheetState(); @@ -392,8 +393,9 @@ class _DelegateSheetState extends State { Widget showItem(GetActionHistoryList actionHistory) { return InkWell( onTap: () { + Navigator.pop(context); showMyBottomSheet(context, - callBackFunc: (){}, + callBackFunc: widget.callBackFunc, child: SelectedItemSheet( "Comment", apiMode: widget.apiMode, @@ -438,8 +440,9 @@ class _DelegateSheetState extends State { Widget showItgItem(WFHistory wfHistory) { return InkWell( onTap: () { + Navigator.pop(context); showMyBottomSheet(context, - callBackFunc: (){}, + callBackFunc: widget.callBackFunc, child: SelectedItgItemSheet( "Comment", apiMode: widget.apiMode, @@ -463,8 +466,9 @@ class _DelegateSheetState extends State { Widget showFavUserItem(GetFavoriteReplacements actionHistory) { return InkWell( onTap: () { + Navigator.pop(context); showMyBottomSheet(context, - callBackFunc: (){}, + callBackFunc: widget.callBackFunc, child: SelectedItemSheet( "Comment", apiMode: widget.apiMode, @@ -509,8 +513,9 @@ class _DelegateSheetState extends State { Widget showInputUserItem(ReplacementList actionHistory) { return InkWell( onTap: () { + Navigator.pop(context); showMyBottomSheet(context, - callBackFunc: (){}, + callBackFunc: widget.callBackFunc, child: SelectedItemSheet( LocaleKeys.comments.tr(), apiMode: widget.apiMode, diff --git a/lib/ui/work_list/sheets/selected_itg_item_sheet.dart b/lib/ui/work_list/sheets/selected_itg_item_sheet.dart index 7381d59..f44ca04 100644 --- a/lib/ui/work_list/sheets/selected_itg_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_itg_item_sheet.dart @@ -128,8 +128,8 @@ class SelectedItgItemSheet extends StatelessWidget { .informationITGRequest(requestDetails.requestType!, requestDetails.iD!, requestDetails.itemID!, AppState().memberInformationList?.eMPLOYEENUMBER ?? "", wfHistory.employeeID!, comment); } Utils.hideLoading(context); - Navigator.pop(context); - Navigator.pop(context); + // Navigator.pop(context); + // Navigator.pop(context); Navigator.pop(context, "delegate_reload"); } catch (ex) { Utils.hideLoading(context); diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index ec02631..0e769e7 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -388,20 +388,20 @@ class _WorkListDetailScreenState extends State { case "DELEGATE": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: LocaleKeys.delegate.tr(), apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "REQUEST_INFO": // do something else showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: LocaleKeys.request_info.tr(), apiMode: "REQUEST_INFO", notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "TRANSFER_INFO": // do something else showMyBottomSheet(context, callBackFunc: reloadWorkList, child: - DelegateSheet(title: notificationButton.bUTTONLABEL!, apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + DelegateSheet(title: notificationButton.bUTTONLABEL!, apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "ANSWER_INFO": performAction(notificationButton.bUTTONACTION!, title: notificationButton.bUTTONLABEL); @@ -417,12 +417,12 @@ class _WorkListDetailScreenState extends State { case "APPROVE_AND_FORWARD": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: "Approve and Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: "Approve and Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "FORWARD": showMyBottomSheet(context, callBackFunc: reloadWorkList, - child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList)); + child: DelegateSheet(title: "Forward", apiMode: notificationButton.bUTTONACTION!, notificationID: workListData!.nOTIFICATIONID, actionHistoryList: actionHistoryList, callBackFunc: reloadWorkList,)); break; case "REJECT": performNetworkCall(context, email: "", userId: ""); @@ -431,6 +431,9 @@ class _WorkListDetailScreenState extends State { Navigator.pop(context); break; } + setState(() { + showFabOptions = false; + }); } Future performNetworkCall(BuildContext context, {String? email, String? userId}) async { @@ -516,7 +519,6 @@ class _WorkListDetailScreenState extends State { } void performAction(String actionMode, {String? title}) { - TextEditingController textEditingController = TextEditingController(); showDialog( context: context, builder: (cxt) => AcceptRejectInputDialog( @@ -823,6 +825,8 @@ class _WorkListDetailScreenState extends State { void getActionHistory() async { try { + isActionHistoryLoaded = false; + actionHistoryList.clear(); // if (apiCallCount == 0) Utils.showLoading(context); // apiCallCount++; actionHistoryList = await WorkListApiClient().getActionHistory(workListData!.nOTIFICATIONID!); diff --git a/lib/widgets/dialogs/accept_reject_input_dialog.dart b/lib/widgets/dialogs/accept_reject_input_dialog.dart index a0faf2c..db9c5d6 100644 --- a/lib/widgets/dialogs/accept_reject_input_dialog.dart +++ b/lib/widgets/dialogs/accept_reject_input_dialog.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; @@ -89,8 +90,12 @@ class AcceptRejectInputDialog extends StatelessWidget { DefaultButton( actionMode == "REJECTED" ? LocaleKeys.reject.tr() : LocaleKeys.ok.tr(), () { - Navigator.pop(context); - onTap(note); + if(note.isNotEmpty) { + Navigator.pop(context); + onTap(note); + } else { + Utils.showToast(LocaleKeys.pleaseEnterComments.tr()); + } }, colors: actionMode == "REJECTED" ? const [ diff --git a/lib/widgets/item_detail_view_widget.dart b/lib/widgets/item_detail_view_widget.dart index 05495e9..5148389 100644 --- a/lib/widgets/item_detail_view_widget.dart +++ b/lib/widgets/item_detail_view_widget.dart @@ -80,9 +80,13 @@ class ItemDetailViewGridItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Flexible(child: "$title:".toText12Auto(isBold: true, color: const Color(0xff2BB8A6))), + title != null ? Flexible(child: "$title:".toText12Auto(isBold: true, color: const Color(0xff2BB8A6))) : Container(), 4.width, - type!.toLowerCase() == "table" ? getStringFromJSON(value!) : Flexible(child: (value!.isEmpty ? "--" : value).toString().toText12Auto(color: MyColors.normalTextColor)), + type != null + ? type!.toLowerCase() == "table" + ? getStringFromJSON(value!) + : Flexible(child: (value!.isEmpty ? "--" : value).toString().toText12Auto(color: MyColors.normalTextColor)) + : Container(), ], ), ); From 09b2f8a23fe573f11835ae84349c4c3a21118a22 Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Wed, 2 Nov 2022 17:32:12 +0300 Subject: [PATCH 26/31] UI Fixes --- lib/ui/marathon/marathon_screen.dart | 7 +- lib/ui/marathon/widgets/countdown_timer.dart | 90 ++++++++++++++------ lib/ui/marathon/widgets/marathon_banner.dart | 69 +++++++++++++-- lib/ui/marathon/widgets/question_card.dart | 19 ++--- 4 files changed, 138 insertions(+), 47 deletions(-) diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index d548122..a02733f 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -16,6 +16,7 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/custom_status_widget.dart' import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:steps_indicator/steps_indicator.dart'; class MarathonScreen extends StatelessWidget { @@ -109,7 +110,7 @@ class _MarathonProgressContainerState extends State { Container( decoration: BoxDecoration( color: MyColors.greenColor, - borderRadius: BorderRadius.circular(12), + borderRadius: BorderRadius.circular(5), ), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8), child: "${widget.provider.currentQuestionNumber.toString()} / ${widget.provider.totalQuestions.toString()} ${LocaleKeys.question.tr()}".toText12(color: MyColors.white), @@ -120,7 +121,7 @@ class _MarathonProgressContainerState extends State { ), 15.height, StepsIndicator( - lineLength: 21, + lineLength: SizerUtil.deviceType == DeviceType.tablet ? MediaQuery.of(context).size.width * 0.077 : MediaQuery.of(context).size.width * 0.054, nbSteps: 10, selectedStep: widget.provider.currentQuestionNumber, doneLineColor: MyColors.greenColor, @@ -130,6 +131,8 @@ class _MarathonProgressContainerState extends State { selectedStepSize: 10, unselectedStepSize: 10, doneStepSize: 10, + selectedStepBorderSize: 0, + unselectedStepBorderSize: 0, selectedStepColorIn: MyColors.greenColor, selectedStepColorOut: MyColors.greenColor, unselectedStepColorIn: MyColors.lightGreyDeColor, diff --git a/lib/ui/marathon/widgets/countdown_timer.dart b/lib/ui/marathon/widgets/countdown_timer.dart index 557cfd3..f5eb92f 100644 --- a/lib/ui/marathon/widgets/countdown_timer.dart +++ b/lib/ui/marathon/widgets/countdown_timer.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:auto_size_text/auto_size_text.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/current_remaining_time.dart'; @@ -21,7 +22,7 @@ class BuildCountdownTimer extends StatelessWidget { }) : super(key: key); final TextStyle styleTextHome = const TextStyle( - fontSize: 7, + // fontSize: 7, color: MyColors.greyACColor, fontStyle: FontStyle.italic, fontWeight: FontWeight.w600, @@ -31,9 +32,8 @@ class BuildCountdownTimer extends StatelessWidget { final TextStyle styleDigitHome = const TextStyle( height: 23 / 27, color: MyColors.white, - fontSize: 24, + // fontSize: 24, fontStyle: FontStyle.italic, - fontFamily: "Poppins", letterSpacing: -1.44, fontWeight: FontWeight.bold, ); @@ -62,12 +62,16 @@ class BuildCountdownTimer extends StatelessWidget { children: [ Column( children: [ - Text( + AutoSizeText( "00", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), - Text( + AutoSizeText( LocaleKeys.days.tr(), + minFontSize: 7, + maxFontSize: 8, style: screenFlag == 0 ? styleTextHome : styleTextMarathon, ), ], @@ -75,12 +79,16 @@ class BuildCountdownTimer extends StatelessWidget { buildSeparator(), Column( children: [ - Text( + AutoSizeText( "00", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), - Text( + AutoSizeText( LocaleKeys.hours.tr(), + minFontSize: 7, + maxFontSize: 8, style: screenFlag == 0 ? styleTextHome : styleTextMarathon, ), ], @@ -88,12 +96,16 @@ class BuildCountdownTimer extends StatelessWidget { buildSeparator(), Column( children: [ - Text( + AutoSizeText( "00", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), - Text( + AutoSizeText( LocaleKeys.minutes.tr(), + minFontSize: 7, + maxFontSize: 8, style: screenFlag == 0 ? styleTextHome : styleTextMarathon, ), ], @@ -101,12 +113,16 @@ class BuildCountdownTimer extends StatelessWidget { buildSeparator(), Column( children: [ - Text( + AutoSizeText( "00", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), - Text( + AutoSizeText( LocaleKeys.seconds.tr(), + minFontSize: 7, + maxFontSize: 8, style: screenFlag == 0 ? styleTextHome : styleTextMarathon, ), ], @@ -116,8 +132,10 @@ class BuildCountdownTimer extends StatelessWidget { } Widget buildSeparator() { - return Text( + return AutoSizeText( " : ", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ); } @@ -140,16 +158,22 @@ class BuildCountdownTimer extends StatelessWidget { Column( children: [ time.days == null - ? Text( + ? AutoSizeText( "00", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ) - : Text( + : AutoSizeText( time.days! < 10 ? "0${time.days.toString()}" : time.days.toString(), + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), - Text( + AutoSizeText( LocaleKeys.days.tr(), + minFontSize: 7, + maxFontSize: 8, style: screenFlag == 0 ? styleTextHome : styleTextMarathon, ), ], @@ -158,16 +182,22 @@ class BuildCountdownTimer extends StatelessWidget { Column( children: [ time.hours == null - ? Text( + ? AutoSizeText( "00", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ) - : Text( + : AutoSizeText( time.hours! < 10 ? "0${time.hours.toString()}" : time.hours.toString(), + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), - Text( + AutoSizeText( LocaleKeys.hours.tr(), + minFontSize: 7, + maxFontSize: 8, style: screenFlag == 0 ? styleTextHome : styleTextMarathon, ), ], @@ -176,16 +206,22 @@ class BuildCountdownTimer extends StatelessWidget { Column( children: [ time.min == null - ? Text( + ? AutoSizeText( "00", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ) - : Text( + : AutoSizeText( time.min! < 10 ? "0${time.min.toString()}" : time.min.toString(), + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), - Text( + AutoSizeText( LocaleKeys.minutes.tr(), + minFontSize: 7, + maxFontSize: 8, style: screenFlag == 0 ? styleTextHome : styleTextMarathon, ), ], @@ -194,16 +230,22 @@ class BuildCountdownTimer extends StatelessWidget { Column( children: [ time.sec == null - ? Text( + ? AutoSizeText( "00", + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ) - : Text( + : AutoSizeText( time.sec! < 10 ? "0${time.sec.toString()}" : time.sec.toString(), + maxFontSize: 24, + minFontSize: 20, style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, ), - Text( + AutoSizeText( LocaleKeys.seconds.tr(), + minFontSize: 7, + maxFontSize: 8, style: screenFlag == 0 ? styleTextHome : styleTextMarathon, ), ], diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index be06e35..379df20 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -23,7 +23,8 @@ class MarathonBanner extends StatelessWidget { MarathonProvider provider = context.read(); return Container( decoration: MyDecorations.shadowDecoration, - height: 90, + height: MediaQuery.of(context).size.height * 0.11, + clipBehavior: Clip.antiAlias, child: Stack( children: [ Transform( @@ -33,8 +34,20 @@ class MarathonBanner extends StatelessWidget { ), child: SvgPicture.asset( "assets/images/marathon_banner_bg.svg", - fit: BoxFit.cover, - width: MediaQuery.of(context).size.width - 40, + fit: BoxFit.fill, + width: double.infinity, + ), + ), + Positioned( + left: -20, + top: -10, + child: Transform.rotate( + angle: 15, + child: Container( + width: 65, + height: 32, + color: MyColors.gradiantStartColor, + ), ), ), SizedBox( @@ -55,7 +68,7 @@ class MarathonBanner extends StatelessWidget { width: double.infinity, height: double.infinity, child: Row( - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, children: [ Column( mainAxisAlignment: MainAxisAlignment.center, @@ -65,9 +78,10 @@ class MarathonBanner extends StatelessWidget { AppState().isArabic(context) ? 0.height : 5.height, AutoSizeText( LocaleKeys.getReadyForContest.tr(), + minFontSize: 08, + maxFontSize: 11, style: const TextStyle( fontStyle: FontStyle.italic, - fontSize: 12, fontWeight: FontWeight.w600, color: MyColors.lightGreyEFColor, letterSpacing: -0.4, @@ -91,16 +105,55 @@ class MarathonBanner extends StatelessWidget { ), ], ).paddingOnly( - left: AppState().isArabic(context) ? 12 : 0, - right: AppState().isArabic(context) ? 0 : 12, + left: AppState().isArabic(context) ? 12 : 3, + right: AppState().isArabic(context) ? 3 : 12, ) ], - ).paddingOnly(right: 20), + ), ), ), ], ), ), + Positioned( + top: 0, + left: 0, + child: SizedBox( + height: 20, + width: 35, + child: Transform.rotate( + angle: -math.pi / 4.5, + child: Text( + LocaleKeys.brainMarathon.tr(), + textAlign: TextAlign.center, + maxLines: 2, + style: const TextStyle( + color: MyColors.kWhiteColor, + fontWeight: FontWeight.bold, + fontSize: 6, + height: 1.2, + ), + ), + ), + ), + ).paddingOnly(top: 3), + !AppState().isArabic(context) + ? Positioned( + right: 0, + bottom: 0, + child: RotatedBox( + quarterTurns: 4, + child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white), + ).paddingAll(15), + ) + : Positioned( + bottom: 0, + left: 0, + child: RotatedBox( + quarterTurns: 2, + child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white), + ).paddingAll(15), + ), ], ).onPress( () => Navigator.pushNamed(context, AppRoutes.marathonIntroScreen), diff --git a/lib/ui/marathon/widgets/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index d5f6bce..a3fe720 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/config/routes.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/models/marathon_question_model.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:provider/provider.dart'; @@ -48,7 +49,7 @@ class _QuestionCardState extends State { Widget build(BuildContext context) { return CupertinoPageScaffold( child: SizedBox( - height: 420, + height: 440, width: double.infinity, child: Consumer( builder: (BuildContext context, MarathonProvider provider, _) { @@ -200,8 +201,6 @@ class _AnswerContentState extends State { updateOption(0, true); }, child: Container( - height: 60, - width: MediaQuery.of(context).size.width - 75, alignment: Alignment.centerLeft, decoration: getContainerColor(0), child: Center( @@ -212,7 +211,7 @@ class _AnswerContentState extends State { fontWeight: FontWeight.w600, fontSize: 16, ), - ), + ).paddingOnly(top: 17, bottom: 17), ), ), ), @@ -231,8 +230,6 @@ class _AnswerContentState extends State { updateOption(1, true); }, child: Container( - height: 60, - width: MediaQuery.of(context).size.width - 75, alignment: Alignment.centerLeft, decoration: getContainerColor(1), child: Center( @@ -243,7 +240,7 @@ class _AnswerContentState extends State { fontWeight: FontWeight.w600, fontSize: 16, ), - ), + ).paddingOnly(top: 17, bottom: 17), ), ), ), @@ -262,8 +259,6 @@ class _AnswerContentState extends State { updateOption(2, true); }, child: Container( - height: 60, - width: MediaQuery.of(context).size.width - 75, alignment: Alignment.centerLeft, decoration: getContainerColor(2), child: Center( @@ -274,7 +269,7 @@ class _AnswerContentState extends State { fontWeight: FontWeight.w600, fontSize: 16, ), - ), + ).paddingOnly(top: 17, bottom: 17), ), ), ), @@ -293,8 +288,6 @@ class _AnswerContentState extends State { updateOption(3, true); }, child: Container( - height: 60, - width: MediaQuery.of(context).size.width - 75, alignment: Alignment.centerLeft, decoration: getContainerColor(3), child: Center( @@ -305,7 +298,7 @@ class _AnswerContentState extends State { fontWeight: FontWeight.w600, fontSize: 16, ), - ), + ).paddingOnly(top: 17, bottom: 17), ), ), ), From ea676e19ca319bb299b15e39406329f9e925ad2c Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 3 Nov 2022 14:39:33 +0300 Subject: [PATCH 27/31] JIRA Fixes --- assets/images/monthly_attendance.svg | 6 +++--- lib/ui/attendance/monthly_attendance_screen.dart | 1 - lib/ui/landing/widget/services_widget.dart | 4 ++-- lib/ui/my_team/view_attendance.dart | 1 - lib/ui/work_list/worklist_detail_screen.dart | 3 ++- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/assets/images/monthly_attendance.svg b/assets/images/monthly_attendance.svg index c84a9a1..b77ccc3 100644 --- a/assets/images/monthly_attendance.svg +++ b/assets/images/monthly_attendance.svg @@ -7,9 +7,9 @@ - - - + + + diff --git a/lib/ui/attendance/monthly_attendance_screen.dart b/lib/ui/attendance/monthly_attendance_screen.dart index 439a5f4..de35da0 100644 --- a/lib/ui/attendance/monthly_attendance_screen.dart +++ b/lib/ui/attendance/monthly_attendance_screen.dart @@ -287,7 +287,6 @@ class _MonthlyAttendanceScreenState extends State { cellBorderColor: Colors.white, selectionDecoration: BoxDecoration( border: Border.all(color: MyColors.white, width: 10), - borderRadius: const BorderRadius.all(Radius.circular(100)), shape: BoxShape.circle, ), dataSource: MeetingDataSource(_getDataSource()), diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart index d822920..0b257c5 100644 --- a/lib/ui/landing/widget/services_widget.dart +++ b/lib/ui/landing/widget/services_widget.dart @@ -22,8 +22,8 @@ class ServicesWidget extends StatelessWidget { "assets/images/monthly_attendance.svg", "assets/images/monthly_attendance.svg", "assets/images/ticket_request.svg", - "assets/images/ticket_request.svg", - "assets/images/ticket_request.svg", + "assets/images/ticket_bal.svg", + "assets/images/vacation_rule.svg", "assets/images/ticket_request.svg", "assets/images/ticket_request.svg", "assets/images/ticket_request.svg" diff --git a/lib/ui/my_team/view_attendance.dart b/lib/ui/my_team/view_attendance.dart index c77b1b4..90414d1 100644 --- a/lib/ui/my_team/view_attendance.dart +++ b/lib/ui/my_team/view_attendance.dart @@ -283,7 +283,6 @@ class _ViewAttendanceState extends State { cellBorderColor: Colors.white, selectionDecoration: BoxDecoration( border: Border.all(color: MyColors.white, width: 10), - borderRadius: const BorderRadius.all(Radius.circular(100)), shape: BoxShape.circle, ), dataSource: MeetingDataSource(_getDataSource()), diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 0e769e7..de7c152 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -846,6 +846,8 @@ class _WorkListDetailScreenState extends State { void getAttachments() async { try { + isAttachmentLoaded = false; + getAttachmentList.clear(); // if (apiCallCount == 0) Utils.showLoading(context); // apiCallCount++; getAttachmentList = await WorkListApiClient().getAttachments(workListData!.nOTIFICATIONID!); @@ -868,7 +870,6 @@ class _WorkListDetailScreenState extends State { 'assets/lottie/loading.json', repeat: true, reverse: false, - fit: BoxFit.contain, ); } } From 8f088c78da1c1a66b37e8521f9dba9cf8dd585fb Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Thu, 3 Nov 2022 15:24:59 +0300 Subject: [PATCH 28/31] Position Fix --- lib/ui/marathon/widgets/marathon_banner.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index 379df20..6fcb514 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -115,9 +115,8 @@ class MarathonBanner extends StatelessWidget { ], ), ), - Positioned( - top: 0, - left: 0, + Align( + alignment: Alignment.topLeft, child: SizedBox( height: 20, width: 35, @@ -136,7 +135,7 @@ class MarathonBanner extends StatelessWidget { ), ), ), - ).paddingOnly(top: 3), + ).paddingOnly(top: 5), !AppState().isArabic(context) ? Positioned( right: 0, From fe8c6f90600166df69f192c76022b2a1380048f6 Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Sun, 6 Nov 2022 12:54:19 +0300 Subject: [PATCH 29/31] Updated Marathon Banner Design --- assets/images/marathon_banner_bg.svg | 254 ++++++++++--------- lib/classes/colors.dart | 1 + lib/ui/marathon/widgets/countdown_timer.dart | 12 +- lib/ui/marathon/widgets/marathon_banner.dart | 14 +- 4 files changed, 142 insertions(+), 139 deletions(-) diff --git a/assets/images/marathon_banner_bg.svg b/assets/images/marathon_banner_bg.svg index 9053afc..767a78c 100644 --- a/assets/images/marathon_banner_bg.svg +++ b/assets/images/marathon_banner_bg.svg @@ -28,87 +28,91 @@ - + + + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - + - + - + @@ -117,121 +121,121 @@ - - + + - + - + - - - - - - - - - - + + + + + + + + + + - - + + - + - - - - + + + + - - + + - + - - + + - + - - - + + + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - + - - + + - + - - - + + + - + - + - + @@ -239,19 +243,19 @@ - - - - - - - - + + + + + + + + - - + + - + @@ -271,10 +275,10 @@ - + - - + + @@ -302,8 +306,8 @@ - - + + diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart index ad91de7..b77e7b1 100644 --- a/lib/classes/colors.dart +++ b/lib/classes/colors.dart @@ -59,4 +59,5 @@ class MyColors { static const Color greyC4Color = Color(0xffC4C4C4); static const Color grey35Color = Color(0xff535353); static const Color grey9DColor = Color(0xff9D9D9D); + static const Color darkDigitColor = Color(0xff2D2F39); } diff --git a/lib/ui/marathon/widgets/countdown_timer.dart b/lib/ui/marathon/widgets/countdown_timer.dart index f5eb92f..93db057 100644 --- a/lib/ui/marathon/widgets/countdown_timer.dart +++ b/lib/ui/marathon/widgets/countdown_timer.dart @@ -14,25 +14,23 @@ class BuildCountdownTimer extends StatelessWidget { final MarathonProvider provider; final int screenFlag; - const BuildCountdownTimer({ + BuildCountdownTimer({ Key? key, required this.provider, required this.timeToMarathon, required this.screenFlag, }) : super(key: key); - final TextStyle styleTextHome = const TextStyle( - // fontSize: 7, - color: MyColors.greyACColor, + final TextStyle styleTextHome = TextStyle( + color: MyColors.grey3AColor.withOpacity(0.45), fontStyle: FontStyle.italic, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w800, letterSpacing: -0.4, ); final TextStyle styleDigitHome = const TextStyle( height: 23 / 27, - color: MyColors.white, - // fontSize: 24, + color: MyColors.darkDigitColor, fontStyle: FontStyle.italic, letterSpacing: -1.44, fontWeight: FontWeight.bold, diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index 6fcb514..10fe17d 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -46,7 +46,7 @@ class MarathonBanner extends StatelessWidget { child: Container( width: 65, height: 32, - color: MyColors.gradiantStartColor, + color: MyColors.darkDigitColor, ), ), ), @@ -80,20 +80,20 @@ class MarathonBanner extends StatelessWidget { LocaleKeys.getReadyForContest.tr(), minFontSize: 08, maxFontSize: 11, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.italic, fontWeight: FontWeight.w600, - color: MyColors.lightGreyEFColor, + color: MyColors.grey3AColor.withOpacity(0.8), letterSpacing: -0.4, ), ), - const AutoSizeText( + AutoSizeText( "Saudi Arabia", style: TextStyle( fontStyle: FontStyle.italic, fontSize: 19, fontWeight: FontWeight.bold, - color: MyColors.lightGreyEFColor, + color: MyColors.grey3AColor.withOpacity(0.8), height: 32 / 22, ), ), @@ -142,7 +142,7 @@ class MarathonBanner extends StatelessWidget { bottom: 0, child: RotatedBox( quarterTurns: 4, - child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white), + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.darkDigitColor), ).paddingAll(15), ) : Positioned( @@ -150,7 +150,7 @@ class MarathonBanner extends StatelessWidget { left: 0, child: RotatedBox( quarterTurns: 2, - child: SvgPicture.asset("assets/images/arrow_next.svg", color: Colors.white), + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.darkDigitColor), ).paddingAll(15), ), ], From b2e03b26477bd2e66db8bfaf1ede05cb2a9ae8f6 Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Sun, 6 Nov 2022 14:34:12 +0300 Subject: [PATCH 30/31] Added attendance svg --- assets/images/attendance.svg | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 assets/images/attendance.svg diff --git a/assets/images/attendance.svg b/assets/images/attendance.svg new file mode 100644 index 0000000..974fba3 --- /dev/null +++ b/assets/images/attendance.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + From 034436425a8d2686c245f3933492af7969fdb794 Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Sun, 6 Nov 2022 17:18:42 +0300 Subject: [PATCH 31/31] Added success tone --- assets/audio/success_tone_android.mp3 | Bin 0 -> 21741 bytes assets/audio/success_tone_ios.caf | Bin 0 -> 254144 bytes lib/ui/dialogs/success_dialog.dart | 55 ++++++++++++++++++++++---- pubspec.yaml | 2 + 4 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 assets/audio/success_tone_android.mp3 create mode 100644 assets/audio/success_tone_ios.caf diff --git a/assets/audio/success_tone_android.mp3 b/assets/audio/success_tone_android.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..b8ad93f95e2b4628ce07ba6493e9f7f96584d660 GIT binary patch literal 21741 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 z zuvI7V)fjE7T?f3j1)U|=a5wPkd3!^-?0WLZK>NT8hfDuhmeXvmJy{3f|EG|e!JQ|( z%HX+_D$b0MTy7iZHG_+-g+SbQ?KOt`idVwZtr)RZ+wXw6lYA!)J$muueT^sz9}zl* zRZnaU$mv^P6KckapEND3d0Lyx$0+}2>FEae*bsfR;~}$oz9Ba_Ve~jG5S-bYY%9@y zlRpzq=MRc+YCVoNPc`T>@)n)S(?tw~HE=&MHsWtVkGY>%{;GzH&Np4Hy;C={HAj7* z?RT#c1V<&%=Y?W<3EWF85TzO&0J__~-O{anCGQgb5&V|UHE^BkK|Ev?I-cGgb|5m5 z*ULUmJ&jRAhWD&8O;XT>H=DicYU^JLnzb$M_WmgF8T22<0Unumm-CEXO+q6c05^1j zO%v5u0+v))FSolfqXKNsDZc+{Zmep`g9}d-{L19Z(4+8KOdQm_(vFX&c*Tg`UCe zp@wlkN0vs<=bfQyQI{cw{h2n0ys%|*!_0MqJ@OFRQ56Q*W3ZY(+pkLUw zp!X^G6V|~{gzOE=3U3R$!-~eV_}z1Fuusrvgu(U8Y7aK~h_aPV^M-CaI34qs=EJJw z>OwzrM^om*0Y0t0^BoACQ94DiU-Vx2+<4RR%)^FE!;NKThAiWG@lJ=R>D8zQzS!<3 zHiX(OoYlapTh)9{GDPLHRk%0!vvBw61?+=d2=@aUOd1t<15oHf+TLjG(usm%@i_HV z%l*!=17o2N2|4WPydYj~Xf)>o^*Q3A_rcDUW`rt7h;O)Ck7%irA2(*Szv|xsn@9M_ zEatr79AZCX9L8H=`2PJJbIjK?lOz(sbMYL_a9elxF|Wjchr|Z1U)Vj~JFbE?ft(pU zZ&2V+>6geKw>lcK>V`5HiVjP3S3F>2;5||=XHAHmJBn378^GQ6|L#e(vkj+IM^6YP$~R8Woc+@q&vKc(@iVD z(*k_^Hd=wo?IHso-tesc1HV=s>+tqG1+frQspmr@!?tms(+5bIC;-UNjWV^WljI8} zT#>&-sVj881l;pip(M18VTdSo1d9WpOvj-7bKD80RykKlXnE3@-?&@wOdH?vcEA83 zqG+_3(6M3DISo`9J}9^tIIAnb(5M_ITPCRxyX0X8iwooPK9G&gpy%>_MFoecn6C)e z;I~2P-3-GViMVw`%Z29iEvLjr!+)-99{@~_Sxx&G@{AY7>L9&AJ%DimA3IL#EOLPi zDO)a|s~%%f_FDZ~5c3E-883P3Bdoj$^fZhzfa)F5Ia2qZIGaDU0Eg$(LDPH9oX2hH(Krj}YEL|$rs*IVx=N9-ijGrot?c(>Rah^_E*el7hlN4BO@ zN)?ZhPE!Y?*h0qQjPO@EAIz50t_WuvGG$WIj2t5DWT zPmBLt^m1}8Qxggf?PGl;oDYfuK6LxGg{dD%yhY2TOH@+~cOC5mXxKBHi0;i`v`h@yy1qy5xpyf&vxXvcLN`2#4BBE#Qm}MTYL@qG>6pUw#mG zf_q;OawBXduRkP%LB%eGfZSLcTfIgU(0I3QePfCU zrWxLrs!o<;2xQjxkguG%Orff#^`$qM|+a73DvNgh|LXG^VF|^}h{}#wv%v5?| zNF7fUI-h-?(u?Bxid~)NG-a&7)_9{nv+12APETpy)4$pO6Ar}K$+d)txhN)sSReeK z_lGX2r9q34wTdBPyK13jmus_EGVBcQDl<9sH19mOlp!PD3C{Ok?>u8b$%L)-jjtPc zEu&@sGtKM@19S!4Burq%hZsXXvtQC`@Q8q8gO59Yn-J=eGLkq+(xCBegZ7pIi-RhO zGubD?(!-L6{*4o-4%jj9-Tt3iD^6%3)f?)ghF(5gwCwJ|0Lj50$kVvwuqiw$+eVAV zI-%YDCmqrHi^`djcF}do70n!bqUSTn18*kNxx>O$;j6jZXym zdQbh_mRR{Gi>s#!cro}INz8e{>kECrhEjRh$xwH{%kkL|tJ*C4Ah|1>qP^;1_8s%v z4BtX5WJmJu@}R6@@_uxj|B1fOHj(OqNX%c=RMzxHuu^rY?TKe3XeJy6!ghy6c&xjIvcQfyXfOsSpuUTA1Bs+PQWC=Oi;q0?LN%Y&!-7WMov|53yX zhw-CZCh#9if^^$DS_dWmYSc$cF#ANvT=pr79g7Y;4diy$TGW~&innsRVo>wQaVE7O|p5x(o;D+zBIaPIb@z3Ln8&%|LO_ z3mZ+M)4lKYc-gwO+hwE0`La=( z$rf1WxWUE%1pXLf{}5l38FGeop4c9=+Usc-z$8)}YrWVQ)tKIzDGxMcb)*dL4tS2Q zrdP9d+_juN^!KNHKhra)&r32CX9XKU;4JnVM30cqWWT(@nV*f(feKmHQP9gi!`lV@FQ=ceY{mQEAUhlIY z_!Maz^En5_Ud(7Gn^E=P37!M((Wavsv`itzEB+dR?Y*9S-#_q3QVn}f$OGU3)6zC{-z+N^oM~R$;w_%4&1n<#l7_ymAZ=jgv!AjUbRvm_TA&lTgFhzSWf{40_K+)qL`4z6S#FFiQe%=`7VhNx@hhcC`qS;3J%@Z% z@B^g1%vG!^#v;lU{02D9cX-dKwiCuAjZwKmk*;=I3SE}~Cm~0Wbnz}XUJyuIPP)QC<+0a76kWEx}r==mA54ILcJhX_(O5p{K$0# zP~lHNLC6J6Gix?2lW-Qb2$l#i4(+q{=%DIPs&%SAdba(XXBTKr5E+|Cm2;ki%x8@w zxzJ$PGOtYM8@*VbBxVaY2oz$xYNplGdj=R05P=y-jb({g->I*0weWwCl>^!BN`q5f ztD31AqrPa^+|KL22JwUI@h9k^+{BPQ%tqo~#BRulfpCXb8zp%xqze8g%#*Ct1lnnR z^ZZT(FU954zOZZA$<$fcQ9UJqnX5Nps%>bz%TC*bMY8(h(**WM}9c z7MgH1cxb)yOlzB@Iwh3yTU)OPze?|GZ?q5bBA`*o4&q$KdM=U^Mcsk%hPC?WdS}_D zYPj+Q`Ce6qw%&ZN^RqW2$RD?a@{p+u2@Sc(sK%whZhC{e*IKd^{;l_0#h;4Q=i+B4P~ z?jmjyeH11J@@?Ql=M~d&d2}nYC04Lb`b@pke8u$uXooMuU!dG)RI+cg=%f<(Pmr}= z*l9A$RX=12@(-Fi(_KeEZ?3Np@rmf6@tJGc*{rXW4rHfan8(pE!?;#XZavuYTX;hL zNf&9O_G|`4BMuQZQl8S!G567J1VK;(u+UTLEHwA3zse6PN9xJeM(4S{WIqEcjhszC z#Nab0GWT(J$)PlPb1@l1C-w5 zdxP3fm}=BZB_xz(7)oxW2$hz$s^kd5_vHX=)|442m4;ax0??HPq9`u=}a|7-Q&G+Ewxm%wy>C z0c&T4?VjPPN+N%vtTZOJ7r9^gWCcva9i|^+&u1;BXOc%^_%O=A^!8DP8_HMWYy5&1 zr#Mnm)t1`b=+zo<2A@h#W`1JKp#CJfQEiZdzP658mhpOqYPVdXiZ=N;H}?+%`3GGm z#50390(KUylW0Jb{m=K6*vIP@$=gI`zMa28{7WlxM7n1K=|L>QGR87iA>$gQnJ^PM z2|VAk*0IzyUaL}NDUwv@Oj|pT4YI(Ya4r$de8ktsa|-)1<0JVsE*(w*o$GzqHqOA(99JbNG3tlrJFXnBMraE1 zA?Y~le8>b2l=>Ez6MO`8x_5`=k1AVoLRcw?6%@)qhHIT$06@r5#9I=Vd4heHfhE?W zvjPTzuQkd9E!dBVMd>DSCeVITqfEi z=n(Xa&M3T0kGknTCj!Xmapc`BD!YSTLtr4n{FedrU1-yL^;YFf6;55GpWQazebuiN zF?#6CP2~86dT}DiR^%gy1;FmyU|22vB3RUF5T2C`S6VHbd-FgCf~R9YQ7*C;aKQAZ zcu0`I@A$wG=Pu(ErAYx(sx=J;yZyT7%Kw7`iIZuM*=xAn?BS$Vc&XpS{>L4B{cCAV ztE{zM^jo%86K_j(H-h64EL;m^H8YxZn#RI%1CoJf`_LUUL!I)kB3F&pXIcmyF9%|w z`!UDJE9ei{{+t)gYXn75G!XCJ;8>#@CppvlRd8N%LAg->$g!`#7D_{z2?}Z`;~6u7 zG7D7*=>h!dIbffsQ!19qPpelL+HB2T`Cf#;+4#*g5HppX%zjUI;l9C=03%$JtTOd? zQ3?NmAY6J1TE^Z6NJ)xlDduGsm3T9@{$} zI0jB55r;li1EeVzG|(t;iZ4sic-zztgz zV}<@L7g`N6p?*@ExaT>L4}V9zNxMdu(9cqD;oU(3pCdh|9XX~oYMGoXCucpy`}u zdaOPtpDZ~pz9L(o{npmlWAM`Z|3F%aBC3MQAm(DG1dsHS^+$I+GWY1~wFR0+U8?zw zQ#cUow<_pA>?DesDQ1yrV0;~-#eePKL+2?|kUCrbLn@PARvgy7og|?N?(EJQ~Nekw?0kVr|r}?S;uy58tjA2frD@qiikOpnN9hG{T|Hld)1%O ze#j7}ye0c3HOdYumB#5E!u}he=YgxxU8K9z0m>QtJcIz|aFt)@fL6 zW4La3eTP0o&c*i+8Dkc)!l(r7h(IYQ$n(;!*5$}AO5swFY^n-u%y)hsj0FD*-iCcn zq0rCMpoAGn5cIy!;@&B3pY_+(YV~I=LEmaU?_zir!qQNYgd4P@tU^{k^%#~L81I|t zw%V!MNEu7~N0K0QDJzVdoIeMvAeHc~xJi@;j0~EPAV9dGSw7sM7H{e4>hbD*+My_I zb+|TpFASKB9#2f6-D7=a)l&Ckt_EO%aCb!88_fghf8tS+wX!nRI}^8aAD|POj<}Dj zqFiGzXqALr2mr+54elvyo1*)ta;k6XvW?H$@ZIBlq5`L4h7&K+P|WMh3zQg?&R^;E zwP%v;w7OHG5eG`T6!Ds?W=mJ6_fl9T(uhwa_tPBIy?A&q*YD_FgNUwEIov(8G=o>PI+k_Ts4*e+OHa(Yk3I0D2 z)N{FGnJHU2Lktk!m-MPW8)F=3_ZiR&_*&diQWj+vHIVcHZG!fA@p~t>^UZ6tJ}Rze zgbC~j=-vSs0|le?WE;JT@rd3|oq+cV{Na7O`%v2geTMvvXr}PI^u6YzWvA0P5CnOI z;t&HUzLaNV4dDy&BV@9q>OKl-kQY!(2z7OMZzN zfZYJ#I@eg(n%6SA@StEox=%aD#&MwlUQibLBIy!!Bo#o;!2b_%AH2SQUMJiZV|c3x zRi$Xk%`cpn`gZtE2?FDTXdSFWOg+s)I*9%ZJv!*?3^2V@f02PjVBuR?rtUQBCyER04sHN`Ucw;NA7MT0??Hre3PPq%+yh_GI`(!ycjRBt7#Y=QL|S z}2PdG{|WSpa3!T&;nq5HfcE|0ZF zkI;muuWI({``ZrpE(A6N9>gpnA7=iKv!0bju0`*KRrp}KFIhII?nwQ`6mhf^shVOg zb^Y)Th3-SHAvDu&GiFl}xZQ9+$Wp-eF0-Xx2UA~H4`|Dc2kbTON1#o?i?EI4fg!h& zh53$DfIRI#3Q*i7GzTlg#qUHr#dl?i>VuZL9v~19a1bRWuAt>JHc8&dri`E?=Y;onkG%v)?Xvx;;QaT~^W|Zh zv(^Va?Y>)r#$hIrurw3nBXt?}N8oEv?to9{5%VL>8WmdIs-J59+kUgp8$1PxC9I@I zGdkJ+OmAX2d^)JQKi#>?ctie2>5u2cpKsqKAJp*wuZij5`^)AioEx^S9b7B2h^XG$2H-`X>Ft~+(4E8L-Zw* zjCO{xg5jjC!}9{;ykGacvwzVamT84=g+HVn>L%0b_U``akUvN(A&PvH`kfX)I*B^u z&jlRnIqa~TxN47zt_?Q>9P7F-19Y$qjFN1idFV>|Ny;T`(ojx!rE9gVNB2sm5JibT z%kS!jSu;8x4_<@5M?WI2BHO5elwX8yL?IYB5bR2`Pc~+&FRNhM$Cm7ldA-lQKL=Fe z=2Fw?-{~)Dd&yMv9si60UuTWwla?lR3!jTlC`kI7ZCuw`uc!bl7D&2GSwgu=zJ-4Z zUk2LNm(aPPjbrFjTU4KPcdfF{JAF9dpP*s*J+w$h96e(wT24bM!Pom@+ndcO&402m z(M0iVw-?&XZhJnJnkJrVsdm6v2E#H1#hni98*@1@&OaX1S&t-nP&*cF3smOOtJ&*!K?o z#ee>H5x+IdLO&oc6ED)S^j%~S=5BB*1U$I1lWxAM`%fFBjn_pQjqO2w zIexI9Y_y!TlQEVxmuA2pg=a%X1F)SRjBe#&sZM%PHb-$ux72>ta~b3pphp!GU(j0U z3rQc*Qv!NGU;3Mz5vI#po+elOM*qwFqGMhEHLwYO4*Qf0qjxebw7a;TK*rA!IexUO+W?Qd0 zI|hpU7b5rICy_7FCotsH@7QkvkAQKWZSBp5x$;IypcJCW)66i@JC+X2g8YRKU{?~G zs4J-k;u<6bqW99e!`fFF-)REXTXc`i!FHG{1h5pULr)+=D6?qI^a9E=OaUy!+qXB# zu}rU({}8LBBxRm%s%3U3cJK-mjl6`rLex+;Q{EER!TZ4@2a9@UI*uEUse9GgI;&-7 zJEX_Q>lsXm*-sixQPYxX3&>;9m;8SX4!Zi1Oh5Q}3 z-L=;CQm2#u6l0u=&uZss z9~k@E@$MTw%c0wlpNU`T8I1YVErcDY(=e0wTbIqcLg%a8B3msDl4G^!+E6_pKtJRn zVl`m`rG)Z=n1i_khd|a0Zs`gf0{q76UTf#-aHiWGz&?iWo`B=%bkY|FnCVNsfiFbj zp|ibKbTwL{G!2SU**&RELDC(y59@tAw4Ssf{RwL+MU*{+<7jeFf}eWezs?jZ(Qr-I zqFbfEIwYeX+kek*WDp7CPkK6J@mWQAgChs?A%TNWIITIWd9-}7vew|`_~=;x zd=8s{T#fG`50bCrIf!=HIp2MK-<=Rku)bMm)4w&|vr)Rz2fssp!>?gW$m8jI7)%Nk z(-`;+bgKWP6Jr#rF3Pvcrz-BK&lx{<%<5m^hYdW6Dj>`z_mFqs?!u4x&-WSO@oTRz zHRvws(hV?EYujGe3V;i`8F_3dR+iDn()r|av>j#v&i8z5*BRQC=VYhlOyzP-lc~}f zF|ZnZBFKT>M2I8rAfs@R!No553@h#!YSyFx*#;kfq9}tB&ZdSoRL#LSFf!;FmCa2;)heq@jw4p#7lU!Bag8 z9NUa`?E&pg!=UvB_TnjA5EOt+x?nd+U7Q)&Wlj<>HdaYpHi> zOR2AkFOloPF9$|<-L!qteUa-VBH4ZQb>m^XU-wpTHq3<@#7`y8CQTyF#yks*050(; zyL{V@8Ht)wO}P=(w!G8S2lovbnlF`<2&#kHLODn{hq&$cx$mE|*}81V3ul$^Wmh#Q z6W{T-hwp6)p8b8|qb|VI6f*OP0;J;Io zXcwp}$XJ{nJ`%Li6WspQ{9JohL6?q}xiu=wX(!3!1za8Y9!nzbCb5ZNoEEhSw$D4Q z=WhEc>l%YqyH7jT_{b5{lQ*dL6T$&_E%gH(NTm}E*pNaKO%=i>%FSGm5u|JKgMv~Hr-^?x^`M`qt_S6aQHdA zoO+w4rEDZjLr)FN0uJvfZ7VaFHLDeNS&!n3?p)iLZqyKnm=X-cK}p9+m+-Y15`2k& zIAD=$cAMOM)X=JP=qcu$j&#p%p8}{4;xS=8&5KT=fbrhQ<*=#V=eq-~)jEgTU$I#Z zSNzji?QuN?05`Y{&cpkX?~o4@0?@~US3o8V-s#G*%`pM>UAij$aPy3gjeWVkQLrn> zA|j3Uh3=x<##JLWLL(oY|1uX4k@oBaV$?2OJs+=Ki6+U z5D$Hf_&?fxMgql#BL_F;tAi8lc76&20g7EhfE^v3yo6OX=2$vbfE`V z`j12U43P`w4ek0-losspfMVbkPeBLT;8qx<$2lknE;9fIO-Ah_oS@94V}|T-&Dewhf)CeCaF`5Z z6k(DWNxR~mgQBj#CN<_YgNAX@Ji?*8gMZn&aojoA6q3c9X@A zwQXK)>&mP3wpX`T+qQk}71#D^+qU`BGEO#Yy!n4Wv&rN;GtcwPB*Q=PT`sIpP{Z9b z(3jVRtEfC6KwQkAaw-?o6zi4UoAiKF)!!oRujSu1eD9UN(DyeN2)|V?1=|um zT~jixnXpT=H$^V%cgFLA{n_EZJ4Iy+HJ*daX1QKsi|#f&)*i_2nmZzARn}Z**xJ+- zPmYo%QjB}=ulL`JfB#fa)t@IEh>q0E1}_swT(>jm49wYs*bo1uTOKfOY?3dK|F4V{tS94)iArW}~b~Mk(S5a@IUey(gSzKly%m4tX|vX9imE2Vz}x=b%>Bug+UJ_F{Rt zq$>xXV7aH+61l=KMba<%=h~mXyg5a8XkYl0Cd)DmbK1vb9?M>mah})-UpJXm5OdKe6X5s zM6#^hj*fel6qR(}^8dj+k=`VZ8UMm2I!0yg$QhGM=k#$7Kplq0$v=WWsCR{}f4urm z{aROe&i9e88XKVBgP4eB&L){vvIe;*TL)meRuexEY@_VJu2Xo@{g?j@E6W+lztM~D5rmJZuS_*L8Q6vb9{x=mQok$e{B1Hb&iOgxUFIky zvgTNZsQW}8i&5I#>ZsIqID4*?Th`Ui)xVa=SJ+dbz)<|MmMxfecNJy?#K z?S7Xp{&M`BmGAYp5ZlBaYfb=&^^R*vR)vf=j)}Ie@EOCXL<>np-}Kk^Q10{I<}@wu zP8~7Kh3*jJGS}vA%LOxy>OZc8T1k}Ro*{e#T*2Q?R41 zUwpjK*;|-@^Vi>b74k**pR`^+rm~y9Ba4ZuuKHPE#(i=bve2|jJtNwRAM0=LPI@}} zrcxXEy^+(Jci<4~T*so!zjL-KJS%9eX4$D36AkiH)~ZfjB%s=+n(J$6IxtqMBfg7@Q;-T{Y5PsXII{#ns1*r~&+ z8|xs-_WNjEL-|Ar={fztQzmcs&xUzz-KXhRQbsJQ z8v|R2uF8@Wqw|>~$GQV}qL~o0NDG;?k8!VbzYEmhePJkS8XRiKE?mAc-6}yx5Z*i4ZqrB z^Rx`3y-FRFwDC7u4ghf2A!OxeOPQ7J{jj${Sn1>&$+I+PTMEoUg*1VY8sQ1?3us<-+w-{?+d+GDopD1+reXa+L@E}IGf3clXK8k z=0)n-;eJe^H@9$KL8W}U@PdyO`o!*P&E_CFo80Z%>^fr4z&zksL*vv~`4C&zpZ1;h zeGOzN8|M!u-x?l5l=XrW&gz-HE@KaI2!3FEo0dX*n0lTj1>XvYf-Obc{mX?r@rk

|5)<%G^7Zmp3`E(bGL|Z1oCY(tzno<deV3xjJ*(4|{|D zw$xc}qa;mK-fv)Oj(FS4}>bm9M%h)8Ps3P z+s}`(6@#DRi!|LWcD%3CoY^I_gKNBf4F0EOtLka^4=xfI=sr+j$!}IPC@@u+8tI)r zZ^}f+ks};W9HYrg*3a;1!;d5vYQjIKAN!|zPxy1#nsUd)L~TvWRJ^Oxo_Q#9k;_JI z!VX$0tCogda>bP1+{J=z`L~M>2MWY7(Z5w!O>5BYF^UUHQ@mkTI} z{+_Rce?9w`{3$t4Hyo&fPj-Tt4>R{Vj}Qyc;pTQ}F+{R1-#7P|f?z@Gq7YSGDi?dN z{%E$N$H`C5ZH`mKNz4sK^}b}W;5$xD-SofqeG1svr^;!Zr~eNukH2$fXC^ag=W5#p zAt{uosBLReN~vAv6dZBlPfQ0y^sN(5gPqy3l*)g_ zKR9rKD-k-Fu48x$m9my`(3#IOCFfY13bq-4PyLkZ(0Rx(ikbJIEo@&M(=wW7+;yzN zGc1d=4dM}rp&q$U71k|udz}8pY#TX}u4G&Zoy3a~9>)?#7u#6aVVt0D6LU+?n701q z{vp(HHcwJV%cy5sYGXOXCdXRWwTui$7IxNrL1T!0m3mMc+@lL_74G#+2oM|@8k=5f zssZo9UlN=n(=OT?L01hcRZz4*YR9PjHs2>|88=>%qcII+apRTAi_R*FN`BV<3Y%aC zRL`UH#R*g+cfEqqg(E#*sha%%!qZe;&Bc)i)~h6GUt_On{TFiTC#95)i{f=U<RRY1MsmM|6?x8d;a@PE5g9fv0uPllD+j%w`S-%zl!3 zCDaIaO19H}24>)KM>QAfoNa$#FE%Li(-O;D<(K z-c->rrUssS@|Dh46)&yisC4{KO?mSL^artu{6svk-a;P&H*^CMjpbE*in&TT118!o zOpJ_3XX-lwFY&z&r)#8hC^;8@4>5+9$vn9-yFQTVd0sTFXtehy+d|%+7^8_<)F@57 zws#>UYa4_HP#qZOf`xo#rZd$wu#z4vY>B*5nG8d~>G*XA?%L#BLzcomfVcFK>G5bP(2 z2=0RRn$BtF#X`~<_8{Gs`kP{zPvWBJ9rZ=iHn@znru~+yr*ko}9EB`xwQQoX^n%{v ztLPc#K|Ejmuetl-SLu(2d0-YchWKfJOxD0H5Mq=x+SoH`7F&Y4LCvSzv7N*V(I@J( zxdr^)y3l^y)!KQPxQ4toZ`am~|CIL9RlL*PkKDYsWB}oAgrBJD7#o52u*1Z6J5O%J z>wssC_0*$d%cbVb_CPd{rhjLTigfgariPhA?$~neA6#9WAreGxnPkntcn4_^RpfEI ztGhpX_XRHURU$d6_ofEWCEP`Pvi~5D;nl%XhRUkp(V&=M>IVJ{oTX24bEK=WE}9dT z8|X7zp5jN1^E^QzgG`XRa%_+oq>g!J7hQ2b@>QqS^7kTtsLPmWcrHGMSY_`=4#FYe zlD=blTJ$e5%rp$t2`pt)eD~lsh2s?h<*+rx3WwRb!`YsAfwVL(RyBw&6?amHJUxqg zx;OYX(EWw!k&Ehy=Jm)}YbJ5TUX1L3*8q;|&ZSmFo{3MHdVVQjr~UkAd1$<=)(VWk zOOp*9ZJhNSXNmtIS_7Rf7U?AvQd2yQip=hwz5=GbxHLLS{l!uoZEyWaJSWc(k1+-q zs*NRwgl~&on2P?-{>St)p;zelM0xEj;1GVCOev_t<|s$#VV~h*YGQb>(3l$T8DFG# zm+-5Ylr%jCXmHCw)MML4W{@L@uGj-bWqq7D5%LK|OhZ58Uro;uW`tFVFN*%X0e@;= zVV_8&-A*bK@8|~08!Z;k3f|xw(k}x|{HN(2!ner!G^w8t{%IZHSnitP z{2zG|_d~Pv&lC58f3j8l&pnfih7>6;UUHp6zb8?x8)$&TUu24@fb%B4g<~tr|baizmd!SK((3Our5#!Wz?@af4x7p44`*9D$ zayno*3qHWt+m+c^y8-_NxlLo$52Lg=k|`f}75E=jjQLZU>v*Lojx7+vR>SdMMm^U6 zvL@QaoYt0$mlu~S%FS7~(_P!M*3a{0BU4pxjW3}!_`q7Ckr-dcgn{P_r@ z-eqFo<<|0K*m2cf4xa~(Ff>dDBZ6>|M*U0u0V>F;q|328+Ll0LtOc>$@y7Mp)rc&M z%rOxvUvz_THqgU8tkCTyz5h~w3N@pRG$qWRk*U_rm$xhoc~R3;4?(8EP6`dss` z?wJHd39bg_xr3P69Xt?dc<+~{hqk;33bClg<8v>*H zoe5T6%Jo-zu`LQ47rpd%;T&?^1g3+)TKG041~ue9n}``K6Eq`YML{pGR_^+}?n7Ia46GtnowgmFLzyXdsPBeyG5HIdY92A5i$ zq~-%t(C}>eJ@E^CnC$tYt@&dr={Q6H`E#bPX97` zx413(Ty@9T3wGF!I>)-A&Z%S>>?`QfDQ}yIG5VTsiF-$p-Cf?liJulxr(OC4WU-F3 zPj-|d>*6u^g&9zEs9xea)SY~apX2C2I`G!e9a9BWI+7GM%tWeKpju!n(@BiS zj%lWt>m#*opPWN8S~<@V3(-oJ`r7Q+aWRJ)F#0#$e+nyo4{Zig;f|4^=R z4%r;nL$GnG>Oka!aFYHWI2C9?5zIZQbnKaiHm8w~gxc9MqqWmbtUxZBCu(NJh6`dK z;d$?F=I-dZADGK0qK(x9P4!@nwVJ)SV<_1MyAAd>99Pweyj3jjRx0Zx>K?mT+7ydv zTU!pJ|05jAv*w)dh}lRh(*gD4SXGgv^q&3hO74r^wNyo+eRQ1qmFYV?%xWNyI&5Sk zY&&pM|02CNa!q(iuMX4-%%WRy^@4`DQ#%nTj%kQ4j)SfR&cnn^#9)-wIz`vU0%@hP zesJIPX{dw3&}cjL4|8+)g;h_svEL;dV8?)2`daDi$Z=6kZ}+DIgXq6GCb%WuQae{c zM!Sidj*YI;&WXfwIA)x!Y7zZSh*7wwYSBXXG2b}4v+yH2UE?x;L)KWQkag`#$lBN| zV6g6BYCxpA5TKX)Px_PeZho*_HojH68+d>>A%{7hIw@xv;xCvtBI!|)e!`@{d-u0O z$z9zyp1vYBiLTe=S}LOztpeH5-jGBw4w$U#q9E|EB0zulKlK;U7kNQu5}5Wla1)11Ge@O5F^8t9r5C!@){QJh{!2{54gp=Y z!DN|m9}!{N2WkW`nh{ono+Yko-vYbwDdbnjNyh{GB3om)gQ2@J!S|iNPSx`KQ#9H= z#ovS-8nng^X!==tpm%J`NgZjoJ;E9T<+Z01J3}u8j@cF16sXIn1y5Mn?W|J+6Y=gO z=Q!gSLO!+bf{liT$rqtf{0wT6w{el^e&FBBIf99J2h9r0Z|Ec234$S3T9fEe3#FZt zC>LrbTxKY$WZ*E8;+y1Z z{Bwq-LFxeWP&^l{mcFFF4?M-*k|&kw79}hg2Bh^3lc)@`Zvt0*q-U#F8|che3l~p5 z))_2)(TTP%WM^9fx5B;66Ep?!k-^)1UFHPcl`hVb;>+kv)o8e(c8 zHqcu4I>7{Au#E#*UXQ21J326%?+{*}+N1k!d5kW$MadIHJIoJVH+|6TiFXW+;kGcj zbVGU^+gtn;U90+O>6*)hQuMpc&Cx{8T?!8Ocf|5)!VPu%+;aF*{HzL~C} z-w!lH*V#PeOJW)J6>4Cru4xu;7;MFrp-<8^=>pa*6_1`*H#a$;ZFqC?cgHu!6q|@_ zFdxR=o6v;IfsBXmosT+Mu=}d0%EcW+js)-GwfI8ds2wsc#w*4R* z5lb;I!079zlF@Qf7gig%tK@GJ|3>Z?cW8QAoai3gCwsP|oc*57i&QgSRF#T$75(&e z?^XA3PaFR%=7H#o{;6(e29ZqsmrW*$h+^0c;DhdCs#RpZgs^bnN}w10Q*g-X_`jMh zmU?J}7-L`T!0o@=HX;t=hV;?MHgN#GNwHYZ9r6!hbEG-Z59;COTF5HvNTLdH!ge3q z0=(D#ojf1@D4u7bz|}woy;GdoXx5u2Ku;{s?a?OB^FwTQ8!A zff2e+2~X%>fntkOJp-%gTf(03#blwbgylUpmK^EW?8qe{{3Z0$@G-S2bdjG=z4Db* zMsBnG3%Q!|@dTl{V7`J@wJjqOL}hCRl4tp-QbSKuDfKDrT|&t4VRM{cSb8asdqY&)^kQOZ$) z$V4QIOJ_-TmcO#!{R!_!?&h?k@h@cv7yb1k{8;SXLw*w<8BOlFcwQUnGFMr@ zK4C^%SWgnyh(_2maH`>kx^ldSY~@xeipM8r2$z&@NBgOco9e&=@PCM-_T%=?L|NpP z8Ptr9C*^kR9{*5J*xSQDnqDkG;q~c14Gee|y>2~EtR!k+JUHIaRy8m7Eg0lxQAuhX z(~|EUY#lwOx?vg%v(|2;+P+0mTWTVOrXuyHct2Uop74+GT=L@n)r?ixAAXl!V5|-` z#;Pk8%h|qRAHlBr=jqe2ioxsL2E}3vrme#LGh%(zxal8ckkwDNw|BR@Y&VdtrZFlZ z);w679pLZoS?%%q?=v67J&~O%lkqv6jia^q3X*we8-a{5RZ(?}wvu`)eeK^oe|k>)-?MY2)6s2;e>%gTaN2gn zM%z?aN#Kd@cJfg~Ej40e)ak$l`nga$G(Vx$lr>jCjfBD8*8T@s#<~UmX8e}^7TF@+ zVha6dJxMPTD9aTK9*m7rMNHM<^SIwO!`2LsqV<7Ry2;5N;jyC3b)hFKerzw?3inGI zHDAr0kZ(5H-o$Po+Tt@|jd4VJRzxROWbOxQc%OJL299!Xc34r;3Ig#w#1r` z+mKq8O*%B;4m}qC$913+bO!TCEFVErp!SjZ8uHavWFKfZ*q&jlA;Rz?jfTev{g|8p z?t{E?;2g(fYk;KeTH9Q78)!64P0tSh5L(jT0wet; z{5X}vy$ZEX_%ts~&7mWBGur{175g1JZXT<{lk-F0gy)==DPnH0Ua?celzOShE&Y*- z)`R3ZJ7QafwgHCg1L=<8uL44k4A}i`{i~^YTp%^~R<_{Y?eh z>&ZExAHqU*C3Av_b3Mf+5nal!Uty7v8P?_GQhToL3R=aIukVy)d2S|DoKQvT2 zIYPI}QWx%r?X*g^LAVO)XuPW#ngqg~g-47`|6+6aZPNG1+|);X5^RBb>uhZ&siiQ%gWY3zUA)Ez5EE2DZjJ*XqR{L8Xk{)yEQ}!x@5y zHPCn2T)`YX9&M0rYG?so#M)Vd#Gk}lTN{)#ztDse$3idoH1*iG&et?Bf_WzR!&Q<# zeL0{jG6DN#ZEKy5%>+XRN>vnJAKEJ1Wq5iXlP^@4+ebs`i-vg+uJ~ptv7T6N4I(k~ zP0g-&G*q6yNxksR@kRqRS(7+Fd@+@yZw4Gfl6Z4#18Xs?2^cdJsg}foq0+*COp5N! ztP(8ps@Ujs%rFPC<27v}ae-)I-Js;#H=30S4nE1RqqeU5;IZ7(f}$f*zd!N4;{DM+;5x$-6&$7I(!yAFBz=wOZhwdTKZ+SrgS|zK3z-yCvXwHVr_4o ziB~~5u#4fls#5ep@R`tv-Od=81^hAjNBold4?_%mhG!A0$qu$pcnNrtxvA!VF+Mn$ zTSe#i&-yM0%CRkih8UjC*WU(CE2m<*^#CR#U4Y|;`6^v>cCZuwojt-#VQBtG2uxJf zIE`Du6mB9GlS6H{v8~Vs(_d;fwoZD@ex#20FZwNkKb1-BHnCHx6Na9E7ky|wW94xz z%mEHVX8LEev*hQ;vul{U?C*jjR6em#b5+r{J7Q^K8oAh(hYf{v#zOVJ*d%EOJCXX` z|G+;opm6Zuz_?Cb$8Zx6&>hyjHUk!i*IE|p&!nG3`%2IGTI@=;3@ZrhLL(D*w3STP zq2<_Tq72!|b`Fh#ZHyV}VzCy|G`2kD^ym4#RA1H~JQyFTer;?AmOv+4$67;JAzaS< zR&Pj;j8>L5azEJ~Y!_~b5DM*1h}zxeK`?~ti7c|0?K`FcWMzZtzcEDW!Tbtb@ShIY zsB>I)@SpfxO(o+qa56f@+QX*BEpRFGa^2~4r)YQSH1~w9#ZKg&h`mB*6YsR^&2wQV zc11bi4{Qt3tH3-xtEv;zNb6Zg;H^Ip*iTR7E(N*xVa)_n2DlJ);J2)+uv^em6Qxt7 znCJ*8!Ry!&>^FXuR6X1|Swj2P{0km~9kpo)r!|JQvlQvA>0#0J(qgt;;I%(VAxwRK zi99`?(EKo+0i$RMe5|!9wqEI=%+>Zv^@~;s>UcHVn$71$>1+6Va+FSGsRQR>9_t6& z3F|@BZrQ4vmO2pCN?ny}-0#0d*_fk3wp^H~pe4@%Tya9U)3@|muVWj!(;A8ZZSMp}CzVap_)KIxAPk^q(ntoN^_^h{E?78;!x zqitfI2c^){cx8MGRu!6V(rX$f;mAmd<((|S?iZQ_i=ud{w63G&C~_BnV#91TtOn$j zWr+4}vUm8tc$LKh>-+-)pV%C+X2`4H+m7bbihrzlUAz-YLBouaIxjIU{7t&fmu4|` znowK*EqXO|LwCU9L#tW)*~Z#j_%URerKNUt;(6F8)?j$$u6qV9u(ie0;Z4bs+GS=B z{0>`!_r*2nG>9=dD{ygBw~dX7E=D2>jwezd)|S@D{1$oyXG zO4vh$Qmy9)miU_owzHk2-y$=UaUE`Hi*&~`@RQhEgaTI^2dK?)Rj9dmn>Vq)v%7^s zAzi$^YLQZ9mY|nyr3t$=f&BwFG`G@RjqjBQ@h6ztffN2UfjjJY>2S1K>WprJr8hDZ z?~NB?7m)>Ed1DK;Gv=3r;$pr8dz$?w^pn~6Xw?gY7U+)lvoZu?Ex?*V=S+g;a{R2^ zf>(Gbr4QhglU*s@jV?-Ky498p1jTFOzp#~v6}WCJt!@|3kY#Z`KZfhf%@r<$p!jCB z%TN^{kUQ3Hwo}$^=wk>nP0<{S%kpx5J2RC!7Kl)VoGJ)L3(|9RXU+HE|6zOZ8CV89 z)WR6HsmsM{g*2j)#W;!YCjJqc92eC43>ScA$aMU@t*x~++8%6eJftZde=3jX2Qtm5 z=hQrU5jQT_CH9-jqOW2ugezm+@UEx`g)L3=QPuZ&G5M=lga3;!&c74Chpr^bX!OPw zz;R>&zRyS?-|5O6PQ zz_;1-)_Ld_Am1=km56teNAn2%KMJBYGhO*g!Bw%Ls(XeBmhW&&^gEu3HG)f<&*^+B zdmNF|!Vm5|cTs30T?p4tl+f6XJh%(V$8)U%a1LztC5%NOC;p&$n1i}A0x0U2SrpgW&B7_A;`&0VLf2QE^V*=^#$(A|Vt zQ`S@-e1U92y;xneG1S|%S(8lOjy94j3R{%Z*iKj@SBv&jHbM_J*MM7L3-BlSHS7pt zw`|ZYPF0QUkiKw-=~jWW)E@Sj_%z&K!MA^!#z1vZJ%*wQo?%S5&Xp9)L4 zo?KO7g4`$iEwxGez&spYg!!zc@dsE>_=KgIu3_?Wn3I}wgXm^~lhl0nxKt*hO_tES zGM$C~MmJy+&=9g5d|+y(nVGm4jt6@Q!?`}3LuexRj8#daI+uAqybrH$U5(RN33#xj zyn?JxhyNCRO1FG!ppcrwu9E6T`Xpy+3QX&uE$9twKbntJ1!tJ*Yc?nT4c`cs5f*aC zxb{K~xk0Q=y1TBSxd+?@N33h`&*&ql!2CtmK6xv=TD;1&r=L;1sVD3)X?WyjlGA3I zW<%r9%h*x$G<*(Vj6Thr#G3F_sX$oHrMTn55V=QeWBRA=fq66BNwIhq7tr-ke{(l& zD!Dn_L~PD-^mFPEZDn6bo1(Q-hqYHtPodQ)g+G{-oy1rs@X>>%ooUW_6BykTqYKl^bq~$`pfzYd-V&<;x3+9B%u!!R6c7C^F6Sq33_n^#H70YmG?i#;eoGrhL@oLQQ4VZ?QmD6*=It)Dy)-qPmm=mi*{|Ggi z8B~gH#_Uq^MC%x-nruKV6Cnycf~&D&u<~Yr9#;J?J}UH^sO6q;|M3Z_QfP5}ta`d} zFla@_VfohHRtwr2IB)2zO2yBF%JKoG0(FJ%!j|BDvN?7^ooir$Zt!gM1twq!^wV5P zS3Ny3c2vGAY~Y%4&3Rc`9|q!I)IW?#kVSvPds!!1P3RzCkN&HwdhDB$!N<|NDU$lB z;QuD___$uZ$hZrvjWoe(<1VZoY%|x?eolRex#ZD;^1V9t8Gl8(93Gn}uR%;rpke4O ze3P{&{ur&T^f8vCH^(Z=cD@-sH;_+VVcQDV zNAJu36BctI>*m>D{YYlwf~LKx7qlLY;XCj+UKhCuRMMAErK3xN|M89KV}UsJh+QZ4 z4xNqvPzOv}@E7t1D~pXpM?o7+pR{F@kD_(uhQeiT0GA_F3SN&CBqwMtm}Ws|u!{IW zd>^&~fh?zVH&UY`FM}m`l732MQJ>j+;?MBt#3W5EQ&p%8S_=COb0CFKS<`mSuVkCZ zu^=xz<92XugsyUCbX%&CwvFjI6vZ~;QG5sHf@fM9>V_n#NVc??drucpU6kw?lmqtmg`=y#+$xY1NeiNQF8OYiK@p7yS;?puu=cQzr3SxV`jL z7{PtxjtDE{MX_D!Te?H$HE=g9Zk>0JoU> zDVV1ybWwQ09;X?)F74&^2YW=*=>@t4=9bVURL1q_JGiRlo8g7}Vq6UUC+P%?@4(L$ z%ge9h2Gt(@0gC}9u({SI_yL9SlrTQm+)BI+oe}tb~&7Tv%rV*^bCB?gx% zoL)sAqW@-2DV23ytiS4a{c>|2bPm0X=U_Q-NlP7lT){kY=%BckU%=N9bmH@nHEvSn z8+uwUDV#n7FU0pD3E-lkKwXrW75YyY!xYeq=!Y!IFADC9wNZ`IKerIj4sXB zS=6sk#pChNNAUAJuDAGvW_JUhyK|kFO={lk&r=_(Uc1JO+lq ztI_i~h=q_dz#j%&^)CKAbV9hmgy_+XnbQi7WB{(4 zI6PDZ=0qL!Fe46{ke-+c zJC3zMngLbyC(?ZEaVS@~!Di7N=xs)Nkad_1GovcV zXZcO9P3J~$$^C>&>{Uj~jO1ccQKVtwr8>{p2%zA6ghT#?=YbVWO|^uAP@2fML}en1 z?bin?9tlI)TTC@(DQ^u{kGxOL(eyD+ z0Wl;SEsgAfO8{4lvc{d95qU2U6~7BMev^pF%VJ>aq_(2*G1vw9f=$6dq!W1CTwB*K zwL0Pn4ihS~er7il;CltyDuL3?e zf)YprsHA0t!J`?NtP&X&6vTYtrEpA)h04bsrLXInnfib=6h){MdIMeuj5FTRc1lJf zW28s?WzNcuWBmdlJ7TrcJ+zc53rNC2G#6?xaCjX7pm*(>W*stt7uB^~pE*@*1Ua$Oj55-~;S_2sa zhRkOSu=;z_5UCoRAPyGpi@DOgQ2*F7l}^W*b>MiUy@CjN_!dw_84Ed|d>Z*n+RZm+ zPqA|pl-V&T#kA?Ux{;>800zE{mP58c#g$t9S$#d36Zs=JQ*0)j7h6fULVv~1q}{rN zxia_{LZA=OC-61EZg`^Up4_5z!7lPm*nim*+*RSF+%{GGy+|c=GrA0(XSrdhs9v22L^7m#JjgC! z@A0+7WpYBnGVSzJ%(KB!@Iqu4f+#iSv~G~9d|V2jl6c{y&|6#+JQ>~@-={jI4_XF6 zvyhqSCUg`$%CbxURwXC8hObCHIEL-RUf{=y(a^-WRkc+A$m{_xz{`-4@OyBCX^K`# z?~5-E&yos-y+Uj8kgSiO@r0_-P|9)wdV*|2$D*a+`j+|n{iQ1Cb#tw&eNhDv7y}*?ch6ewQ zj85!VPcclk9Do|bUEz+}Bl!3tsz(J1W>?Ta-_mDG$hnt;CWFysuf z0iF)_HGS7Xshd$g1d2ucP|nQF6JE)!qZN{!)p>@)mOIezaC0aLezEK^#5En08=?n7 zdxDL{?P5FWeTa?SNuAfcG*$yf!Sj*V$U?Xj;4{tBK1)rA&Xm`RTllUV!p#!i$_t}M zl3z6~4TXRSx(OeIo!}8mSHpcxPO@<{E98)9ai&;Dx)}1tlIaTCmd07Y7WgWfg`9;g zzy?zZ?UGc9s7_Xi75O?`MQ)EE$PZ%WQ}Z-WjOBsK5CuPjA+VeIt6_-xOM;1I z#KYnuDHtvm|08`}`^NYH*a;s;NhJ=BStR39ZH}VzJP4i@wfu1I5T7gl9x5F>ozBrV zHMRi^&_#GRbOX3$&eq>o&r4j5OqTzWo=JdID!5iTjh|ILbR$eSFdy!QTtuov4ofk^ zLCyH&qR8^#T!G~eDIEN#m9I*Mp`Rz-%avw1RJei_Km27uBbdNTgY?zHpvD&L0*QNISz-4(6DITWC`_q!yje=91CZ{X?P{r*|c5PA{~j} z49}3(@p-(KzbnoS3X$H4*XsL*n&w5oGpH9NKxWHm!x7Dq)aSS>JTllRi^0(=cF1F)tt+5_oYac4M3n#jN8ME;j3$p1u<$Akg6BiGfmOyw+Ty8|v9Y0J zQay#|z2iSggNA^E&0qCN_2J|{v5H|$u(SA3G6m)E+c=)O zsnr?h0F9tk@Hn_PG!&>{oT8|c;pnSS0}17iaQFCUQuom2ScOy*&1Yjz%LDKX)DNlv zLgwxIN9vx*D$(nqH^G6TU&@w=NSXMabbIY!9$Dp|0R-V41nNeyUoRxEJjd+8&%Nm67_(JtAuowbB9Y z3u8X894dgO~_)eH`jx=3r}xsmsY%c^y{-ll56|2ewKC@GGvUDh_Ui#r6j06~Mhy99R$ zuEBy^aCdhJ?iyTzgy0Zdf(MsnXQrj>yWe{_{M%FARrfx2d#2}bk~B$<#XpEMoUx#8 z%f&vgR^-dKg$eMMw1l3K@7$P3i_)_+b~xNQzCrwNalJwd?Idgws>&aERif7-RTD=h z-ijXgzmtXV59~jCLikRSoJr2d9}TaxpBnvf7E#l^5gGoic|yjoek^myq>axyWUlr&Zwf}L*i$fm@L zk(|-`Zlhp?+Di*tX+x>vTE|C|{1RUwG}ydIK4}^}js20>B%yyomV|fUJL3JT>SyxC zT;~i6Z;nqEpF2Fq-e45Qhg80xe=HW6mv}nTFnYwjAAEv5IMx~x>Jc|M{!)^haek<< z*_pIe{eoe!>4{Ymx+WC-Ry0w@76)b2VOrHPoHOA)aWCUOh1=Pk*h!p2ZVw8@-oc6& zBEw=?yso^jZbvUz7eWW)=Etv%zZkd3xn{h_r{#?xKGqpl{3W42xP;ZPn>+e@y4m_A zlstSWZeiTO&@1Z$D~iU*RQ|2l->~AH$nMy3Kb^>~-?AUpK^4w_!vOT`!Ji>#zgLyO~Z+}t?${+6|j9@mdVPrrF=c4Q=+yr0}otX8iE@5lo(euZfN*z zsIpa)w$V-aP488#b7WHD%gDcOfgp$c8F3b~ZvlT7j_(+^6_ld^Yo{OcP2Ts>+TRir zrX{QchgsAgArX3Kq_nSv8^pDYs~+y*tTT6#Kh+kV)oUBe6PX!_k7jdM2G`X0c#F}; z$sU%#CUxSfgoayx(7U<;XYQQHhi@+vwk6z1Toqd%WRZJtKckbw!sFwH#^nizoFB}( zq`#^eY(er~LEGK81JO^S0u+w85zJ(5wzf@({MIUx#LX9Qb%C@n?l?KZE8-T%nW27mML_=@ zdEEEi3eh!@tC2sVr@UhPq@GVRnJt}Oac2CG_)6jRPAT&za!D-?%Ewkm%6&`xHsIU! z$Pjk|@2qQ*%VrWMV|Ykh@9;UtvsSWya4$K=Kkvpz7e|vt%f^~`2SiDfh3+xWIFrM# z;>*XQa7BBiv6$pl`TR(%RfNHcXA+x6w5$1B{epHhdph~UZQ|;O*E-v+jI0XsWl4Wp z>|(S%tT-~Z!$)Ei8pd*1xt!hMTk+}RUWYT;4UKI0fPCbijpa?e_U+-f*NK~>&0w;f z3zel;%%e`_aP_!C;YrRg^Cya=C+dla`i zblG~qCg7B^n?Eip61RN&CoyXzd-RQWMl3^zSpzG*(>$Cm{61XC$!V6O1yG#W<=2SK zi582NjAe7z`yXUcoRz(@9)@UmUEH#`cA+`eBxa!L((v0vV~MN3T~4eN86E53=MgWF zWb3W&z!OIJbU3rE4VRqJYeY9cN34G|6wMZ^;s(J_ax(N-ZM#LNclc`D%(!x)0agpT z9mR`TK8@~8Z2E0nV#dhQ*e3rMnGshuZ0oV}cQ|c$M>u3B7*|P8T~ws>{8;nIyQm#& z>D37i$~$seN?7S>Jv~FD@Qy?mBv$y=B{3andOH8T9EIl_-Rvr% zB;oYok)a#*DPtDaY9HU_U5V9;JdNnsP;Uz_qZ$!v{OiPr!(kCuBD~f4VBRJlG~yGy zR?&WmMZYyqOc!n$rrVQ@MtH3%&Z~OMW3?kMBRn?E`@*+^ zTdrtQr&PFPScbobi#flVgUB>BjoY3RZJ$`@+u+0s(Ux9v9;bSd@}^-YgcgLeg;Xf3 zoyQ=!w!9L&_eR9JM$<$K#LoN8MJZj0tTIbD9m4J6X!tm>I7 zwk>gRbfY&1t{o*y%t}uF(D`tV&>?5DwTrDp&t$!zr-iF6L}=T%@FiaOL85%(P@E9$3^2eFfe*K~C!N{6DWrbP4#F_mMWyA?}jkk@|x)GD=yCou#37 zp)bxTD>dtl_p5_^pf^6YC6+n%n>)Zy!uROXwznOrdrTko8Wp-Z8^ouAAL^exV!YVgwD&#}p|P;8@n&z~c{)3az* zv$wr5ls{Y~+$Yr3dc@Y?)~W(e<-UkkPy8BTfY$lmQU14{N9&s9>}t-w(BjZPg<9cfKq-=iaPNwCu09xask4AiZ$ zo89junrlUmm<~C%%fLk4|@&`mVSQDUVojcGP(tD&ah``xt+d(YldX6_jvQ ztaUUY_RV|Ei^)^y0(8VM=Sb*m=woP%Q{8+`$LdRBlz#*elRq&M$s0ZBieR$rh>il= zws1;0euz3lZD#Z*nbaMT#ed@_#zw@_yE**w{FG{gE3ygJR_A@_dFVzcvwhC&LsRPJ z-1lp{DWWAJnIo;Ef!CL3kneCxHqM#=y9qn@oYdAbBMm;UdhiYYRQFbFW~`)J#UCp2 zsn_@zyKB7+#~3$XHK)Rtq`xYR5W9 z%}B+_xJ$+!(cDPNfOmC*ynzTWs10wE|F8Q9)4lbRSzNUjk>nud3 z`dcJJrD!VSFS|y_4vln{TW^fpv^{DexUW6z#>XzXX}v1JJb4r|`o`>PZw>txZW=me zb8{7qq4%<<|H@4l9T>S7xfmVk77xO57&=E+m|5(uu;LJBvbEXhN}lTkvBy8`{tL)FKUhG0Ne`HtWWAu_cH|Qe&#g$lE zbGSV-lqA&G>29@WpGhk{O0@L*xcy^0Vt3tzUX)i={qa-wuT|7Z5*i=Q85(MjGR~1l z`o37;SB#C1_>pbVg0ZSz+Tf*Xk8iLo<}-Vj6AhJevYJuW3RvO`_xyrx<=8S8K2GW{ z;LnsG-HjgBdZ&D-d+1Rpi=E0SO$zFQBCQw1Iz&E1&PAuh?f|9-t0$zsk;%$!Z*g`z z_w7^W6nYJ(Qv>*ZKaE>1_Pblc8y4giy>xf-r*YQ$;xr4D0=)cT?F8SyT&>~7?n)O>`W%54%m?+*6f2WKSFk7))o zxn0od>(K@;Sl;G)+eRxd)7f?Jej8#2o?P8U32Tku7iIX$hWIFbc~)e57>{K7a_x0WKT55 z(TOO7NC@hCRxB-egoIdqZ%FW3PC~!YL*{h5gOkO{X>YXp8l^}XommVIT6weF!m-ot zYDgSJO#>y$V}+e!p~9iO&KSG8S&|ml2SgumtQ({6BM&06SWoW^{~6Q`v8?77`>fN= zDQNe%(y@Q>J+* z1Dnhb6|}k4(kMu(sB^rFcP92N`bX4>)`R@iU-Z_si37aT)yeLxu!VKj%u79RtWSAb z|9jVUtGM~SY(Z`C5}C*aqk;7&u(LwpO4v1 zIvdy;;C%1=Zhy9>7+2|L^g8+B72?Ec*vrz0>YL?n3vj zcRzR|Z=o-AyAiRtvmw;Yd1{w330;of$xFdJ_j9ae^iXtvtfqS*XfCIrt+bJ`$XelK zaHiNh&Cl#US%KnYo}jlk-reS|@zVK4cuAEB*I+5k26kR&U8s?B*0zl;G&8V7|DdtE zKb9rBI(j#@(#suel@D<|J#Bol&NykDLH1m8KN~E+^XP{^z8j&av|js01Cks63M zvq|O=y9?Z7VP~mz#i&6R>1PrJraK}Ui7t*gF7wv&tg10y$ZDHStq)GffnQiMf2L79 zMW+%&{m))nx3hb|TjO(q)eXYfJ1gFv?96mrr@1wjJtU59CRX@2+z!#V(M_>>?odA$ zT>A(XY_GY_M)oHsJ@ig$IvqP|lPKz6@u=Izz3C+eLjb8IfaPmgUG1aJWam#O-pbE@ z!Q<2!k<}mP7LHztZi!8F-}(ndR$Yt?F!EZ|E@(fsUqjcPqDfI-73L@XDegnJy8Fa0 z5qywX?;z)l&DL@Iy))DqW$!Wnq8@suGV=L;ZkI+6N4Ligdd-8{VxQhgo*7H6E_OTn zlD*!VZS*7C^=CPqcl6u1*WH?~>yP8z72OKrov0XTT0d@(Lq z=wrCYUfz#^A%0T3aUS~EoNX_2raA-c!`3)s9=WI|i4j3^uT<=G^iDLvt>F*lpH&~6 zg1$4y*~RS(_DE~5*_k!MayHvYxlG)BN=I? z(+Shx1oMHDF%m22&h+n!{>sM_SrK!G-NOFIZe_JH66kB32Uuc*|I9lKsJ`y)2-eAB z`fpN0)rsx( zas=~bAM_oW${t&`J=1FY6}4B`AMK>zP3Dn-`n^mS%=TV* z1-vZYbbmeHta{+u^n!86+UTTp_B&~<0f4|SsI}}93GP<1JMaT#(K+ z7Fw0k7IbWeM={m#L2@l|gGJuh!%w3`8kHnXRLfAVliwNg0#P`6<$H*`)4uQ&Mq zReA+kV}#B9)(v~KJo2Dq3lvOjO*_wvGUk4u9b z+*K(6fn&|o)?ItQ9kq{J=Zs4fBU`rP%zNOPknifcbN$x*XL%m2pwo@dR%bhG7q$K| zmjgc?(HX?^;HzKM_1*K{(O|F`tXAQ4^nuyIPHA7Zuh}iEN=9WeR1X#xA(?D)lg7%$ z=DXZa6lqmooSr^2^IH?FnDxkNV8+vrxU5<(1_g)xN*;W|$j=(MGPSM}U?ijI(NuYtuMX1t8ND&yIDZWP zRlY%W$!}~oc;!a+9bnM>#&&uNmr)J*0)LWM5Zqvb+s?bsbIW}wJ?Y4PH@8_I?DSS= zvp73MPNK4ME^p>P^0YU{+wC9X2UR(Al*Ej9(2XI0)OuzV^t?9uOFrjW{p9W~H(yM+ zQ~lI@xXO*zk$(+rzOhr=`K`LfTUMRa(3fSl;DtZLyW}nPUin&t)ec;p{$>odD%(qJ zZkL0){6%)4qOx7E!CU1{aMQba-Mjt({$3ph^#5vfw=&yB>>^e!V*=D=J0NRU@T;HR zTjlKq#p)@>=py(9%VK=7#@L(f1RE;Jek4?{67PaaUKLQb3~oQKs{c~716F>)sBzA! zY8SJ!n2APangeH24@AeHi1);s>^<=32e-t(dOm5%)|id0E%rKat6$6{^b8&ZT{|m4 zUdV-)M!I{vok0U}44iTU*4z16ZC0`BSg$}|`m%N;jgHFK z{H*_v_q#XIFCTQ}Pvr|VidHbDTJcuI9tgV8z^F#{q1^H&pXs-7SI3?~j;QMI?(HdeV7_(_7cva6nafK)MXL*~vGyV-= zoqRe!p3O3uHLX>4Ht4ZMW-C@6&sHzQ(%^URg*(Y*?lPYRSHvl$0jpWeI4h0S)2e1J zHFA*msEhhe)C`V*SKi`14N~!k^0IzNet@1mZuxdyOIhWOr}Pl=RVn^9NCwK*&PDD4 zzc#NX+vwFKJ6mavw)$CftwLsVsLKqUAQ$nIL1Vv&H{W|4VH znZ_*0v@7LRKG5Ih)pF~(wtLlwcQeB&rY95GTl0*y+1h9&HMuJ!v-10B^HT?YkE*>Xy>v4ED z-DFI#a@kq!OjZ%&6l3_4?k4^S`gkwBr0!w&IjH3d5$LXXKAmq2Ha%;H)!wYj?$GbB zp_Yn@!6^SXKf7PlzsbwVF8VIXz>*lZAcNMkD_NzDrF1`@t&@x1!FS#Q_l~>S1=AB; zl0WKw_$_^CthbU|M`6XnY$dseE~^0|YtY^w;1~CQ33Bl{axcn7`mjcz8}*@gZ1bB@ zj@HHn)Zd~4OdBS<@Md6VLHB`ltA0`4;sfYgt?4qWQ+^ z4t%!`@DfD?5cpS+)o>sL>n~-eWaC)6lQm;tCe8w12vdLenMFwjZOFa0!yrR zeeY_J6nLx^iqI15y;;c01RVbf{McAP;2`-kaP1LK`1$-O|4!^vcX3;K)>vWQvwpXU zwb5+KD&l8)zHAJ*a@+%MNB5l<4LXWC>J;uy4;$Ugsa6eZocYRVN2}r#8VSKof0*~D zZ}>j1E226BUdxgiAFb5ZaZt+{W(k%IFMz3p8{F~!bCT*IX308yh zZ*aSL-}^K9k1~tyPY7#jd^In^t_`yR`;*K?W!3kDRI!VEUdn*8Sbx>s<(@iLq(|I!eDY zDw}Jpl;#_=z0sK-z+F{LeBhme{C;(x`6qd6*;=>4ZRkYEL=~(TP?i6TtLz8-To)3% zgVTN!uZ+9cz2b*C0miG0d(d6RG0U)iGGCY}*lU^{{iSM)GQk!9hM&hz?!V_dkspQ(UtDRZPZ$kG{_D*#M~wBXTK(7r=$8URxGm_hHLjW&l!hUck(-G z1?qb{80qivE5j+479rIf%_Y-VFS9IgZ7OTB*@)euNziRohM)4^fcAdxe)3xS`}ti} z3Uwu|SrtQD8Ld+0uSQk+ocw^O+{8BrUH!lPdH&g8ml&juBaggfOU$BHU+X4t#8XzA zOhdm&&X@Sty_;S)a548`PE|%NL+1f6&5al4OEU_-`xb4F59>p6EMFY-@Du#^L3y4> zJk)7%6IzU&hAB`{Yl8W}7(h?rn0DnZ-rGOq-2hHL>Ng8EioH4+E=LKQV*G2KFwYo| zSs(Hc7uSttCEhn^=(|C-U=3d?E9;^754zAGW5O@#Z0tP z0RAqKf6-TMOUe;odZ%~9uO8&(6XbAxof!0#fsBYb+3ad`rx&qA)zx%yl&1wfcpvoO zl|?U=6cr%@fX9}b{h?>Sm|58bG6D@$lR*Rb`=z|;-hRJlFn~Xj*HCuSo~1LYnMuvj zW^JPqor8DiH>#8vA4GlOKMh9kVd4+f8Vv*|vB0=(&Ne@oH;gE&M+%|Ts(@$~%I8TE_x_V$DL*cgsa@y~@|E2+ z5F9SbqP~*`l60m*7A+xagli{&fGy}GDRykQD z4^H_n{l~#}9+5qD5^U3AMq0C`dCEL({%j1Q=kZKkOE%>@f*-uV`_=n5AmB`rt9LjJ zt;H0uL}jyx@dsN>&O)R2E0+6{ElTi@DM)Wb|P_fvcUW>WY3GUK8Wj^TYnq;GUZ%PrA|j|(0KV}ir{1h7sEcSEzJ(VWGTO*oY@Fa+zggZW zO;160&r*BD_TYp6*q`EW43Y%zMIY50x;qW+#g-cj4d0juE;$iT))MeCi02K~!5QY@ zcV$@JMXzAWk>1E>#+kFs21W_G9RG)ksWzg0u*#q1*Y;-z-|={{K&=8C45nwA5vJ<2t+VE*v89>kgTR1oRM(W&S-9?G)J06jTFFlv-AyRi(J6~zbkm6 zRY6PW33#zMrsQvylxgFj5iel-oV zrtyXSO>LZ2w~?Fq`=Ev2-mm0e4-WEsvaN1{`_MwHGxW|rv@;4gzi zLG54{Unq7dqz~c4bR~-!$IL8dapO-mlN?5e)k|5N&kW+hw`K5e1s_0t|I~-^J-UJ2 zGDaHzK&|uAv-lIrs3yoTUmHvUrd`6gVK`1G%zw5YmD>83gC$0c#+<(GKmv>crY@^2bK9x)>WrbFVc(^ zGRBxG%#6leqbU7MEd5-56P>u_KlF3@m4jly^6AuWG?`3d6^z=(Mq`;#lZ~gTaRJCL zyTw4z={Z5GAP`mLIb8$2AbX(~x0~4vWlRG^|NoWy%PArh-1YB(R{k1{6<99TKcJ7` z1$!B7jm1Vg_8Pi&Ejp(Dk@dw7yn3)a7{^PA<*I}}3yNj2UB*AaP4A6{Y!J&dn`rbh<{D+#M*1gdgML%1WhN2FD+5bx=3T^fH4>%3 z%RmGFG#;4+jO#`kmW$khCou0Nn;UZ~Be9NtNDu(3u9qYGU5EAjDhlos61W&Vl}?DQ*X zgEQ)x^1k?mZ{VGHZ~ljvAiwHkxG%XtpELNhlySfy^fDQQ)94xU9QdbygEm3qU>46R zs!Lzr$Aig1dXXJ9su`(RVG_ef(XXKUKZ~TiBmapn7wLsi{ZM7BVb67q)W%w4IlBt# z@)2<5$$ETOFgwT-Gz$I%_1&U6q53#R3$je?g;CG2m<@baQws%s%5MUP72{h)Q&~@) z0Uqm2;all&-5th!_6IGG=Oe1di}$=;P|g1olnb8o6CzLt&=%5>E@gcT$7pIG`i1mG z@AYg|Ok4o0e&H$kVKHBB&>2tyxxn%n*cfdbHpa5KMB*ZPx(bUKJarKE&jf`6&6TX7 z6gan&G+>8~AB>hPk=`X`(GvZ=yer1>7Qwl|h3lS@Z^6lzrfJxCIO`q88DOX3ki;gR7_)C9M zZDeZxH3))f!At%@R#2-^cKn7OHFAMYelfNhDXB-wqk^i6ILrsZByEmAEclU+1oiEK z(m@5!v53(J5R-xRr^RqT=p0}C&94SJ*a$l*B-iK^Xcj3&6O1~5=YNg<>^NNpPX3yF zBHHn?L4ALlzcm=b@5nalAsS4|(N9JSW2n&p@bVpbhO_I+a*tTRPr`}cdA7k$iPzsb^Hr}=#3(k+^fr=vyf>GBdamoD8^RPt7H*+ zsj2KETJqm{u0ZnPVuz{@JzIkuU_Th0jnCl4Bny$-Q0Zc_3cnIO4QlxbL8{=Z=&P~; zcmGI^u);=hxW_Q7PMeVQ(6w7+dXb7x;-z?TsEbmYP(6H%CS@IrLB<NS2S9)6Z9}yh#Ts^ zR7$akZ{`hn6TV6`mdkWKP|Csdckq^zjjKizRuLS`Z~CjsE4uPzLFb@i&?k7$-^n4m zHsYi`ox$cA6^!a^2^~(#0A6~_i=sJjPEp>TUl+^de|i;eN8tBPK+PwC`W9psS%Nd^ z+43PwYhMR7fOY2b0-_Aels4ej|Ko`5MtP{;5J2iPG(jf=SDTNw089@S1~`)+^*g+k zW@P!8YfOa>57Qf@20E+@$Qe8VPBD8>6x?rbFjSy&n2FX@~Jbj zCXey_JUJf+p0?xg(6H#NpRS~`uc+m)c3~uuS;u%aD>JW>z zW);~3BM*zPbmS=Hp}$lw8PD(WEId8`U5t@4)N4qA4S;oaLPz{+G-WGkHM|fqL`U(K zkA*De2bID7nzEw0gcgxHbRp}^9vkuCH(rsE=$#%4>HI(b7p$0%-x8PP8(j`PB6ERD z9zgwC8ktxt65tAYl0sq)a7nv>Lg!QyZRJXx6>u<*{==rTC+t0&Pk;Y^-=m1~N z@SLCq67;GT%&`lR+u%Vd@Mk&pjD;c3{;RXd4Wc72AG8hPgW-IT*b3Y|1m`8!n8miU zhwKb%O1r@6)KgdGA~BQi;01V7kyAESi=i%Ei3dHK%BT(;zY?_fXS7<~l`TY0V5bg2 z&R`wiCy8pWZ{ogCm!j+|xm=}u)CllWl8rV>81-2q zT)8V@sHz$c)0M{ohkGm?{Kdb>mg+1jf{)S)tP6X??y`RLBDsXy>b=mlS`^^(d2K#N zjFJy@eYA(900rD(G%*^(U#5fHbVLX02eBJm){CHP&^-7gvIEO!LvskBeb{LB74EV! zg|vv1>YnnAxGK_t1`g&IV8W40Z^j|gif&@(j1ERUwufFP$8jsY9=f|T?;czZ1_h&e z4$(~pdLsHjYS9&JHROWhED0@2a-h?2-Ydiu{+=)AGkJoDsi7zt9!?I>XY7^H*QmmN z16=(CUbTuGE8=->a4?g>TmCE#!YTT=Em=cvvEzorHUNv=!pBf2bxGD0Rrm$Ik)IN! zWL0$){fb}GBrGlSjBZ8_R*h!DPtj=gSmx$uf^Wgb;P>DI-z6Pzg5B|X@(H@^f`Qmn zx|oc{EkG;B%A_I%-^#b~_t4!7b#`=>l%>sCCGgYDm(N>y6YOQ1svur*$@lUHqJnrK6CmZJBqQlW)_}b=atoUj`OS zs`Ba`z&iiXM{Jg18Tr{!x``A+M|2aY-ymKtSQ;$jHs2#w$r$|Q&*T{0!Wu$Vj4lWu1-0L@R?dWOk$Tu@I?8NjPP3EW_6a0z_YHhC2i?KV=KPGx1-P&Sa|p`A%u zG+C#U5s5?&K8w$Q6-%pjdM^4(hQlcyHQ4{S z2GnIc>%eBSek=}j$VJ^%g1jPLiA;O}pAWs*NKMu!p?;I;zw9Kec%Sv6yTB#C(uL(Q zv4ZanqTrNY@N*)nis{klGx>$?V69=#)#z;+#@A2{bzSZdcOe~|;+MogIal3)3}26I zrtjEM_JwU_-+}h#Ma$F&$lQGa14)A$kcLvr7HXY-jmwdB6!Hce0Gu;{?7#zcf*K<` zi%lXszt6ci1Wa2Vjlug#BFg~x7h^NPwS5M!nqQ5SjxZtTc)?R%54voxPKUbUUBGw_ zo6knl7%fj40!K_!Nkk&lK!FE5D?Y6$RCZ@Bhv(A~$uZ)_y< z@IX{S{VRuw?)*RgLgW-{w_!=5bSEp$da|T6H~t2vxIlG~`9vv52SSXK#Z_)_j0vP2 zaQt^{E<4YrgD2{bsot!b3B~{BBzVlr@Mq!=`A|24*+qF;7*w?~>qIq;$CuG0-BJ~l zw#drQ@IWk;T~tSKFj>hox_}h}3~pj==|oZ-ozk6PhW>;f<2ZQ3+lY*k!L{eZ?4loS zPG5iumZ#UiSx!c!!0QC!6QKWZkw#pRJJn9m)HdW4J;Um=$!rqKPwV0Y)K`b(O_+ME z3?h(A#(?TKS0nXH+>e}rS%bw20}9rW)i5*pPn`s0ofnj!5!rxRtY{@>z~82# zM`;EUht})DipjiU1iZfCh3F!Cstqs^G)X-=jr9SJAI~st2rl`Jt^?h@hd+n8KqAk@ z6JFh2~A$l_IjBU%B|8n`SO0Is$?YYB*MLZ;x+=zDcS&K4I$Q^=^_ivuv> z$btrfKR-Z^vN3=H;63seXm4NjMh<`su^ZfK1wIKlV!rYq(RL@}A!FrYKhjgwB1Q3! zI;K_uUe1VKqLCO3jwp%lh7REC`(}&eS*#Ul5KX=&e4k zy2^A=mm|Q9=S5z~+?DlC^a1||Np&nuq>pJC(iHbVzv@;hhs-LLh>2pKw4onPp{#fi zs6jbk@5ZbNJqC52hlc5fiilG%jhqRt=#%IREWZ{qU|Uk3hCvS)Fn21F1cy)x!2V5f zN3<4Q#4%X{5?crjz?UH#OkiPfZjI??G8xxIS(Gmii!rcTdr%D|mdmN?5o(P$lSQ;5 zy#U&Bi<2xu)0y->A53$^=8z|*c(g&y0Pt`Fw1N_)L z-k2{Fxx_t~z@~$)eM9chzHon<9wJZiUNl}0S0m&gF&8+jo_Hb`tNwa6a6~iOiE>sQ z)HfTTAQxnf9;%AW4LEJjOTtvHCE%cd9*Pp77mLw7^fPqMGB}-IP;Q+}!FNBwQ43KF zoX#mg^xrr;@aJNd7b@MD*|at=?OZ@XSi+~G;12VEo_B`HMMFIsvRDV&kY1o)>3cdK zoaIQAQzMlWR_w{a*@}O`N1Oq?WF_P1YEbjetPXW)1!AEopynTdODJ!|Gx2G#Vkgxb z=FTC~oAv?@#q_%3Tb!Elr4Vn&8Wk2Q0 z3*xpQyaO-9SAY|ou9oUQaRxGo4x;bqH+lxRdp5XV50cX(nN5s`v#t+%6^7H!j%$$_ zbR8?l>OxPkU*W&;{(Q4&CdaB*s5ov;I)N8V!79)P^gB`o*F_nCb;gQa zz&bTVKk-)H(>c*-P|7vnldG{6Fo~Q?=Hl_F3An8BqAfqbNAk%Wb|iP`)Tk$(2#&h_ z|EmE#OQOWVNkCIq%bsGTXdqfaGS3W*+!7tcPhf&Kmz87_fV;Z`_Di6UIwISNYJ5A? zWjDChv+^By%dPl0Sx(!-uHyk$M}hB->5b|a*+9&JdmJI|z}Ym>O92Jx2)ywVRHG$S zIv;fRJ4nbgWpz;+(&B3V6nHTN$!Q|GhhLH1v>ClhpVDq*JRXC7)1y>7@V`q$53xa} zl6%x5eFbMG6#&yKnaK*!+c4X_jdtjHs;4XgQ?FfchmM#Bvye_OYd1+!a*;Nr2k8k~ zku=5?Q3YKSuv$$l7JbDLSy{eQmvj_YC0%I&x``$-gKi^N@M_dkHv+}V3eIu|%=z+) z^Ky!sqo3fSqyl+QThLW>CCy1n;fyGW&ZP3oig1tpfoVId^vXqPa0hrwQ;Y7V&*=*~ zh3p2Tme%Q2G8q!NV7_uxloOxj5$K%=T)R1Cv@@MgCs3PYM4o=FJe5Y4`QM5+xYl>kDcFbnSid9ZUuuh@tW) zaEztU&w#A;v^4DvcliV8%Ndwj4pvj;C7DBPgU$)d2kNZejrQSNZlFN*6GRgQOky60SQAM?f z0%Ahnj-V51adLuW!R1jp^-*Ej3w-|-aaT4|RdgHF3D+m3;k1u|QcfaYNJZQg)r2|r zW$_JAnne&%1vE7tDp(9SG#in06dg`egR=dLv3{%mln-SCX^2-6$;oP%UXC{588CM) z2<-Wo4kH%{!rwuq&jU+b7Hvd6=*3@UQSe!V0R25kZJLCRgl7;5q%K|ru6B=FDEG;t zlEQk0pu@K7f6!Ze3AnZ_Jp}u13>4nFlc`)(*872+WL`hLf z^c4TdC2F63j{@k4$uu*p*pQsWQJfRi24vNe13=wkGPfKJb+KW(S)b%1*TMhpp_`!> zE8r@qJ~)ZevalE~ii^5pfpp|G^%guwVa&-=nwGYL`pw6Gpa%#8vT_4M`9jNDa=&V< zE1)iT9BBn^r!^pT8j&Og4x^Mhi^?Fs1BNdIjCWX;gXeK6VFufYd=I*c@=$mE6N`(LH@1o)Ec!>7PXr(HqpapDLou zqF;b(Yl9XgqlJl2TH^k|W82j;m0Wg!N61WS(;9G>1<6Xh6D`*( z!J9mhCahK&<_uxE6|}84nuk}ArsOnH;GG_ma<~y{ttYFCDqi-GDP=*qR+Uz-^)YlB zUm+`Ka#{trCpB=y0yJC?RI}v~@fB34oR}rE%NuH$UW|_7i)0co8T{xR`G@4gKcXTU zW_I#F*-#oXpWLO|=(PF^`iv973FfCYVLtVa)WLKsT_A(Fb+*L>P2vh~7mI$DN<8)oXYF6UFijM&Ub4d|A1FhC;)KvwOVL4FNhpB2ojr3JC2e&6B0sBQE zKb!*;Yy=(pU9FUNKsR0i<86mMe^8h8YH*h=NHOvk@WV;c6@SCEQG4B1O_G7!D0@Sl zH>gIsI7*Ek;*~JFuxMSHg={D3aZligo~pH+D^mmVH;NO`IjMD={)qm-lSw1;loF^- zU3>X?ofY^luGL1Wj$KtE(U3Y1apFNNk2| zR|ga@FG`Qz<2~dT;?wlx3OJn|NTIAcvnnAs$gZ-b>?2RAez0N}TpGV8^CA8Ape4w9 z{2FIQ<#iG8mQ}YguVh`-^l52zV>Ehy16l9j9gw#`5;kYsS)-SukV+SkAj>1A!uj7;hRtau5Z zAl=D*xW^_mBc%P&;K#Or3%w;`VhHs2ap2Ii;5oLywYL*^`a_NXb(xK`p;~$@d>-a5 zBo`*j%iXGkdJf(A3cn!piAPJ)27uLGfc+kNq*@^lf*0%w|1Q9O-l?Pd5@f7IQ1MJO@(=A5QYT>a5eir!yR4z;%<*;!x>tq$aL`it37ht3~1;(N1&* zrX8$u0RjV@nlQ4Qyo7FykVP;Dy{n(=6si?C9hykFN1#~mB1;-fkwY3!$2!H0RsP0>HepxFJ&qDMjZs_ z-5nBbCz=}ENeh~Z?8geZ`m#C-btwQIrV@Dcr@$w(zG^dey8 ziGZvsaOI1Dm=UNyV0wtWCL2NxU&FlHP!atY9miV$FIB)FbRvoj1-E)c&rtp45}_d9 zHG|a6;BM*iNP<=T`Qn6c1g}FdoRa_TE>Ch*9mP{d4c&8J7JvkLL|+Ca8bi{f^G8mu57ODq$Spzw+J8;Ahd0Lgz1Tky@3i<$p z76pI)g5(8G?xSY{UUrE8W9mNOzMB94@t^aql#()|q@lf~L7}2F$Z9A_OM_Gr?U0g0 z5*eXVG?bP^DoT54h?X=cqKptq*E#?DIr)5l|J!woi|f_%^&F4q<2lZ`uInG1Gyn9@ zSn8)}dwfI}Gb?j#W?tr>%+buF_BzLcvT?g;gt*+2RZB(KjJ?mZjl3*8DFgo%>&7Zp z*|1h{d)!;M`o`(~wjtwAAI!Ql>yKzp{CgOLTQeOp-s$0;C+$IZW5(L%i0N4sMY>(q z=h5BqWkF%jaxeEp;L>b&WV=IVU8z>ql&SY;4ac<)nHUe4rE^8cf^1;{%s4o+JKMQD z`DC~tSQj6UD@I-PwZ*aB?R4xGm-TK|RqXVcuJP7vO;d^GgDc`|%&JeH-eN8p0^JWq zg`?BKxnYSg&WzNHMXVmELs%5=h|i1eQn5;BMJl_jvy=k zCC)_EvmVwpK4R;YGiy3)s>*Htbv-U#5HbZZIK!LKnIt>snYG=*eO| zJpW}pEqF~%_sSgPnJ+S9GZ%&RgW4GHarI!3j>VIiwSf|)|IC})z8n)Y7`ZXPR5&pd1jsd`i;|>jdK6@@Cun#IJ!sg-CwU<%}($E zUMvzE3)f`EXDgGfNw$2McQOTaJI!ojs>!Ilr$06`Zua!$E_=(1^+j7V<3!~&MAp|) z|LiS^V^Nu``R0Qg)vXO`;8Q`TutNA}W`PWBB3B;?cZ3&s59hQg;;z$wpI$}gNzXM$ z+Vi&#uLzG}?^E*XMcwKk{Io{5b57QztcSAhQ>{;#u@+*+yD~Yk#AR4#N2ab0Z>z2D zK2^1WiDL)kRLt5EeS|}w4V#2f=FQAsB0VTPWcD4dFZ$T5GbXEN)&Lc&O!P~hv|(czb4BrnmX?H~G>^?tf}N z$jU01)g^0N)FZw@Z96x7KT|3*Nc4tga)fuNFMHz>s^tb2Kb7@GRM)&eOvSocUOkdo zq9XtUdp_ec`Q7cb`mpmJN2{X>hK=b zP2Umy7*Dr->SKx+53%3z;;nj<$(Zr?s7lrlmF>%{+*yO8Jm&pT!5|y_Ak&dGlQW(f zn(l7$+2xO%%RMOxOM<^Pl&ce7kMw`HyvYcnN{9y z?md|3CxZQcI=8Sg)OTw2jm3i@5KB^MV3JwL?)xg(GFmGq|5WQSxyRJboJ9q%W3&Jj!0Oie^@r$n|V}Uxi<3zE_qHT@n@VXx-n~!N?APX@~rNx*%FWQ z{#cH1ai)P&-7M>gnd|V#kK|2W^7QL4~+y^giDC zUS<6wsv6CW9|*29i@jj;H4tvz^7QP@;P0SGJUp74^#=xRst!GZpE{d$&XN5s!d-CI zo5U|M?R-;m+vpuV-cCOMC#nsz4~a|O5FciS=yax=KVJ*J52|}BWk%M|@YPU79g_8> z46GLv4fclJ!vmRmnVy+OBwic5t*W+)rr57;vrEn%HH}uO8n=a)$kd|z_#Td`8jcFK znRL2&?({wE)WM)*vyMfNd8??jEzl$3LG`VZEZ7*94}8Cv`l~0&+Adozj5fydJl=OUoI)68@E`ooT~6%fkY}1M%na zRng08)`qM-qW3iHObzu0+DwKkXchNZ)g zGI=xC>5huYmndi$zhnP22-_~=>tedBBGCA(+|S6E=QCsMr~TA(J>zt2a=TMEL1PP? zcXRZEyB`mmy1RO&l`Td&Xbe0J91dk2?B?IK*SRQqBd!wfQdJ+cUwu3?MZVl0M&T_s zX``d9cxQ^bmM5#W+-em48qW!y4(|?6W$w^z*>{-6PUG4h(HGGjS%;jR6P*)Hi0i~h zgIVFDnG!6XFD~uE-@+S%`*dzgqC#1(WL=e&FY5+REjq+`-e_5LL)L!%$%5ztnc6%EOv!_6cV5dZ#G;MEUE!6%T{^PqQEqjkX4b`KvUSnJ z@cm8jPS_)pKXX5cci2#m3w{VLikn35s=x%yPI{=t_)?)V1yt|HhtXGu1M~@O=GnO;|Y? z6>ruxHq=u;u16SZGPyzjv;vEs7rvIsow+$vj~BgJY5JWM{T8)1bNn8i63+NF6Mpqn?h4$vAZ!$V zn8_mttA=|#FPRnOiyw`4naKXKwLDK;w%D8$555mag{RH(eK17@oBks~Wqs)Os2t4R zr|vI|F0mo27vzGncKAD2rlJ{nt*-yM_*mQmzOT;uPBpkF>ZgAi7F;9JZ)MKQ+=-Pt z*4bL&EkB8_wb6PwxJsm7*U41Ijs?P{VJVek zMO?(rhA|cB-Yd8J%Jmuhtq9> zYB+r^-YJex7RDDxW20g=YU@ZGW-s^w#=9t7=GLB>2SoZPe9wq?LG3`@;8 z%VGJ(yf`B)t)ef8{)*bmf|3)#lrbf; zbnDSgy2f5MgLA_M;a6%~S9AO?Zq5qsj7LQqA!1k7#H>-?(6~?qZWDyT6t!auc{SZU zUtRs!bD~z!QneTI;oL*FQZNeC_7$81KBSh2#w<@nW1eFsKx4 z3GWMk%+z5^-f)`klie+=&qmIe87=rBFm zi?G<=9C&fG+M8TWgI~j;y6;xHlS{(4^`WEU1F$okhKJ{6x z%5(^i*v`$2v&_kT^#_A(B?o6Mib_XY<2PU;6OPo$G)S53`QYE6bG$k(5Iq{@%sQBL zBJvZ@ztEiZ?hr!vhj*_ED7?~P00#x3TEUh2%=sBv^O{!kSx9=;j=i&1U} zPkA=IPxjB%y>&N1eJ3t;qls}DOg24i?(L$AnJ(~MD_k7r3)RG7ihVb7la&e{jvZAH3ykV8-Qn0JQis~qh!CG3=s+w2Z8 zCtshnn7oHn)dJpdtsegsd>VEPH{+dhD*vAFwqTODw8uNG<t zY%lO+6va;mWrBU46y?NZ%`>&bzx6wtgLC4$V63M8WCVO~if)WHdmkr{n$zOXQM@6EXdYHH3;_s~V7@vsi;-~6z|8-pZZFG-m zXP^rFS=csQXOjLYT#eJt)5oljYews%N22Pg^sO-4Al{-9{X*iunW{RDQ{kNOdfqu? zPd(X2`;g~U3uS9>z1B;tS*a6U248!^S)QT&Yi9feL#>J)C#|+hvo>yS=6@jgBYZqO zZoa(COglC#YFGSKTrzq!x>9GfBIUec@um8mYsIjoo&2$ICys2QW;KuJn>jv;21a+0 z+0RC+w@CZxP2tmOOeqYyU8flYz2fD1w;|DGcz%Oto5i9jaou=#aGy@Ji#mBU{G3(g zf=_H>$3{^!KI$5^jM_ynsFkBx@_tx8oM85@MB-}C(01tt-?SaL2Wof1_%ZCg(hQS3 zcqP1mq}}14;ij-pm?L=JoYgJ*D(b23)^mP*oJ%iwTW~nM*Jh$1<|)RaI>Gy}^H8+h z4soaXX?@m7eDYm9md%?n)U5DCCbvH8A#?JB@jm^|Yz$U3suZ<}-iZs!z=!nn!}Zi< zu}LZYQw49F{N~B{8#>^RZL5}vOY7(-oAkSEFFU9mft|!YmH#_4%(}R$?z@(!SXVeT z6LwZ(&|=|4`^y?~zbpdE0Awe6)SqhEcQ)Hv$GKkvKy+;Au~<}+m-!gxD^y7BvQ zF-%s@nTy0`fqJk_T&hA$R_00wzasp|vz1N|Q6w7bt<(uR$L0FV$4$yBu|$z@Ot?pO z<>$*z!8*Of1f9{CsBDxGz21?Z6YUArtEMMEX@A8 z&^<2eIr~08B|L7VJDCgJYstGw7E6j=^kC+2}2_B zSUgwE@@#4dWB`*_VfJn~Uz&mE{g6 zLE}iBR$e>Xf6elf$^63`+~rjMerCbZ;Xf*MKAClQa6m6H(bJHJZO8INdFl98e0_Wz zB8qwo;v60IotZrNzf{|LV)>=XM3(h$G&nA=7Cj!G6%ON{V(Rn~edsp5@{Bk; z?9{}zrJ~!ScjN0kS$&nnv7WBhG@1PCZO^Qrr|$dmXi$_(@3!7{_44S&xQ1uwBg5Rh zw+nLq4c`r~3Kj&F(tc+s?aE<_N6ir}%~@0N&Wqt;m9<#7KkQ3VRrrF+nt`#6Ve?>R zP%WNm0)AFxzE_Jb70DIQcv?SyiB9Hy`L|UMa6vFuU42aszNV7ba*9teUZDP#^Yx^1 zobrUDjb6F7>@O3&sT=&obBmJEgDUXN=Fn&KjqSy5E$oa8FAiP|E|#rj?X@~bw~NpF zakjWee2O27s86&lz9l{!4Aa}T;q&?7Jl5w8 zMw$g*x1aw^pVvY?SQcNR1I`w_9+omAe8!fqRLcf>w=3d_`jdGwC5KF?X>avIe79#3 z!^HX?XD30#{q{Qp<=``{*~sUeqo?In^>~76`L@W6rrkP-cwWCVO{E^jJF}s|@1Ktv zcpE)e+&|9pM(p`&%t$i(nY_OZ+Q;9-z4YI!&4WF#=}&R9cv(;__&B@{Lv19{ysoDn zZQtKE`bh+9o5#+!MOYY@HcMOz6{W(#xOu#P)(iFox5b~vH<`)a;pw~O*rE6yIe4?m z(M(Pq#mP&;A)Y6{Z02a8;~8W+iLxRYHajk>8kO>9YOV0qaFLsb(Q$v!LRQy_z7^x{ zurt6!eP{fI{xXrcT<-s7P9CDad{t-E!gH#@aGOW3RUaB_m?bKi(yQ>x`{5Mzw`#DR zj*H_OxNJP8y;ldYH*RZYY#n^Ay1f^EE7mh$L+ws=+~GuheNjQUSRz}O1eJA!#h~I{ zdUmj#^q{)yGw z^%LGGi|X+D=lruLxWksU7>SdeYr&S8p5QOFW!+)K$rd_bg4s1v`TlaC74r)SBBmOw9=Hw{$JWJx=@%=j1 z$8`R;=&QHuj3&}?Q_#v&r5mG#rjwFtdTn0c2xmV94+jU_JxZ)+hWx~V|;=}Tf{0l&0TS) zAiI5Re%hP+BZIj>tB;wH}cI~GsnOnulE(J;Ihwg-m!3jiENP#&y@I5 zo-T_e0y;jfhk8J_{H|v)k3iTeI`#{*rCB`~JHDwmxdq!UH35(ETz7t0P2aJK)!(F6 z&kYL3FUjgx>3CWWHZ+}N!zdRAbHXwtP6+3kv$_N)>>Cfo568KorYq(d%-a>@>Se)u zVP*LGge{-&dT9~N89(Oc@gkkqYG;YA(=q+io*+)6U2eVq4eDDSPoJ{~<8@I3W#Cj;Yo`ky z6#q=ee9^}&ZmEY_PGZ7k6L{x&yz_;)JVoM6^X0(kB+Oo;+X}G#1YOzF_S%!}-k)*z zA{o{d!iUJM&bp}SdXpypEQu@WC$0!)c%D6;yq%cmDbtDHqY(G86&({@XPcj8qL>t4 z?(WM)rZVk5(G8Bn5HG_&9;&nlN(_0lWT*!|PdP`)D4Z#|_o1M`F(uP3gVO;jT zo@ciW!9*MKZRFm7Cmz7`4Q!XX=wiy)dxZpM}|pYE4f5uC1z9^Cal? z=owz0tE=uEN5N2?dgJg7^>+(KsVrk|HhtHS)ot-uS$g*IenWe2RX*tMYei<3-QcZk zdBe_OmZxN&Mx)iNSH&fVCz5$p+|%KmD%*NB_&JeYDyvt@>Uq(fG%O>#21onjZhFx{ zf#-{Kd|#yR@_xf}K@mHi^3h8229UZ$bsGp{qirYd=E1~|uX!%`5zhOR#P=~zaUVD8 zk`7|#KZC)nY3SB@PIu6$kF{HV&z^M!{(e}MTL!fQNPN-s)=^d^?D#5)^L5}KnnV|o zSV#xe825e0tOqidEN>38k*h>z^W%i|N`D8U~EpOH& zu}u7~F5v@wa+ztODWCsD$G?JS?K|#N1K&*0Cx#IAJQ&z&5a{;3A0i^Udf)%JZ~6-dEN;x<)5Ks_S89U@h-#{ac5h# zMI=5Fy=B95N4(e`agk1Mq-;k255ryjG0v)kfYo;6l9p_IeiBgwoE zL#;5qeQG=LPqZLGJilXu6$ffAQ-ad>!7(-fjBUvHFg^L2LM~&NtmLL}Aly zACc~)1Ha3J;`^(03S*%yzl;NW+aW3}DMPoi^Y@T2Vi z9LDD0`C_>7LeuT$xV0R-&(^q|ZRqBdPl^YA9;fF!mx|yZ(M$OD8(#fWtv+Vj+K|cU zZa=lfP`%^brr>!ZU0CmU9tK|;H@1gr9ef3iN!9ug>z2b4_0_kc(PDmSPv%q6zW82U za4$DEm-|O;M&{7*d;8ek_~ZkeT!MxroZg_H*cWu*pT@FviS1xF8=0Bj=zKRWDXX7^ zhXEMvWc-NDi?_Z)xla*@F#Hvk-JR>7Qwkg;H;a@RLWf4^grnS$j@W3qejcVJU~kuJ0JYPgb_skBQ-7C>;G^EGdP=U2 zR4?C95iY}zJv`^kACJ^8Pm}*G?3iAXGdI{y+->_dz{wB9y1%-4%yXrwoRtl2>$)>4&tyc+yk7()1c3Dwe9Oy6S3cy4^-DpePxCf(5!4qSkqMoz& z$+3bYwurxTvVuyukj<+}>=v&Ns^~j%W2g~icE^oB>Jm<+5?7lf+Q@`aa9fvu&g0?Z zW|X#JYn9<#Tj*x;|4};rYL;0juP%%qu~WOwY?MfRT6Eg0F$ZMK?`dze%v9e2y2siC zH`mh_3r5=$)R$kaJd26#z#5wAJIlgDIAES?S%4jgH z-!c1d+$Rq0JO;D6HQV>tJA4q>p$8}A%tLOjtv^}BkNe{8B<}SDb*?AhXZf$abe!cG zMko0<-r0({tY3T@CuJk?2|Zy~xY%cBwbCRr&c?GITy*5`li0DT-AK3i923RIu(MUK z^{`2_O|UHVT_=$9f?lf#l-(Eq8uyA$$@@p`V|tiUe$at`p+lJ-#NkceIp|>1@;&)A z<4tiJ+wyg+{!B$L6c5C=U4um%?i2Q`bZ-e+{x5d?THWfPc8nJ5+`$x+`sZ#ws^{ow1|JnI_V&r6 zrl{^VN9UVS9(1lmutCRip51K|Q|m&Ry}^u7TOOPT5r6P=5BPpg7aaNTBJrZQsX6Z% z*m)ot$3I2lXH?dq!MF0Yg|qFv{k2l<_$z)@ca&6_Nj9nfKB-Vrvq&o7A7h%#V3Kc%_U^Bv!y>_ln^2bo}1N>~*pE zTQ52di;fY$Th;v$xUsoT{aMeJCXl!fYTBwDWAu5IRR3fa`Yo&}UpkmsO9Y<>_o(X6 zsF^>B%Ov>DZf=}UVltH_IzFjeZo-da@a=2P9e|oH(DNc@u4O{W6+F)BD@}0CWMU!x zL`NOUD0llFKiu;fo^RpZv-~>3BjNQB@i1Gi_GZ9yBKW4d^_%z&(M?Q{)%9&v;-Du~ zR3PzIb8}v}RY&cjZj5tzC+ai(_t|kf9m<74AKxEV1;To;xg?Z5&5sj30XwGicuu{X z0gX-gCwp+e%|jvG$MtOfH(25s^zSCZ>q$Il@3~v$xL@CKMKC1T6IO(q&gaX5?5r)Ru6aUhicRH>iVsWOak!HPe4#R@bp1 z{G4r-TIrDg;>Q*ueVu7yVsL|MG%&sp&rdM#%!3E&yR!d zsjA2MSnsedbCz93N#1UP^S%fM+SF}wSK;V8Z?=4kO|E10alO$>b3!e(sJ$K7so-^+ zksT!ZZMM4kF_`%Po_ItT<>{tpR)u6u5}D07tC0E4+bPj6IQ&;nPg>~RPX`@?PccO~ zmNZafj_`iTcx~KMZQZ0xnTS#TwEG)jhjM4|Zt$JH=VE>ONi5pd+u!fAy1cj5j(YZW z73m)b=it1xs!V0~R#q>!1dl-DdnUlM^$F8qahn?4%)8owZgiNHoMHXHq5f*XgU*2fp={y$R( zhsx?poh_#mJtFRn^%Em8VjdE|_T36K@X&q|Ur71H&oLwMtYDQ6+%q)Y|8Hu?n)~Ne$le(A0C*6H_@ScphBD@jK@{8a@-mPAZ zVGGE?FKw4|V&3Ovbq5_v4(M(zudA|pl&2WmNz8Ai_frh%_^l_2L%g?fH%2+mxX4Al*L3TXWhFV-Kb{W(?jSK{A1<((oj8F_u4Y59FDnA>DMNH*t@FK6M2UOLQdBC{a)Qv{3o zPKWGxVz8~_QW8r>N8oXZ`gU%7o9g|mt|lTUo3{>@!*_m99cG)so0%4m@MG@aFZ}(c zI`~)ocHGf(!3)%bbK|Sk!FBqw&hYrR+EEsZ{(=8`dV(?oI~FugZ1p`!2gL9})|@TY z(^H8#%{%MiwyEm>8s;n`?{ldA*U7Z6O@#f;B&XrFtm^hdFgNIy@@;c9;Rn@qqdi>_ ze7?f`)`^Ez4GNT>G-9~bwwdx({kU4>lhya*vWrxYnRLu6(tmpb_7bcAWpyik;5n?$YYOhCpD3k&_(*LnEe}fQI}(W( z>Tlcd_5pQflZ?4QceI3m?i1?+B6Ggyh+D9#r=YsbyIFk>tIs#(4bl6T4f^Sa{uY_) zI+>qg;y(TD0y>_Bl{f2he~?`r;^o-!L3w@1lyZp*yiP5tD>BpIpa^+6SW*w4Y~#l# z_38l~tF!tSzHen`Jy&FM%bB&J{evmEt7o?*)zXEj)dlFdO7~U64)rbdw2+-qHt}l| z4_CJ;sU0iy^%sfFg>vvUw)_o!x0{Z>&{OP;BDpZoR<=ADp9Du)eU6M-%v)u>!Q?vz z@NpnE71;l>zT;{vx<#xn*3F!4q95g1!nYW_z6ow8tG{!$F0S7n)G-Zh7R1*)`aP!6QZ&!rXejgn4?!AK{4>qWdR#6=h8TWrJ-UKfx2FRl>Du;U1B` z*VCNSPR=$boQHX`=|$(_va?~LJKd7Hbqa=h=)iNz_V-9EibF3`SvRP5#V}M?b?Z1U zuEad~V0eaSvbP13v12ZkDLl9Af#BZ=@i{PwO;-w`1sPo7nmIHiu>gDqNEl&_n zVCDVn>TCA@4WjQQu_!yL(spbrae%LWqq<(CUhd$XhTi#`ip>a#mCx?8B{;z9`^_6Auta0=dnZ0*Up7P~{|3|ksfSu(Mk{ZU znP|sR#$0wnr7kZ@<5Z8bL2q)_sOP(N!LP#c#X9D9#VoTLBqUesQYo?L0tAQ23SwxS330<;XQA>%~apRBwPXCwIuOl75Hj= z`zcvJ>C?Ajf}SRxUFutV+>~4P=M$G6HWr65b06_oWpdky8(+j5dE$+B9zEE5l~ebK z^hR0TNZ+(Zt{jK4tq`1W-d4D}%lk1oJ%i56OONUses}i}eaYwQ^jhe6I=IEgbCv$H zGbXL-R6B9`!gHgW@$EV`pWyG!5ZoQ}tcU$3;+Gwtg0neO#wEKn$yk^lkk4Mw$nGU~sd@{OZp#*u2jC z_8|+df}N9ir#Souaf;pb^@OYNZ5Q8Lv2j6$?bBHUF%Ih~qr8R`=h4e^&EIQ#iX+&L&y- zsgAihj@_C{{D&uJvh93tMGjNdbLql=cI>bYYJVm1bD!U-dTfB|7NS>J zt!W0upV)#m*0ZhV!`~rtHzw$$)7xl9ZmQ0lR1wahXVS^dwoBTg5EFnrC_ZEd9|lm~<`wSLIGCG--P@=+(O zx?8?BgRRA4vR1afsM1!k$(#dOZE#Nmk$xQC{u5O7mGLC*Ve=||$0Kh3U5|4=#FkRC ziturYeZ&TTB(FY8L_gIzbD@Ql*;z98lFE1+F zC(OX2wISjPNUI0mb3C!G;qKSyxQRuRu~1`mYmZFs4i!ydvMYS75Whwywi!+xqUA<^ z;~rD%L9EnXUKjRJUJU!F2`6#aLvkjOxJowm(Lv`{Jzkd0i5KtC%Z)Y>=7F7&{JbUA zai#ju)NHg}#^058M+MZH#@J=C?d?sX_9pbKr{h}~tE$dpJv6o#!#X7P!ndE>tG6U& zJ`e7c2P=5~b`^88*}R1ce4)rx)1!?rZRH?w0Er7=_G8%TY3_(+>o{?1j7wUYwWh>h zk$9`9&0@zk9{&&;o5pw_RIDYWzLNU;q}-ZFQX5Z}I;wTk zbb9BhXHUuHr4X@Hg!-p^yMg}QM5LmgwIR>HqHoQvCOm>2W~y0J<0G)T~R(kA11Gh1zTSAmQH>D}jw;Xvq`M&5XxV@vhzkc=54 zQ`+K+#Ea{ov7E{`M%`LX$0QFryZI-~H2`X_(NkQ_p2y7>hts>C<)07L*9qA6R$G~` z;dB^3Hd8mciP2h}dR6{-jjy*t&WG^Zg~Y>pqh2su0r!+)bw3i1>dQLt-eQSEZu~*-*jANUDi>Dr zF_ynv4qhY6rrN+?rk8#e zD{gTAd-{pH^;_S&YcMXmh0GS_>JRlDrR^O?@Z*=N>l)f7xc$R3t4B$!jC;zcvEAM9 zqlu!G2+t>Pxf~nr?-e6)Hq3M)tp(P7M&I$bCx0DT@DVg_6YtUZq@+H020m$|!z?S- zx3DI;yR5H0L%UC%eiJ4d$?E;7)g9U0fuCMcfpfuFFWy-wv(}5@llr%d;%`KzCp)UC zFE>H%X#AbS&hvikI19?=$u zoIC4aiiGJqsYajU@5X6XFOV^FNN$hwPNg-bo0v3b^W*f`saD@kujwMQp2W$xrMh#U z$+~+;E5nmFxqY09kRSdAW1hLGjtR;t%Y?Nm)kE?=kvI%C_oNbsVWtnD;$#2rm*(I` z9_b7ZRrIa(={UxIBAaK?JyhWtGHW)gy9G5(Q9EVR0JpbvYKTsK3qRJyAusaxQXkV~ zLL)uqJ`o(^-dg&w}?zN80tpHPi;{XR6Nb+Ge~{W->PY{-i_Ob)31#V;W<;ipeVLt$q4!$ zva@Q4^WJ9h3TT|9;?z;AS7DxxsUNFg=guOtfgi6GxAE>?K*!OEM3dfXeA9=9E$BI% zj{BgeF-xcZCvhSj>*_mJvon!cNvs>vak8E;@pvB+-y?IHX{Cd1^n|@Z{UP-N%2GNN;{oWbP*OE<8DoCO_Fb){-ZFvK|%~jHR!Y z)jzZPZ9X6F))zb-`pWxi74%_!oS7)j&&bsqf=l!hpJ3xYJlPI%28;A6yQl)N-+|Ac z#Z{)+_{a!b8y*mI*#)c;SGGZLRXeg9yFITPs)Yoc)Kms=J)32XL^~zGNG%Q zG}75^GNFjbBoc=}SZ6(KIhfeTAJa%2O@sIJ0zaDHs$tQGNgT!I0peF48uzM^FVU_o zO!VQUS)Od1CgE0nl%IDglK1gI0khFQ{uwX(hC$^#8Tb=?-za`hh|KFaatPKhqf6Kg zsZX)^?vzE7-1-LdT*rb(_-8afKByPC%w}{O&7Q*)18F%!=l-W!bSn*?6PM}wnBnv- z?c7>k@w1d=;cetTt0EuZpSt9XbnmO~@2Bs$K&}1^_Md>oZZP>4uKZPZ+nk1P>L_MG z&uG?ERAZK>(`{4TNqu%dMUUMi-sJ8C6K`XI{xYoqeYbiMQBK{)pqo!9=3tqddQy)ul*$ z40C^wGTF#9SAP?i=bUMR9dAf$Ow!8~hTFjqmf&`@_}m2Fhn-9$cJnb19yjPP%gVav zo(| zP~M#PG%qg1^KbBIOWTBR#dbv6wO*^nbmoC&sl*n(J|T_ZGdlHa;d`&UpM%)MkNwRO zn`Ct*m>q>nJ|Hpi_iehZBY1NdmTx33w?p|@x$uv>TS3=&5+~EKD?H|-<9qIY$eEsE z{ic2}z{2;5#}v$yNPL9%3wg6`KFlUtf?F~3L$JF(y}LC(z6@jI>DtByB&RNF4v7y! zSZ}pvCZ5QpB6M}*WR++hs~>^)^VFhwB(~N2-_DzZu$AARz{*ZyI94W%m4$cGIn=99 zV@+@D*vB){S@Pfl5*}dnJLJ6!YhBYW;Y$^*AAH{eKW+JEvOeKlR(6E5SLrwoS2fW? zW$6>%k}q9Twtbeq2fTZCi?6-_iSsb?3nX66mani$UlMPJ#m@XQ)%#PIkkOMhZ}QMf zklsWOmE_iV61&rJ5Hv29)rCoXm=#lbaVp;H$U8xL^CP6)qF#5kok;L~5#H>g2YpFZ zcsga#i$rj#j2TGcgYKOmem~=(2pAtSc4iM{ivINt*wD zI+_f4nZzNoqB{OQfU{rZ=Lg|o7*B1KG3D@gf{3@td<7bBweS3eEzdi3H@n-C{EAAO za8y%F|8&Y^ePvb+{@$gYy{sSWL+WT*u~S9A($|LZ_H_PEs#X)7`VTz(5=m{@-Gvw5 z;f23~GVbm#GSA}Xo^CE}PrnPxjl=Z4MQ5zf_u4vE!!^Spb`q40RH<*2tKa$B^X}~| zS08}O>9CXC6x>Wbcn%((gtw%|B=}xH$Kj&#l$d{P`p!+qmN@<;+4_n&c7nO{NnGUI zAZ*gf?a#Apr;1RLUOnM)sPkPRq?D&`+uc1$);}#@CSbB7_8k@7)|)M3*xrlu8Yawr zZhjFj_ZROccrm#~>H3M|1MqQ;itxAEGao8mbLMpjTQ7bWs(W|A<1jHC1Z_>y z8uOKNudrhPln<5t%XC|3v+{PB>Em=)_SfK@<0Q^?auoI%FJCs{??U|6i4{-F!^fev z5i};Y%wk7xxb4G7Z;1R4?yd!^5Aoq}x!+1=6(DgP431TMM~L)fh&V1|8o2lAG_zhN zxg||P)$MJ%^+-9dH!m&qOuYa^--mIY7wf^as0S0js#8)pL4QAlsJ9nGnv09xwR97x5cBQ<;5Wr_;qv~DuOSt`$2!NFo_#g=;xgMpN_w(9CwKD zFnKlJ**>zOgwAoJX!M1}_B=U+=a;a?PwT=WeMx&7&Rgl+^Xtmi(QyRX`AJ^vA=c$(%vbu^*I{Ca*t{k8 zzmbEL&7Olud(odEbf|4c@OvK8p7lWz`@-dXvHw@aYz{X=-TpY6o5FXJgC9c82wC_9 z9T%iIc$I1~m}g$`=P~%LMdCr{k{v-OS=dKhX3N1$nuEPae9F!D>&g;|U#T5qY1o&{ z7yjdk%4zmLPvTg&cjv2%RMrn=|3Dnkf#uISxkG&`FHaIQK11dsx~&R$c}JSnLuJBH zx-M1`a?3!0NA5^@?!N&zX^=KAcFTW73t4#by2I z_#&U~`~OLNozy4b)=%J4f#+j~zN$edXnfAe{kC8gQ$~4CZVlj_`gUL^QZ$ZY^&rtn zc;ZK>y;d}a<1s(Y)XBSHBD-mMDm3&W@c~>h)_3e2PEXzoH6uwJh*7Um5x$p8Nu&p{ zdbo~fwW*`1eyxYBdJ~r={a~}Sb6f+BLrCkSVh)nkEA=Or@o;xGk0G&tDlxDAWIkIT z)9pM$;@f!QBvx)tvzOH0NhCgs*OIEW0up-bP+E&jUmjnRR-;?tf3&m>hSQx)X15;d!5jF* z&$njFp|jW^@HLv zRi}Q+G?7&5VYGaj4tJYO&ry~s1U^aH zeY}{UY^#o^FhBN!+>zL<4}8~zvaiKr0$ERxI#&F4*r}Ix^BI4S;l(cLl=q8_nFQf| z$?FFbb7lDnF|6QT zbl&L=W1~cHwR(ApN_`Jm1AQbFCaGCJu_d|rNtyi$FRsTsMIgVcTpcBXPx!39n|~!? z5<7Z9&m$zh%Zn#5RDD?OFEUAmxfPq|WXmTcj$-vF@tLi*{jCZ%Vaa21AnD#ZsW9ic zd8Kntkk|`HjHU0F*t;||cH_litnMmCWjtFxfahOJz4#2@%y%wMw;ersa5Vg!VebpQ zzr2c$Pm0Sx7QF!-oM0?r zygY3Am{$hN{C*@(GC7~=CECO75Fd}|UhC=d{uGz@jpk~g0!c3 zs4I*W*I#bdX^a--p5pS1xNL^*LbU4mpUwBnf{Onam#5tQgiM_0-0$gJ)Q7z1Q;A7M zFDlYWcQQhzCVk_x?An?}FzI9bCKfmMU`u8Dn536@LmmvK<4cgf(-c}-2KJSwV`SDq z{=Na@9pddb#N{Dbov`wJe=`dvZcg)HxVYRW(#eGICB4Q$*#Hv9>BRj`2a#?GVTl(< zlH69mb6#5clelzOSNpJjzLOc~yF;!Hg`NIxZY%?{NSsU3FcmY|@q8!)bD9uZk(BiF z$T%S%1$s`hK}1we3hq%!}o+VQ}c;f>r`Um z$9{HnwdC}EGR8aA7kY+}{b`!hmFSrG@iBRLw|!4BmE%kLj~C_V+&dM9k3mE&2t1?X z2sSn2?}YI_koA5Wm5<@>UI9Djo1pH1?*VCCk_n+e$`Ui7>}k<^6*|`0`CZI!tx0;E zcLuVh0qi6<&%s|qQh$%e%4^b-SIZbb#hlIEF!YsdIYO&s^Y%Q9Po(V@EPuJ!-itev zZg3E^)x{Ej=#{67$75nMT;|MAIkcpct;KqfkNbJCl)mVo+A~GZHk#Bae7{F8Q2{e{ z=D%b%c~p$5r9JfqH$MZlgV^&r5A4)6mWKWI_lOg=*j?$&h7tKV6PVMmdd=r{q|_c>V(0^6~=k4WE3$3k*-r`z6ea%9T2EAUP> zsJ%@tKZ@@Lk(_Kd9BounR|(&c@IwO`}OGm$>x zTzPe)v-k}lwTmn(P2xd1PABn6Jo*X*Z-B-e|M~GjT6SjFH7Ry>^5aa^YCJD}sIvWT zda5Eao!HUa?XB2yxtn*2+9dvdGUeI@_~e*bxsv#{b+$c@s85qTnCx?Mrjqv>o0ie| zU;I>?obL4N>+b*6wr!$2k&Yvw!cR@sji1DM*U0}aJk;L58>k1_W&c{pdW*&5Q;7#e zx)}T=+t|UW&CTS`rO>zqE4?Xx&yYINjI`U-f0>!L89V$&1`_M>!C9$y=EMJMu=BRO zI)ryFBcnBo2SG$vwXHIi_*oY{hyR|zkI&O!iM}SW=4yG;Nd@f6>T5(gN+r(Xp9#D; zM_wIK&r7-OUeX?e+s68(GKX!5w z4QH`rhZ(e>yP81lLp<3H7HhI4%gvvN->cZ^HUIwD-}?)nR1x16;}eZSu%^-V|ddq^c}!mEjQw!zLDSo8(HoJr#TRL8okZR6f{Y_BC>PT5s& zq2mOn-qCTaP4_@$MYlCH^pdOXbW>$@z(3&O*-pKH@g|FT66v#iIA{HoC7SG0}0XNPj?&qfl1fS6iwrZD??-dT_Cg z=pLAu#p*=Ik6Ct96)Y)!ZTYdgyPM1Dq9VPI#QAQ1S+o-l{Q`E*<>8yjYD;2se9ZDe(0cM`#*68){xf1-PNQ=BKJd2j$GF40@v3fb*wd7HVr zI9q<8eS*d}Sv`xl59kmI!rvVt@_;aFG*ZJCUF9ZZ_;43Ov^IkB@){^+t$CY z){&hSuk|84-O0CP!CKym^*gnAyK~B*t=UpB&A@fKrtzXOjxXmz+|T@792##IlaBPf zMOIwOI|tl07ZxY+;`^}k3*VG6fwknrWIvZ=R{0c-n|ysTjJ-t1Bm)y>EbZi-sg7;b zn#!K-{3+)?VZ+-roC-UeZK`uZZC%`Wzeqp8KlQ}vEIGZ3R}zekC-(z!`NKq=NNmoF z_p<2*nRT9>){d0DC%AWpjly=eoZ~BvNa{k%gr91u+}UN;dhvKG_0DvD`a(_@pj90a zxksk9B)hnr{!?sM&~Y-G=a9HH-Crgw(JGBhC;qM`v*NV=zU$l+_RNBgeKPA3ch{ri zz3y-7=3*j!SdXxX#}nRpUmf}ugI*%iXT06P$%Zm8kDT5v(r>f)4R_C%w}<3Q3H;iK z741a2Da2hQ0}slq_jzz?s^KQ*vdNG7Fw=q6ok?r}wdefD5>p}ZE#678|Ck7t73oHF zya&b`ir=~F#vWBQVehwO{$g?Y5hBXTt5)LI!OeH_PEnhxgAg&BuU~a`Ht%c^!8~N# zz?!>R-OArd;*vaROfqYF%45syseW~?jNEU@l6Erd4ta1n)E?lGk61E+Cle0cBhvZd zw7wX(cG~awfQUTm#+M>J$H{4IUxTCn5a~q6mg%`W*;F;f*k1llGAog|;6HyCz%)0B z^zEY8P^KpJ1ygY{w=fJ}b`H}+y>XDbQU32Ga!&nG8erq6U6KOb`=M$Urr99Ru z_08>WE)9!6LEjR{naGwIK1-M}FIH#@i9NA*N4H<+h5%+iW$}3V_X_MRrpX_+ZdG~j zOmC8O5|z~RV=(X`iBm*6Vef6ao%3bEna-^z?6j1P#i4sIi8FA{3uL}6(qE^&Ni}!h z>r}^-pUTrQ$<#UIy`h>bn^6M=5fCrAGtaH7r>Y`#LRrMy=Oe)rTahaeRyv*kbkNuKj@kZ9P zV@XT+t!TbW`r0KVCb>U@#P$C@HEAf)_o)X-T#{!Ykw~v#!yED?;in}K_q(`UrM}!v zV!~r}bP{LTkZ%_?zh%mwh3wx2W9K_}3oE+f#ST8Jg1b++d682uipoT~uHwa{XRIo| zx4QLCk`ulQcrl6eJ5Eid;aYhX^I{z*+N3#sw|uE2Q~ykDnMS{)`YvS4cmMTcE$DYI zn;VjTiF`Ro%KIcvVbK!EJR&Yd#jgcC^q}LtPL?%y|A;?6aw_rS6rXLy5xLS{uo-La zalWzYRnYUAy}UCo<%rp-#H1P|bwBC(yRo@BUMT}(KmONI|38lSJ?-$Wm(Q(z+yS#? zq5A}hYgzpsF8e@^?XoG(LtvUN#CC%v_PUilPYn$@njrh5w zuIP6%R+2T_M-rDk;*y-ZmbdT15_jOKE7i(KkG>w;OeJwDFRe;*`W#l*mi2egvk^oT z=bfMB=4Y7kU0QzR?|fsEmgIf|(vog9nIbBsEdPz0lgv8PQLiBJ1ngAdpJqJMl#bP~ zPlH-y@J_JUu)*t;~G>}*mikMZ{vB6vsYox5mS zBkdXYrCyxHKePOe?R=A$7wfpUy;$GNnrrzW7u0TH!!#J1H!!uR-4){*w)e@Hr zRD<0zaIU-GWzkZ4{7Pckv{H7IgYD^hwO%E}CL7o=jgD_SnK0vDGO#oq6Mr}7#TvYr zhb`OL{GObe#p}!Y^!R^OBdL^UCa3>-F{$Qn(J|@KSKzUKY#S=^UNbr-=oUXW|A-5h zx-;SKMbNPiI~9b}ChkotR+9VW)XFm*$9v*3nSYX+`hz?uELZFEV@pVDAVvis;;=mU zn7nDQvy}87oh!m4x50Nu5|f%*N|ioN`y}@#k~s(KZgn!rgSz~jV62&lSAmFsU?o9! z5|=r+^h@lNi#N{nZ3%-W)gWP$q;CAbNGDzGF{mvmYPay=naWl!olEwzbkToSCvo{X zl~@b9T8ncVUcUyLgejXWV#_-`{=T?;nRe7ASa2)EHY4|X-pQYK5^G>$4xfMUe_4>+ z+>|AEyZa{oE+7LBL2crlDQUi}qGXycx06>7>lA^pU-8pQR?jDI8N3}5mkZJ^ zEAdWC-mI7QFiC%~oNhB|n6Swf{1l2{6&%u(CvSG{N;7VV<+qWzn9M~i+0NS;|Nkm+ zOXAnU>7+{MR4aF|U?EFp%C4k``9(i=nQB>=ez&C=T@oVx#*CXpc!AqL7NOm|nBBQ* zc&-HPf6Xtqeo07 z=R;pjH#ef+wX7Wg1tUi=+uH>BQ~N9HFfxn)yiBq^SDxJ62fZ+*}_Y{Fi}A1gntPR8}?h?@CxABeN2T3wb;7PV(FN66{nZ zF}e8;606fW2h@I@=IU%ZE~4XCYG8JERTq`SnnpZcM)f_NTD^g+mvy{3wIzJ6>M zn?L34c_QBMQc}m4Q%)zD^=WEzlG8t^`xn#dTBjPZJYka(BJH<; z%BQ95{mA_r{H=s_F4GfS$Bw4-tl`}GX{3`3Oe8KB$t0%(Tw5yj<1Hj!50^!G=eIP{ zOX)Y;pQJPSLk3>LKUcduIah^c7viU5X}&DtnPqO?A)=?{exhT8RL44LPUmLJUSD7C z=EeT3^zEtIvOv1()z#O&+`{wYiM{KFhgXPAuZ> z4@pdL`^SG)C;qvSO%=#LM^!z<$19ylByQ%N<073frS-uYL=w$N=c?+ z*SfbnM4Z9S*Ceg;k;wa&7jwW^B{p17zq&LitrLtOVlRoS_+}ZKcF_0_5-)+q+Vrc% zn|qI)F-?eX7HipA@Aun9EQC9#OSO1OIidy{&eRNph3feU%(8WJ18PA#8b ztQ!36YYBIMM#qFB{!p7H_@HSk)Vxth&oASai~ zc0dMhqTfm~cc#(1&|OJf>iMYUX1~*y7Z32sXY5@fw-N^ZP44G+@=Dg+kb1i~4Nr+f z5|uOcDy{pxop3~g?)v^*o#xfqDLZX)?h`VX(>3AbTxw`(?0sDt=_+EBWOPzr&PZJ8 zX7xptz97w)`p}(ZK?M=am!f;S2(BV^6>azZ$2z58rWP#LWL3gC85Qab7S}uVB`^M( z_An*bT7$H!#knl+_>G;=w}Wo0|C6{s)v*Ap%d)!$bf4jf({$V~lQ;6=1`+y(j)A-? z;#^hoYLQq%{>4!Ht(vu-Cs#PVOZJ?=PZzP~DmT}lK?y#{i%pKwaf>sFhI@JS1O_cg zUUIHhYD-Z!glVR3bMI=X_&m**lWO4Q|97$)k6yx-1mC;)FR}S68YU9Y#&G3nm{@&{ ze;0T2DK{s!tS50@YRfUKlbNl_=4sLN=0Ba=m1>yeLGpXxf5T7tNGt~pRr#ij_~m2s znN0nhXSSs05{|flB^8`X&~qi5FVxlk11q~&yvCm-3y!FiXYq=N?xfeL20ICAt3Ysq#h=rg*Zs#3`(ZP|Vo^3%{y!Zr7QcVeJV-FMiqxcI z{3qq)q_WjZYjim^J8wEU?Sh=u&aI*8|MH*^OeY+A#ybf|B$3|X%rYkvgdHU@>E)}C zSUdf=3MS5W?g$;faB{hmTVUsyPB5RZRZbC6oz+)BQi8E>omi4uw5`g#(VwN9S#clH#u72qMs{{OFCGk>o7yv{hA*dzgB-wZa3F%Z|uG)dE$ z{Lufs({a)yt(Smp7GoB%2?@k1vG(&h&-cCe%5f%>Oq-w(@A;nPInP<%SDYVJ z>J?)6S9k#l?cC6?`rZXCDq>$gPmDO#=6u={;DW=GEMw0Gzc#%$LSn2% zSbZ!rRm-1LkDp?1yGzu+BbMJ(zq^A*r~XM$`3bpE?f}er3G1zb-|+ej%QuECtM$8o zCKkEr2BNI!hEk9V{Ox=FDUHi;BhGeUCkG6PZni|2eUoD~+qfd=0r@ z!-wC3;`QQ~v-f;?m`Ulr@tBN#11|P>JzQiOYy)k(j`_1M?k^t~Mt$)!zPnXj%-z!Z z6YVp_oDDTyoEpxdFX-J%RQ@y^NS*#1jn|vMzeDaT(79V2Q&NpTM&J8bwq6$a^!NDq8~$Fx z@>B5M4suQn=h|svacV3Rr|4vF`pYzEzY<>aHE|T-ROamvD znbyaj;OkK~i*?{_EXw^J&GRKU3&JOe!kEtxvv@lVt|Iw4*1tse12VlH)}BI_OgzhX z@3BX?gWe*BFOmDaG(MsBcMyxy*PZBW#j+7}+-fg?;}_)bJ3L+`=0ijvC!G3jZBwvz z3At2(c)P(&VfhGs)2V+Bv=8xfGW|_iwyxaT*3-uhWBC&_e$3ZnRJ2n=bS`4~v#MxO z+)Ot)j>hxk<{Z%u-5&2Ctj)X zN4!qs?Obgpx2dNK$SHXftX^YzH*(I(Ps(yO%SAr@8jabB?i2H-iaD0W+aCWGM%=~6 z%Xs+}|K3958`ymiOwNMfkFkBSVtGX@qWuMV{u)NOpSvF%BX8#l$J&Xgz!%_s1DP+8 zma|XL=ssqxeuB=R;~ZKbYck?<{=H5%SIWo3*gj3%r_sHauJalntt|JkRO(~$va?V; zkG_wQJxoV_O{bm5;)T+vZ5go@9Y=}bERi&JuOfMy7{2Cpm6(^VrgWrcV}% z8)41^?1hV0!D$IbOjRr=LFW{5_B$uwA`A=KSNSe@Pvg~lh2n?E9VAcoh(&z70n*>{ z_XdpfY%s^C$FY0{jYr7KR$|fecf7tOB74aTGPsq`#8D5Afj~5x!K)ziEngqN?pMTO z9h^k+H1?0dsNeGSR)z}=`{4jELV`n0?Wxus&n zWvm-ZX5~)sK8Bo`K8(g0`k4Lc239YFkug6b7BhVUxes}r0L5A4MCT^jjQA!M{jlm_ zj+j4!6Lz};V6}}{mO$|)-d(L&mf_+iESYIJD;HbWxrK~OG|x+g;tXh8f9H!6Obxou z6TGsrF7diX%xy}a!n-rYo)g5f3CmB2hhVs>9o^KKxb-`lZ)nW zI~-Hvd2Fk3hPrw}EH{bxtE%anL;kY2eN11proCym-_7IQmvqJpaKhd#7mvU$JLvgB zXBR%Y;eAI=E>~6-u<#B`_PcZFGn(Vzy`Gpw@gn-ZMEV9k+8JlD<`(lYa&FyQs_Wba z<t=z;+xefiZaJKxK}=Yhm;llvSzRS z^E~>T2gjZV9GQT2+Sk;J zZ2X#t?Gm^7`5m^?8BbvKAo^yi(>@~7`HI?U?q;&3U`(#f^H7-%{*QjRe`3@Mo zB7d{w;s{bF_?u3fecE_$;pr`6(ZeY?;pTP})b|nBboD#CiM{p`f8Da)63K2P)TqAQ z)y3Z6(*hCPDxG)BvikPp+X>>%9Gb0}dI#V1(Ej-V^zCDNOU|irjAwSj#kbg+FYolx znX!SGod$L%*>C{ca_lLVGYzhR`5m}uciL07Ph$ND+IJ3f{~n*u^zFUS7>k99Kc&XGL{Mc6AM0U^P-95NrUtEuzUE(A7a0*?io<=G7{Q(wzF zz{DN&1X_0%x1XU!{N{PxLUR}!A7*FYF<4c=1Z{g8oFUO%-Ibe4wZ*W?j`D} zn)+(HT{`KXplB@apeNBO7oFzbpxfiGm;GB+e^b2g#^DCzesB=mo9Nw-z{HBa#uIn> z={2#q>l{O$8V^)7?$cJ_WnONz_T&v{oEtLz0iKGZo5>QN+9kxham?=IwkkfHJ}YYH zi`~gRLdz?KxLc@uo7>nfnDdUjxD#Ek*9~+(qOzvIV;^xJ=cSMCIxj(3_L#rhu)+?y z8C!eN6iE?}q?@waiFsMVf;bxWdqdO*dCJYr9LicH?_qhhdhK3fIEt*(MMk_t?jfHm zccbEdSk*7$M?msDN>#(36eU{~SNBL*pVEt!g>GT$b&4N*ymo z?7-)ZXcX_;{Ph*QH>1y}5A%0_>DvIy^zknGWY{v?St07J6}9Lb!^hyg!l(9=d8D(e zZX(J#@K)my{>+@;59BZj*Ipz+!5g(oW z*0fof8)ESU>efGxO7Cti-^7U?BXRO z_v7sh9=^ublR?&PYz50sK{o`eKp*$itW@qHsN8{Ji|Bt%ESu4heaB8a$5S%gbA$*g zxl|Rcob&hnVk0w^=+?t;_o8&C`|7Ox&7fsp*)=a)$>3XjTt?FaWR}U_YveYeV-DYr zmVe4^1f6i!-ejgl(OAsP9-`L2ZJ_w3woB)#a#mp2EhFsT?-4t5h?dz_J{`+wd|qa;p4_aaUXj3kR7?GkIw0I zWcyuiibVSm{$(?nW&UbAv;QuUh>*7-PV`;aG>2BfR?s%nkNI35sVX8_U$yGYvd3Gi zIhWW$7tpo<=8uU?bi~G8Vt>V+zWAbIxsS#>Xna)sw$r9VxW(AV*5lz*?Aj%aO1P}?s^qE(iiN*ipK3&n=M*trQSUCT-f=i9V_7L*nMB))x6agXhrWZxXINgwyN5*eM0|>4){DH+ zE)`hS{|pbaZ`gNUlItm~+2`Gy%%aoR9cB?-50Mtf)bw^fx1#0OW-9t^)q!1X30X19 z6x;|88>fY}1+mW<)FTxwoC3Z&ZWjz|LX*pr!vUX#! zY_a%lt+M}CP3K-InU)h9@F~1`fIhnzcvl^`740wPXn9L*C(0W2Lt>V-nFsdT~rDB{WA^1vMXQ}$o^ z-B_C*YBx#L{_e+Z$BK4t8TAJ8;si9y#=MC3w^(w=v&+ke$zB^D!?H|+9p$Bx-2D=r zz0ul|WA;#dEEMhXt>0CxBG-C}l7%;!b}wp{vmrPSnvX+W;bYshtb_DA=39CQd z#42#>pDV28x2Lvsc?ZPC1eLRU z+jXofW45yFV^(1F$sBvhQzCP-l@qB|^S6$OSBb?gp-#I=rhzEte#d!k|2Ar8YIx&* z(B^qgjCE54XWeQ=+gQ@QpHP8TmRqPj!l~*O`WDIT66$oaIeo`@F`C9&ca!ke%6dlB z-rzg=_mbz>-bmE1Dw=G{?pd*HB?Iq&V!tt!U*fY4*Hy^vm>N~wi%c+ zgdV0p$q2iNI8Ii-8$wPS$>4hOkPX2eWj_(e&Dc)o@jk-6XakvUlPxpTTknGmBr(e;@iNgv!M7FbgzZn?r3BgmFnVuq+RDm1bEE=cK==nVRbbM^KmGqv> z`D-+86WQLZRjRr;meZ=+N$wAWqxT%{m*SHf7H<(!gZ2sUikdz>th)<*bgE7hturv^ ztu>M24lJ_Uuh_%vIYakjekJNH)#Lu<>~krRiV$2;3#Gegwgh}b3EPOPuY zU(vCPW*g)dovggWOYbF8g|gN;J;i69v&6>iS%coOWLCO=*Ay(--0wK2t-(#`bPhT@ z>=R?|gp0~~3%doa&JH(GUuMR8Q(5aKDnk2^^k(2q#jQrqmFyMmFlU zvF6P70$i;@C$(5-bEMnNY?p|KX4-n$gofOShKn1@ zM>8YZGRITa8_=<~+`hBLh>mAQD@G699@C@NA?dWP`}@+b&R6J32k?f4^G3yOUc|R969%E*lZtmV2v5?!wC&jK6uz97IeBue%?Zk@VZlLPg9lw^K|e`X+qL>BOl0eTmO!ZrLZCM(Lr-x!dMe z3A;oRY{W5BhE9)VZ`0*Y_T+GJwNUg_)Vjn*EN3R9#r5=4Qfr5h3ee=7^#h^j;!t^fpFDFayyq=W{OFS=_dJ zXBLG!Ij^RBZvmU!rpsHmc{Avp-wHPEB-kDFh28FqX4?Bcd$Q-YWcxAvmWz$uG9sq~ zr@H!{Bo6c&by(*4B!VUk{X%dZ3>%~4zB7e4X8JiuKPB>I{NnQJGO+1t#^ zuD88-Bg5Wc*;$mXm(5mv;=PTReVhJ=q+Lh zk~M1Y)U20rt!6iJa@f1=Te)4zo<*&eZ8QB888wQwx4_XJ&%9`r1xr#bhGL?{wQ2JmFjw!`$z< z^=}1BXL@ddoiTMjC?B1_POY3(sTjOY|IXe`w*{FgbmmTb)EkRoM(wR+enaK%rtR(M z^t8qQUqK&#@ZL;2GmOS=YehSOQ`7b*J7ci1=XrPeyfC*%?5LM~6dV7fFPrK5oj}Es zy~FCCMN(EceVuLTI=OKWA8l)0xpprh8?A!JygW-du@cJ+a&;?Fk)-qBzaJdg=cJQd0gnJv?QlQ{*04 zv~w#d7gK?`DXUWv9;Qnu*E+qGKzA)^`I9q@)7Ocf+a=i};#O-qxQOdv_Vi#ViZ$Cx zqxEXUwG|Ob`n>$svR>NhjV66wY}^uZvJH3A=bij^iZ)>;yP5l2SfGF%V6DJl4&>k+&Xx_n%+3hwXvwLP2ko=xq%uuA%@OO zXSM#RFVQ3~PU=jA+-mD#?sm0nRa>W`sLsg7%Z5$ZZM}FFWcx-aQm&l!82y9+eeKi zU4qBK$Q{#8#{N|L@*AzpBAHXHMatb)xiBZP+ICmZskX31haKEr#x~D$_=s(9JMGMB zbeD0Xmlf$go?)ExOvlm~&Sn;w8*ib#e~z5`Qd#NpIZ?aIdQ!KC4_hNToic7*vdsHc z>awEDMj;p3SL^-k;95?f$f+z9m@}vdvil7&2XE_&lNCC0?~u(%srZ<_EaLw5!U)}> zf}$}egVw7v!KoVNBx>(5a$8(`dGXP{ldaXB=kxaP#xmn0%E5Z$Sah00Yt`RJL|>3G zW?$9mjSw&G0RHyL%A!MQsBml?lZ{5>{Y3tMf#(L%wu`#E`PWG#HlBmMbF5vWe#Rs8 z+NGQaR!Uy7!fBn&T0UfQMQ0@GF{LqEUg`z0lC(Fs+Ak!~>p9PJn?E;(xxr*>cK$k} zWRJWp$?6eUL8n_!eiz~ino2^8^-mYV<+HhgM55qU<5kKwnB$Q_tBo!gN1rri9w3%gr~i?T1j zZ&WH6_>Oy7P7+pDF|_QM8TZR{lX28~ng0`zn5~&QckA;IPr7}bs?nuoE!hFwVZ=tn z1DYIYv-8eqqXHGVLnA$jd~a#iAIFc z?A)x=uV87NPejP>-5A!`=8mQ!tcc6gtPkjQ+BeUI61^W=;mZ*)FnB@>=`N(y-@J!A)eMjc^|b_ zb#4ZXBw5Hz$muqzeJRh0r4=qCF;uWY~VSa zgcWiidy0H9pS~l9>`_F*JI3K3Gd=1j{H&k)=na80COcW8o+>`J%{FnTzO-vBsZP7H zeNn{AIyxJ}bE_5G$zf)Kc-6j!tbKIE@6ynwOb}0Q^1leY)e>>>Pe&>Lj3g0O)K*uE zBtBVro`;jc>~C@`Cvfk;f?Hy#--Ql{p&Ff@D_Rw_ZX%AkF>?O<$J|V83B03hvTHU5 zD}$ty!%thsPKUxrOjbO|d2c2AD}Mtv;dgFN^t#wQ_*i|q@*;OyKN)Lu&g9&t&UzB< zTFz9h`m2c1tpB`%j0ie?m8{z(4Evr_!TXV+Kh+aHV;8AEz$S< z`=hfzXIr~w`^4{}X_ON%9dIpgwHxgN9|r55x6F(T*Hb?oBr87Ns;@O^hVMtHA?Xv< z-3F;PXY3P0A1o=&iQDj}o{O&{OLrWeZ!t}HS&ugF{XuSc9<+mtdAdyTaBQods)$Ro z&&O{*s9Y37N{aV&t28Hi-wB@0kM=b({);NbB3yb0BNsmiQ$$a16dLmB;uL;GYZ<~ct%xE#1kwE=4`gHQ`;giTt zT3Gw^#3N(B$80Klg}mov{ve-7zTYt>6g96STOUME!{4`t_(#5%*7p8{or-nj|KKA( z4;{L+PwM53!TtoogWibLC!Zf{AAc9o;DZyTJK6`CdT)&Ggz9{o zI3rc>#9}>NF;AkN&lFp0F{iiQ z6Vl)FproU7(vN0;O(w^9Hj5LLFz6lmF!=dLzD#&H@@-`E51$#^tIz(pWPS2I>9M-O z>YC3dJei1Q{LJKcYqXb^@zdk)CZCx6{*QY-DfL6&kNjTad6WFh^)?M_zYh9Fd0G4E z|F)n0yV3cxNKIszSm zjzCACBhV4(2y_HG0v&;lKu4e>&=KeebObsA9f6KON1!9n5$FhX1Udp8fsQ~&pd-)` z=m>NKIszSmjzCACBhV4(2y_HG0v&;lKu4e>&=KeebObsA9f6KON1!9n5$FhX1Udp8 zfsQ~&pd-)`=m>NKIszSmjzCACBhV4(2y_HG0v&;lKu4e>&=KeebObsA9f6KON1!9n z5$FhX1Udp8fsQ~&pd-)`=m>NKIszSmjzCACBhV4(2y_HG0v&;lKu4e>&=KeebObsA z9f6KON1!9n5$FhX1Udp8fsQ~&pd-)`=m>NKIszSmjzCACBhV4(2y_HG0v&;lKu4e> z&=KeebObsA9f6KON1!9n5$FhX1Udp8fsQ~&pd-)`=m>NKIszSmjzCACBhV4(2y_HG p0v&;lKu4e>&=KeebObsA9f6KON1!9n5$FhX1Udp8fxkWi{{@{Oi0%LY literal 0 HcmV?d00001 diff --git a/lib/ui/dialogs/success_dialog.dart b/lib/ui/dialogs/success_dialog.dart index 8e1de54..5150110 100644 --- a/lib/ui/dialogs/success_dialog.dart +++ b/lib/ui/dialogs/success_dialog.dart @@ -1,11 +1,41 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:just_audio/just_audio.dart'; import 'package:lottie/lottie.dart'; -class SuccessDialog extends StatelessWidget { +class SuccessDialog extends StatefulWidget { bool isFromDashboard; SuccessDialog(this.isFromDashboard); + @override + State createState() => _SuccessDialogState(); +} + +class _SuccessDialogState extends State with TickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + _controller = AnimationController(vsync: this); + + super.initState(); + } + + Future playSuccessSound() async { + AudioPlayer player = AudioPlayer(); + String audioAsset = ""; + if (Platform.isAndroid) { + audioAsset = "assets/audio/success_tone_android.mp3"; + } else { + audioAsset = "assets/audio/success_tone_ios.caf"; + } + await player.setAsset(audioAsset); + await player.load(); + player.play(); + } + @override Widget build(BuildContext context) { double size = MediaQuery.of(context).size.width / 1.8; @@ -18,13 +48,22 @@ class SuccessDialog extends StatelessWidget { width: size, height: size, child: Card( - child: Lottie.asset('assets/lottie/lt_success.json', repeat: false, reverse: false, onLoaded: (v) { - print("calling_lottie " + v.seconds.toString()); - Future.delayed(Duration(seconds: 2)).then((value) { - Navigator.pop(context); - if (isFromDashboard) Navigator.pop(context); - }); - }), + child: Lottie.asset( + 'assets/lottie/lt_success.json', + repeat: false, + reverse: false, + controller: _controller, + onLoaded: (LottieComposition v) async { + print("calling_lottie " + v.seconds.toString()); + await playSuccessSound(); + _controller + ..duration = v.duration + ..forward().whenComplete(() async { + Navigator.pop(context); + if (widget.isFromDashboard) Navigator.pop(context); + }); + }, + ), ), ), ], diff --git a/pubspec.yaml b/pubspec.yaml index 633edd7..16c5737 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -92,6 +92,7 @@ dependencies: video_player: ^2.4.7 + just_audio: ^0.9.30 dev_dependencies: flutter_test: @@ -124,6 +125,7 @@ flutter: - assets/langs/ - assets/icons/ - assets/lottie/ + - assets/audio/ - assets/images/ - assets/images/login/ - assets/icons/chat/