From c51af6522cc2707f05f3a799005a197a756ebf6c Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Wed, 7 Dec 2022 10:55:42 +0300 Subject: [PATCH 01/23] fix issues --- assets/langs/ar-SA.json | 3 +++ assets/langs/en-US.json | 3 +++ lib/classes/consts.dart | 4 ++-- lib/generated/codegen_loader.g.dart | 16 ++++++++++++-- lib/generated/locale_keys.g.dart | 3 +++ .../add_leave_balance_screen.dart | 10 ++++----- lib/ui/misc/request_submit_screen.dart | 22 +++++++++---------- lib/ui/profile/contact_details.dart | 12 +++++----- 8 files changed, 47 insertions(+), 26 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 59c0814..65f81ea 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -424,6 +424,9 @@ "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", "currentPassword": "كلمة المرور الحاليه", "concurrentReports": "التقارير المتزامنه", + "EnterNewAddressMoved" : "أدخل عنوان جديد إذا كنت قد انتقلت", + "CorrectAddress": "تصحيح أو تعديل هذا العنوان", + "SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.", "profile": { "reset_password": { "label": "Reset Password", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index b0ab50e..647a956 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -424,6 +424,9 @@ "typeCurrentPasswordBelow": "Type Your Current password below", "currentPassword": "Current password", "concurrentReports": "Concurrent Reports", + "EnterNewAddressMoved" : "Enter a new address if you have moved", + "CorrectAddress": "Correct or amend this address", + "SelectChangeWantToMake": "Select the type of change you want to make", "profile": { "reset_password": { "label": "Reset Password", diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 944a29b..45bfcf9 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -2,8 +2,8 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; 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 a54ff37..95f1d94 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -440,6 +440,9 @@ class CodegenLoader extends AssetLoader{ "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", "currentPassword": "كلمة المرور الحاليه", "concurrentReports": "التقارير المتزامنه", + "EnterNewAddressMoved": "أدخل عنوان جديد إذا كنت قد انتقلت", + "CorrectAddress": "تصحيح أو تعديل هذا العنوان", + "SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.", "profile": { "reset_password": { "label": "Reset Password", @@ -516,7 +519,10 @@ class CodegenLoader extends AssetLoader{ "codeExpire": "انتهت صلاحية رمز التحقق", "typeheretoreply": "اكتب هنا للرد", "favorite": "مفضلتي", - "searchfromchat": "البحث من الدردشة" + "searchfromchat": "البحث من الدردشة", + "yourAnswerCorrect": "إجابتك صحيحة", + "youMissedTheQuestion": "فاتك !! أنت خارج اللعبة. لكن يمكنك المتابعة.", + "wrongAnswer": "إجابة خاطئة! أنت خارج اللعبة. لكن يمكنك المتابعة." }; static const Map en_US = { "mohemm": "Mohemm", @@ -944,6 +950,9 @@ static const Map en_US = { "typeCurrentPasswordBelow": "Type Your Current password below", "currentPassword": "Current password", "concurrentReports": "Concurrent Reports", + "EnterNewAddressMoved": "Enter a new address if you have moved", + "CorrectAddress": "Correct or amend this address", + "SelectChangeWantToMake": "Select the type of change you want to make", "profile": { "reset_password": { "label": "Reset Password", @@ -1020,7 +1029,10 @@ static const Map en_US = { "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply", "favorite": "My Favorites", - "searchfromchat": "Search from chat" + "searchfromchat": "Search from chat", + "yourAnswerCorrect": "Your answer is correct", + "youMissedTheQuestion": "You Missed !! You are out of the game. But you can follow up.", + "wrongAnswer": "Wrong Answer! You are out of the game. But you can follow up." }; 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 2f7efcc..9b9d1c3 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -425,6 +425,9 @@ abstract class LocaleKeys { static const typeCurrentPasswordBelow = 'typeCurrentPasswordBelow'; static const currentPassword = 'currentPassword'; static const concurrentReports = 'concurrentReports'; + static const EnterNewAddressMoved = 'EnterNewAddressMoved'; + static const CorrectAddress = 'CorrectAddress'; + static const SelectChangeWantToMake = 'SelectChangeWantToMake'; 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/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index c879f9c..4b4d73f 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -96,7 +96,7 @@ class _AddLeaveBalanceScreenState extends State { } void validateAbsenceTransaction() async { - try { + // try { Utils.showLoading(context); Map dffDataMap = {}; for (int i = 1; i <= 20; i++) { @@ -145,10 +145,10 @@ class _AddLeaveBalanceScreenState extends State { } 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/misc/request_submit_screen.dart b/lib/ui/misc/request_submit_screen.dart index 84adf9f..51a2440 100644 --- a/lib/ui/misc/request_submit_screen.dart +++ b/lib/ui/misc/request_submit_screen.dart @@ -164,17 +164,17 @@ class _RequestSubmitScreenState extends State { @override Widget build(BuildContext context) { - if (dynamicParams == null) { - dynamicParams = ModalRoute - .of(context)! - .settings - .arguments; - if (dynamicParams.isNotEmpty) { - AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; - selectedEmp =dynamicParams; - submitRequest(); - } - } + // if (dynamicParams == null) { + // dynamicParams = ModalRoute + // .of(context)! + // .settings + // .arguments; + // if (dynamicParams.isNotEmpty) { + // AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; + // selectedEmp =dynamicParams; + // submitRequest(); + // } + // } if (params == null) { params = ModalRoute.of(context)!.settings.arguments as RequestSubmitScreenParams; getApproverList(); diff --git a/lib/ui/profile/contact_details.dart b/lib/ui/profile/contact_details.dart index 95c867a..8bfe7f6 100644 --- a/lib/ui/profile/contact_details.dart +++ b/lib/ui/profile/contact_details.dart @@ -155,13 +155,13 @@ class _ContactDetailsState extends State { void addUpdateAddress() { Widget cancelButton = TextButton( - child: Text("Cancel"), + child: Text(LocaleKeys.cancel.tr()), onPressed: () { Navigator.pop(context); }, ); Widget continueButton = TextButton( - child: Text("Next"), + child: Text(LocaleKeys.next.tr()), onPressed: () { continueDynamicForms(); }, @@ -169,7 +169,7 @@ class _ContactDetailsState extends State { StatefulBuilder alert = StatefulBuilder(builder: (context, setState) { return AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))), - title: Text("Confirm"), + title: Text(LocaleKeys.confirm.tr()), content: Builder(builder: (context) { // Get available height and width of the build area of this widget. Make a choice depending on the size. var height = MediaQuery.of(context).size.height * .5; @@ -177,14 +177,14 @@ class _ContactDetailsState extends State { height: height, child: Column(children: [ Text( - "Select the type of change you want to make.", + LocaleKeys.SelectChangeWantToMake.tr(), style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), Divider(), Column( children: [ ListTile( - title: Text("Correct or amend this address"), + title: Text(LocaleKeys.CorrectAddress.tr()), leading: Radio( value: 1, groupValue: correctOrNew, @@ -197,7 +197,7 @@ class _ContactDetailsState extends State { ), ), ListTile( - title: Text("Enter a new address if you have moved"), + title: Text(LocaleKeys.EnterNewAddressMoved.tr()), leading: Radio( value: 2, groupValue: correctOrNew, From 2790d18c1dad369e0f7e19e51feb3b4aa4697bbf Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 11 Dec 2022 15:03:55 +0300 Subject: [PATCH 02/23] fixes --- android/app/src/main/AndroidManifest.xml | 1 + ios/Runner/Info.plist | 6 +++++- lib/ui/screens/announcements/announcement_details.dart | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index dd9a8de..30555e1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ NSPhotoLibraryUsageDescription This app requires photo library access to select image as document & upload it. NSMicrophoneUsageDescription - This app requires microphone access to for call. + This app requires microphone access to for call. UIBackgroundModes remote-notification @@ -69,6 +69,10 @@ UIViewControllerBasedStatusBarAppearance + com.apple.developer.nfc.readersession.formats + + TAG + com.apple.developer.nfc.readersession.felica.systemcodes 0000 diff --git a/lib/ui/screens/announcements/announcement_details.dart b/lib/ui/screens/announcements/announcement_details.dart index dbe1eb2..210a8f7 100644 --- a/lib/ui/screens/announcements/announcement_details.dart +++ b/lib/ui/screens/announcements/announcement_details.dart @@ -60,7 +60,7 @@ class _AnnouncementDetailsState extends State { ), ), Html( - data: getAnnouncementDetailsObj?.bodyEN, + data: AppState().isArabic(context) ? getAnnouncementDetailsObj?.bodyAR : getAnnouncementDetailsObj?.bodyEN, ).paddingOnly(top: 12), ], ).objectContainerView().paddingAll(21), From cd813a163fff0f4f392eb2ac68dd9db25d0cbe30 Mon Sep 17 00:00:00 2001 From: Fatimah Alshammari Date: Sun, 11 Dec 2022 15:37:42 +0300 Subject: [PATCH 03/23] fix issues --- lib/api/dashboard_api_client.dart | 5 +- lib/api/leave_balance_api_client.dart | 35 +++++++++++--- .../add_leave_balance_screen.dart | 47 +++++++++++++------ .../leave_balance/leave_balance_screen.dart | 31 +++++++++--- lib/ui/misc/request_submit_screen.dart | 7 ++- .../dynamic_listview_screen.dart | 4 +- .../services_menu_list_screen.dart | 2 +- lib/widgets/balances_dashboard_widget.dart | 4 +- 8 files changed, 102 insertions(+), 33 deletions(-) diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index e30af91..3eab65b 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -65,10 +65,13 @@ class DashboardApiClient { }, url, postParams); } - Future> getAccrualBalances(String effectiveDate) async { + Future> getAccrualBalances(String effectiveDate, {String? empID}) async { String url = "${ApiConsts.erpRest}GET_ACCRUAL_BALANCES"; Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; postParams.addAll(AppState().postParamsJson); + if (empID!.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel responseData = GenericResponseModel.fromJson(json); return responseData.getAccrualBalancesList ?? []; diff --git a/lib/api/leave_balance_api_client.dart b/lib/api/leave_balance_api_client.dart index cd577ba..f9c5e21 100644 --- a/lib/api/leave_balance_api_client.dart +++ b/lib/api/leave_balance_api_client.dart @@ -17,27 +17,33 @@ class LeaveBalanceApiClient { factory LeaveBalanceApiClient() => _instance; - Future> getAbsenceTransactions(int pSelectedResopID) async { + Future> getAbsenceTransactions(int pSelectedResopID, {String? empID}) async { String url = "${ApiConsts.erpRest}GET_ABSENCE_TRANSACTIONS"; Map postParams = {"P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1, "P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": pSelectedResopID}; postParams.addAll(AppState().postParamsJson); + if (empID!.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.getAbsenceTransactionList ?? []; }, url, postParams); } - Future> getAbsenceAttendanceTypes() async { + Future> getAbsenceAttendanceTypes({String? empID}) async { String url = "${ApiConsts.erpRest}GET_ABSENCE_ATTENDANCE_TYPES"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); + if (empID!.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.getAbsenceAttendanceTypesList ?? []; }, url, postParams); } - Future calculateAbsenceDuration(int pAbsenceAttendanceTypeID, String pDateStart, String pDateEnd, int pSelectedResopID) async { + Future calculateAbsenceDuration(int pAbsenceAttendanceTypeID, String pDateStart, String pDateEnd, int pSelectedResopID, {String? empID}) async { String url = "${ApiConsts.erpRest}CALCULATE_ABSENCE_DURATION"; Map postParams = { "P_ABSENCE_ATTENDANCE_TYPE_ID": pAbsenceAttendanceTypeID, @@ -49,16 +55,22 @@ class LeaveBalanceApiClient { "P_TIME_START": null, }; postParams.addAll(AppState().postParamsJson); + if (empID!.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.calculateAbsenceDuration!; }, url, postParams); } - Future> getAbsenceDffStructure(String pDescFlexContextCode, String pFunctionName, int pSelectedResopID) async { + Future> getAbsenceDffStructure(String pDescFlexContextCode, String pFunctionName, int pSelectedResopID, {String? empID}) async { String url = "${ApiConsts.erpRest}GET_ABSENCE_DFF_STRUCTURE"; Map postParams = {"P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, "P_FUNCTION_NAME": pFunctionName, "P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": pSelectedResopID}; postParams.addAll(AppState().postParamsJson); + if (empID!.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.getAbsenceDffStructureList ?? []; @@ -67,7 +79,7 @@ class LeaveBalanceApiClient { Future validateAbsenceTransaction( String pDescFlexContextCode, String pFunctionName, int pAbsenceAttendanceTypeID, String pReplacementUserName, String pDateStart, String pDateEnd, int pSelectedResopID, Map data, - {String comments = ""}) async { + {String comments = "", String? empID}) async { String url = "${ApiConsts.erpRest}VALIDATE_ABSENCE_TRANSACTION"; Map postParams = { "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, @@ -86,6 +98,9 @@ class LeaveBalanceApiClient { }; postParams.addAll(data); postParams.addAll(AppState().postParamsJson); + if (empID!.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData; @@ -94,7 +109,7 @@ class LeaveBalanceApiClient { Future submitAbsenceTransaction( String pDescFlexContextCode, String pFunctionName, int pAbsenceAttendanceTypeID, String pReplacementUserName, String pDateStart, String pDateEnd, int pSelectedResopID, Map data, - {String comments = ""}) async { + {String comments = "", String? empID}) async { String url = "${ApiConsts.erpRest}SUBMIT_ABSENCE_TRANSACTION"; Map postParams = { "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, @@ -113,6 +128,9 @@ class LeaveBalanceApiClient { }; postParams.addAll(data); postParams.addAll(AppState().postParamsJson); + if (empID!.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.sumbitAbsenceTransactionList!; @@ -129,7 +147,7 @@ class LeaveBalanceApiClient { }, url, postParams); } - Future startAbsenceApprovalProcess(int pTransactionID, String comments, int pSelectedResopID) async { + Future startAbsenceApprovalProcess(int pTransactionID, String comments, int pSelectedResopID,{String? empID}) async { String url = "${ApiConsts.erpRest}START_ABSENCE_APPROVAL_PROCESS"; Map postParams = { "P_TRANSACTION_ID": pTransactionID, @@ -138,6 +156,9 @@ class LeaveBalanceApiClient { "P_MENU_TYPE": "E", }; postParams.addAll(AppState().postParamsJson); + if (empID!.isNotEmpty) { + postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; + } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.startAbsenceApprovalProccess!; diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index 1a4958e..dde2f02 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/leave_balance_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -24,7 +25,8 @@ import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; class AddLeaveBalanceScreen extends StatefulWidget { - AddLeaveBalanceScreen({Key? key}) : super(key: key); + final String selectedEmp; + AddLeaveBalanceScreen({this.selectedEmp ='', Key? key}) : super(key: key); @override _AddLeaveBalanceScreenState createState() { @@ -42,19 +44,21 @@ class _AddLeaveBalanceScreenState extends State { int? totalDays; String comment = ""; ReplacementList? selectedReplacementEmployee; + dynamic dynamicParams; + String selectedEmp =""; DateTime selectedDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day); @override void initState() { super.initState(); - getAbsenceAttendanceTypes(); + //getAbsenceAttendanceTypes(); } void getAbsenceAttendanceTypes() async { try { Utils.showLoading(context); - absenceList = await LeaveBalanceApiClient().getAbsenceAttendanceTypes(); + absenceList = await LeaveBalanceApiClient().getAbsenceAttendanceTypes(empID: selectedEmp); Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -67,7 +71,7 @@ class _AddLeaveBalanceScreenState extends State { try { Utils.showLoading(context); getabsenceDffStructureList.clear(); - getabsenceDffStructureList = await LeaveBalanceApiClient().getAbsenceDffStructure(selectedAbsenceType!.dESCFLEXCONTEXTCODE!, "HR_LOA_SS", -999); + getabsenceDffStructureList = await LeaveBalanceApiClient().getAbsenceDffStructure(selectedAbsenceType!.dESCFLEXCONTEXTCODE!, "HR_LOA_SS", -999, empID: selectedEmp); Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -80,7 +84,7 @@ class _AddLeaveBalanceScreenState extends State { try { Utils.showLoading(context); CalculateAbsenceDuration duration = await LeaveBalanceApiClient() - .calculateAbsenceDuration(selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, Utils.getMonthNamedFormat(startDateTime!), Utils.getMonthNamedFormat(endDateTime!), -999); + .calculateAbsenceDuration(selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, Utils.getMonthNamedFormat(startDateTime!), Utils.getMonthNamedFormat(endDateTime!), -999, empID: selectedEmp); totalDays = duration.pABSENCEDAYS?.toInt(); Utils.hideLoading(context); @@ -91,8 +95,8 @@ class _AddLeaveBalanceScreenState extends State { } } - void validateAbsenceTransaction() async { - // try { + void validateAbsenceTransaction(selectedID) async { + try { Utils.showLoading(context); Map dffDataMap = {}; for (int i = 1; i <= 20; i++) { @@ -118,7 +122,8 @@ class _AddLeaveBalanceScreenState extends State { DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), -999, dffDataMap, - comments: comment); + comments: comment, + empID: selectedEmp); SumbitAbsenceTransactionList submit = await LeaveBalanceApiClient().submitAbsenceTransaction( selectedAbsenceType!.dESCFLEXCONTEXTCODE!, @@ -129,7 +134,8 @@ class _AddLeaveBalanceScreenState extends State { DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), -999, dffDataMap, - comments: comment); + comments: comment, + empID: selectedEmp); Utils.hideLoading(context); @@ -139,10 +145,10 @@ class _AddLeaveBalanceScreenState extends State { } 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 @@ -152,6 +158,19 @@ class _AddLeaveBalanceScreenState extends State { @override Widget build(BuildContext context) { + if (dynamicParams == null) { + dynamicParams = ModalRoute + .of(context)! + .settings + .arguments; + if (dynamicParams.isNotEmpty) { + AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; + selectedEmp =dynamicParams; + getAbsenceAttendanceTypes(); + }else{ + getAbsenceAttendanceTypes(); + } + } return Scaffold( backgroundColor: Colors.white, appBar: AppBarWidget( @@ -269,7 +288,7 @@ class _AddLeaveBalanceScreenState extends State { validateFieldData() ? null : () { - validateAbsenceTransaction(); + validateAbsenceTransaction(selectedEmp); }, ).insideContainer ], diff --git a/lib/ui/leave_balance/leave_balance_screen.dart b/lib/ui/leave_balance/leave_balance_screen.dart index 548ca99..a397c11 100644 --- a/lib/ui/leave_balance/leave_balance_screen.dart +++ b/lib/ui/leave_balance/leave_balance_screen.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/leave_balance_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -13,7 +14,8 @@ import 'package:mohem_flutter_app/widgets/balances_dashboard_widget.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; class LeaveBalance extends StatefulWidget { - LeaveBalance({Key? key}) : super(key: key); + final String selectedEmp; + LeaveBalance({this.selectedEmp ='', Key? key}) : super(key: key); @override _LeaveBalanceState createState() { @@ -25,12 +27,16 @@ class _LeaveBalanceState extends State { List? absenceTransList; DateTime accrualDateTime = DateTime.now(); + dynamic dynamicParams; + String selectedEmp =""; @override void initState() { super.initState(); - - getAbsenceTransactions(); + // if (selectedEmp.isNotEmpty) {} + // else { + // getAbsenceTransactions(); + // } } @override @@ -39,9 +45,9 @@ class _LeaveBalanceState extends State { } void getAbsenceTransactions() async { - try { + try { Utils.showLoading(context); - absenceTransList = await LeaveBalanceApiClient().getAbsenceTransactions(-999); + absenceTransList = await LeaveBalanceApiClient().getAbsenceTransactions(-999, empID: selectedEmp); Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -52,6 +58,19 @@ class _LeaveBalanceState extends State { @override Widget build(BuildContext context) { + if (dynamicParams == null) { + dynamicParams = ModalRoute + .of(context)! + .settings + .arguments; + if (dynamicParams.isNotEmpty) { + AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; + selectedEmp =dynamicParams; + getAbsenceTransactions(); + }else{ + getAbsenceTransactions(); + } + } return Scaffold( backgroundColor: Colors.white, appBar: AppBarWidget( @@ -111,7 +130,7 @@ class _LeaveBalanceState extends State { ), child: const Icon(Icons.add, color: Colors.white, size: 30), ).onPress(() { - Navigator.pushNamed(context, AppRoutes.addLeaveBalance); + Navigator.pushNamed(context, AppRoutes.addLeaveBalance, arguments: selectedEmp ??''); }), ); } diff --git a/lib/ui/misc/request_submit_screen.dart b/lib/ui/misc/request_submit_screen.dart index f05bacb..170e288 100644 --- a/lib/ui/misc/request_submit_screen.dart +++ b/lib/ui/misc/request_submit_screen.dart @@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/api/leave_balance_api_client.dart'; import 'package:mohem_flutter_app/api/my_attendance_api_client.dart'; import 'package:mohem_flutter_app/api/profile_api_client.dart'; import 'package:mohem_flutter_app/api/termination_dff_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -35,7 +36,8 @@ class RequestSubmitScreenParams { } class RequestSubmitScreen extends StatefulWidget { - RequestSubmitScreen({Key? key}) : super(key: key); + final String selectedEmp; + RequestSubmitScreen({this.selectedEmp ='',Key? key}) : super(key: key); @override _RequestSubmitScreenState createState() { @@ -50,6 +52,8 @@ class _RequestSubmitScreenState extends State { List approverList = []; List attachmentFiles = []; List attachments = []; + dynamic dynamicParams; + String selectedEmp =""; @override void initState() { @@ -123,6 +127,7 @@ class _RequestSubmitScreenState extends State { params!.transactionId, comments.text, -999, + empID: widget.selectedEmp ); } else if (params!.approvalFlag == 'eit') { await MyAttendanceApiClient().startEitApprovalProcess( diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index 5c4053c..a670cbb 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -102,8 +102,8 @@ class _DynamicListViewScreenState extends State { itemBuilder: (cxt, int parentIndex) => getEITTransactionList![parentIndex].collectionTransaction!.isEmpty ? const SizedBox() : GridView( - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 1.9 / 0.75), - padding: const EdgeInsets.all(12.0), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 1.0 / 0.75), + padding: const EdgeInsets.only(left: 12,right: 21,top: 12), shrinkWrap: true, primary: false, physics: const ScrollPhysics(), diff --git a/lib/ui/my_attendance/services_menu_list_screen.dart b/lib/ui/my_attendance/services_menu_list_screen.dart index cd76132..7a61029 100644 --- a/lib/ui/my_attendance/services_menu_list_screen.dart +++ b/lib/ui/my_attendance/services_menu_list_screen.dart @@ -54,7 +54,7 @@ class ServicesMenuListScreen extends StatelessWidget { } return; } else if (servicesMenuData.list[index].requestType == "ABSENCE") { - Navigator.pushNamed(context, AppRoutes.leaveBalance); + Navigator.pushNamed(context, AppRoutes.leaveBalance, arguments: servicesMenuData?.selectedEmp ??''); return; } if (servicesMenuData.list[index].requestType == "EIT") { diff --git a/lib/widgets/balances_dashboard_widget.dart b/lib/widgets/balances_dashboard_widget.dart index e546acf..510137a 100644 --- a/lib/widgets/balances_dashboard_widget.dart +++ b/lib/widgets/balances_dashboard_widget.dart @@ -45,6 +45,8 @@ class _BalancesDashboardWidgetState extends State { late DateTime accrualDateTime; GetAccrualBalancesList? leaveBalanceAccrual; List? ticketBalanceAccrualList; + dynamic dynamicParams; + String selectedEmp =""; @override void initState() { @@ -60,7 +62,7 @@ class _BalancesDashboardWidgetState extends State { void changeAccrualDate() async { try { Utils.showLoading(context); - List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime)); + List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime),empID: selectedEmp); if (accrualList.isNotEmpty) { if (widget.isLeaveBalance) { leaveBalanceAccrual = accrualList[0]; From f1b7b897cc7cfca0022c6f8139184eaa051e7ac1 Mon Sep 17 00:00:00 2001 From: Sultan khan <> Date: Sun, 11 Dec 2022 16:12:34 +0300 Subject: [PATCH 04/23] leave balance page updated --- .../add_leave_balance_screen.dart | 107 +++++++++--------- .../leave_balance/leave_balance_screen.dart | 26 ++--- lib/widgets/balances_dashboard_widget.dart | 5 +- 3 files changed, 65 insertions(+), 73 deletions(-) diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index dde2f02..4df7233 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -26,7 +26,7 @@ import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget class AddLeaveBalanceScreen extends StatefulWidget { final String selectedEmp; - AddLeaveBalanceScreen({this.selectedEmp ='', Key? key}) : super(key: key); + AddLeaveBalanceScreen({this.selectedEmp = '', Key? key}) : super(key: key); @override _AddLeaveBalanceScreenState createState() { @@ -45,14 +45,14 @@ class _AddLeaveBalanceScreenState extends State { String comment = ""; ReplacementList? selectedReplacementEmployee; dynamic dynamicParams; - String selectedEmp =""; + String selectedEmp = ""; DateTime selectedDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day); @override void initState() { super.initState(); - //getAbsenceAttendanceTypes(); + //getAbsenceAttendanceTypes(); } void getAbsenceAttendanceTypes() async { @@ -96,59 +96,59 @@ class _AddLeaveBalanceScreenState extends State { } void validateAbsenceTransaction(selectedID) async { - try { - Utils.showLoading(context); - Map dffDataMap = {}; - for (int i = 1; i <= 20; i++) { - dffDataMap["P_ATTRIBUTE$i"] = null; - 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!) : ""; - } else { - dffDataMap["P_ATTRIBUTE$i"] = getabsenceDffStructureList[dffIndex].eSERVICESDV?.pIDCOLUMNNAME; - } - break; + //try { + Utils.showLoading(context); + Map dffDataMap = {}; + for (int i = 1; i <= 20; i++) { + dffDataMap["P_ATTRIBUTE$i"] = null; + 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!) : ""; + } else { + dffDataMap["P_ATTRIBUTE$i"] = getabsenceDffStructureList[dffIndex].eSERVICESDV?.pIDCOLUMNNAME; } + break; } } - 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, - empID: selectedEmp); + } + 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, + empID: selectedEmp); - SumbitAbsenceTransactionList submit = await LeaveBalanceApiClient().submitAbsenceTransaction( - 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, - empID: selectedEmp); + SumbitAbsenceTransactionList submit = await LeaveBalanceApiClient().submitAbsenceTransaction( + 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, + empID: selectedEmp); - Utils.hideLoading(context); + Utils.hideLoading(context); - var res = await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submit.pTRANSACTIONID!, "", "add_leave_balance")); - if (res != null && res == true) { - Utils.showLoading(context); - } - await LeaveBalanceApiClient().cancelHrTransaction(submit.pTRANSACTIONID!); - Utils.hideLoading(context); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); + var res = await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen, arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submit.pTRANSACTIONID!, "", "add_leave_balance")); + if (res != null && res == true) { + Utils.showLoading(context); } + await LeaveBalanceApiClient().cancelHrTransaction(submit.pTRANSACTIONID!); + Utils.hideLoading(context); + // } catch (ex) { + // Utils.hideLoading(context); + // Utils.handleException(ex, context, null); + // } } @override @@ -159,15 +159,12 @@ class _AddLeaveBalanceScreenState extends State { @override Widget build(BuildContext context) { if (dynamicParams == null) { - dynamicParams = ModalRoute - .of(context)! - .settings - .arguments; + dynamicParams = ModalRoute.of(context)!.settings.arguments; if (dynamicParams.isNotEmpty) { AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; - selectedEmp =dynamicParams; + selectedEmp = dynamicParams; getAbsenceAttendanceTypes(); - }else{ + } else { getAbsenceAttendanceTypes(); } } diff --git a/lib/ui/leave_balance/leave_balance_screen.dart b/lib/ui/leave_balance/leave_balance_screen.dart index a397c11..07d6a7c 100644 --- a/lib/ui/leave_balance/leave_balance_screen.dart +++ b/lib/ui/leave_balance/leave_balance_screen.dart @@ -15,7 +15,7 @@ import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; class LeaveBalance extends StatefulWidget { final String selectedEmp; - LeaveBalance({this.selectedEmp ='', Key? key}) : super(key: key); + LeaveBalance({this.selectedEmp = '', Key? key}) : super(key: key); @override _LeaveBalanceState createState() { @@ -28,15 +28,12 @@ class _LeaveBalanceState extends State { DateTime accrualDateTime = DateTime.now(); dynamic dynamicParams; - String selectedEmp =""; + String selectedEmp = ""; @override void initState() { super.initState(); - // if (selectedEmp.isNotEmpty) {} - // else { - // getAbsenceTransactions(); - // } + absenceTransList = []; } @override @@ -45,10 +42,10 @@ class _LeaveBalanceState extends State { } void getAbsenceTransactions() async { - try { - Utils.showLoading(context); + try { + // Utils.showLoading(context); absenceTransList = await LeaveBalanceApiClient().getAbsenceTransactions(-999, empID: selectedEmp); - Utils.hideLoading(context); + //Utils.hideLoading(context); setState(() {}); } catch (ex) { Utils.hideLoading(context); @@ -59,15 +56,12 @@ class _LeaveBalanceState extends State { @override Widget build(BuildContext context) { if (dynamicParams == null) { - dynamicParams = ModalRoute - .of(context)! - .settings - .arguments; + dynamicParams = ModalRoute.of(context)!.settings.arguments; if (dynamicParams.isNotEmpty) { AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; - selectedEmp =dynamicParams; + selectedEmp = dynamicParams; getAbsenceTransactions(); - }else{ + } else { getAbsenceTransactions(); } } @@ -130,7 +124,7 @@ class _LeaveBalanceState extends State { ), child: const Icon(Icons.add, color: Colors.white, size: 30), ).onPress(() { - Navigator.pushNamed(context, AppRoutes.addLeaveBalance, arguments: selectedEmp ??''); + Navigator.pushNamed(context, AppRoutes.addLeaveBalance, arguments: selectedEmp ?? ''); }), ); } diff --git a/lib/widgets/balances_dashboard_widget.dart b/lib/widgets/balances_dashboard_widget.dart index 510137a..2c56c7e 100644 --- a/lib/widgets/balances_dashboard_widget.dart +++ b/lib/widgets/balances_dashboard_widget.dart @@ -46,12 +46,13 @@ class _BalancesDashboardWidgetState extends State { GetAccrualBalancesList? leaveBalanceAccrual; List? ticketBalanceAccrualList; dynamic dynamicParams; - String selectedEmp =""; + String selectedEmp = ""; @override void initState() { super.initState(); accrualDateTime = DateTime.now(); + changeAccrualDate(); } @override @@ -62,7 +63,7 @@ class _BalancesDashboardWidgetState extends State { void changeAccrualDate() async { try { Utils.showLoading(context); - List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime),empID: selectedEmp); + List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime), empID: selectedEmp); if (accrualList.isNotEmpty) { if (widget.isLeaveBalance) { leaveBalanceAccrual = accrualList[0]; From ecaede0deb29d0f3f139334ae2b49a51b0dd6edc Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 11 Dec 2022 16:22:54 +0300 Subject: [PATCH 05/23] Updates & fixes --- lib/classes/utils.dart | 3 +- lib/ui/work_list/worklist_detail_screen.dart | 32 ++++++++++---------- pubspec.yaml | 1 + 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 3b30d05..050ae4d 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -121,7 +121,8 @@ class Utils { ), ); } else { - showToast(errorMessage); + // showToast(errorMessage); + confirmDialog(cxt, errorMessage); } } } diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 8b22041..75ee88f 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -233,9 +233,9 @@ class _WorkListDetailScreenState extends State { ), child: Row( children: [ - (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") ? myTab(LocaleKeys.details.tr(), 0) : myTab(LocaleKeys.request.tr(), 0), - myTab(LocaleKeys.actions.tr(), 1), - myTab(LocaleKeys.info.tr(), 2), + myTab(LocaleKeys.info.tr(), 0), + (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") ? myTab(LocaleKeys.details.tr(), 1) : myTab(LocaleKeys.request.tr(), 1), + myTab(LocaleKeys.actions.tr(), 2), myTab(LocaleKeys.attachments.tr(), 3), ], ), @@ -249,6 +249,19 @@ class _WorkListDetailScreenState extends State { }); }, children: [ + InfoFragment( + poHeaderList: getPoNotificationBody?.pOHeader ?? [], + workListData: workListData, + itemCreationHeader: getItemCreationNtfBody?.itemCreationHeader ?? [], + getStampMsNotifications: getStampMsNotifications, + getStampNsNotifications: getStampNsNotifications, + getEitCollectionNotificationBodyList: getEitCollectionNotificationBodyList, + getPhonesNotificationBodyList: getPhonesNotificationBodyList, + getBasicDetNtfBodyList: getBasicDetNtfBodyList, + getAbsenceCollectionNotificationBodyList: getAbsenceCollectionNotificationBodyList, + getContactNotificationBodyList: getContactNotificationBodyList, + getPrNotificationBodyList: getPrNotificationBody, + ), (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") ? DetailFragment(workListData, memberInformationListModel) : RequestFragment( @@ -266,19 +279,6 @@ class _WorkListDetailScreenState extends State { voidCallback: reloadWorkList, ) : showLoadingAnimation(), - InfoFragment( - poHeaderList: getPoNotificationBody?.pOHeader ?? [], - workListData: workListData, - itemCreationHeader: getItemCreationNtfBody?.itemCreationHeader ?? [], - getStampMsNotifications: getStampMsNotifications, - getStampNsNotifications: getStampNsNotifications, - getEitCollectionNotificationBodyList: getEitCollectionNotificationBodyList, - getPhonesNotificationBodyList: getPhonesNotificationBodyList, - getBasicDetNtfBodyList: getBasicDetNtfBodyList, - getAbsenceCollectionNotificationBodyList: getAbsenceCollectionNotificationBodyList, - getContactNotificationBodyList: getContactNotificationBodyList, - getPrNotificationBodyList: getPrNotificationBody, - ), isAttachmentLoaded ? getAttachmentList.isEmpty ? Utils.getNoDataWidget(context) diff --git a/pubspec.yaml b/pubspec.yaml index 4fc00c8..0d5cda5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -98,6 +98,7 @@ dependencies: video_player: ^2.4.7 just_audio: ^0.9.30 + safe_device: ^1.1.2 dev_dependencies: flutter_test: From 810920a93468d298af78e902009c7a591bc9f4f5 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Sun, 11 Dec 2022 16:57:14 +0300 Subject: [PATCH 06/23] Pushing after resolving multiple times API calling issue --- lib/api/marathon/marathon_api_client.dart | 63 ++- lib/classes/consts.dart | 6 +- lib/config/routes.dart | 3 - lib/extensions/string_extensions.dart | 12 +- lib/generated/codegen_loader.g.dart | 22 +- lib/generated/locale_keys.g.dart | 500 ------------------ lib/main.dart | 5 + lib/models/marathon/winner_model.dart | 17 + lib/ui/marathon/marathon_provider.dart | 86 +-- lib/ui/marathon/marathon_screen.dart | 57 +- .../marathon_sponsor_video_screen.dart | 51 +- lib/ui/marathon/marathon_waiting_screen.dart | 123 +++-- .../marathon/marathon_winner_selection.dart | 90 ---- lib/ui/marathon/widgets/countdown_timer.dart | 182 ++----- lib/ui/marathon/widgets/marathon_banner.dart | 74 ++- .../marathon_qualifiers_container.dart | 6 +- lib/ui/marathon/widgets/question_card.dart | 30 +- 17 files changed, 423 insertions(+), 904 deletions(-) delete mode 100644 lib/generated/locale_keys.g.dart create mode 100644 lib/models/marathon/winner_model.dart delete mode 100644 lib/ui/marathon/marathon_winner_selection.dart diff --git a/lib/api/marathon/marathon_api_client.dart b/lib/api/marathon/marathon_api_client.dart index 132ec30..a9266d2 100644 --- a/lib/api/marathon/marathon_api_client.dart +++ b/lib/api/marathon/marathon_api_client.dart @@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_generic_model.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; import 'package:mohem_flutter_app/models/marathon/question_model.dart'; +import 'package:mohem_flutter_app/models/marathon/winner_model.dart'; import 'package:signalr_netcore/hub_connection.dart'; class MarathonApiClient { @@ -19,6 +20,7 @@ class MarathonApiClient { String employeeSession = AppState().postParamsObject?.pSessionId.toString() ?? ""; Map jsonObject = {"userName": employeeUserName, "password": employeeSession}; + Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonParticipantLoginUrl, jsonObject); var json = jsonDecode(response.body); @@ -80,10 +82,11 @@ class MarathonApiClient { return marathonDetailModel; } - Future joinMarathonAsParticipant() async { + Future joinMarathonAsParticipant() async { Map jsonObject = { "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "", - "employeeName": AppState().memberInformationList!.eMPLOYEENAME ?? "", + "employeeNameAr": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "", + "employeeNameEn": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "", "marathonId": AppState().getMarathonProjectId!, }; @@ -95,31 +98,33 @@ class MarathonApiClient { if (marathonModel.statusCode == 208) { // means participant is already in the marathon i.e already joined - return true; + return marathonModel.data["remainingTime"]; } if (marathonModel.statusCode == 200) { if (marathonModel.data != null && marathonModel.isSuccessful == true) { logger.i("joinMarathonAsParticipant: ${marathonModel.data}"); - return true; + return marathonModel.data["remainingTime"]; } else { - return false; + return null; } } else { - return false; + return null; } } Future getNextQuestion({required String? questionId, required String marathonId}) async { Map jsonObject = { - "questionId": questionId, + "previousQuestionId": questionId, "marathonId": marathonId, - }; + }; Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonNextQuestionUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken()); var json = jsonDecode(response.body); + + logger.i("json in NextQuestion: $json"); var data = json["data"]; if (data != null) { @@ -130,13 +135,13 @@ class MarathonApiClient { } } - Future submitSelectedOption({required String? selectedAnswerId}) async { - Map jsonObject = {"selectedOptionId": selectedAnswerId}; + Future submitSelectedOption({required String marathonId, required String? questionId, required String? selectedAnswerId}) async { + Map jsonObject = {"marathonId": marathonId, "questionId": questionId, "selectedOptionId" : selectedAnswerId}; Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonSubmitAnswerUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken()); var json = jsonDecode(response.body); - logger.i("json: $json"); + logger.i("json in submitSelectedOption : $json"); MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json); @@ -147,6 +152,42 @@ class MarathonApiClient { return marathonModel.isSuccessful!; } + Future getQualifiers({required String marathonId}) async { + Map params = {"marathonId": marathonId}; + Response response = await ApiClient().getJsonForResponse(ApiConsts.marathonQualifiersUrl, queryParameters: params, token: AppState().getMarathonToken ?? await getMarathonToken()); + + var json = jsonDecode(response.body); + logger.i("json in getQualifiers: $json"); + + MarathonGenericModel marathonGenericModel = MarathonGenericModel.fromJson(json); + + if (marathonGenericModel.isSuccessful == true && marathonGenericModel.statusCode == 200 && marathonGenericModel.data != null) { + return marathonGenericModel.data["winnerCount"]; + } + return null; + } + + Future?> getSelectedWinner({required String marathonId}) async { + Map params = {"marathonId": marathonId}; + Response response = await ApiClient().getJsonForResponse(ApiConsts.marathonSelectedWinner, queryParameters: params, token: AppState().getMarathonToken ?? await getMarathonToken()); + + var json = jsonDecode(response.body); + logger.i("json in getSelectedWinner: $json"); + + MarathonGenericModel marathonGenericModel = MarathonGenericModel.fromJson(json); + + if (marathonGenericModel.isSuccessful == true && marathonGenericModel.statusCode == 200 && marathonGenericModel.data != null) { + List winners = []; + List data = marathonGenericModel.data as List; + + for (Map winner in data) { + winners.add(WinnerModel.fromJson(winner)); + } + return winners; + } + return null; + } + // Future buildHubConnection(BuildContext context, String prizeId) async { // HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); // hubConnection = HubConnectionBuilder() diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 1230c8b..7ee0c23 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -25,21 +25,21 @@ class ApiConsts { static String chatFavUser = chatServerBaseApiUrl + "FavUser/"; static String chatUserImages = chatServerBaseUrl + "empservice/api/employee/"; - //Brain Marathon Constants static String marathonBaseUrl = "https://marathoon.com/service/api/"; static String marathonParticipantLoginUrl = marathonBaseUrl + "auth/participantlogin"; static String marathonProjectGetUrl = marathonBaseUrl + "Project/Project_Get"; static String marathonUpcomingUrl = marathonBaseUrl + "marathon/upcoming/"; - static String marathonJoinParticipantUrl = marathonBaseUrl + "participant/participant_join"; + static String marathonJoinParticipantUrl = marathonBaseUrl + "participant/join"; static String marathonNextQuestionUrl = marathonBaseUrl + "question/next"; static String marathonSubmitAnswerUrl = marathonBaseUrl + "question/submit"; static String marathonQualifiersUrl = marathonBaseUrl + "winner/getWinner/"; static String marathonSelectedWinner = marathonBaseUrl + "winner/getSelectedWinner/"; //DummyCards for the UI - static CardContent dummyQuestion = const CardContent(); + + static int tabletMinLength = 500; } class SharedPrefsConsts { diff --git a/lib/config/routes.dart b/lib/config/routes.dart index d1b6b08..af6af26 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -22,7 +22,6 @@ import 'package:mohem_flutter_app/ui/marathon/marathon_intro_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_sponsor_video_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_waiting_screen.dart'; -import 'package:mohem_flutter_app/ui/marathon/marathon_winner_selection.dart'; import 'package:mohem_flutter_app/ui/marathon/winner_screen.dart'; import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart'; @@ -186,7 +185,6 @@ class AppRoutes { //Marathon static const String marathonIntroScreen = "/marathonIntroScreen"; static const String marathonScreen = "/marathonScreen"; - static const String marathonWinnerSelection = "/marathonWinnerSelection"; static const String marathonWinnerScreen = "/marathonWinnerScreen"; static const String marathonSponsorVideoScreen = "/marathonSponsorVideoScreen"; static const String marathonWaitingScreen = "/marathonWaitingScreen"; @@ -296,7 +294,6 @@ class AppRoutes { // Marathon marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(), marathonScreen: (BuildContext context) => MarathonScreen(), - marathonWinnerSelection: (BuildContext context) => MarathonWinnerSelection(), marathonWinnerScreen: (BuildContext context) => WinnerScreen(), marathonSponsorVideoScreen: (BuildContext context) => const SponsorVideoScreen(), marathonWaitingScreen: (BuildContext context) => const MarathonWaitingScreen(), diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 3261149..494daaf 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -140,8 +140,9 @@ extension EmailValidator on String { style: TextStyle(color: color ?? MyColors.grey3AColor, fontSize: 21, letterSpacing: -0.84, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600)), ); - Widget toText22({Color? color, bool isBold = false}) => Text( + Widget toText22({Color? color, bool isBold = false, bool isCentered = false}) => Text( this, + textAlign: isCentered ? TextAlign.center : null, style: TextStyle(height: 1, color: color ?? MyColors.darkTextColor, fontSize: 22, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); @@ -151,12 +152,13 @@ extension EmailValidator on String { ); Widget toText30({Color? color, bool isBold = false}) => Text( - this, - style: TextStyle(height: 20 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.2, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), - ); + this, + style: TextStyle(height: 20 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.2, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), + ); - Widget toText32({Color? color, bool isBold = false}) => Text( + Widget toText32({Color? color, bool isBold = false, bool isCentered = false}) => Text( this, + textAlign: isCentered ? TextAlign.center : null, style: TextStyle(height: 32 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.92, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index a54ff37..8a2113d 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -516,7 +516,16 @@ class CodegenLoader extends AssetLoader{ "codeExpire": "انتهت صلاحية رمز التحقق", "typeheretoreply": "اكتب هنا للرد", "favorite": "مفضلتي", - "searchfromchat": "البحث من الدردشة" + "searchfromchat": "البحث من الدردشة", + "yourAnswerCorrect": "إجابتك صحيحة", + "youMissedTheQuestion": "نفد منك الوقت. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", + "wrongAnswer": "إجابتك غير صحيحة. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", + "oops": "أوه!!!", + "winner": "الفائز", + "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", + "ourSponsor": "راعينا:", + "startingIn": "يبدأ في", + "youAreOutOfContest": "أنت خارج المسابقة." }; static const Map en_US = { "mohemm": "Mohemm", @@ -1020,7 +1029,16 @@ static const Map en_US = { "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply", "favorite": "My Favorites", - "searchfromchat": "Search from chat" + "searchfromchat": "Search from chat", + "yourAnswerCorrect": "Your answer is correct", + "youMissedTheQuestion": "You ran out of time. You are out of the game. But you can continue and as a viewer.", + "wrongAnswer": "Your answer is Incorrect. You are out of the game. But you can continue and as a viewer.", + "oops": "Ooopsss!!!!", + "winner": "WINNER", + "youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.", + "ourSponsor": "Our Sponsor:", + "startingIn": "Starting in", + "youAreOutOfContest": "You are out of the contest." }; 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 deleted file mode 100644 index 1d28232..0000000 --- a/lib/generated/locale_keys.g.dart +++ /dev/null @@ -1,500 +0,0 @@ -// DO NOT EDIT. This is code generated via package:easy_localization/generate.dart - -abstract class LocaleKeys { - static const mohemm = 'mohemm'; - static const english = 'english'; - static const arabic = 'arabic'; - static const login = 'login'; - static const pleaseEnterLoginDetails = 'pleaseEnterLoginDetails'; - static const username = 'username'; - static const password = 'password'; - static const welcomeBack = 'welcomeBack'; - static const wouldYouLikeToLoginWithCurrentUsername = 'wouldYouLikeToLoginWithCurrentUsername'; - static const lastLoginDetails = 'lastLoginDetails'; - static const verificationType = 'verificationType'; - static const pleaseVerify = 'pleaseVerify'; - static const pleaseVerifyForBio = 'pleaseVerifyForBio'; - static const verifyThroughFace = 'verifyThroughFace'; - static const verifyThroughFingerprint = 'verifyThroughFingerprint'; - static const verifyThroughSMS = 'verifyThroughSMS'; - static const verifyThroughWhatsapp = 'verifyThroughWhatsapp'; - static const useAnotherAccount = 'useAnotherAccount'; - static const pleaseEnterTheVerificationCodeSentTo = 'pleaseEnterTheVerificationCodeSentTo'; - static const theVerificationCodeWillExpireIn = 'theVerificationCodeWillExpireIn'; - static const goodMorning = 'goodMorning'; - static const markAttendance = 'markAttendance'; - static const timeLeftToday = 'timeLeftToday'; - static const checkIn = 'checkIn'; - static const workList = 'workList'; - static const leaveBalance = 'leaveBalance'; - static const missingSwipes = 'missingSwipes'; - static const ticketBalance = 'ticketBalance'; - static const services = 'services'; - static const viewAllServices = 'viewAllServices'; - static const monthlyAttendance = 'monthlyAttendance'; - static const vacationRule = 'vacationRule'; - static const vacationType = 'vacationType'; - static const startDateT = 'startDateT'; - static const endDateT = 'endDateT'; - static const workFromHome = 'workFromHome'; - static const ticketRequest = 'ticketRequest'; - static const viewAllOffers = 'viewAllOffers'; - static const offers = 'offers'; - static const discounts = 'discounts'; - static const newString = 'newString'; - static const setTheNewPassword = 'setTheNewPassword'; - static const typeYourNewPasswordBelow = 'typeYourNewPasswordBelow'; - static const confirmPassword = 'confirmPassword'; - static const update = 'update'; - static const title = 'title'; - static const home = 'home'; - static const mySalary = 'mySalary'; - static const createRequest = 'createRequest'; - static const forgotPassword = 'forgotPassword'; - static const employeeId = 'employeeId'; - static const loginCodeWillSentToMobileNumber = 'loginCodeWillSentToMobileNumber'; - static const changePassword = 'changePassword'; - static const ok = 'ok'; - static const confirm = 'confirm'; - static const passwordChangedSuccessfully = 'passwordChangedSuccessfully'; - static const itemsForSale = 'itemsForSale'; - static const attendanceDetails = 'attendanceDetails'; - static const order = 'order'; - static const earlyOut = 'earlyOut'; - static const shortage = 'shortage'; - static const excess = 'excess'; - static const lateIn = 'lateIn'; - static const approvedCheckOut = 'approvedCheckOut'; - static const approvedCheckIn = 'approvedCheckIn'; - static const actualCheckOut = 'actualCheckOut'; - static const actualCheckIn = 'actualCheckIn'; - static const present = 'present'; - static const pres = 'pres'; - static const shiftTime = 'shiftTime'; - static const absent = 'absent'; - static const attendance = 'attendance'; - static const scheduleDays = 'scheduleDays'; - static const offDays = 'offDays'; - static const nonAnalyzed = 'nonAnalyzed'; - static const shortageHour = 'shortageHour'; - static const stats = 'stats'; - static const completed = 'completed'; - static const msg = 'msg'; - static const msg_named = 'msg_named'; - static const clickMe = 'clickMe'; - static const doNotUseRecentPassword = 'doNotUseRecentPassword'; - static const atLeastOneLowercase = 'atLeastOneLowercase'; - static const atLeastOneUppercase = 'atLeastOneUppercase'; - static const atLeastOneNumeric = 'atLeastOneNumeric'; - static const minimum8Characters = 'minimum8Characters'; - static const doNotAddRepeatingLetters = 'doNotAddRepeatingLetters'; - static const itShouldContainSpecialCharacter = 'itShouldContainSpecialCharacter'; - static const confirmPasswordMustMatch = 'confirmPasswordMustMatch'; - static const sms = 'sms'; - static const fingerPrint = 'fingerPrint'; - static const face = 'face'; - static const whatsapp = 'whatsapp'; - static const reject = 'reject'; - static const approve = 'approve'; - static const cancel = 'cancel'; - static const requestedItems = 'requestedItems'; - static const request = 'request'; - static const myRequest = 'myRequest'; - static const actions = 'actions'; - static const delegate = 'delegate'; - static const request_info = 'request_info'; - static const attachments = 'attachments'; - static const info = 'info'; - static const employeeNumber = 'employeeNumber'; - static const assignmentNumber = 'assignmentNumber'; - static const employeeName = 'employeeName'; - static const scheduleDate = 'scheduleDate'; - static const shiftType = 'shiftType'; - static const shift = 'shift'; - static const breakText = 'breakText'; - static const actualSwipeStart = 'actualSwipeStart'; - static const actualSwipeEnd = 'actualSwipeEnd'; - static const approvedSwipeStart = 'approvedSwipeStart'; - static const approvedSwipeStartReason = 'approvedSwipeStartReason'; - static const approvedSwipeEnd = 'approvedSwipeEnd'; - static const approvedSwipeEndReason = 'approvedSwipeEndReason'; - static const from = 'from'; - static const to = 'to'; - static const sent = 'sent'; - static const closed = 'closed'; - static const id = 'id'; - static const responder = 'responder'; - static const jobTitle = 'jobTitle'; - static const grade = 'grade'; - static const jobCategory = 'jobCategory'; - static const category = 'category'; - static const employeeEmailAddress = 'employeeEmailAddress'; - static const payrollBranch = 'payrollBranch'; - static const yourChangeHasBeenSavedSuccessfully = 'yourChangeHasBeenSavedSuccessfully'; - static const code = 'code'; - static const unit = 'unit'; - static const quantity = 'quantity'; - static const dateRequired = 'dateRequired'; - static const lineStatus = 'lineStatus'; - static const statusDate = 'statusDate'; - static const transactionType = 'transactionType'; - static const operatingUnit = 'operatingUnit'; - static const organizationCode = 'organizationCode'; - static const organization = 'organization'; - static const fromSubInventory = 'fromSubInventory'; - static const fromLocator = 'fromLocator'; - static const toSubInventory = 'toSubInventory'; - static const toLocator = 'toLocator'; - static const shipToLocator = 'shipToLocator'; - static const itemHistory = 'itemHistory'; - static const mfg = 'mfg'; - static const lineType = 'lineType'; - static const price = 'price'; - static const lineAmount = 'lineAmount'; - static const lineDiscount = 'lineDiscount'; - static const needByDate = 'needByDate'; - static const promisedDate = 'promisedDate'; - static const deliverToLocation = 'deliverToLocation'; - static const requisitionNumber = 'requisitionNumber'; - static const requester = 'requester'; - static const quotationAnalysis = 'quotationAnalysis'; - static const subject = 'subject'; - static const description = 'description'; - static const supplier = 'supplier'; - static const site = 'site'; - static const buyer = 'buyer'; - static const preparer = 'preparer'; - static const creationDate = 'creationDate'; - static const shipToLocation = 'shipToLocation'; - static const quotationNumber = 'quotationNumber'; - static const quotationDate = 'quotationDate'; - static const paymentTerms = 'paymentTerms'; - static const currency = 'currency'; - static const grossAmount = 'grossAmount'; - static const discountAmount = 'discountAmount'; - static const customDuty = 'customDuty'; - static const shipHandle = 'shipHandle'; - static const otherCharges = 'otherCharges'; - static const totalPOAmountWithVAT = 'totalPOAmountWithVAT'; - static const totalPOAmountInWords = 'totalPOAmountInWords'; - static const requestNumber = 'requestNumber'; - static const uom = 'uom'; - static const operatingCode = 'operatingCode'; - static const poNumber = 'poNumber'; - static const revision = 'revision'; - static const quantityOrdered = 'quantityOrdered'; - static const quantityReceived = 'quantityReceived'; - static const bonusQuantity = 'bonusQuantity'; - static const purchasePrice = 'purchasePrice'; - static const discountPer = 'discountPer'; - static const balanceQuantity = 'balanceQuantity'; - static const netPrice = 'netPrice'; - static const closureStatus = 'closureStatus'; - static const quotationNetPrice = 'quotationNetPrice'; - static const quotationUOM = 'quotationUOM'; - static const quotationQty = 'quotationQty'; - static const itemCode = 'itemCode'; - static const vendorName = 'vendorName'; - static const quotationMFGPartNumber = 'quotationMFGPartNumber'; - static const quotationDeliveryDate = 'quotationDeliveryDate'; - static const quotationBonusQuantity = 'quotationBonusQuantity'; - static const quotationLineTotal = 'quotationLineTotal'; - static const rfqUOM = 'rfqUOM'; - static const rfqQty = 'rfqQty'; - static const rfqNumber = 'rfqNumber'; - static const human = 'human'; - static const resources = 'resources'; - static const details = 'details'; - static const noDataAvailable = 'noDataAvailable'; - static const productName = 'productName'; - static const productDescription = 'productDescription'; - static const unitPrice = 'unitPrice'; - static const manufacturerName = 'manufacturerName'; - static const manufacturerPartName = 'manufacturerPartName'; - static const supplierName = 'supplierName'; - static const supplierContact = 'supplierContact'; - static const chargeToPatient = 'chargeToPatient'; - static const justification = 'justification'; - static const itemDescription = 'itemDescription'; - static const groupCode = 'groupCode'; - static const primaryUOM = 'primaryUOM'; - static const subgroupDescription = 'subgroupDescription'; - static const subgroupCode = 'subgroupCode'; - static const groupDescription = 'groupDescription'; - static const templateName = 'templateName'; - static const itemCreationStatus = 'itemCreationStatus'; - static const standardizationApprovalStatus = 'standardizationApprovalStatus'; - static const standardizationApprovalRejectionReason = 'standardizationApprovalRejectionReason'; - static const analyzedBy = 'analyzedBy'; - static const approvedDate = 'approvedDate'; - static const itemType = 'itemType'; - static const relatedTo = 'relatedTo'; - static const requestDate = 'requestDate'; - static const analyzedDate = 'analyzedDate'; - static const urgent = 'urgent'; - static const requestDetails = 'requestDetails'; - static const approvalLevel = 'approvalLevel'; - static const requesterDetails = 'requesterDetails'; - static const myAttendance = 'myAttendance'; - static const workOnBreak = 'workOnBreak'; - static const next = 'next'; - static const apply = 'apply'; - static const mobile = 'mobile'; - static const completingYear = 'completingYear'; - static const year = 'year'; - static const month = 'month'; - static const day = 'day'; - static const address = 'address'; - static const phoneNumber = 'phoneNumber'; - static const businessGroup = 'businessGroup'; - static const Payroll = 'Payroll'; - static const civilIdentityNumber = 'civilIdentityNumber'; - static const dateOfBirth = 'dateOfBirth'; - static const maritalStatus = 'maritalStatus '; - static const fullName = 'fullName'; - static const remove = 'remove'; - static const submit = 'submit'; - static const areYouSureYouWantToSubmit = 'areYouSureYouWantToSubmit'; - static const comments = 'comments'; - static const writeComment = 'writeComment'; - static const approversList = 'approversList'; - static const yourRequestHasBeenSubmittedForApprovals = 'yourRequestHasBeenSubmittedForApprovals'; - static const monthlyPaySlip = 'monthlyPaySlip'; - static const particular = 'particular'; - static const earnings = 'earnings'; - static const deductions = 'deductions'; - static const paymentMethodName = 'paymentMethodName'; - static const bankName = 'bankName'; - static const branchCode = 'branchCode'; - static const accountNo = 'accountNo'; - static const summaryOfInformation = 'summaryOfInformation'; - static const totalPayAmount = 'totalPayAmount'; - static const paymentInformation = 'paymentInformation'; - static const performance = 'performance'; - static const performanceEvaluation = 'performanceEvaluation'; - static const performanceEvaluationIn = 'performanceEvaluationIn'; - static const valuationIn = 'valuationIn'; - static const amount = 'amount'; - static const correctCurrentDatails = 'correctCurrentDatails'; - static const selectType = 'selectType'; - static const enterNewInfo = 'enterNewInfo'; - static const endDate = 'endDate'; - static const removeThisMember = 'removeThisMember'; - static const wantUpdateThisMember = 'wantUpdateThisMember '; - static const addNewFamilyMember = 'addNewFamilyMember'; - static const addRow = 'addRow'; - static const pleaseSelect = 'pleaseSelect'; - static const delete = 'delete'; - static const edit = 'edit'; - static const add = 'add'; - static const myProfile = 'myProfile'; - static const mowadhafhi = 'mowadhafhi'; - static const searchAnnouncements = 'searchAnnouncements'; - static const announcements = 'announcements'; - static const swipeRequest = 'swipeRequest'; - static const serviceType = 'serviceType'; - static const departmentName = 'departmentName'; - static const selectDepartment = 'selectDepartment'; - static const relatedSection = 'relatedSection'; - static const selectSection = 'selectSection'; - static const relatedTopic = 'relatedTopic'; - static const selectTopic = 'selectTopic'; - static const supportingDocument = 'supportingDocument'; - static const mowadhafhiRequest = 'mowadhafhiRequest'; - static const ticketReference = 'ticketReference'; - static const section = 'section'; - static const topic = 'topic'; - static const actionBy = 'actionBy'; - static const pending = 'pending'; - static const pendingTransactions = 'pendingTransactions'; - static const selectRequestType = 'selectRequestType'; - static const dateFrom = 'dateFrom'; - static const dateTo = 'dateTo'; - static const requestName = 'requestName'; - static const createdFor = 'createdFor'; - static const requestCreatedSuccessfully = 'requestCreatedSuccessfully'; - static const search = 'search'; - static const wantToReject = 'wantToReject'; - static const requestType = 'requestType'; - static const employeeDigitalID = 'employeeDigitalID'; - static const businessCard = 'businessCard'; - static const viewBusinessCard = 'viewBusinessCard'; - static const logout = 'logout'; - static const checkOut = 'checkOut'; - static const regular = 'regular'; - static const mark = 'mark'; - static const selectMethodOfAttendance = 'selectMethodOfAttendance'; - static const comeNearHMGWifi = 'comeNearHMGWifi'; - static const deliverNotificationToMeRegardless = 'deliverNotificationToMeRegardless'; - static const close = 'close'; - static const respond = 'respond'; - static const vacationRuleAdded = 'vacationRuleAdded'; - static const selectTypeT = 'selectTypeT'; - static const notification = 'notification'; - static const selectNotification = 'selectNotification'; - static const ifAllSelectedYouWillSkip = 'ifAllSelectedYouWillSkip'; - static const applyForVacationRule = 'applyForVacationRule'; - static const step1 = 'step1'; - static const step2 = 'step2'; - static const step3 = 'step3'; - static const message = 'message'; - static const writeAMessage = 'writeAMessage'; - static const notificationReassign = 'notificationReassign'; - static const selectEmployee = 'selectEmployee'; - static const searchEmployeeForReplacement = 'searchEmployeeForReplacement'; - static const searchForEmployee = 'searchForEmployee'; - static const pleaseSpecifyEndTime = 'pleaseSpecifyEndTime'; - static const pleaseSelectNotificationReassign = 'pleaseSelectNotificationReassign'; - static const pleaseSelectEmployeeForReplacement = 'pleaseSelectEmployeeForReplacement'; - static const pleaseSelectAction = 'pleaseSelectAction'; - static const pleaseSelectDate = 'pleaseSelectDate'; - static const todayAttendance = 'todayAttendance'; - static const viewAttendance = 'viewAttendance'; - static const teamMembers = 'teamMembers'; - static const profileDetails = 'profileDetails'; - static const noResultsFound = 'noResultsFound'; - static const searchBy = 'searchBy'; - static const myTeamMembers = 'myTeamMembers'; - static const save = 'save'; - static const TurnNotificationsFor = 'TurnNotificationsFor'; - static const worklistSettings = 'worklistSettings'; - static const absenceType = 'absenceType'; - static const absenceCategory = 'absenceCategory'; - static const days = 'days'; - static const hours = 'hours'; - static const approvalStatus = 'approvalStatus'; - static const absenceStatus = 'absenceStatus'; - static const subordinateLeave = 'subordinateLeave'; - static const numberDays = 'numberDays'; - static const poweredBy = 'poweredBy'; - static const cloudSolutions = 'cloudSolutions'; - static const selectTemplate = 'selectTemplate'; - static const myPostedAds = 'myPostedAds'; - static const browseCategories = 'browseCategories'; - static const searchItems = 'searchItems'; - static const offerAndDiscounts = 'offerAndDiscounts'; - static const offerValid = 'offerValid'; - static const offerExpired = 'offerExpired'; - static const whatAreYouOffering = 'whatAreYouOffering'; - static const selectCategory = 'selectCategory'; - static const inProgress = 'inProgress'; - static const locked = 'locked'; - static const addDetails = 'addDetails'; - static const reviewAndSell = 'reviewAndSell'; - static const itemTitle = 'itemTitle'; - static const itemCondition = 'itemCondition'; - static const used = 'used'; - static const region = 'region'; - static const selectRegion = 'selectRegion'; - static const itemPrice = 'itemPrice'; - static const itemPhotos = 'itemPhotos'; - static const itemInfo = 'itemInfo'; - static const uploadAttachment = 'uploadAttachment'; - static const selectFromGalleryOrOpenCamera = 'selectFromGalleryOrOpenCamera'; - static const openCamera = 'openCamera'; - static const uploadFromGallery = 'uploadFromGallery'; - static const name = 'name'; - static const email = 'email'; - static const noHistoryAvailable = 'noHistoryAvailable'; - static const purchaseRequisition = 'purchaseRequisition'; - static const moveOrder = 'moveOrder'; - static const humanResource = 'humanResource'; - static const purchaseOrder = 'purchaseOrder'; - static const ITGForms = 'ITGForms'; - static const itemCreation = 'itemCreation'; - static const stamp = 'stamp'; - static const addFavoriteList = 'addFavoriteList'; - static const feedbackUserExperience = 'feedbackUserExperience'; - static const rateUI = 'rateUI'; - static const submitSurvey = 'submitSurvey'; - static const typeHere = 'typeHere'; - static const infoDetail = 'infoDetail'; - static const amount_detail = 'amount_detail'; - static const currentBalance = 'currentBalance'; - static const currentLeaveBalance = 'currentLeaveBalance'; - static const calculatedDays = 'calculatedDays'; - static const totalDays = 'totalDays'; - static const usedBalance = 'usedBalance'; - static const infants = 'infants'; - static const child = 'child'; - static const adult = 'adult'; - static const updateMember = 'updateMember'; - static const fieldIsEmpty = 'fieldIsEmpty'; - static const pleaseEnterComments = 'pleaseEnterComments'; - 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'; - static const profile_reset_password = 'profile.reset_password'; - static const profile_profileCompletionPer = 'profile.profileCompletionPer'; - static const profile_completeProfile = 'profile.completeProfile'; - static const profile_personalInformation = 'profile.personalInformation'; - static const profile_basicDetails = 'profile.basicDetails'; - static const profile_address = 'profile.address'; - static const profile_contactDetails = 'profile.contactDetails'; - static const profile_familyDetails = 'profile.familyDetails'; - static const profile_effectiveDate = 'profile.effectiveDate'; - static const profile_country = 'profile.country'; - static const profile = 'profile'; - static const clicked = 'clicked'; - static const gender_with_arg = 'gender.with_arg'; - static const gender = 'gender'; - static const reset_locale = 'reset_locale'; - static const chat = 'chat'; - static const mychats = 'mychats'; - static const advancedSearch = 'advancedSearch'; - static const openNot = 'openNot'; - static const fyi = 'fyi'; - static const toDo = 'toDo'; - static const all = 'all'; - static const meNot = 'meNot'; - static const view = 'view'; - static const fromUserName = 'fromUserName'; - static const sentDate = 'sentDate'; - static const itemTypeDisplayName = 'itemTypeDisplayName'; - static const none = 'none'; - static const createNewChat = 'createNewChat'; - static const brainMarathon = 'brainMarathon'; - static const contestTopicAbout = 'contestTopicAbout'; - static const gameDate = 'gameDate'; - static const gameTime = 'gameTime'; - static const joinMarathon = 'joinMarathon'; - static const joinDemoMarathon = 'joinDemoMarathon'; - static const minutes = 'minutes'; - static const seconds = 'seconds'; - static const note = 'note'; - static const demoMarathonNoteP1 = 'demoMarathonNoteP1'; - static const demoMarathonNoteP2 = 'demoMarathonNoteP2'; - static const demoMarathonNoteP3 = 'demoMarathonNoteP3'; - static const sponsoredBy = 'sponsoredBy'; - static const question = 'question'; - static const marathoners = 'marathoners'; - static const prize = 'prize'; - static const winnerSelection = 'winnerSelection'; - static const qualifiers = 'qualifiers'; - static const getReadyForContest = 'getReadyForContest'; - static const winnerSelectedRandomly = 'winnerSelectedRandomly'; - 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'; - static const typeheretoreply = 'typeheretoreply'; - static const favorite = 'favorite'; - static const searchfromchat = 'searchfromchat'; - static const yourAnswerCorrect = 'yourAnswerCorrect'; - static const youMissedTheQuestion = 'youMissedTheQuestion'; - static const wrongAnswer = 'wrongAnswer'; - static const oops = 'oops'; - static const winner = 'winner'; - static const youWantToLeaveMarathon = 'youWantToLeaveMarathon'; - static const ourSponsor = 'ourSponsor'; - static const startingIn = 'startingIn'; - static const youAreOutOfContest = 'youAreOutOfContest'; - -} diff --git a/lib/main.dart b/lib/main.dart index 4709be1..aa9f933 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/generated/codegen_loader.g.dart'; import 'package:mohem_flutter_app/models/post_params_model.dart'; @@ -32,11 +33,15 @@ class MyHttpOverrides extends HttpOverrides { } } +bool isTablet = false; + Future main() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); AppState().setPostParamsInitConfig(); HttpOverrides.global = MyHttpOverrides(); + isTablet = MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.shortestSide >= ApiConsts.tabletMinLength; + runApp( EasyLocalization( supportedLocales: const [ diff --git a/lib/models/marathon/winner_model.dart b/lib/models/marathon/winner_model.dart new file mode 100644 index 0000000..5663bf1 --- /dev/null +++ b/lib/models/marathon/winner_model.dart @@ -0,0 +1,17 @@ +class WinnerModel { + String? id; + String? marathoneId; + String? employeeId; + String? nameEn; + String? nameAr; + + WinnerModel({id, marathoneId, employeeId, nameEn, nameAr}); + + WinnerModel.fromJson(Map json) { + id = json['id']; + marathoneId = json['marathoneId']; + employeeId = json['employeeId']; + nameEn = json['nameEn']; + nameAr = json['nameAr']; + } +} diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index 1cf8efd..2d778b9 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -9,6 +9,7 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; import 'package:mohem_flutter_app/models/marathon/question_model.dart'; +import 'package:mohem_flutter_app/models/marathon/winner_model.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; import 'package:video_player/video_player.dart'; @@ -22,10 +23,10 @@ class MarathonProvider extends ChangeNotifier { QuestionModel currentQuestion = QuestionModel(); List answerStatusesList = []; QuestionCardStatus questionCardStatus = QuestionCardStatus.question; - + List? selectedWinners; int? selectedOptionIndex; String? selectedOptionId; - int totalQualifiers = 0; + int? totalQualifiers; bool _isLoading = false; @@ -110,6 +111,7 @@ class MarathonProvider extends ChangeNotifier { //****************TIMERS********** + int sponsorsSecondsCounter = 0; int totalSponsorVideoSeconds = 0; Timer timerForSponsorVideo = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); @@ -118,6 +120,7 @@ class MarathonProvider extends ChangeNotifier { timerForSponsorVideo = Timer.periodic( oneSec, (Timer timer) async { + sponsorsSecondsCounter++; if (totalSponsorVideoSeconds == 0) { timer.cancel(); notifyListeners(); @@ -134,12 +137,15 @@ class MarathonProvider extends ChangeNotifier { int totalSecondsToWaitForMarathon = 20; Timer timerToWaitForMarathon = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); - void startTimerToMarathon(BuildContext context) { + void startTimerToWaitForMarathon() { const Duration oneSec = Duration(seconds: 1); timerToWaitForMarathon = Timer.periodic( oneSec, (Timer timer) async { if (totalSecondsToWaitForMarathon == 0) { + callNextQuestionApi(); + timer.cancel(); + return; } else { totalSecondsToWaitForMarathon--; } @@ -163,6 +169,8 @@ class MarathonProvider extends ChangeNotifier { } if (totalCurrentQuestionTime == currentGapTime) { + totalCurrentQuestionTime--; + updateCardStatusToAnswer(); await callSubmitOptionApi().then((bool value) async { @@ -175,6 +183,7 @@ class MarathonProvider extends ChangeNotifier { if (totalCurrentQuestionTime == 0) { updateCardData(); if (currentQuestionNumber == marathonDetailModel.totalQuestions! - 1) { + callGetQualifiersApi(); updateQuestionCardStatus(QuestionCardStatus.findingWinner); timer.cancel(); cancelTimer(); @@ -182,7 +191,9 @@ class MarathonProvider extends ChangeNotifier { } return; } else { - totalCurrentQuestionTime--; + if (totalCurrentQuestionTime != currentGapTime) { + totalCurrentQuestionTime--; + } } notifyListeners(); @@ -214,7 +225,17 @@ class MarathonProvider extends ChangeNotifier { //****************FUNCTIONS********* Future callSubmitOptionApi() async { - return await MarathonApiClient().submitSelectedOption(selectedAnswerId: selectedOptionId); + return await MarathonApiClient().submitSelectedOption(marathonId: marathonDetailModel.id!, questionId: currentQuestion.id, selectedAnswerId: selectedOptionId); + } + + Future callGetQualifiersApi() async { + totalQualifiers = await MarathonApiClient().getQualifiers(marathonId: marathonDetailModel.id!); + notifyListeners(); + } + + Future callGetSelectedWinnersApi() async { + selectedWinners = await MarathonApiClient().getSelectedWinner(marathonId: marathonDetailModel.id!); + notifyListeners(); } // TODO: here I need to add a logic where I should call this function for Api but for the 1st question it should behave differently @@ -222,6 +243,7 @@ class MarathonProvider extends ChangeNotifier { Future callNextQuestionApi() async { if (currentQuestionNumber < marathonDetailModel.totalQuestions!) { if (currentQuestionNumber == 0) { + Utils.showLoading(AppRoutes.navigatorKey.currentContext!); currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!))!; if (Utils.isLoading) { Utils.hideLoading(AppRoutes.navigatorKey.currentContext!); @@ -239,8 +261,7 @@ class MarathonProvider extends ChangeNotifier { void updateCardData() { if (currentQuestionNumber > 0) { - print("swiped it away!!"); - swipeCardLeft(); + swiperController.swipeLeft(); } selectedOptionIndex = null; currentQuestionNumber++; @@ -249,6 +270,7 @@ class MarathonProvider extends ChangeNotifier { currentGapTime = currentQuestion.nextQuestGap!; totalMarathoners = currentQuestion.remainingParticipantCount!; questionCardStatus = QuestionCardStatus.question; + notifyListeners(); } void populateQuestionStatusesList() { @@ -316,20 +338,21 @@ class MarathonProvider extends ChangeNotifier { } } - void swipeCardLeft() { - swiperController.swipeLeft(); - notifyListeners(); - } - void resetValues() async { _currentQuestionNumber = 0; cardContentList.clear(); timerForWinnerSelection.cancel(); + timerForSponsorVideo.cancel(); + timerToWaitForMarathon.cancel(); timerForQuestion.cancel(); _isMarathonCompleted = false; + isUserOutOfGame = false; totalCurrentQuestionTime = 0; + sponsorsSecondsCounter = 0; + totalSponsorVideoSeconds = 0; + totalSecondsToWaitForMarathon = 20; + currentGapTime = 0; currentQuestion = QuestionModel(); - notifyListeners(); } @@ -354,40 +377,23 @@ class MarathonProvider extends ChangeNotifier { }); } - Future buildConnectionWithSignalR(BuildContext context) async { - Utils.showLoading(context); + Future onJoinMarathonPressed(BuildContext context) async { try { + Utils.showLoading(context); resetValues(); - // await MarathonApiClient().buildHubConnection(context, marathonDetailModel.sponsors!.first.sponsorPrizes!.first.id!); + int? remainingTime = await MarathonApiClient().joinMarathonAsParticipant(); + if (remainingTime != null) { + totalSecondsToWaitForMarathon = remainingTime; + notifyListeners(); + startTimerToWaitForMarathon(); + Navigator.pushReplacementNamed(context, AppRoutes.marathonWaitingScreen); + } } catch (e) { if (kDebugMode) { - print("error in buildConnectionWithSignalR: ${e.toString()}"); + print("error in onJoinMarathonPressed: ${e.toString()}"); } Utils.hideLoading(context); Utils.confirmDialog(context, e.toString()); } } - - Future onJoinMarathonPressed(BuildContext context) async { - //TODO: here we need to put a check to make sure we should not display sponsor when remaining time to marathon is less than 30 seconds plus video duration e.g. 30 seconds + video duration time - // if (marathonDetailModel.sponsors!.first.video != null && marathonDetailModel.sponsors!.first.video != "") { - if (false) { - await initializeVideoPlayer().then((_) { - startTimerForSponsorVideo(); - Navigator.pushNamed(context, AppRoutes.marathonSponsorVideoScreen); - }); - } else { - try { - Utils.showLoading(context); - bool isJoined = await MarathonApiClient().joinMarathonAsParticipant(); - if (isJoined) { - print("joined"); - callNextQuestionApi(); - } - } catch (e, s) { - Utils.hideLoading(context); - Utils.confirmDialog(context, e.toString()); - } - } - } } diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index e14f8c9..2ae3f64 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -8,7 +8,7 @@ import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/classes/lottie_consts.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'; @@ -21,6 +21,7 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_qualifiers_contai import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card_builder.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:provider/provider.dart'; class MarathonScreen extends StatelessWidget { @@ -63,22 +64,28 @@ class MarathonScreen extends StatelessWidget { SizedBox( height: 50, child: Stack( - children: [ + children: [ Align( alignment: Alignment.center, child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50), ), Align( alignment: Alignment.center, - child: LocaleKeys.winner.tr().toText32(color: MyColors.white, isBold: true).paddingOnly(top: 07), + child: LocaleKeys.winner.tr().toText32(color: MyColors.white, isBold: true, isCentered: true).paddingOnly(top: 07), ) ], ), ), 12.height, - "Muhammad Shrouff".toText22(color: MyColors.grey3AColor), - "837436".toText22(color: MyColors.grey57Color), - 80.height, + if (provider.selectedWinners != null) ...[ + (AppState().isArabic(context) ? provider.selectedWinners!.first.nameEn : provider.selectedWinners!.first.nameEn)!.toText22( + color: MyColors.grey3AColor, + isCentered: true, + ), + 8.height, + provider.selectedWinners!.first.employeeId!.toText22(color: MyColors.grey57Color), + ], + 60.height, if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...[ Row( mainAxisAlignment: MainAxisAlignment.center, @@ -118,12 +125,12 @@ class MarathonScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr!) + (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!) .toText17(isBold: true, color: MyColors.white), AppState().memberInformationList!.eMPLOYEENUMBER!.toText17(isBold: true, color: MyColors.white), ], ), - ).paddingOnly(left: 20, right: 20, top: 12, bottom: 20); + ).paddingOnly(left: 20, right: 20, top: 12, bottom: 10); } @override @@ -135,10 +142,38 @@ class MarathonScreen extends StatelessWidget { context, title: LocaleKeys.brainMarathon.tr(), onHomeTapped: () { - Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); + if (provider.questionCardStatus == QuestionCardStatus.winnerFound) { + provider.resetValues(); + Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard)); + } else { + showDialog( + context: context, + builder: (BuildContext context) => ConfirmDialog( + message: LocaleKeys.youWantToLeaveMarathon.tr(), + onTap: () { + provider.resetValues(); + Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard)); + }, + ), + ); + } }, onBackTapped: () { - Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); + if (provider.questionCardStatus == QuestionCardStatus.winnerFound) { + provider.resetValues(); + Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard)); + } else { + showDialog( + context: context, + builder: (BuildContext context) => ConfirmDialog( + message: LocaleKeys.youWantToLeaveMarathon.tr(), + onTap: () { + provider.resetValues(); + Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard)); + }, + ), + ); + } }, ), body: SingleChildScrollView( @@ -156,7 +191,7 @@ class MarathonScreen extends StatelessWidget { getNameContainer(context), ], QuestionCardBuilder( - onQuestion: (BuildContext context) => QuestionCard(provider: provider), + onQuestion: (BuildContext context) => const QuestionCard(), onCompleted: (BuildContext context) => CustomStatusWidget( asset: Lottie.asset(MyLottieConsts.allQuestions, height: 200), title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor), diff --git a/lib/ui/marathon/marathon_sponsor_video_screen.dart b/lib/ui/marathon/marathon_sponsor_video_screen.dart index c81f59b..12d5949 100644 --- a/lib/ui/marathon/marathon_sponsor_video_screen.dart +++ b/lib/ui/marathon/marathon_sponsor_video_screen.dart @@ -25,6 +25,9 @@ class SponsorVideoScreen extends StatelessWidget { return WillPopScope( onWillPop: () { provider.videoController.dispose(); + provider.sponsorsSecondsCounter = 0; + provider.totalSponsorVideoSeconds = 0; + provider.timerForSponsorVideo.cancel(); return Future.value(true); }, child: Scaffold( @@ -52,9 +55,11 @@ class SponsorVideoScreen extends StatelessWidget { child: provider.totalSponsorVideoSeconds == 0 ? InkWell( onTap: () { - Navigator.pop(context); provider.videoController.dispose(); - provider.buildConnectionWithSignalR(AppRoutes.navigatorKey.currentState!.overlay!.context); + provider.sponsorsSecondsCounter = 0; + provider.totalSponsorVideoSeconds = 0; + provider.timerForSponsorVideo.cancel(); + Navigator.pushReplacementNamed(context, AppRoutes.marathonIntroScreen); }, child: const Icon(Icons.close, size: 12), ) @@ -64,24 +69,30 @@ class SponsorVideoScreen extends StatelessWidget { ), ), ).paddingOnly(top: 20, right: 18), - Align( - alignment: Alignment.topLeft, - child: InkWell( - onTap: () { - Navigator.pop(context); - provider.videoController.dispose(); - provider.buildConnectionWithSignalR(AppRoutes.navigatorKey.currentState!.overlay!.context); - }, - child: Container( - decoration: BoxDecoration(color: MyColors.white, borderRadius: BorderRadius.circular(15)), - padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 6), - child: Directionality( - textDirection: ui.TextDirection.ltr, - child: LocaleKeys.skip.tr().toText11(color: MyColors.darkTextColor), - ), - ), - ), - ).paddingOnly(top: 20, left: 18), + + //TODO: WE WILL INCREASE THIS 2 BEFORE GOING LIVE + provider.sponsorsSecondsCounter >= 2 + ? Align( + alignment: Alignment.topLeft, + child: InkWell( + onTap: () { + provider.videoController.dispose(); + provider.sponsorsSecondsCounter = 0; + provider.totalSponsorVideoSeconds = 0; + provider.timerForSponsorVideo.cancel(); + Navigator.pushReplacementNamed(context, AppRoutes.marathonIntroScreen); + }, + child: Container( + decoration: BoxDecoration(color: MyColors.white, borderRadius: BorderRadius.circular(15)), + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 6), + child: Directionality( + textDirection: ui.TextDirection.ltr, + child: LocaleKeys.skip.tr().toText11(color: MyColors.darkTextColor), + ), + ), + ), + ).paddingOnly(top: 20, left: 18) + : const SizedBox(), ], ), ), diff --git a/lib/ui/marathon/marathon_waiting_screen.dart b/lib/ui/marathon/marathon_waiting_screen.dart index 27f0c08..7191ff2 100644 --- a/lib/ui/marathon/marathon_waiting_screen.dart +++ b/lib/ui/marathon/marathon_waiting_screen.dart @@ -4,12 +4,13 @@ import 'package:lottie/lottie.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/classes/lottie_consts.dart'; -import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:provider/provider.dart'; class MarathonWaitingScreen extends StatelessWidget { @@ -18,44 +19,90 @@ class MarathonWaitingScreen extends StatelessWidget { @override Widget build(BuildContext context) { MarathonProvider provider = context.watch(); - return Scaffold( - appBar: AppBarWidget( - context, - title: LocaleKeys.brainMarathon.tr(), - onHomeTapped: () { - Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); - }, - onBackTapped: () { - Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); - }, - ), - body: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: double.infinity, - margin: const EdgeInsets.all(21), - decoration: MyDecorations.shadowDecoration, - child: Stack( - children: [ - Align( - child: Lottie.asset(MyLottieConsts.marathonWaiting, height: 200), - ), - Align( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - LocaleKeys.startingIn.tr().toText16(), - "00:${provider.totalSecondsToWaitForMarathon < 10 ? "0${provider.totalSecondsToWaitForMarathon}" : provider.totalSecondsToWaitForMarathon}" - .toText18(color: provider.totalSecondsToWaitForMarathon < 5 ? MyColors.redColor : MyColors.black), - ], + return WillPopScope( + onWillPop: () { + showDialog( + context: context, + builder: (BuildContext context) => ConfirmDialog( + message: LocaleKeys.youWantToLeaveMarathon.tr(), + onTap: () { + provider.resetValues(); + Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard)); + }, + ), + ); + return Future.value(false); + }, + child: Scaffold( + appBar: AppBarWidget( + context, + title: LocaleKeys.brainMarathon.tr(), + onHomeTapped: () { + showDialog( + context: context, + builder: (BuildContext context) => ConfirmDialog( + message: LocaleKeys.youWantToLeaveMarathon.tr(), + onTap: () { + provider.resetValues(); + Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard)); + }, + ), + ); + }, + onBackTapped: () { + showDialog( + context: context, + builder: (BuildContext context) => ConfirmDialog( + message: LocaleKeys.youWantToLeaveMarathon.tr(), + onTap: () { + provider.resetValues(); + Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard)); + }, + ), + ); + }, + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: double.infinity, + margin: const EdgeInsets.all(21), + decoration: MyDecorations.shadowDecoration, + child: Stack( + children: [ + Align( + child: Lottie.asset(MyLottieConsts.marathonWaiting, height: 200), + ), + Align( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocaleKeys.startingIn.tr().toText16(), + provider.totalSecondsToWaitForMarathon.toString().toText18(color: provider.totalSecondsToWaitForMarathon < 5 ? MyColors.redColor : MyColors.black), + ], + ), + ), + Align( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + InkWell( + onTap: () { + provider.callNextQuestionApi(); + provider.timerToWaitForMarathon.cancel(); + }, + child: "Join Now".toText16(), + ).paddingOnly(bottom: 20), + ], + ), ), - ), - ], - ), - ).expanded, - ], + ], + ), + ).expanded, + ], + ), ), ); } diff --git a/lib/ui/marathon/marathon_winner_selection.dart b/lib/ui/marathon/marathon_winner_selection.dart deleted file mode 100644 index ed49f04..0000000 --- a/lib/ui/marathon/marathon_winner_selection.dart +++ /dev/null @@ -1,90 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; -import 'package:lottie/lottie.dart'; -import 'package:mohem_flutter_app/classes/colors.dart'; -import 'package:mohem_flutter_app/classes/lottie_consts.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/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_qualifiers_container.dart'; -import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; -import 'package:provider/provider.dart'; - -class MarathonWinnerSelection extends StatelessWidget { - const MarathonWinnerSelection({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - MarathonProvider provider = context.read(); - return Scaffold( - appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()), - body: SingleChildScrollView( - child: Column( - children: [ - 20.height, - QualifiersContainer(provider: provider,).paddingOnly(left: 21, right: 21), - 12.height, - InkWell( - onTap: () { - Navigator.pushNamed(context, AppRoutes.marathonWinnerScreen); - }, - child: Container( - height: 50, - decoration: BoxDecoration( - color: MyColors.greenColor, - borderRadius: BorderRadius.circular(15), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - "Muhammad Shrouff".toText17(isBold: true, color: MyColors.white), - "837436".toText17(isBold: true, color: MyColors.white), - ], - ), - ), - ).paddingOnly(left: 20, right: 20), - ), - CustomStatusWidget( - asset: Lottie.asset( - MyLottieConsts.winnerLottie, - height: 168, - ), - title: Text( - LocaleKeys.fingersCrossed.tr(), - style: const TextStyle( - height: 27 / 27, - color: MyColors.greenColor, - fontSize: 27, - letterSpacing: -1.08, - fontWeight: FontWeight.w600, - ), - ), - subTitle: Text( - LocaleKeys.winnerSelectedRandomly.tr(), - textAlign: TextAlign.center, - style: const TextStyle( - color: MyColors.darkTextColor, - fontSize: 18, - letterSpacing: -0.72, - fontWeight: FontWeight.w600, - ), - )).paddingOnly(left: 21, right: 21, top: 20, bottom: 20), - ], - ), - ), - ); - } -} diff --git a/lib/ui/marathon/widgets/countdown_timer.dart b/lib/ui/marathon/widgets/countdown_timer.dart index cfa3b1b..3a33697 100644 --- a/lib/ui/marathon/widgets/countdown_timer.dart +++ b/lib/ui/marathon/widgets/countdown_timer.dart @@ -8,6 +8,7 @@ import 'package:flutter_countdown_timer/current_remaining_time.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; class BuildCountdownTimer extends StatelessWidget { @@ -29,9 +30,10 @@ class BuildCountdownTimer extends StatelessWidget { letterSpacing: -0.4, ); - final TextStyle styleDigitHome = const TextStyle( + final TextStyle styleDigitHome = TextStyle( height: 22 / 27, color: MyColors.white, + fontSize: isTablet ? 30 : 15, fontStyle: FontStyle.italic, letterSpacing: -1.44, fontWeight: FontWeight.bold, @@ -53,6 +55,33 @@ class BuildCountdownTimer extends StatelessWidget { fontWeight: FontWeight.bold, ); + Widget buildSeparator() { + return AutoSizeText( + " : ", + maxFontSize: 24, + minFontSize: 20, + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + ); + } + + Widget getTimeDigit(String text) { + return AutoSizeText( + text, + maxFontSize: 24, + minFontSize: 20, + style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, + ); + } + + Widget getTimeText(String text) { + return AutoSizeText( + text, + minFontSize: 7, + maxFontSize: 8, + style: screenFlag == 0 ? styleTextHome : styleTextMarathon, + ); + } + Widget buildEmptyWidget() { return Directionality( textDirection: ui.TextDirection.ltr, @@ -63,70 +92,29 @@ class BuildCountdownTimer extends StatelessWidget { children: [ Column( children: [ - // todo @faiz: Make a separate method and pass string , so we can minimize code replication - AutoSizeText( - "00", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ), - AutoSizeText( - LocaleKeys.days.tr(), - minFontSize: 7, - maxFontSize: 8, - style: screenFlag == 0 ? styleTextHome : styleTextMarathon, - ), + getTimeDigit("00"), + getTimeText(LocaleKeys.days.tr()), ], ), buildSeparator(), Column( children: [ - AutoSizeText( - "00", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ), - AutoSizeText( - LocaleKeys.hours.tr(), - minFontSize: 7, - maxFontSize: 8, - style: screenFlag == 0 ? styleTextHome : styleTextMarathon, - ), + getTimeDigit("00"), + getTimeText(LocaleKeys.hours.tr()), ], ), buildSeparator(), Column( children: [ - AutoSizeText( - "00", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ), - AutoSizeText( - LocaleKeys.minutes.tr(), - minFontSize: 7, - maxFontSize: 8, - style: screenFlag == 0 ? styleTextHome : styleTextMarathon, - ), + getTimeDigit("00"), + getTimeText(LocaleKeys.minutes.tr()), ], ), buildSeparator(), Column( children: [ - AutoSizeText( - "00", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ), - AutoSizeText( - LocaleKeys.seconds.tr(), - minFontSize: 7, - maxFontSize: 8, - style: screenFlag == 0 ? styleTextHome : styleTextMarathon, - ), + getTimeDigit("00"), + getTimeText(LocaleKeys.seconds.tr()), ], ), ], @@ -134,15 +122,6 @@ class BuildCountdownTimer extends StatelessWidget { ); } - Widget buildSeparator() { - return AutoSizeText( - " : ", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ); - } - Widget buildCountdownTimer(CurrentRemainingTime? time) { if (time == null) { if (!provider.itsMarathonTime) { @@ -162,98 +141,29 @@ class BuildCountdownTimer extends StatelessWidget { children: [ Column( children: [ - // todo @faiz: Make a separate method and pass value and string , so we can minimize code replication - time.days == null - ? AutoSizeText( - "00", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ) - : AutoSizeText( - time.days! < 10 ? "0${time.days.toString()}" : time.days.toString(), - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ), - AutoSizeText( - LocaleKeys.days.tr(), - minFontSize: 7, - maxFontSize: 8, - style: screenFlag == 0 ? styleTextHome : styleTextMarathon, - ), + time.days == null ? getTimeDigit("00") : getTimeDigit(time.days! < 10 ? "0${time.days.toString()}" : time.days.toString()), + getTimeText(LocaleKeys.days.tr()), ], ), buildSeparator(), Column( children: [ - time.hours == null - ? AutoSizeText( - "00", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ) - : AutoSizeText( - time.hours! < 10 ? "0${time.hours.toString()}" : time.hours.toString(), - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ), - AutoSizeText( - LocaleKeys.hours.tr(), - minFontSize: 7, - maxFontSize: 8, - style: screenFlag == 0 ? styleTextHome : styleTextMarathon, - ), + time.hours == null ? getTimeDigit("00") : getTimeDigit(time.hours! < 10 ? "0${time.hours.toString()}" : time.hours.toString()), + getTimeText(LocaleKeys.hours.tr()), ], ), buildSeparator(), Column( children: [ - time.min == null - ? AutoSizeText( - "00", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ) - : AutoSizeText( - time.min! < 10 ? "0${time.min.toString()}" : time.min.toString(), - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ), - AutoSizeText( - LocaleKeys.minutes.tr(), - minFontSize: 7, - maxFontSize: 8, - style: screenFlag == 0 ? styleTextHome : styleTextMarathon, - ), + time.min == null ? getTimeDigit("00") : getTimeDigit(time.min! < 10 ? "0${time.min.toString()}" : time.min.toString()), + getTimeText(LocaleKeys.minutes.tr()), ], ), buildSeparator(), Column( children: [ - time.sec == null - ? AutoSizeText( - "00", - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ) - : AutoSizeText( - time.sec! < 10 ? "0${time.sec.toString()}" : time.sec.toString(), - maxFontSize: 24, - minFontSize: 20, - style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon, - ), - AutoSizeText( - LocaleKeys.seconds.tr(), - minFontSize: 7, - maxFontSize: 8, - style: screenFlag == 0 ? styleTextHome : styleTextMarathon, - ), + time.sec == null ? getTimeDigit("00") : getTimeDigit(time.sec! < 10 ? "0${time.sec.toString()}" : time.sec.toString()), + getTimeText(LocaleKeys.seconds.tr()), ], ), ], diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index d805362..2be08a9 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -1,16 +1,18 @@ import 'dart:math' as math; -import 'package:auto_size_text/auto_size_text.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.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/decorations_helper.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/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart'; import 'package:provider/provider.dart'; @@ -26,10 +28,10 @@ class MarathonBanner extends StatelessWidget { return provider.marathonDetailModel.startTime != null ? Container( decoration: MyDecorations.shadowDecoration, - height: MediaQuery.of(context).size.height * 0.11, + height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11, clipBehavior: Clip.antiAlias, child: Stack( - children: [ + children: [ Transform( alignment: Alignment.center, transform: Matrix4.rotationY( @@ -48,8 +50,8 @@ class MarathonBanner extends StatelessWidget { child: Transform.rotate( angle: 10, child: Container( - width: 65, - height: 32, + width: isTablet ? 70 : 65, + height: isTablet ? 40 : 32, color: MyColors.darkDigitColor, ), ), @@ -60,8 +62,8 @@ class MarathonBanner extends StatelessWidget { child: Transform.rotate( angle: 15, child: Container( - width: 65, - height: 32, + width: isTablet ? 70 : 65, + height: isTablet ? 40 : 32, color: MyColors.darkDigitColor, ), ), @@ -70,7 +72,7 @@ class MarathonBanner extends StatelessWidget { width: double.infinity, height: double.infinity, child: Row( - children: [ + children: [ const Expanded( flex: 3, child: SizedBox( @@ -92,28 +94,27 @@ class MarathonBanner extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ AppState().isArabic(context) ? 0.height : 5.height, - AutoSizeText( + Text( LocaleKeys.getReadyForContest.tr(), - minFontSize: 08, - maxFontSize: 11, style: TextStyle( + fontSize: isTablet ? 20 : 11, fontStyle: FontStyle.italic, fontWeight: FontWeight.w600, color: MyColors.white.withOpacity(0.83), letterSpacing: -0.4, ), ), - AutoSizeText( + Text( AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "", style: TextStyle( fontStyle: FontStyle.italic, - fontSize: 19, + fontSize: isTablet ? 30 : 19, fontWeight: FontWeight.bold, color: MyColors.white.withOpacity(0.83), height: 32 / 22, ), ), - 3.height, + isTablet ? 10.height : 3.height, BuildCountdownTimer( timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, provider: provider, @@ -135,18 +136,18 @@ class MarathonBanner extends StatelessWidget { ? Align( alignment: Alignment.topRight, child: SizedBox( - height: 20, - width: 35, + height: isTablet ? 30 : 20, + width: isTablet ? 45 : 35, child: Transform.rotate( angle: math.pi / 4.5, child: Text( LocaleKeys.brainMarathon.tr(), textAlign: TextAlign.center, maxLines: 2, - style: const TextStyle( + style: TextStyle( color: MyColors.white, fontWeight: FontWeight.bold, - fontSize: 6, + fontSize: isTablet ? 8 : 6, height: 1.2, ), ), @@ -156,18 +157,18 @@ class MarathonBanner extends StatelessWidget { : Align( alignment: Alignment.topLeft, child: SizedBox( - height: 20, - width: 35, + height: isTablet ? 30 : 20, + width: isTablet ? 45 : 35, child: Transform.rotate( angle: -math.pi / 4.5, child: Text( LocaleKeys.brainMarathon.tr(), textAlign: TextAlign.center, maxLines: 2, - style: const TextStyle( + style: TextStyle( color: MyColors.kWhiteColor, fontWeight: FontWeight.bold, - fontSize: 6, + fontSize: isTablet ? 8 : 6, height: 1.2, ), ), @@ -181,7 +182,7 @@ class MarathonBanner extends StatelessWidget { child: RotatedBox( quarterTurns: 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), - ).paddingAll(15), + ).paddingAll(isTablet ? 20 : 15), ) : Positioned( bottom: 0, @@ -189,12 +190,31 @@ class MarathonBanner extends StatelessWidget { child: RotatedBox( quarterTurns: 2, child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), - ).paddingAll(15), + ).paddingAll(isTablet ? 20 : 15), ), ], - ).onPress( - () => Navigator.pushNamed(context, AppRoutes.marathonIntroScreen), - ), + ).onPress(() async { + int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes; + + if (remainingTimeInMinutes > 2) { + Utils.showLoading(context); + try { + await provider.initializeVideoPlayer().then((_) { + Utils.hideLoading(context); + provider.startTimerForSponsorVideo(); + Navigator.pushNamed(context, AppRoutes.marathonSponsorVideoScreen); + }); + } catch (e, s) { + if (kDebugMode) { + print("Error in VideoPlayer: ${e.toString()}"); + } + Utils.hideLoading(context); + Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); + } + } else { + Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); + } + }), ) : const SizedBox(); } diff --git a/lib/ui/marathon/widgets/marathon_qualifiers_container.dart b/lib/ui/marathon/widgets/marathon_qualifiers_container.dart index 0308027..dc9d7e4 100644 --- a/lib/ui/marathon/widgets/marathon_qualifiers_container.dart +++ b/lib/ui/marathon/widgets/marathon_qualifiers_container.dart @@ -20,6 +20,7 @@ class _QualifiersContainerState extends State { @override void initState() { widget.provider.startTimerForWinnerSelection(); + widget.provider.callGetSelectedWinnersApi(); super.initState(); } @@ -36,13 +37,14 @@ class _QualifiersContainerState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ LocaleKeys.winnerSelection.tr().toText21(color: MyColors.grey3AColor), - "00:${widget.provider.totalSecondsToWaitForWinner < 10 ? "0${widget.provider.totalSecondsToWaitForWinner}" : widget.provider.totalSecondsToWaitForWinner}".toText18(color: MyColors.redColor), + "00:${widget.provider.totalSecondsToWaitForWinner < 10 ? "0${widget.provider.totalSecondsToWaitForWinner}" : widget.provider.totalSecondsToWaitForWinner}" + .toText18(color: MyColors.redColor), ], ), 10.height, Row( children: [ - widget.provider.totalQualifiers.toString().toText30(color: MyColors.greenColor, isBold: true), + widget.provider.totalQualifiers != null ? widget.provider.totalQualifiers.toString().toText30(color: MyColors.greenColor, isBold: true) : const SizedBox(), 2.width, LocaleKeys.qualifiers.tr().toText16(color: MyColors.greenColor), ], diff --git a/lib/ui/marathon/widgets/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index 4009983..5f419c5 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -1,4 +1,5 @@ import 'package:appinio_swiper/appinio_swiper.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; @@ -6,38 +7,35 @@ import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/classes/lottie_consts.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.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'; class QuestionCard extends StatelessWidget { - final MarathonProvider provider; - - const QuestionCard({Key? key, required this.provider}) : super(key: key); + const QuestionCard({Key? key}) : super(key: key); @override Widget build(BuildContext context) { + MarathonProvider provider = context.read(); return CupertinoPageScaffold( child: provider.cardContentList.isEmpty ? Lottie.asset(MyLottieConsts.hourGlassLottie, height: 250).paddingOnly(top: 50) : SizedBox( height: 440, width: double.infinity, - child: Consumer( - builder: (BuildContext context, MarathonProvider provider, _) { - return AppinioSwiper( - duration: const Duration(milliseconds: 400), - padding: EdgeInsets.zero, - isDisabled: true, - controller: provider.swiperController, - unswipe: (int index, AppinioSwiperDirection direction) {}, - onSwipe: (int index, AppinioSwiperDirection direction) {}, - cards: provider.cardContentList, - ); - }, + child: AppinioSwiper( + duration: const Duration(milliseconds: 400), + padding: EdgeInsets.zero, + isDisabled: true, + controller: provider.swiperController, + unswipe: (int index, AppinioSwiperDirection direction) {}, + onSwipe: (int index, AppinioSwiperDirection direction) {}, + cards: provider.cardContentList, ), ), ); @@ -163,7 +161,7 @@ class AnswerTileForText extends StatelessWidget { MarathonProvider provider = context.watch(); return InkWell( onTap: () { - provider.isUserOutOfGame ? null : onAnswerTapped() ; + provider.isUserOutOfGame ? Utils.showToast(LocaleKeys.youAreOutOfContest.tr()) : onAnswerTapped(); }, child: Container( alignment: Alignment.centerLeft, From 4c53fcfdb6191b0a4b944c0832b8aa206946c12c Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 11 Dec 2022 17:20:39 +0300 Subject: [PATCH 07/23] updates & fixes --- lib/api/dashboard_api_client.dart | 2 +- lib/ui/leave_balance/add_leave_balance_screen.dart | 2 +- lib/ui/leave_balance/leave_balance_screen.dart | 4 ++-- .../dynamic_screens/dynamic_input_screen.dart | 7 ++++++- .../dynamic_screens/dynamic_listview_screen.dart | 2 +- lib/ui/my_team/create_request.dart | 8 ++++---- lib/widgets/balances_dashboard_widget.dart | 9 +++++---- 7 files changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 3eab65b..076a353 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -69,7 +69,7 @@ class DashboardApiClient { String url = "${ApiConsts.erpRest}GET_ACCRUAL_BALANCES"; Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { + if (empID != null && empID.isNotEmpty) { postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; } return await ApiClient().postJsonForObject((json) { diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index 4df7233..ed8396f 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -160,7 +160,7 @@ class _AddLeaveBalanceScreenState extends State { Widget build(BuildContext context) { if (dynamicParams == null) { dynamicParams = ModalRoute.of(context)!.settings.arguments; - if (dynamicParams.isNotEmpty) { + if (dynamicParams!= null && dynamicParams.isNotEmpty) { AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; selectedEmp = dynamicParams; getAbsenceAttendanceTypes(); diff --git a/lib/ui/leave_balance/leave_balance_screen.dart b/lib/ui/leave_balance/leave_balance_screen.dart index 07d6a7c..d1a64c6 100644 --- a/lib/ui/leave_balance/leave_balance_screen.dart +++ b/lib/ui/leave_balance/leave_balance_screen.dart @@ -57,7 +57,7 @@ class _LeaveBalanceState extends State { Widget build(BuildContext context) { if (dynamicParams == null) { dynamicParams = ModalRoute.of(context)!.settings.arguments; - if (dynamicParams.isNotEmpty) { + if (dynamicParams!= null && dynamicParams.isNotEmpty) { AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; selectedEmp = dynamicParams; getAbsenceTransactions(); @@ -75,7 +75,7 @@ class _LeaveBalanceState extends State { physics: const BouncingScrollPhysics(), padding: const EdgeInsets.all(21), children: [ - BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true), + BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true, selectedEmp), 12.height, absenceTransList == null ? const SizedBox() 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 62cafbd..2461e4b 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -621,7 +621,12 @@ class _DynamicInputScreenState extends State { ).paddingOnly(bottom: 12), itemBuilder: (_) => >[ if (model.rEADONLY != "Y") - for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem(child: Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), value: i), + for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem(value: i, child: Column( + children: [ + Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), + const PopupMenuDivider(), + ], + )), ], onSelected: (int popipIndex) async { ESERVICESDV eservicesdv = ESERVICESDV( diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index a670cbb..d1c21e1 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -91,7 +91,7 @@ class _DynamicListViewScreenState extends State { padding: const EdgeInsets.all(21), children: [ // HMG_TKT_NEW_EIT_SS Id used for ticket balance dashboard - if (isTicketRequest) ...[const BalancesDashboardWidget("Current Ticket Balance", false), 12.height], + if (isTicketRequest) ...[const BalancesDashboardWidget("Current Ticket Balance", false, ""), 12.height], getEITTransactionList == null ? const SizedBox() : (getEITTransactionList!.isEmpty diff --git a/lib/ui/my_team/create_request.dart b/lib/ui/my_team/create_request.dart index 53205c9..2b3e063 100644 --- a/lib/ui/my_team/create_request.dart +++ b/lib/ui/my_team/create_request.dart @@ -65,14 +65,14 @@ class _CreateRequestState extends State { return menus; } - void handleOnPress(context, Menus menu) { - + void handleOnPress(context, Menus menu) { if (menu.menuEntry.menuEntryType == "FUNCTION") { if (menu.menuEntry.requestType == "EIT") { - Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(menu.menuEntry.prompt!, menu.menuEntry.functionName!)); + Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(menu.menuEntry.prompt!, menu.menuEntry.functionName!, selectedEmp: getEmployeeSubordinates?.eMPLOYEENUMBER ?? '')); } else {} } else { - Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(menu.menuEntry.prompt!, menu.menuEntiesList, selectedEmp: getEmployeeSubordinates?.eMPLOYEENUMBER??'')); + Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, + arguments: ServicesMenuListScreenParams(menu.menuEntry.prompt!, menu.menuEntiesList, selectedEmp: getEmployeeSubordinates?.eMPLOYEENUMBER ?? '')); } return; } diff --git a/lib/widgets/balances_dashboard_widget.dart b/lib/widgets/balances_dashboard_widget.dart index 2c56c7e..9689de4 100644 --- a/lib/widgets/balances_dashboard_widget.dart +++ b/lib/widgets/balances_dashboard_widget.dart @@ -31,8 +31,9 @@ class BalancesDashboardWidget extends StatefulWidget { final String title; final List chartModelList; final bool isLeaveBalance; + final String selectedEmp; - const BalancesDashboardWidget(this.title, this.isLeaveBalance, {Key? key, this.chartModelList = const []}) : super(key: key); + const BalancesDashboardWidget(this.title, this.isLeaveBalance, this.selectedEmp, {Key? key, this.chartModelList = const []}) : super(key: key); @override _BalancesDashboardWidgetState createState() { @@ -62,8 +63,8 @@ class _BalancesDashboardWidgetState extends State { void changeAccrualDate() async { try { - Utils.showLoading(context); - List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime), empID: selectedEmp); + // Utils.showLoading(context); + List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime), empID: widget.selectedEmp); if (accrualList.isNotEmpty) { if (widget.isLeaveBalance) { leaveBalanceAccrual = accrualList[0]; @@ -79,7 +80,7 @@ class _BalancesDashboardWidgetState extends State { ]; } } - Utils.hideLoading(context); + // Utils.hideLoading(context); setState(() {}); } catch (ex) { Utils.hideLoading(context); From 1e7ff09f140942ff4ff7137f969c28f84ad1a856 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 11 Dec 2022 17:23:25 +0300 Subject: [PATCH 08/23] loader uncommented --- lib/ui/leave_balance/add_leave_balance_screen.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index ed8396f..5ef03f4 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -96,7 +96,7 @@ class _AddLeaveBalanceScreenState extends State { } void validateAbsenceTransaction(selectedID) async { - //try { + try { Utils.showLoading(context); Map dffDataMap = {}; for (int i = 1; i <= 20; i++) { @@ -145,10 +145,10 @@ class _AddLeaveBalanceScreenState extends State { } 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 From 8a3ca3135bba87cc5debaf3ce67827c24cd8e5ba Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Sun, 11 Dec 2022 17:29:34 +0300 Subject: [PATCH 09/23] Pushing after resolving multiple times API calling issue --- lib/generated/locale_keys.g.dart | 500 +++++++++++++++++++++++++++++++ 1 file changed, 500 insertions(+) create mode 100644 lib/generated/locale_keys.g.dart diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart new file mode 100644 index 0000000..1d28232 --- /dev/null +++ b/lib/generated/locale_keys.g.dart @@ -0,0 +1,500 @@ +// DO NOT EDIT. This is code generated via package:easy_localization/generate.dart + +abstract class LocaleKeys { + static const mohemm = 'mohemm'; + static const english = 'english'; + static const arabic = 'arabic'; + static const login = 'login'; + static const pleaseEnterLoginDetails = 'pleaseEnterLoginDetails'; + static const username = 'username'; + static const password = 'password'; + static const welcomeBack = 'welcomeBack'; + static const wouldYouLikeToLoginWithCurrentUsername = 'wouldYouLikeToLoginWithCurrentUsername'; + static const lastLoginDetails = 'lastLoginDetails'; + static const verificationType = 'verificationType'; + static const pleaseVerify = 'pleaseVerify'; + static const pleaseVerifyForBio = 'pleaseVerifyForBio'; + static const verifyThroughFace = 'verifyThroughFace'; + static const verifyThroughFingerprint = 'verifyThroughFingerprint'; + static const verifyThroughSMS = 'verifyThroughSMS'; + static const verifyThroughWhatsapp = 'verifyThroughWhatsapp'; + static const useAnotherAccount = 'useAnotherAccount'; + static const pleaseEnterTheVerificationCodeSentTo = 'pleaseEnterTheVerificationCodeSentTo'; + static const theVerificationCodeWillExpireIn = 'theVerificationCodeWillExpireIn'; + static const goodMorning = 'goodMorning'; + static const markAttendance = 'markAttendance'; + static const timeLeftToday = 'timeLeftToday'; + static const checkIn = 'checkIn'; + static const workList = 'workList'; + static const leaveBalance = 'leaveBalance'; + static const missingSwipes = 'missingSwipes'; + static const ticketBalance = 'ticketBalance'; + static const services = 'services'; + static const viewAllServices = 'viewAllServices'; + static const monthlyAttendance = 'monthlyAttendance'; + static const vacationRule = 'vacationRule'; + static const vacationType = 'vacationType'; + static const startDateT = 'startDateT'; + static const endDateT = 'endDateT'; + static const workFromHome = 'workFromHome'; + static const ticketRequest = 'ticketRequest'; + static const viewAllOffers = 'viewAllOffers'; + static const offers = 'offers'; + static const discounts = 'discounts'; + static const newString = 'newString'; + static const setTheNewPassword = 'setTheNewPassword'; + static const typeYourNewPasswordBelow = 'typeYourNewPasswordBelow'; + static const confirmPassword = 'confirmPassword'; + static const update = 'update'; + static const title = 'title'; + static const home = 'home'; + static const mySalary = 'mySalary'; + static const createRequest = 'createRequest'; + static const forgotPassword = 'forgotPassword'; + static const employeeId = 'employeeId'; + static const loginCodeWillSentToMobileNumber = 'loginCodeWillSentToMobileNumber'; + static const changePassword = 'changePassword'; + static const ok = 'ok'; + static const confirm = 'confirm'; + static const passwordChangedSuccessfully = 'passwordChangedSuccessfully'; + static const itemsForSale = 'itemsForSale'; + static const attendanceDetails = 'attendanceDetails'; + static const order = 'order'; + static const earlyOut = 'earlyOut'; + static const shortage = 'shortage'; + static const excess = 'excess'; + static const lateIn = 'lateIn'; + static const approvedCheckOut = 'approvedCheckOut'; + static const approvedCheckIn = 'approvedCheckIn'; + static const actualCheckOut = 'actualCheckOut'; + static const actualCheckIn = 'actualCheckIn'; + static const present = 'present'; + static const pres = 'pres'; + static const shiftTime = 'shiftTime'; + static const absent = 'absent'; + static const attendance = 'attendance'; + static const scheduleDays = 'scheduleDays'; + static const offDays = 'offDays'; + static const nonAnalyzed = 'nonAnalyzed'; + static const shortageHour = 'shortageHour'; + static const stats = 'stats'; + static const completed = 'completed'; + static const msg = 'msg'; + static const msg_named = 'msg_named'; + static const clickMe = 'clickMe'; + static const doNotUseRecentPassword = 'doNotUseRecentPassword'; + static const atLeastOneLowercase = 'atLeastOneLowercase'; + static const atLeastOneUppercase = 'atLeastOneUppercase'; + static const atLeastOneNumeric = 'atLeastOneNumeric'; + static const minimum8Characters = 'minimum8Characters'; + static const doNotAddRepeatingLetters = 'doNotAddRepeatingLetters'; + static const itShouldContainSpecialCharacter = 'itShouldContainSpecialCharacter'; + static const confirmPasswordMustMatch = 'confirmPasswordMustMatch'; + static const sms = 'sms'; + static const fingerPrint = 'fingerPrint'; + static const face = 'face'; + static const whatsapp = 'whatsapp'; + static const reject = 'reject'; + static const approve = 'approve'; + static const cancel = 'cancel'; + static const requestedItems = 'requestedItems'; + static const request = 'request'; + static const myRequest = 'myRequest'; + static const actions = 'actions'; + static const delegate = 'delegate'; + static const request_info = 'request_info'; + static const attachments = 'attachments'; + static const info = 'info'; + static const employeeNumber = 'employeeNumber'; + static const assignmentNumber = 'assignmentNumber'; + static const employeeName = 'employeeName'; + static const scheduleDate = 'scheduleDate'; + static const shiftType = 'shiftType'; + static const shift = 'shift'; + static const breakText = 'breakText'; + static const actualSwipeStart = 'actualSwipeStart'; + static const actualSwipeEnd = 'actualSwipeEnd'; + static const approvedSwipeStart = 'approvedSwipeStart'; + static const approvedSwipeStartReason = 'approvedSwipeStartReason'; + static const approvedSwipeEnd = 'approvedSwipeEnd'; + static const approvedSwipeEndReason = 'approvedSwipeEndReason'; + static const from = 'from'; + static const to = 'to'; + static const sent = 'sent'; + static const closed = 'closed'; + static const id = 'id'; + static const responder = 'responder'; + static const jobTitle = 'jobTitle'; + static const grade = 'grade'; + static const jobCategory = 'jobCategory'; + static const category = 'category'; + static const employeeEmailAddress = 'employeeEmailAddress'; + static const payrollBranch = 'payrollBranch'; + static const yourChangeHasBeenSavedSuccessfully = 'yourChangeHasBeenSavedSuccessfully'; + static const code = 'code'; + static const unit = 'unit'; + static const quantity = 'quantity'; + static const dateRequired = 'dateRequired'; + static const lineStatus = 'lineStatus'; + static const statusDate = 'statusDate'; + static const transactionType = 'transactionType'; + static const operatingUnit = 'operatingUnit'; + static const organizationCode = 'organizationCode'; + static const organization = 'organization'; + static const fromSubInventory = 'fromSubInventory'; + static const fromLocator = 'fromLocator'; + static const toSubInventory = 'toSubInventory'; + static const toLocator = 'toLocator'; + static const shipToLocator = 'shipToLocator'; + static const itemHistory = 'itemHistory'; + static const mfg = 'mfg'; + static const lineType = 'lineType'; + static const price = 'price'; + static const lineAmount = 'lineAmount'; + static const lineDiscount = 'lineDiscount'; + static const needByDate = 'needByDate'; + static const promisedDate = 'promisedDate'; + static const deliverToLocation = 'deliverToLocation'; + static const requisitionNumber = 'requisitionNumber'; + static const requester = 'requester'; + static const quotationAnalysis = 'quotationAnalysis'; + static const subject = 'subject'; + static const description = 'description'; + static const supplier = 'supplier'; + static const site = 'site'; + static const buyer = 'buyer'; + static const preparer = 'preparer'; + static const creationDate = 'creationDate'; + static const shipToLocation = 'shipToLocation'; + static const quotationNumber = 'quotationNumber'; + static const quotationDate = 'quotationDate'; + static const paymentTerms = 'paymentTerms'; + static const currency = 'currency'; + static const grossAmount = 'grossAmount'; + static const discountAmount = 'discountAmount'; + static const customDuty = 'customDuty'; + static const shipHandle = 'shipHandle'; + static const otherCharges = 'otherCharges'; + static const totalPOAmountWithVAT = 'totalPOAmountWithVAT'; + static const totalPOAmountInWords = 'totalPOAmountInWords'; + static const requestNumber = 'requestNumber'; + static const uom = 'uom'; + static const operatingCode = 'operatingCode'; + static const poNumber = 'poNumber'; + static const revision = 'revision'; + static const quantityOrdered = 'quantityOrdered'; + static const quantityReceived = 'quantityReceived'; + static const bonusQuantity = 'bonusQuantity'; + static const purchasePrice = 'purchasePrice'; + static const discountPer = 'discountPer'; + static const balanceQuantity = 'balanceQuantity'; + static const netPrice = 'netPrice'; + static const closureStatus = 'closureStatus'; + static const quotationNetPrice = 'quotationNetPrice'; + static const quotationUOM = 'quotationUOM'; + static const quotationQty = 'quotationQty'; + static const itemCode = 'itemCode'; + static const vendorName = 'vendorName'; + static const quotationMFGPartNumber = 'quotationMFGPartNumber'; + static const quotationDeliveryDate = 'quotationDeliveryDate'; + static const quotationBonusQuantity = 'quotationBonusQuantity'; + static const quotationLineTotal = 'quotationLineTotal'; + static const rfqUOM = 'rfqUOM'; + static const rfqQty = 'rfqQty'; + static const rfqNumber = 'rfqNumber'; + static const human = 'human'; + static const resources = 'resources'; + static const details = 'details'; + static const noDataAvailable = 'noDataAvailable'; + static const productName = 'productName'; + static const productDescription = 'productDescription'; + static const unitPrice = 'unitPrice'; + static const manufacturerName = 'manufacturerName'; + static const manufacturerPartName = 'manufacturerPartName'; + static const supplierName = 'supplierName'; + static const supplierContact = 'supplierContact'; + static const chargeToPatient = 'chargeToPatient'; + static const justification = 'justification'; + static const itemDescription = 'itemDescription'; + static const groupCode = 'groupCode'; + static const primaryUOM = 'primaryUOM'; + static const subgroupDescription = 'subgroupDescription'; + static const subgroupCode = 'subgroupCode'; + static const groupDescription = 'groupDescription'; + static const templateName = 'templateName'; + static const itemCreationStatus = 'itemCreationStatus'; + static const standardizationApprovalStatus = 'standardizationApprovalStatus'; + static const standardizationApprovalRejectionReason = 'standardizationApprovalRejectionReason'; + static const analyzedBy = 'analyzedBy'; + static const approvedDate = 'approvedDate'; + static const itemType = 'itemType'; + static const relatedTo = 'relatedTo'; + static const requestDate = 'requestDate'; + static const analyzedDate = 'analyzedDate'; + static const urgent = 'urgent'; + static const requestDetails = 'requestDetails'; + static const approvalLevel = 'approvalLevel'; + static const requesterDetails = 'requesterDetails'; + static const myAttendance = 'myAttendance'; + static const workOnBreak = 'workOnBreak'; + static const next = 'next'; + static const apply = 'apply'; + static const mobile = 'mobile'; + static const completingYear = 'completingYear'; + static const year = 'year'; + static const month = 'month'; + static const day = 'day'; + static const address = 'address'; + static const phoneNumber = 'phoneNumber'; + static const businessGroup = 'businessGroup'; + static const Payroll = 'Payroll'; + static const civilIdentityNumber = 'civilIdentityNumber'; + static const dateOfBirth = 'dateOfBirth'; + static const maritalStatus = 'maritalStatus '; + static const fullName = 'fullName'; + static const remove = 'remove'; + static const submit = 'submit'; + static const areYouSureYouWantToSubmit = 'areYouSureYouWantToSubmit'; + static const comments = 'comments'; + static const writeComment = 'writeComment'; + static const approversList = 'approversList'; + static const yourRequestHasBeenSubmittedForApprovals = 'yourRequestHasBeenSubmittedForApprovals'; + static const monthlyPaySlip = 'monthlyPaySlip'; + static const particular = 'particular'; + static const earnings = 'earnings'; + static const deductions = 'deductions'; + static const paymentMethodName = 'paymentMethodName'; + static const bankName = 'bankName'; + static const branchCode = 'branchCode'; + static const accountNo = 'accountNo'; + static const summaryOfInformation = 'summaryOfInformation'; + static const totalPayAmount = 'totalPayAmount'; + static const paymentInformation = 'paymentInformation'; + static const performance = 'performance'; + static const performanceEvaluation = 'performanceEvaluation'; + static const performanceEvaluationIn = 'performanceEvaluationIn'; + static const valuationIn = 'valuationIn'; + static const amount = 'amount'; + static const correctCurrentDatails = 'correctCurrentDatails'; + static const selectType = 'selectType'; + static const enterNewInfo = 'enterNewInfo'; + static const endDate = 'endDate'; + static const removeThisMember = 'removeThisMember'; + static const wantUpdateThisMember = 'wantUpdateThisMember '; + static const addNewFamilyMember = 'addNewFamilyMember'; + static const addRow = 'addRow'; + static const pleaseSelect = 'pleaseSelect'; + static const delete = 'delete'; + static const edit = 'edit'; + static const add = 'add'; + static const myProfile = 'myProfile'; + static const mowadhafhi = 'mowadhafhi'; + static const searchAnnouncements = 'searchAnnouncements'; + static const announcements = 'announcements'; + static const swipeRequest = 'swipeRequest'; + static const serviceType = 'serviceType'; + static const departmentName = 'departmentName'; + static const selectDepartment = 'selectDepartment'; + static const relatedSection = 'relatedSection'; + static const selectSection = 'selectSection'; + static const relatedTopic = 'relatedTopic'; + static const selectTopic = 'selectTopic'; + static const supportingDocument = 'supportingDocument'; + static const mowadhafhiRequest = 'mowadhafhiRequest'; + static const ticketReference = 'ticketReference'; + static const section = 'section'; + static const topic = 'topic'; + static const actionBy = 'actionBy'; + static const pending = 'pending'; + static const pendingTransactions = 'pendingTransactions'; + static const selectRequestType = 'selectRequestType'; + static const dateFrom = 'dateFrom'; + static const dateTo = 'dateTo'; + static const requestName = 'requestName'; + static const createdFor = 'createdFor'; + static const requestCreatedSuccessfully = 'requestCreatedSuccessfully'; + static const search = 'search'; + static const wantToReject = 'wantToReject'; + static const requestType = 'requestType'; + static const employeeDigitalID = 'employeeDigitalID'; + static const businessCard = 'businessCard'; + static const viewBusinessCard = 'viewBusinessCard'; + static const logout = 'logout'; + static const checkOut = 'checkOut'; + static const regular = 'regular'; + static const mark = 'mark'; + static const selectMethodOfAttendance = 'selectMethodOfAttendance'; + static const comeNearHMGWifi = 'comeNearHMGWifi'; + static const deliverNotificationToMeRegardless = 'deliverNotificationToMeRegardless'; + static const close = 'close'; + static const respond = 'respond'; + static const vacationRuleAdded = 'vacationRuleAdded'; + static const selectTypeT = 'selectTypeT'; + static const notification = 'notification'; + static const selectNotification = 'selectNotification'; + static const ifAllSelectedYouWillSkip = 'ifAllSelectedYouWillSkip'; + static const applyForVacationRule = 'applyForVacationRule'; + static const step1 = 'step1'; + static const step2 = 'step2'; + static const step3 = 'step3'; + static const message = 'message'; + static const writeAMessage = 'writeAMessage'; + static const notificationReassign = 'notificationReassign'; + static const selectEmployee = 'selectEmployee'; + static const searchEmployeeForReplacement = 'searchEmployeeForReplacement'; + static const searchForEmployee = 'searchForEmployee'; + static const pleaseSpecifyEndTime = 'pleaseSpecifyEndTime'; + static const pleaseSelectNotificationReassign = 'pleaseSelectNotificationReassign'; + static const pleaseSelectEmployeeForReplacement = 'pleaseSelectEmployeeForReplacement'; + static const pleaseSelectAction = 'pleaseSelectAction'; + static const pleaseSelectDate = 'pleaseSelectDate'; + static const todayAttendance = 'todayAttendance'; + static const viewAttendance = 'viewAttendance'; + static const teamMembers = 'teamMembers'; + static const profileDetails = 'profileDetails'; + static const noResultsFound = 'noResultsFound'; + static const searchBy = 'searchBy'; + static const myTeamMembers = 'myTeamMembers'; + static const save = 'save'; + static const TurnNotificationsFor = 'TurnNotificationsFor'; + static const worklistSettings = 'worklistSettings'; + static const absenceType = 'absenceType'; + static const absenceCategory = 'absenceCategory'; + static const days = 'days'; + static const hours = 'hours'; + static const approvalStatus = 'approvalStatus'; + static const absenceStatus = 'absenceStatus'; + static const subordinateLeave = 'subordinateLeave'; + static const numberDays = 'numberDays'; + static const poweredBy = 'poweredBy'; + static const cloudSolutions = 'cloudSolutions'; + static const selectTemplate = 'selectTemplate'; + static const myPostedAds = 'myPostedAds'; + static const browseCategories = 'browseCategories'; + static const searchItems = 'searchItems'; + static const offerAndDiscounts = 'offerAndDiscounts'; + static const offerValid = 'offerValid'; + static const offerExpired = 'offerExpired'; + static const whatAreYouOffering = 'whatAreYouOffering'; + static const selectCategory = 'selectCategory'; + static const inProgress = 'inProgress'; + static const locked = 'locked'; + static const addDetails = 'addDetails'; + static const reviewAndSell = 'reviewAndSell'; + static const itemTitle = 'itemTitle'; + static const itemCondition = 'itemCondition'; + static const used = 'used'; + static const region = 'region'; + static const selectRegion = 'selectRegion'; + static const itemPrice = 'itemPrice'; + static const itemPhotos = 'itemPhotos'; + static const itemInfo = 'itemInfo'; + static const uploadAttachment = 'uploadAttachment'; + static const selectFromGalleryOrOpenCamera = 'selectFromGalleryOrOpenCamera'; + static const openCamera = 'openCamera'; + static const uploadFromGallery = 'uploadFromGallery'; + static const name = 'name'; + static const email = 'email'; + static const noHistoryAvailable = 'noHistoryAvailable'; + static const purchaseRequisition = 'purchaseRequisition'; + static const moveOrder = 'moveOrder'; + static const humanResource = 'humanResource'; + static const purchaseOrder = 'purchaseOrder'; + static const ITGForms = 'ITGForms'; + static const itemCreation = 'itemCreation'; + static const stamp = 'stamp'; + static const addFavoriteList = 'addFavoriteList'; + static const feedbackUserExperience = 'feedbackUserExperience'; + static const rateUI = 'rateUI'; + static const submitSurvey = 'submitSurvey'; + static const typeHere = 'typeHere'; + static const infoDetail = 'infoDetail'; + static const amount_detail = 'amount_detail'; + static const currentBalance = 'currentBalance'; + static const currentLeaveBalance = 'currentLeaveBalance'; + static const calculatedDays = 'calculatedDays'; + static const totalDays = 'totalDays'; + static const usedBalance = 'usedBalance'; + static const infants = 'infants'; + static const child = 'child'; + static const adult = 'adult'; + static const updateMember = 'updateMember'; + static const fieldIsEmpty = 'fieldIsEmpty'; + static const pleaseEnterComments = 'pleaseEnterComments'; + 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'; + static const profile_reset_password = 'profile.reset_password'; + static const profile_profileCompletionPer = 'profile.profileCompletionPer'; + static const profile_completeProfile = 'profile.completeProfile'; + static const profile_personalInformation = 'profile.personalInformation'; + static const profile_basicDetails = 'profile.basicDetails'; + static const profile_address = 'profile.address'; + static const profile_contactDetails = 'profile.contactDetails'; + static const profile_familyDetails = 'profile.familyDetails'; + static const profile_effectiveDate = 'profile.effectiveDate'; + static const profile_country = 'profile.country'; + static const profile = 'profile'; + static const clicked = 'clicked'; + static const gender_with_arg = 'gender.with_arg'; + static const gender = 'gender'; + static const reset_locale = 'reset_locale'; + static const chat = 'chat'; + static const mychats = 'mychats'; + static const advancedSearch = 'advancedSearch'; + static const openNot = 'openNot'; + static const fyi = 'fyi'; + static const toDo = 'toDo'; + static const all = 'all'; + static const meNot = 'meNot'; + static const view = 'view'; + static const fromUserName = 'fromUserName'; + static const sentDate = 'sentDate'; + static const itemTypeDisplayName = 'itemTypeDisplayName'; + static const none = 'none'; + static const createNewChat = 'createNewChat'; + static const brainMarathon = 'brainMarathon'; + static const contestTopicAbout = 'contestTopicAbout'; + static const gameDate = 'gameDate'; + static const gameTime = 'gameTime'; + static const joinMarathon = 'joinMarathon'; + static const joinDemoMarathon = 'joinDemoMarathon'; + static const minutes = 'minutes'; + static const seconds = 'seconds'; + static const note = 'note'; + static const demoMarathonNoteP1 = 'demoMarathonNoteP1'; + static const demoMarathonNoteP2 = 'demoMarathonNoteP2'; + static const demoMarathonNoteP3 = 'demoMarathonNoteP3'; + static const sponsoredBy = 'sponsoredBy'; + static const question = 'question'; + static const marathoners = 'marathoners'; + static const prize = 'prize'; + static const winnerSelection = 'winnerSelection'; + static const qualifiers = 'qualifiers'; + static const getReadyForContest = 'getReadyForContest'; + static const winnerSelectedRandomly = 'winnerSelectedRandomly'; + 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'; + static const typeheretoreply = 'typeheretoreply'; + static const favorite = 'favorite'; + static const searchfromchat = 'searchfromchat'; + static const yourAnswerCorrect = 'yourAnswerCorrect'; + static const youMissedTheQuestion = 'youMissedTheQuestion'; + static const wrongAnswer = 'wrongAnswer'; + static const oops = 'oops'; + static const winner = 'winner'; + static const youWantToLeaveMarathon = 'youWantToLeaveMarathon'; + static const ourSponsor = 'ourSponsor'; + static const startingIn = 'startingIn'; + static const youAreOutOfContest = 'youAreOutOfContest'; + +} From 7d1086522d094c6886cadd720acfb5bf9d9f3b02 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 12 Dec 2022 11:04:28 +0300 Subject: [PATCH 10/23] Chat Fixes & Counter Updated on Signal R --- lib/api/chat/chat_api_client.dart | 98 ++++++---- lib/api/dashboard_api_client.dart | 7 +- .../chat/chat_count_conversation_model.dart | 28 +-- .../chat/get_search_user_chat_model.dart | 36 ++-- lib/provider/chat_provider_model.dart | 169 ++++++++++++++---- lib/provider/dashboard_provider_model.dart | 23 +-- lib/ui/chat/chat_bubble.dart | 50 +++--- lib/ui/chat/chat_detailed_screen.dart | 61 ++++--- lib/ui/chat/chat_home.dart | 18 +- lib/ui/chat/chat_home_screen.dart | 38 ++-- lib/ui/chat/favorite_users_screen.dart | 25 +-- lib/ui/landing/dashboard_screen.dart | 9 +- lib/widgets/app_bar_widget.dart | 13 ++ .../search_employee_bottom_sheet.dart | 3 +- lib/widgets/image_picker.dart | 2 +- 15 files changed, 367 insertions(+), 213 deletions(-) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index bea5b7c..3ef8fba 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -2,11 +2,11 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; -import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/exceptions/api_exception.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart'; @@ -29,6 +29,9 @@ class ChatApiClient { "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", }, ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } user.UserAutoLoginModel userLoginResponse = user.userAutoLoginModelFromJson(response.body); return userLoginResponse; } @@ -38,33 +41,36 @@ class ChatApiClient { "${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync/$sName/$cUserId", token: AppState().chatDetails!.response!.token, ); - return searchUserJsonModel(response.body); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } + return List.from(json.decode(response.body).map((x) => ChatUser.fromJson(x))); } - List searchUserJsonModel(String str) => List.from(json.decode(str).map((x) => ChatUser.fromJson(x))); - Future getRecentChats() async { try { Response response = await ApiClient().getJsonForResponse( "${ApiConsts.chatRecentUrl}getchathistorybyuserid", token: AppState().chatDetails!.response!.token, ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } return ChatUserModel.fromJson( json.decode(response.body), ); } catch (e) { - e as APIException; - if (e.message == "api_common_unauthorized") { - user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); - if (userLoginResponse.response != null) { - AppState().setchatUserDetails = userLoginResponse; - getRecentChats(); - } else { - Utils.showToast( - userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", - ); - } - } + // if (e.message == "api_common_unauthorized") { + // user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); + // if (userLoginResponse.response != null) { + // AppState().setchatUserDetails = userLoginResponse; + // getRecentChats(); + // } else { + // Utils.showToast( + // userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", + // ); + // } + // } throw e; } } @@ -74,9 +80,10 @@ class ChatApiClient { "${ApiConsts.chatFavUser}getFavUserById/${AppState().chatDetails!.response!.id}", token: AppState().chatDetails!.response!.token, ); - return ChatUserModel.fromJson( - json.decode(favRes.body), - ); + if (!kReleaseMode) { + logger.i("res: " + favRes.body); + } + return ChatUserModel.fromJson(json.decode(favRes.body)); } Future getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false, required int paginationVal}) async { @@ -85,24 +92,30 @@ class ChatApiClient { "${ApiConsts.chatSingleUserHistoryUrl}GetUserChatHistory/$senderUID/$receiverUID/$paginationVal", token: AppState().chatDetails!.response!.token, ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } return response; } catch (e) { - e as APIException; - if (e.message == "api_common_unauthorized") { - user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); - if (userLoginResponse.response != null) { - AppState().setchatUserDetails = userLoginResponse; - getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal); - } else { - Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); - } - } + // e as APIException; + // if (e.message == "api_common_unauthorized") { + // user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); + // if (userLoginResponse.response != null) { + // AppState().setchatUserDetails = userLoginResponse; + // getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal); + // } else { + // Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); + // } + // } throw e; } } Future favUser({required int userID, required int targetUserID}) async { Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatFavUser}addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); return favoriteChatUser; } @@ -114,20 +127,23 @@ class ChatApiClient { {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token, ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } + fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); return favoriteChatUser; } catch (e) { e as APIException; - if (e.message == "api_common_unauthorized") { - logger.d("Token Generated On APIIIIII"); - user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); - if (userLoginResponse.response != null) { - AppState().setchatUserDetails = userLoginResponse; - unFavUser(userID: userID, targetUserID: targetUserID); - } else { - Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); - } - } + // if (e.message == "api_common_unauthorized") { + // user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); + // if (userLoginResponse.response != null) { + // AppState().setchatUserDetails = userLoginResponse; + // unFavUser(userID: userID, targetUserID: targetUserID); + // } else { + // Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); + // } + // } throw e; } } @@ -138,6 +154,7 @@ class ChatApiClient { request.files.add(await MultipartFile.fromPath('files', file.path)); request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'}); StreamedResponse response = await request.send(); + if (!kReleaseMode) {} return response; } @@ -159,6 +176,9 @@ class ChatApiClient { {"encryptedEmails": encryptedEmails, "fromClient": false}, token: AppState().chatDetails!.response!.token, ); + if (!kReleaseMode) { + logger.i("res: " + response.body); + } return chatUserImageModelFromJson(response.body); } } diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index e30af91..48063c3 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -180,12 +180,7 @@ class DashboardApiClient { }, url, postParams); } - Future getChatCount() async { - Response response = await ApiClient().getJsonForResponse( - "${ApiConsts.chatLoginTokenUrl}unreadconversationcount/${AppState().getUserName}", - ); - return chatUnreadCovnCountModelFromJson(response.body); - } + // Future setAdvertisementViewed(String masterID, int advertisementId) async { // String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed"; diff --git a/lib/models/chat/chat_count_conversation_model.dart b/lib/models/chat/chat_count_conversation_model.dart index e584d32..1906803 100644 --- a/lib/models/chat/chat_count_conversation_model.dart +++ b/lib/models/chat/chat_count_conversation_model.dart @@ -1,8 +1,8 @@ -import 'dart:convert'; - -ChatUnreadCovnCountModel chatUnreadCovnCountModelFromJson(String str) => ChatUnreadCovnCountModel.fromJson(json.decode(str)); +// To parse this JSON data, do +// +// final chatUnreadCovnCountModel = chatUnreadCovnCountModelFromMap(jsonString); -String chatUnreadCovnCountModelToJson(ChatUnreadCovnCountModel data) => json.encode(data.toJson()); +import 'dart:convert'; class ChatUnreadCovnCountModel { ChatUnreadCovnCountModel({ @@ -13,13 +13,17 @@ class ChatUnreadCovnCountModel { int? singleChatCount; int? groupChatCount; - factory ChatUnreadCovnCountModel.fromJson(Map json) => ChatUnreadCovnCountModel( - singleChatCount: json["singleChatCount"] == null ? null : json["singleChatCount"], - groupChatCount: json["groupChatCount"] == null ? null : json["groupChatCount"], - ); + factory ChatUnreadCovnCountModel.fromJson(String str) => ChatUnreadCovnCountModel.fromMap(json.decode(str)); + + String toJson() => json.encode(toMap()); + + factory ChatUnreadCovnCountModel.fromMap(Map json) => ChatUnreadCovnCountModel( + singleChatCount: json["singleChatCount"] == null ? null : json["singleChatCount"], + groupChatCount: json["groupChatCount"] == null ? null : json["groupChatCount"], + ); - Map toJson() => { - "singleChatCount": singleChatCount == null ? null : singleChatCount, - "groupChatCount": groupChatCount == null ? null : groupChatCount, - }; + Map toMap() => { + "singleChatCount": singleChatCount == null ? null : singleChatCount, + "groupChatCount": groupChatCount == null ? null : groupChatCount, + }; } diff --git a/lib/models/chat/get_search_user_chat_model.dart b/lib/models/chat/get_search_user_chat_model.dart index fe87061..3d023fd 100644 --- a/lib/models/chat/get_search_user_chat_model.dart +++ b/lib/models/chat/get_search_user_chat_model.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + class ChatUserModel { ChatUserModel({ this.response, @@ -35,6 +37,7 @@ class ChatUser { this.isTyping, this.isImageLoaded, this.isImageLoading, + this.userLocalDownlaodedImage, }); int? id; @@ -52,24 +55,25 @@ class ChatUser { bool? isTyping; bool? isImageLoaded; bool? isImageLoading; + File? userLocalDownlaodedImage; factory ChatUser.fromJson(Map json) => ChatUser( - id: json["id"] == null ? null : json["id"], - userName: json["userName"] == null ? null : json["userName"], - email: json["email"] == null ? null : json["email"], - phone: json["phone"], - title: json["title"], - userStatus: json["userStatus"] == null ? null : json["userStatus"], - image: json["image"], - unreadMessageCount: json["unreadMessageCount"] == null ? null : json["unreadMessageCount"], - userAction: json["userAction"], - isPin: json["isPin"] == null ? null : json["isPin"], - isFav: json["isFav"] == null ? null : json["isFav"], - isAdmin: json["isAdmin"] == null ? null : json["isAdmin"], - isTyping: false, - isImageLoaded: false, - isImageLoading: true, - ); + id: json["id"] == null ? null : json["id"], + userName: json["userName"] == null ? null : json["userName"], + email: json["email"] == null ? null : json["email"], + phone: json["phone"], + title: json["title"], + userStatus: json["userStatus"] == null ? null : json["userStatus"], + image: json["image"], + unreadMessageCount: json["unreadMessageCount"] == null ? null : json["unreadMessageCount"], + userAction: json["userAction"], + isPin: json["isPin"] == null ? null : json["isPin"], + isFav: json["isFav"] == null ? null : json["isFav"], + isAdmin: json["isAdmin"] == null ? null : json["isAdmin"], + isTyping: false, + isImageLoaded: false, + isImageLoading: true, + userLocalDownlaodedImage: null); Map toJson() => { "id": id == null ? null : id, diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 5fb4cbf..94a296a 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/encryption.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/main.dart'; +import 'package:mohem_flutter_app/models/chat/chat_count_conversation_model.dart'; import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart'; import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; @@ -19,6 +20,8 @@ import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' a import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/widgets/image_picker.dart'; +import 'package:open_file/open_file.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:signalr_netcore/hub_connection.dart'; import 'package:signalr_netcore/signalr_client.dart'; import 'package:uuid/uuid.dart'; @@ -39,6 +42,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List repliedMsg = []; List favUsersList = []; int paginationVal = 0; + bool currentUserTyping = false; + + //Chat + int chatUConvCounter = 0; Future getUserAutoLoginToken() async { userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); @@ -56,30 +63,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await chatHubConnection.start(); print("Startedddddddd"); chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); + chatHubConnection.on("OnGetChatConversationCount", onNewChatConversion); } Future getHubConnection() async { HubConnection hub; - // try { HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); hub = HubConnectionBuilder() .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).build(); - // isChatHubLoding = false; return hub; - // } catch (e) { - // getUserAutoLoginToken().whenComplete(() { - // getHubConnection(); - // }); - // throw e; - // } } void registerEvents() { chatHubConnection.on("OnUpdateUserStatusAsync", changeStatus); // chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); // hubConnection.on("OnSeenChatUserAsync", onChatSeen); - //hubConnection.on("OnUserTypingAsync", onUserTyping); + chatHubConnection.on("OnUserTypingAsync", onUserTyping); chatHubConnection.on("OnUserCountAsync", userCountAsync); // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); @@ -164,7 +164,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } isLoading = false; notifyListeners(); + markRead(userChatHistory, receiverUID); + generateConvId(); } @@ -176,26 +178,28 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void markRead(List data, int receiverID) { if (data != null) { for (SingleUserChatModel element in data!) { - if (element.isSeen != null) { - if (!element.isSeen!) { - element.isSeen = true; - dynamic data = [ - { - "userChatHistoryId": element.userChatHistoryId, - "TargetUserId": element.currentUserId == receiverID ? element.currentUserId : element.targetUserId, - "isDelivered": true, - "isSeen": true, - } - ]; - updateUserChatHistoryStatusAsync(data); - notifyListeners(); + if (AppState().chatDetails!.response!.id! == element.targetUserId) { + if (element.isSeen != null) { + if (!element.isSeen!) { + element.isSeen = true; + dynamic data = [ + { + "userChatHistoryId": element.userChatHistoryId, + "TargetUserId": element.currentUserId == receiverID ? element.currentUserId : element.targetUserId, + "isDelivered": true, + "isSeen": true, + } + ]; + updateUserChatHistoryStatusAsync(data); + notifyListeners(); + } + } + for (ChatUser element in searchedChats!) { + if (element.id == receiverID) { + element.unreadMessageCount = 0; + chatUConvCounter = 0; + } } - } - } - for (ChatUser element in searchedChats!) { - if (element.id == receiverID) { - element.unreadMessageCount = 0; - // notifyListeners(); } } notifyListeners(); @@ -346,9 +350,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } } - dynamic contain = searchedChats!.where((ChatUser element) => element.id == data.first.currentUserId); - if (contain.isEmpty) { - searchedChats!.add(ChatUser(id: data.first.currentUserId, userName: data.first.currentUserName, unreadMessageCount: 0, isImageLoading: false, image: "", isImageLoaded: true, userStatus: 1)); + + if (searchedChats != null) { + dynamic contain = searchedChats!.where((ChatUser element) => element.id == data.first.currentUserId); + if (contain.isEmpty) { + searchedChats!.add( + ChatUser( + id: data.first.currentUserId, + userName: data.first.currentUserName, + unreadMessageCount: 0, + isImageLoading: false, + image: "", + isImageLoaded: true, + userStatus: 1, + isTyping: false, + userLocalDownlaodedImage: null), + ); + } } setMsgTune(); @@ -368,6 +386,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { {"userChatHistoryId": data.first.userChatHistoryId, "TargetUserId": temp.first.targetUserId, "isDelivered": true, "isSeen": isChatScreenActive ? true : false} ]; updateUserChatHistoryOnMsg(list); + invokeChatCounter(userId: AppState().chatDetails!.response!.id!); notifyListeners(); } @@ -384,7 +403,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (user.id == parameters![1] && parameters[0] == true) { user.isTyping = parameters[0] as bool?; Future.delayed( - const Duration(seconds: 2), + const Duration(seconds: 1), () { user.isTyping = false; notifyListeners(); @@ -392,6 +411,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ); } } + if (isChatScreenActive) { + currentUserTyping = true; + notifyListeners(); + Future.delayed( + const Duration(seconds: 2), + () { + currentUserTyping = false; + notifyListeners(); + }, + ); + } notifyListeners(); } @@ -473,7 +503,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { required bool isImageLoaded}) async { Uuid uuid = const Uuid(); String contentNo = uuid.v4(); - String msg = message.text; SingleUserChatModel data = SingleUserChatModel( chatEventId: chatEventId, @@ -492,8 +521,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { fileTypeResponse: isAttachment ? FileTypeResponse( fileTypeId: fileTypeId, - fileTypeName: getFileType(getFileExtension(selectedFile.path).toString()), - fileKind: getFileExtension(selectedFile.path), + fileTypeName: getFileExtension(selectedFile.path).toString(), + fileKind: "file", fileName: selectedFile.path.split("/").last, fileTypeDescription: getFileTypeDescription(getFileExtension(selectedFile.path).toString()), ) @@ -517,7 +546,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); if (contain.isEmpty) { searchedChats!.add( - ChatUser(id: targetUserId, userName: targetUserName, unreadMessageCount: 0, isImageLoading: false, image: "", isImageLoaded: true), + ChatUser( + id: targetUserId, + userName: targetUserName, + unreadMessageCount: 0, + isImageLoading: false, + image: "", + isImageLoaded: true, + isTyping: false, + isFav: false, + userLocalDownlaodedImage: null, + ), ); notifyListeners(); } @@ -530,6 +569,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: false, chatReplyId: null, isReply: false, isImageLoaded: false, image: null); } // normal Text msg if (isFileSelected && !isMsgReply) { + bool isImage = false; print("Normal Attachment Msg"); Utils.showLoading(context); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); @@ -605,6 +645,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { String? getFileExtension(String fileName) { try { + print("Ext: " + "." + fileName.split('.').last); return "." + fileName.split('.').last; } catch (e) { return null; @@ -740,6 +781,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUserImageModel uImage in chatImages) { if (user.email == uImage.email) { user.image = uImage.profilePicture ?? ""; + user.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, user.id.toString()); user.isImageLoading = false; user.isImageLoaded = true; } @@ -749,6 +791,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUserImageModel uImage in chatImages) { if (favUser.email == uImage.email) { favUser.image = uImage.profilePicture ?? ""; + favUser.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, favUser.id.toString()); favUser.isImageLoading = false; favUser.isImageLoaded = true; } @@ -758,6 +801,35 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); } + Future downloadImageLocal(String? encodedBytes, String userID) async { + File? myfile; + if (encodedBytes == null) { + return myfile; + } else { + await deleteFile(userID); + Uint8List decodedBytes = base64Decode(encodedBytes); + Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1 + late File imageFile = File("${appDocumentsDirectory.path}/$userID.jpg"); + imageFile.writeAsBytesSync(decodedBytes); + return imageFile; + } + } + + Future deleteFile(String userID) async { + Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); + late File imageFile = File('${appDocumentsDirectory.path}/$userID.jpg'); + if (await imageFile.exists()) { + await imageFile.delete(); + } + } + + Future downChatMedia(Uint8List bytes, String ext) async { + String dir = (await getApplicationDocumentsDirectory()).path; + File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext); + await file.writeAsBytes(bytes); + return file.path; + } + void setMsgTune() async { AudioPlayer player = AudioPlayer(); await player.setVolume(1.0); @@ -775,4 +847,29 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { print("Error: $e"); } } + + Future getChatMedia({required String fileName, required String fileTypeName, required int fileTypeID}) async { + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) { + Uint8List encodedString = await ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: getFileTypeDescription(fileTypeName)); + try { + String path = await downChatMedia(encodedString, fileTypeName ?? ""); + OpenFile.open(path); + } catch (e) { + Utils.showToast("Cannot open file."); + } + } + } + + void onNewChatConversion(List? params) { + dynamic items = params!.toList(); + logger.d(items); + chatUConvCounter = items[0]["singleChatCount"] ?? 0; + notifyListeners(); + } + + Future invokeChatCounter({required int userId}) async { + print("invokedd"); + await chatHubConnection.invoke("GetChatCounversationCount", args: [userId]); + return ""; + } } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index 48531b7..c1a186a 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -7,7 +7,6 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/main.dart'; -import 'package:mohem_flutter_app/models/chat/chat_count_conversation_model.dart'; import 'package:mohem_flutter_app/models/dashboard/drawer_menu_item_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accrual_balances_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; @@ -20,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/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; /// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool @@ -35,9 +35,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool isWorkListLoading = true; int workListCounter = 0; - //Chat - bool isChatCounterLoding = true; - int chatUConvCounter = 0; + //Misssing Swipe bool isMissingSwipeLoading = true; @@ -96,8 +94,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { accrualList = null; leaveBalanceAccrual = null; - isChatCounterLoding = true; - chatUConvCounter = 0; ticketBalance = 0; isServicesMenusLoading = true; @@ -273,21 +269,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification(); return res; } - - void fetchChatCounts() async { - try { - ChatUnreadCovnCountModel response = await DashboardApiClient().getChatCount(); - chatUConvCounter = response.singleChatCount!; - isChatCounterLoding = false; - notifyListeners(); - } catch (ex) { - logger.wtf(ex); - notifyListeners(); - Utils.handleException(ex, null, null); - } - } - - void notify() { notifyListeners(); } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index ea43004..3e99678 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -1,17 +1,23 @@ +import 'dart:convert'; import 'dart:typed_data'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/api/chat/chat_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/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/main.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/chat_full_image_preview.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; +import 'package:open_file/open_file.dart'; +import 'package:provider/provider.dart'; // todo: @aamir use extension methods, and use correct widgets. @@ -19,11 +25,12 @@ class ChatBubble extends StatelessWidget { ChatBubble({Key? key, required this.dateTime, required this.cItem}) : super(key: key); final String dateTime; final SingleUserChatModel cItem; - bool isCurrentUser = false; bool isSeen = false; bool isReplied = false; int? fileTypeID; + String? fileTypeName; + late ChatProviderModel data; String? fileTypeDescription; bool isDelivered = false; @@ -35,6 +42,7 @@ class ChatBubble extends StatelessWidget { isSeen = cItem.isSeen == true ? true : false; isReplied = cItem.userChatReplyResponse != null ? true : false; fileTypeID = cItem.fileTypeId; + fileTypeName = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeName : ""; fileTypeDescription = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeDescription : ""; isDelivered = cItem.currentUserId == AppState().chatDetails!.response!.id && cItem.isDelivered == true ? true : false; userName = AppState().chatDetails!.response!.userName == cItem.currentUserName.toString() ? "You" : cItem.currentUserName.toString(); @@ -45,6 +53,8 @@ class ChatBubble extends StatelessWidget { Size windowSize = MediaQuery.of(context).size; screenOffset = Offset(windowSize.width / 2, windowSize.height / 2); makeAssign(); + data = Provider.of(context, listen: false); + return isCurrentUser ? currentUser(context) : receiptUser(context); } @@ -77,22 +87,6 @@ class ChatBubble extends StatelessWidget { if (cItem.userChatReplyResponse != null && cItem.userChatReplyResponse!.fileTypeId == 12 || cItem.userChatReplyResponse!.fileTypeId == 3 || cItem.userChatReplyResponse!.fileTypeId == 4) - // Container( - // padding: EdgeInsets.all(0), // Border width - // decoration: BoxDecoration(color: Colors.red, borderRadius: const BorderRadius.all(Radius.circular(8))), - // child: ClipRRect( - // borderRadius: const BorderRadius.all( - // Radius.circular(8), - // ), - // child: SizedBox.fromSize( - // size: Size.fromRadius(8), // Image radius - // child: showImage( - // isReplyPreview: true, - // fileName: cItem.userChatReplyResponse!.contant!, - // fileTypeDescription: cItem.userChatReplyResponse!.fileTypeResponse!.fileTypeDescription ?? "image/jpg"), - // ), - // ), - // ), ClipRRect( borderRadius: BorderRadius.circular(8.0), child: SizedBox( @@ -116,8 +110,15 @@ class ChatBubble extends StatelessWidget { anchorPoint: screenOffset, builder: (BuildContext context) => ChatImagePreviewScreen(imgTitle: cItem.contant!, img: cItem.image!), ); - }), - cItem.contant!.toText12(), + }) + else + Row( + children: [ + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) + SvgPicture.asset(data.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10), + (cItem.contant ?? "").toText12(), + ], + ), Align( alignment: Alignment.centerRight, child: Row( @@ -200,7 +201,16 @@ class ChatBubble extends StatelessWidget { ); }) else - (cItem.contant ?? "").toText12(color: Colors.white), + Row( + children: [ + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) + SvgPicture.asset(data.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly( + left: 0, + right: 10, + ), + (cItem.contant ?? "").toText12(color: Colors.white), + ], + ), Align( alignment: Alignment.centerRight, child: dateTime.toText10(color: Colors.white.withOpacity(.71)), diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 2ab5fd8..335eda7 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -12,6 +12,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/main.dart'; import 'package:mohem_flutter_app/models/chat/call.dart'; +import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/call/chat_outgoing_call_screen.dart'; @@ -23,9 +24,15 @@ import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:signalr_netcore/signalr_client.dart'; import 'package:swipe_to/swipe_to.dart'; +class ChatDetailedScreenParams { + ChatUser? chatUser; + bool? isNewChat; + + ChatDetailedScreenParams(this.chatUser, this.isNewChat); +} + class ChatDetailScreen extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - ChatDetailScreen({Key? key}) : super(key: key); + const ChatDetailScreen({Key? key}) : super(key: key); @override State createState() => _ChatDetailScreenState(); @@ -33,16 +40,16 @@ class ChatDetailScreen extends StatefulWidget { class _ChatDetailScreenState extends State { final RefreshController _rc = RefreshController(initialRefresh: false); - dynamic userDetails; late ChatProviderModel data; + ChatDetailedScreenParams? params; void getMoreChat() async { - if (userDetails != null) { + if (params != null) { data.paginationVal = data.paginationVal + 10; - if (userDetails != null) { + if (params != null) { data.getSingleUserChatHistory( senderUID: AppState().chatDetails!.response!.id!.toInt(), - receiverUID: userDetails["targetUser"].id, + receiverUID: params!.chatUser!.id!, loadMore: true, isNewChat: false, ); @@ -56,14 +63,14 @@ class _ChatDetailScreenState extends State { @override Widget build(BuildContext context) { - userDetails = ModalRoute.of(context)!.settings.arguments; + params = ModalRoute.of(context)!.settings.arguments as ChatDetailedScreenParams; data = Provider.of(context, listen: false); - if (userDetails != null) { + if (params != null) { data.getSingleUserChatHistory( senderUID: AppState().chatDetails!.response!.id!.toInt(), - receiverUID: userDetails["targetUser"].id, + receiverUID: params!.chatUser!.id!, loadMore: false, - isNewChat: userDetails["isNewChat"], + isNewChat: params!.isNewChat!, ); } @@ -71,9 +78,10 @@ class _ChatDetailScreenState extends State { backgroundColor: MyColors.backgroundColor, appBar: AppBarWidget( context, - title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, + title: params!.chatUser!.userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, - image: userDetails["targetUser"].image == null || userDetails["targetUser"].image.isEmpty ? null : userDetails["targetUser"].image, + image: params!.chatUser!.image == null || params!.chatUser!.image.isEmpty ? null : params!.chatUser!.image, + showTyping: true, actions: [ SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() { // makeCall(callType: "AUDIO", con: hubConnection); @@ -124,8 +132,13 @@ class _ChatDetailScreenState extends State { m.userChatHistory[i], ); }, - ).onPress(() { - logger.d(jsonEncode(m.userChatHistory[i])); + ).onPress(() async { + if (m.userChatHistory[i].fileTypeResponse != null) { + m.getChatMedia( + fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", + fileTypeID: m.userChatHistory[i].fileTypeResponse!.fileTypeId!, + fileName: m.userChatHistory[i].contant!); + } }); }, ), @@ -152,7 +165,7 @@ class _ChatDetailScreenState extends State { ], ).expanded, 12.width, - if (m.isMsgReply && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg), + if (m.isMsgReply && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg, m), 12.width, const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), ], @@ -209,7 +222,7 @@ class _ChatDetailScreenState extends State { ), ).paddingOnly(right: 25), SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26).onPress( - () => m.sendChatMessage(userDetails["targetUser"].id, userDetails["targetUser"].userName, context), + () => m.sendChatMessage(params!.chatUser!.id!, params!.chatUser!.userName!, context), ), ], ), @@ -223,7 +236,8 @@ class _ChatDetailScreenState extends State { ); } - Widget showReplyImage(List data) { + Widget showReplyImage(List data, ChatProviderModel m) { + logger.d(jsonEncode(data)); if (data.first.isImageLoaded! && data.first.image != null) { return Container( width: 43, @@ -232,7 +246,14 @@ class _ChatDetailScreenState extends State { border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), image: DecorationImage(image: MemoryImage(data.first.image!), fit: BoxFit.cover)), ); } else { - return const SizedBox(); + return data.first.fileTypeResponse != null + ? Container( + width: 43, + height: 43, + constraints: BoxConstraints(), + decoration: BoxDecoration(border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), color: Colors.white), + child: SvgPicture.asset(m.getType(data.first.fileTypeResponse!.fileTypeName), alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 5, right: 5, top: 5, bottom: 5)) + : SizedBox(); } } @@ -240,7 +261,7 @@ class _ChatDetailScreenState extends State { print("================== Make call Triggered ============================"); Map json = { "callerID": AppState().chatDetails!.response!.id!.toString(), - "callReceiverID": userDetails["targetUser"].id.toString(), + "callReceiverID": params!.chatUser!.id.toString(), "notification_foreground": "true", "message": "Aamir is calling", "title": "Video Call", @@ -259,7 +280,7 @@ class _ChatDetailScreenState extends State { { "isSeen": false, "isDelivered": false, - "targetUserId": userDetails["targetUser"].id, + "targetUserId": params!.chatUser!.id!, "targetUserStatus": 4, } ], diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 76aa027..7d0631e 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -30,6 +30,16 @@ class _ChatHomeState extends State { super.initState(); data = Provider.of(context, listen: false); data.registerEvents(); + } + + @override + void dispose() { + super.dispose(); + data.clearAll(); + } + + void fetchAgain() { + print("Fetch Triggered"); if (chatHubConnection.state != HubConnectionState.Connected) { data.getUserAutoLoginToken().whenComplete(() async { await data.buildHubConnection(); @@ -42,14 +52,9 @@ class _ChatHomeState extends State { } } - @override - void dispose() { - super.dispose(); - data.clearAll(); - } - @override Widget build(BuildContext context) { + fetchAgain(); return Scaffold( backgroundColor: MyColors.white, appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true), @@ -85,7 +90,6 @@ class _ChatHomeState extends State { onPageChanged: (int pageIndex) { setState(() { tabIndex = pageIndex; - }); }, children: [ diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 804332a..669504f 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -1,22 +1,19 @@ import 'dart:convert'; -import 'dart:typed_data'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_des/flutter_des.dart'; import 'package:flutter_svg/flutter_svg.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/encryption.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; -import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; @@ -53,7 +50,9 @@ class _ChatHomeScreenState extends State { body: Consumer( builder: (BuildContext context, ChatProviderModel m, Widget? child) { return m.isLoading - ? ChatHomeShimmer(isDetailedScreen: false,) + ? ChatHomeShimmer( + isDetailedScreen: false, + ) : Column( children: [ TextField( @@ -102,20 +101,24 @@ class _ChatHomeScreenState extends State { height: 48, width: 48, ).toShimmer().circle(30), - if (m.searchedChats![index].isImageLoaded! && m.searchedChats![index].image.isNotEmpty) - CircularAvatar( - radius: 20, - height: 48, - width: 48, - url: m.searchedChats![index].image, - isImageBase64: true, - ), - if (!m.searchedChats![index].isImageLoading! && m.searchedChats![index].isImageLoaded! && m.searchedChats![index].image.isEmpty) + if (!m.searchedChats![index].isImageLoading! && m.searchedChats![index].userLocalDownlaodedImage == null) SvgPicture.asset( "assets/images/user.svg", height: 48, width: 48, ), + if (!m.searchedChats![index].isImageLoading! && m.searchedChats![index].userLocalDownlaodedImage != null) + Container( + width: 48.0, + height: 48.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + fit: BoxFit.cover, + image: FileImage(m.searchedChats![index].userLocalDownlaodedImage!), + ), + ), + ), Positioned( right: 5, bottom: 1, @@ -128,14 +131,13 @@ class _ChatHomeScreenState extends State { ).circle(10), ) ], - ).onPress(() { - print(jsonEncode(m.searchedChats![index])); - }), + ), Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 13), + (m.searchedChats![index].isTyping! ? "Typing ..." : "").toText10(color: MyColors.lightGreyColor).paddingOnly(left: 11, top: 0), ], ).expanded, SizedBox( @@ -194,7 +196,7 @@ class _ChatHomeScreenState extends State { Navigator.pushNamed( context, AppRoutes.chatDetailed, - arguments: {"targetUser": m.searchedChats![index], "isNewChat": false}, + arguments: ChatDetailedScreenParams(m.searchedChats![index], false), ).then((Object? value) { m.clearSelections(); m.notifyListeners(); diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index 9378625..157a884 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -9,6 +9,7 @@ import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; @@ -45,20 +46,24 @@ class ChatFavoriteUsersScreen extends StatelessWidget { height: 48, width: 48, ).toShimmer().circle(30), - if (m.favUsersList![index].isImageLoaded! && m.favUsersList![index].image != null && m.favUsersList![index].image.isNotEmpty) - CircularAvatar( - radius: 20, - height: 48, - width: 48, - url: m.favUsersList![index].image, - isImageBase64: true, - ), - if (!m.favUsersList![index].isImageLoading! && m.favUsersList![index].isImageLoaded! && m.favUsersList![index].image.isEmpty) + if (!m.favUsersList![index].isImageLoading! && m.favUsersList![index].userLocalDownlaodedImage == null) SvgPicture.asset( "assets/images/user.svg", height: 48, width: 48, ), + if (!m.favUsersList![index].isImageLoading! && m.favUsersList![index].userLocalDownlaodedImage != null) + Container( + width: 48.0, + height: 48.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + fit: BoxFit.cover, + image: FileImage(m.favUsersList![index].userLocalDownlaodedImage!), + ), + ), + ), Positioned( right: 5, bottom: 1, @@ -106,7 +111,7 @@ class ChatFavoriteUsersScreen extends StatelessWidget { Navigator.pushNamed( context, AppRoutes.chatDetailed, - arguments: {"targetUser": m.favUsersList![index], "isNewChat": false}, + arguments: ChatDetailedScreenParams(m.favUsersList![index], false), ).then( (Object? value) { m.clearSelections(); diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 4e6988b..0e9053a 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -90,7 +90,6 @@ class _DashboardScreenState extends State { data.fetchMenuEntries(); data.getCategoryOffersListAPI(context); marathonProvider.getMarathonDetailsFromApi(); - data.fetchChatCounts(); _refreshController.refreshCompleted(); } @@ -503,8 +502,8 @@ class _DashboardScreenState extends State { "assets/icons/chat/chat.svg", color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color, ).paddingAll(4), - Consumer( - builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { + Consumer( + builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { return Positioned( right: 0, top: 0, @@ -538,9 +537,7 @@ class _DashboardScreenState extends State { } else if (index == 3) { Navigator.pushNamed(context, AppRoutes.itemsForSale); } else if (index == 4) { - Navigator.pushNamed(context, AppRoutes.chat).then((Object? value) { - data.fetchChatCounts(); - }); + Navigator.pushNamed(context, AppRoutes.chat); } }, ), diff --git a/lib/widgets/app_bar_widget.dart b/lib/widgets/app_bar_widget.dart index 199074a..3903327 100644 --- a/lib/widgets/app_bar_widget.dart +++ b/lib/widgets/app_bar_widget.dart @@ -5,7 +5,9 @@ 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/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; +import 'package:provider/provider.dart'; AppBar AppBarWidget(BuildContext context, {required String title, @@ -13,6 +15,7 @@ AppBar AppBarWidget(BuildContext context, bool showNotificationButton = false, bool showMemberButton = false, String? image, + bool showTyping = false, List? actions, void Function()? onHomeTapped, void Function()? onBackTapped}) { @@ -43,6 +46,16 @@ AppBar AppBarWidget(BuildContext context, ), if (image != null) 14.width, title.toText24(color: MyColors.darkTextColor, isBold: true).expanded, + if(showTyping) + Consumer( + builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { + if (data.currentUserTyping) { + return ("Typing ...").toText10(color: MyColors.lightGreyColor).paddingOnly(left: 5, top: 0); + } else { + return const SizedBox(); + } + }, + ), ], ), centerTitle: false, diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index 475c4a5..77501bc 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -20,6 +20,7 @@ import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart'; import 'package:mohem_flutter_app/models/get_action_history_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; +import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; @@ -238,7 +239,7 @@ class _SearchEmployeeBottomSheetState extends State { Navigator.pushNamed( context, AppRoutes.chatDetailed, - arguments: {"targetUser": chatUsersList![index], "isNewChat": true}, + arguments: ChatDetailedScreenParams(chatUsersList![index], true), ); }, ), diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index 69bf7e4..75466fc 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -45,7 +45,7 @@ class ImageOptions { onFilesTap: () async { FilePickerResult? result = await FilePicker.platform.pickFiles( type: FileType.custom, - allowedExtensions: ['jpg', 'jpeg ', 'pdf', 'txt', 'docx', 'doc', 'pptx', 'xlsx', 'png', 'rar', 'zip', 'xls'], + allowedExtensions: ['jpg', 'jpeg ', 'pdf', 'txt', 'docx', 'doc', 'pptx', 'xlsx', 'png', 'rar', 'zip',], ); List files = result!.paths.map((path) => File(path!)).toList(); image(result.files.first.path.toString(), files.first); From ff3592a120223a1e468e8e69bae1896c6fe6f80e Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 12 Dec 2022 14:48:38 +0300 Subject: [PATCH 11/23] Chat Fixes & Counter Updated on Signal R --- lib/provider/chat_provider_model.dart | 13 +---- lib/ui/chat/chat_bubble.dart | 6 +-- lib/ui/chat/chat_detailed_screen.dart | 4 +- lib/ui/chat/chat_home_screen.dart | 2 +- lib/widgets/app_bar_widget.dart | 26 --------- lib/widgets/chat_app_bar_widge.dart | 78 +++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 43 deletions(-) create mode 100644 lib/widgets/chat_app_bar_widge.dart diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index c0dbb52..4263569 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -44,6 +44,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List favUsersList = []; int paginationVal = 0; bool currentUserTyping = false; + int? cTypingUserId = 0; //Chat int chatUConvCounter = 0; @@ -412,17 +413,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ); } } - if (isChatScreenActive) { - currentUserTyping = true; - notifyListeners(); - Future.delayed( - const Duration(seconds: 2), - () { - currentUserTyping = false; - notifyListeners(); - }, - ); - } notifyListeners(); } @@ -869,7 +859,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } Future invokeChatCounter({required int userId}) async { - print("invokedd"); await chatHubConnection.invoke("GetChatCounversationCount", args: [userId]); return ""; } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 3e99678..288a13f 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -116,7 +116,7 @@ class ChatBubble extends StatelessWidget { children: [ if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) SvgPicture.asset(data.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10), - (cItem.contant ?? "").toText12(), + (cItem.contant ?? "").toText12().expanded, ], ), Align( @@ -208,12 +208,12 @@ class ChatBubble extends StatelessWidget { left: 0, right: 10, ), - (cItem.contant ?? "").toText12(color: Colors.white), + (cItem.contant ?? "").toText12(color: Colors.white).expanded, ], ), Align( alignment: Alignment.centerRight, - child: dateTime.toText10(color: Colors.white.withOpacity(.71)), + child: dateTime.toText10(color: Colors.white.withOpacity(.71),), ), ], ), diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 335eda7..9454e75 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -18,6 +18,7 @@ import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/call/chat_outgoing_call_screen.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/chat_app_bar_widge.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; @@ -76,12 +77,13 @@ class _ChatDetailScreenState extends State { return Scaffold( backgroundColor: MyColors.backgroundColor, - appBar: AppBarWidget( + appBar: ChatAppBarWidget( context, title: params!.chatUser!.userName.toString().replaceAll(".", " ").capitalizeFirstofEach, showHomeButton: false, image: params!.chatUser!.image == null || params!.chatUser!.image.isEmpty ? null : params!.chatUser!.image, showTyping: true, + chatUser: params!.chatUser, actions: [ SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() { // makeCall(callType: "AUDIO", con: hubConnection); diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index 669504f..fe4291f 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -137,7 +137,7 @@ class _ChatHomeScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 13), - (m.searchedChats![index].isTyping! ? "Typing ..." : "").toText10(color: MyColors.lightGreyColor).paddingOnly(left: 11, top: 0), + (m.searchedChats![index].isTyping! ? "Typing ..." : "").toText10(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 0), ], ).expanded, SizedBox( diff --git a/lib/widgets/app_bar_widget.dart b/lib/widgets/app_bar_widget.dart index 3903327..8bca3f3 100644 --- a/lib/widgets/app_bar_widget.dart +++ b/lib/widgets/app_bar_widget.dart @@ -14,19 +14,11 @@ AppBar AppBarWidget(BuildContext context, bool showHomeButton = true, bool showNotificationButton = false, bool showMemberButton = false, - String? image, - bool showTyping = false, List? actions, void Function()? onHomeTapped, void Function()? onBackTapped}) { return AppBar( leadingWidth: 0, - // leading: GestureDetector( - // behavior: HitTestBehavior.opaque, - // onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context), - // child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), - // ), - //titleSpacing: -1.44, title: Row( children: [ GestureDetector( @@ -37,25 +29,7 @@ AppBar AppBarWidget(BuildContext context, child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), ), 4.width, - if (image != null) - CircularAvatar( - url: image, - height: 40, - width: 40, - isImageBase64: true, - ), - if (image != null) 14.width, title.toText24(color: MyColors.darkTextColor, isBold: true).expanded, - if(showTyping) - Consumer( - builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { - if (data.currentUserTyping) { - return ("Typing ...").toText10(color: MyColors.lightGreyColor).paddingOnly(left: 5, top: 0); - } else { - return const SizedBox(); - } - }, - ), ], ), centerTitle: false, diff --git a/lib/widgets/chat_app_bar_widge.dart b/lib/widgets/chat_app_bar_widge.dart new file mode 100644 index 0000000..3a9dee4 --- /dev/null +++ b/lib/widgets/chat_app_bar_widge.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/classes/colors.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/models/chat/get_search_user_chat_model.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; +import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; +import 'package:provider/provider.dart'; + +AppBar ChatAppBarWidget(BuildContext context, + {required String title, + bool showHomeButton = true, + String? image, + ChatUser? chatUser, + bool showTyping = false, + List? actions, + void Function()? onHomeTapped, + void Function()? onBackTapped}) { + return AppBar( + leadingWidth: 0, + title: Row( + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: Feedback.wrapForTap(() { + (onBackTapped == null ? Navigator.maybePop(context) : onBackTapped()); + }, context), + child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), + ), + 4.width, + if (image != null) + CircularAvatar( + url: image, + height: 40, + width: 40, + isImageBase64: true, + ), + if (image != null) 14.width, + SizedBox( + height: 40, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + title.toText20(color: MyColors.darkTextColor, isBold: true).expanded, + if (showTyping) + Consumer( + builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { + if (chatUser!.isTyping!) { + return ("Typing ...").toText10(color: MyColors.darkTextColor); + } else { + return const SizedBox(); + } + }, + ), + ], + ).expanded, + ) + ], + ), + centerTitle: false, + elevation: 0, + backgroundColor: Colors.white, + actions: [ + if (showHomeButton) + IconButton( + onPressed: () { + onHomeTapped == null ? Navigator.popUntil(context, ModalRoute.withName(AppRoutes.dashboard)) : onHomeTapped(); + }, + icon: const Icon(Icons.home, color: MyColors.darkIconColor), + ), + ...actions ?? [] + ], + ); +} From 668efb8412e9c1cc880c8da8c6aab51b3145bf8b Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 12 Dec 2022 15:00:02 +0300 Subject: [PATCH 12/23] Chat Fixes & Counter Updated on Signal R --- lib/ui/chat/chat_detailed_screen.dart | 270 +++++++++++++------------- 1 file changed, 136 insertions(+), 134 deletions(-) diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 9454e75..619e850 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -95,145 +95,147 @@ class _ChatDetailScreenState extends State { 21.width, ], ), - body: Consumer( - builder: (BuildContext context, ChatProviderModel m, Widget? child) { - return (m.isLoading - ? ChatHomeShimmer( - isDetailedScreen: true, - ) - : Column( - children: [ - SmartRefresher( - enablePullDown: false, - enablePullUp: true, - onLoading: () { - getMoreChat(); - }, - header: const MaterialClassicHeader( - color: MyColors.gradiantEndColor, - ), - controller: _rc, - reverse: true, - child: ListView.separated( - controller: m.scrollController, - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - reverse: true, - itemCount: m.userChatHistory.length, - padding: const EdgeInsets.all(21), - separatorBuilder: (cxt, index) => 8.height, - itemBuilder: (BuildContext context, int i) { - return SwipeTo( - iconColor: MyColors.lightGreenColor, - child: ChatBubble( - dateTime: m.dateFormte(m.userChatHistory[i].createdDate!), - cItem: m.userChatHistory[i], - ), - onRightSwipe: () { - m.chatReply( - m.userChatHistory[i], - ); - }, - ).onPress(() async { - if (m.userChatHistory[i].fileTypeResponse != null) { - m.getChatMedia( - fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", - fileTypeID: m.userChatHistory[i].fileTypeResponse!.fileTypeId!, - fileName: m.userChatHistory[i].contant!); - } - }); + body: SafeArea( + child: Consumer( + builder: (BuildContext context, ChatProviderModel m, Widget? child) { + return (m.isLoading + ? ChatHomeShimmer( + isDetailedScreen: true, + ) + : Column( + children: [ + SmartRefresher( + enablePullDown: false, + enablePullUp: true, + onLoading: () { + getMoreChat(); }, - ), - ).expanded, - if (m.isMsgReply) - SizedBox( - height: 82, - child: Row( - children: [ - Container(height: 82, color: MyColors.textMixColor, width: 6), - Container( - color: MyColors.darkTextColor.withOpacity(0.10), - padding: const EdgeInsets.only(top: 11, left: 14, bottom: 14, right: 21), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() - ? "You" - : m.repliedMsg.first.currentUserName.toString().replaceAll(".", " ")) - .toText14(color: MyColors.lightGreenColor), - (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2) - ], - ).expanded, - 12.width, - if (m.isMsgReply && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg, m), - 12.width, - const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), - ], - ), - ).expanded, - ], + header: const MaterialClassicHeader( + color: MyColors.gradiantEndColor, ), - ), - if (m.isFileSelected && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") - SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), - const Divider( - height: 1, - color: MyColors.lightGreyEFColor, - ), - TextField( - controller: m.message, - decoration: InputDecoration( - hintText: m.isFileSelected ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), - hintStyle: TextStyle(color: m.isFileSelected ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - filled: true, - fillColor: MyColors.white, - contentPadding: const EdgeInsets.only( - left: 21, - top: 20, - bottom: 20, + controller: _rc, + reverse: true, + child: ListView.separated( + controller: m.scrollController, + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + reverse: true, + itemCount: m.userChatHistory.length, + padding: const EdgeInsets.all(21), + separatorBuilder: (cxt, index) => 8.height, + itemBuilder: (BuildContext context, int i) { + return SwipeTo( + iconColor: MyColors.lightGreenColor, + child: ChatBubble( + dateTime: m.dateFormte(m.userChatHistory[i].createdDate!), + cItem: m.userChatHistory[i], + ), + onRightSwipe: () { + m.chatReply( + m.userChatHistory[i], + ); + }, + ).onPress(() async { + if (m.userChatHistory[i].fileTypeResponse != null) { + m.getChatMedia( + fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", + fileTypeID: m.userChatHistory[i].fileTypeResponse!.fileTypeId!, + fileName: m.userChatHistory[i].contant!); + } + }); + }, ), - prefixIconConstraints: const BoxConstraints(), - prefixIcon: m.sFileType.isNotEmpty - ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15) - : null, - suffixIcon: SizedBox( - width: 100, + ).expanded, + if (m.isMsgReply) + SizedBox( + height: 82, child: Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.center, // added line children: [ - if (m.sFileType.isNotEmpty) - Row( - children: [ - const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), - ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), + Container(height: 82, color: MyColors.textMixColor, width: 6), + Container( + color: MyColors.darkTextColor.withOpacity(0.10), + padding: const EdgeInsets.only(top: 11, left: 14, bottom: 14, right: 21), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (AppState().chatDetails!.response!.userName == m.repliedMsg.first.currentUserName.toString() + ? "You" + : m.repliedMsg.first.currentUserName.toString().replaceAll(".", " ")) + .toText14(color: MyColors.lightGreenColor), + (m.repliedMsg.isNotEmpty ? m.repliedMsg.first.contant! : "").toText12(color: MyColors.grey71Color, maxLine: 2) + ], + ).expanded, + 12.width, + if (m.isMsgReply && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg, m), + 12.width, + const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), ], - ).onPress(() => m.removeAttachment()).paddingOnly(right: 25), - if (m.sFileType.isEmpty) - RotationTransition( - turns: const AlwaysStoppedAnimation(45 / 360), - child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( - () => m.selectImageToUpload(context), - ), - ).paddingOnly(right: 25), - SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26).onPress( - () => m.sendChatMessage(params!.chatUser!.id!, params!.chatUser!.userName!, context), - ), + ), + ).expanded, ], ), - ).paddingOnly(right: 21), + ), + if (m.isFileSelected && m.sFileType == ".png" || m.sFileType == ".jpeg" || m.sFileType == ".jpg") + SizedBox(height: 200, width: double.infinity, child: Image.file(m.selectedFile, fit: BoxFit.cover)).paddingOnly(left: 21, right: 21, top: 21), + const Divider( + height: 1, + color: MyColors.lightGreyEFColor, + ), + TextField( + controller: m.message, + decoration: InputDecoration( + hintText: m.isFileSelected ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), + hintStyle: TextStyle(color: m.isFileSelected ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + filled: true, + fillColor: MyColors.white, + contentPadding: const EdgeInsets.only( + left: 21, + top: 20, + bottom: 20, + ), + prefixIconConstraints: const BoxConstraints(), + prefixIcon: m.sFileType.isNotEmpty + ? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15) + : null, + suffixIcon: SizedBox( + width: 100, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, // added line + children: [ + if (m.sFileType.isNotEmpty) + Row( + children: [ + const Icon(Icons.cancel, size: 15, color: MyColors.redA3Color).paddingOnly(right: 5), + ("Clear").toText11(color: MyColors.redA3Color, isUnderLine: true).paddingOnly(left: 0), + ], + ).onPress(() => m.removeAttachment()).paddingOnly(right: 25), + if (m.sFileType.isEmpty) + RotationTransition( + turns: const AlwaysStoppedAnimation(45 / 360), + child: const Icon(Icons.attach_file_rounded, size: 26, color: MyColors.grey3AColor).onPress( + () => m.selectImageToUpload(context), + ), + ).paddingOnly(right: 25), + SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26).onPress( + () => m.sendChatMessage(params!.chatUser!.id!, params!.chatUser!.userName!, context), + ), + ], + ), + ).paddingOnly(right: 21), + ), ), - ), - ], - )); - }, + ], + )); + }, + ), ), ); } @@ -248,14 +250,14 @@ class _ChatDetailScreenState extends State { border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), image: DecorationImage(image: MemoryImage(data.first.image!), fit: BoxFit.cover)), ); } else { - return data.first.fileTypeResponse != null + return data.first.fileTypeResponse != null && data.first.fileTypeResponse!.fileTypeName != null ? Container( width: 43, height: 43, - constraints: BoxConstraints(), + constraints: const BoxConstraints(), decoration: BoxDecoration(border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), color: Colors.white), - child: SvgPicture.asset(m.getType(data.first.fileTypeResponse!.fileTypeName), alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 5, right: 5, top: 5, bottom: 5)) - : SizedBox(); + child: SvgPicture.asset(m.getType(data.first.fileTypeResponse!.fileTypeName ?? ""), alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 5, right: 5, top: 5, bottom: 5)) + : const SizedBox(); } } From ae559df29f07b036756db0d2953a715ba76223ed Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 12 Dec 2022 15:56:52 +0300 Subject: [PATCH 13/23] Chat Fixes & Counter Updated on Signal R --- lib/provider/chat_provider_model.dart | 7 +++++-- lib/ui/chat/chat_detailed_screen.dart | 6 ++---- lib/ui/chat/chat_home_screen.dart | 10 +++++++++- lib/widgets/chat_app_bar_widge.dart | 10 ++++++++-- pubspec.yaml | 1 + 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 4263569..d3639c9 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -405,7 +405,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (user.id == parameters![1] && parameters[0] == true) { user.isTyping = parameters[0] as bool?; Future.delayed( - const Duration(seconds: 1), + const Duration(seconds: 2), () { user.isTyping = false; notifyListeners(); @@ -839,12 +839,15 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - Future getChatMedia({required String fileName, required String fileTypeName, required int fileTypeID}) async { + Future getChatMedia(BuildContext context, {required String fileName, required String fileTypeName, required int fileTypeID}) async { + Utils.showLoading(context); if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) { Uint8List encodedString = await ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: getFileTypeDescription(fileTypeName)); try { String path = await downChatMedia(encodedString, fileTypeName ?? ""); + Utils.hideLoading(context); OpenFile.open(path); + } catch (e) { Utils.showToast("Cannot open file."); } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 619e850..15b2156 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -137,10 +137,8 @@ class _ChatDetailScreenState extends State { }, ).onPress(() async { if (m.userChatHistory[i].fileTypeResponse != null) { - m.getChatMedia( - fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", - fileTypeID: m.userChatHistory[i].fileTypeResponse!.fileTypeId!, - fileName: m.userChatHistory[i].contant!); + m.getChatMedia(context, + fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!); } }); }, diff --git a/lib/ui/chat/chat_home_screen.dart b/lib/ui/chat/chat_home_screen.dart index fe4291f..a9814ee 100644 --- a/lib/ui/chat/chat_home_screen.dart +++ b/lib/ui/chat/chat_home_screen.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'package:animated_text_kit/animated_text_kit.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -137,7 +138,14 @@ class _ChatHomeScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 13), - (m.searchedChats![index].isTyping! ? "Typing ..." : "").toText10(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 0), + m.searchedChats![index].isTyping! + ? AnimatedTextKit( + animatedTexts: [ + ScaleAnimatedText('Typing...', textStyle: const TextStyle(color: MyColors.textMixColor, fontSize: 10, letterSpacing: -0.4, fontStyle: FontStyle.normal)), + ], + ).paddingOnly(left: 11) + : const SizedBox() + //(m.searchedChats![index].isTyping! ? "Typing ..." : "").toText10(color: MyColors.textMixColor).paddingOnly(left: 11, top: 0), ], ).expanded, SizedBox( diff --git a/lib/widgets/chat_app_bar_widge.dart b/lib/widgets/chat_app_bar_widge.dart index 3a9dee4..0feac6c 100644 --- a/lib/widgets/chat_app_bar_widge.dart +++ b/lib/widgets/chat_app_bar_widge.dart @@ -1,3 +1,4 @@ +import 'package:animated_text_kit/animated_text_kit.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -50,14 +51,19 @@ AppBar ChatAppBarWidget(BuildContext context, Consumer( builder: (BuildContext cxt, ChatProviderModel data, Widget? child) { if (chatUser!.isTyping!) { - return ("Typing ...").toText10(color: MyColors.darkTextColor); + // return ("Typing ...").toText10(color: MyColors.textMixColor); + return AnimatedTextKit( + animatedTexts: [ + ScaleAnimatedText('Typing...', textStyle: const TextStyle(color: MyColors.textMixColor, fontSize: 10, letterSpacing: -0.4, fontStyle: FontStyle.normal)), + ], + ); } else { return const SizedBox(); } }, ), ], - ).expanded, + ), ) ], ), diff --git a/pubspec.yaml b/pubspec.yaml index 0d5cda5..2e3c4c2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -92,6 +92,7 @@ dependencies: swipe_to: ^1.0.2 flutter_webrtc: ^0.9.16 camera: ^0.10.0+4 + animated_text_kit: ^4.2.2 #Encryption flutter_des: ^2.1.0 From 43fb34c218c7455d725193e24abe300efd4979b9 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Mon, 12 Dec 2022 16:15:50 +0300 Subject: [PATCH 14/23] fixes --- lib/classes/utils.dart | 4 ++-- lib/models/member_information_list_model.dart | 2 +- lib/ui/profile/contact_details.dart | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 050ae4d..1336f3f 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -121,8 +121,8 @@ class Utils { ), ); } else { - // showToast(errorMessage); - confirmDialog(cxt, errorMessage); + showToast(errorMessage); + // confirmDialog(cxt, errorMessage); } } } diff --git a/lib/models/member_information_list_model.dart b/lib/models/member_information_list_model.dart index 4225905..4871855 100644 --- a/lib/models/member_information_list_model.dart +++ b/lib/models/member_information_list_model.dart @@ -48,7 +48,7 @@ class MemberInformationListModel { String? nATIONALITYCODE; String? nATIONALITYMEANING; String? nATIONALIDENTIFIER; - String? nORMALHOURS; + dynamic? nORMALHOURS; int? nOOFROWS; int? oRGANIZATIONID; String? oRGANIZATIONNAME; diff --git a/lib/ui/profile/contact_details.dart b/lib/ui/profile/contact_details.dart index 4d28a81..749978e 100644 --- a/lib/ui/profile/contact_details.dart +++ b/lib/ui/profile/contact_details.dart @@ -160,7 +160,7 @@ class _ContactDetailsState extends State { right: 1, child: const Icon(Icons.add_location_alt_outlined, size: 20).onPress(continueDynamicForms), ), - Utils.getNoDataWidget(context).expanded, + Utils.getNoDataWidget(context), ], ).objectContainerView() ], From ef347f1078041c406a54a61d60a4d888eebd8259 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 12 Dec 2022 16:53:21 +0300 Subject: [PATCH 15/23] Sort Fix --- lib/provider/chat_provider_model.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index d3639c9..d5b81fe 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -125,6 +125,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { AppState().chatDetails!.response!.id.toString(), ), ); + sort(); notifyListeners(); if (searchedChats!.isNotEmpty) { getUserImages(); From feb5c5071caa3e636e258e41841c7d8d50a94f0e Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 13 Dec 2022 09:54:32 +0300 Subject: [PATCH 16/23] Fav Users Images Fix --- lib/provider/chat_provider_model.dart | 22 +++++++++++----------- lib/ui/landing/dashboard_screen.dart | 3 +++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index d5b81fe..ca07b9b 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -127,7 +127,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ); sort(); notifyListeners(); - if (searchedChats!.isNotEmpty) { + if (searchedChats!.isNotEmpty || favUsersList.isNotEmpty) { getUserImages(); } } @@ -142,19 +142,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (isNewChat) userChatHistory = []; if (!loadMore) paginationVal = 0; isChatScreenActive = true; - // if (chatHubConnection.state != HubConnectionState.Connected) { - // getUserAutoLoginToken().whenComplete(() async { - // await buildHubConnection(); - // getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore); - // }); - // return; - // } Response response = await ChatApiClient().getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal); if (response.statusCode == 204) { if (isNewChat) { userChatHistory = []; } else if (loadMore) { - // userChatHistory = []; Utils.showToast("No More Data To Load"); } } else { @@ -765,9 +757,18 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void getUserImages() async { List emails = []; - for (ChatUser element in searchedChats!) { + List exists = [], unique = []; + exists.addAll(searchedChats!); + exists.addAll(favUsersList!); + Map profileMap = {}; + for (ChatUser item in exists) { + profileMap[item.email!] = item; + } + unique = profileMap.values.toList(); + for (ChatUser element in unique!) { emails.add(await EmailImageEncryption().encrypt(val: element.email!)); } + List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); for (ChatUser user in searchedChats!) { for (ChatUserImageModel uImage in chatImages) { @@ -848,7 +849,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { String path = await downChatMedia(encodedString, fileTypeName ?? ""); Utils.hideLoading(context); OpenFile.open(path); - } catch (e) { Utils.showToast("Cannot open file."); } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 0e9053a..1800aa3 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -72,6 +72,9 @@ class _DashboardScreenState extends State { void _bHubCon() { cProvider.getUserAutoLoginToken().whenComplete(() { cProvider.buildHubConnection(); + Future.delayed(const Duration(seconds: 2), () { + cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!); + }); }); } From 2a39ee9ddc8f929bc9d4b1caabb7652b7e26cdb9 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 13 Dec 2022 10:00:27 +0300 Subject: [PATCH 17/23] Fav Users Images Fix --- lib/ui/chat/chat_home.dart | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 7d0631e..807af1a 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -38,23 +38,23 @@ class _ChatHomeState extends State { data.clearAll(); } - void fetchAgain() { - print("Fetch Triggered"); - if (chatHubConnection.state != HubConnectionState.Connected) { - data.getUserAutoLoginToken().whenComplete(() async { - await data.buildHubConnection(); - data.getUserRecentChats(); - }); - return; - } - if (data.searchedChats == null || data.searchedChats!.isEmpty) { - data.getUserRecentChats(); - } - } + // void fetchAgain() { + // print("Fetch Triggered"); + // if (chatHubConnection.state != HubConnectionState.Connected) { + // data.getUserAutoLoginToken().whenComplete(() async { + // await data.buildHubConnection(); + // data.getUserRecentChats(); + // }); + // return; + // } + // if (data.searchedChats == null || data.searchedChats!.isEmpty) { + // data.getUserRecentChats(); + // } + // } @override Widget build(BuildContext context) { - fetchAgain(); + // fetchAgain(); return Scaffold( backgroundColor: MyColors.white, appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true), From 45b4adc2528986a5b59c7fbdd800f2fc381aa14d Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 13 Dec 2022 10:09:20 +0300 Subject: [PATCH 18/23] Fav Users Images Fix --- lib/provider/chat_provider_model.dart | 3 ++- lib/ui/chat/chat_bubble.dart | 3 +-- lib/ui/chat/chat_detailed_screen.dart | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index ca07b9b..3a4e70b 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -526,7 +526,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await chatHubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); } - void sendChatMessage(int targetUserId, String targetUserName, BuildContext context) async { + void sendChatMessage(int targetUserId, int userStatus, String targetUserName, BuildContext context) async { dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); if (contain.isEmpty) { searchedChats!.add( @@ -539,6 +539,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isImageLoaded: true, isTyping: false, isFav: false, + userStatus: userStatus, userLocalDownlaodedImage: null, ), ); diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 288a13f..c79c66b 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -54,11 +54,10 @@ class ChatBubble extends StatelessWidget { screenOffset = Offset(windowSize.width / 2, windowSize.height / 2); makeAssign(); data = Provider.of(context, listen: false); - return isCurrentUser ? currentUser(context) : receiptUser(context); } - Widget currentUser(context) { + Widget currentUser(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 15b2156..05e674a 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -223,7 +223,7 @@ class _ChatDetailScreenState extends State { ), ).paddingOnly(right: 25), SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26).onPress( - () => m.sendChatMessage(params!.chatUser!.id!, params!.chatUser!.userName!, context), + () => m.sendChatMessage(params!.chatUser!.id!, params!.chatUser!.userStatus ?? 0, params!.chatUser!.userName!, context), ), ], ), @@ -239,7 +239,6 @@ class _ChatDetailScreenState extends State { } Widget showReplyImage(List data, ChatProviderModel m) { - logger.d(jsonEncode(data)); if (data.first.isImageLoaded! && data.first.image != null) { return Container( width: 43, From 4a513c08d905ba8e82613ce4f0f889a9953e088f Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 13 Dec 2022 10:46:30 +0300 Subject: [PATCH 19/23] fixes --- lib/classes/consts.dart | 1 + lib/classes/utils.dart | 2 +- lib/main.dart | 5 ++++ .../get_time_card_summary_list_model.dart | 24 +++++++++---------- lib/ui/landing/dashboard_screen.dart | 2 +- lib/ui/work_list/worklist_detail_screen.dart | 22 ++++++++++++++++- 6 files changed, 41 insertions(+), 15 deletions(-) diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index e9b902a..3d58efd 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -3,6 +3,7 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; 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://erptstapp.srca.org.sa"; // SRCA 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 diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 1336f3f..3be8356 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -37,7 +37,7 @@ class Utils { timeInSecForIosWeb: 1, backgroundColor: Colors.black54, textColor: Colors.white, - fontSize: 16.0); + fontSize: 13.0); } static dynamic getNotNullValue(List list, int index) { diff --git a/lib/main.dart b/lib/main.dart index aa9f933..fdc4ad6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:logger/logger.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -37,6 +38,10 @@ bool isTablet = false; Future main() async { WidgetsFlutterBinding.ensureInitialized(); + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); await EasyLocalization.ensureInitialized(); AppState().setPostParamsInitConfig(); HttpOverrides.global = MyHttpOverrides(); diff --git a/lib/models/get_time_card_summary_list_model.dart b/lib/models/get_time_card_summary_list_model.dart index 85a2a8e..becc1d2 100644 --- a/lib/models/get_time_card_summary_list_model.dart +++ b/lib/models/get_time_card_summary_list_model.dart @@ -1,41 +1,41 @@ class GetTimeCardSummaryList { - int? aBSENTDAYS; + num? aBSENTDAYS; dynamic? aCTUALHRS; dynamic? aPPROVEDTIMEBACKHRS; - int? aSSIGNMENTID; - int? aTTENDEDDAYS; - int? bUSINESSTRIP; + num? aSSIGNMENTID; + num? aTTENDEDDAYS; + num? bUSINESSTRIP; dynamic? cOMPOFFHHRS; dynamic? cOMPOFFNHRS; dynamic? cOMPOFFWHRS; dynamic? dESIREDSCHEDULEDHRS; dynamic? eARLYOUTHRS; dynamic? eXCESSHRS; - int? hALFDAYLEAVE; + num? hALFDAYLEAVE; dynamic? lATEINHRS; dynamic? lEAVESHOLIDAYSHRS; dynamic? nONSCHEDULEDAYS; dynamic? nOTANALYZEDDAYS; - int? oFFDAYS; + num? oFFDAYS; dynamic? oNCALLHRS; dynamic? pAIDLEAVE; - int? pERIODDAYS; + num? pERIODDAYS; dynamic? pLANNEDOTHRS; - int? pUBLICHOLIDAY; + num? pUBLICHOLIDAY; dynamic? sCHEDULEDHRS; dynamic? sCHEDULEDONCALLHRS; dynamic? sCHEDULEDPLANNEDOTHRS; - int? sCHEDULEDAYS; + num? sCHEDULEDAYS; dynamic? sHORTAGEHRS; dynamic? sHORTAGESCHEDULEHRS; - int? sICKLEAVE; + num? sICKLEAVE; dynamic? tIMEBACKHRS; dynamic? tIMEBACKBALANCE; - int? uNAUTHORIZEDLEAVE; + num? uNAUTHORIZEDLEAVE; dynamic? uNCOVERDSHORTAGEHRS; - int? uNPAIDLEAVE; + num? uNPAIDLEAVE; GetTimeCardSummaryList( {this.aBSENTDAYS, diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 0e9053a..15fc795 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -196,7 +196,7 @@ class _DashboardScreenState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.goodMorning.tr().toText14(color: MyColors.grey77Color), + LocaleKeys.welcomeBack.tr().toText14(color: MyColors.grey77Color), (AppState().memberInformationList!.eMPLOYEENAME ?? "").toText24(isBold: true), 16.height, Row( diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index 75ee88f..b5129a5 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -106,6 +106,19 @@ class _WorkListDetailScreenState extends State { void getData() async { // try { // Utils.showLoading(context); + + getEitCollectionNotificationBodyList!.clear(); + getAbsenceCollectionNotificationBodyList!.clear(); + getPrNotificationBody = null; + getStampMsNotifications.clear(); + getStampNsNotifications.clear(); + getPoNotificationBody?.pOHeader!.clear(); + getItemCreationNtfBody?.itemCreationHeader!.clear(); + getPhonesNotificationBodyList!.clear(); + getBasicDetNtfBodyList!.clear(); + getAbsenceCollectionNotificationBodyList!.clear(); + getContactNotificationBodyList = null; + if (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") { getUserInformation(); } @@ -688,7 +701,7 @@ class _WorkListDetailScreenState extends State { GenericResponseModel model = await WorkListApiClient().postNotificationActions(payload); Utils.hideLoading(context); Utils.showToast(LocaleKeys.yourChangeHasBeenSavedSuccessfully.tr()); - animationIndex=animationIndex+1; + animationIndex = animationIndex + 1; AppState().workList!.removeAt(AppState().workListIndex!); if (AppState().workList!.isEmpty) { Navigator.pop(context, "delegate_reload"); @@ -725,6 +738,7 @@ class _WorkListDetailScreenState extends State { try { if (apiCallCount == 0) Utils.showLoading(context); apiCallCount++; + getEitCollectionNotificationBodyList!.clear(); getEitCollectionNotificationBodyList = await WorkListApiClient().GetEitNotificationBody(workListData!.nOTIFICATIONID); apiCallCount--; if (apiCallCount == 0) { @@ -742,6 +756,7 @@ class _WorkListDetailScreenState extends State { try { if (apiCallCount == 0) Utils.showLoading(context); apiCallCount++; + memberInformationListModel = null; memberInformationListModel = await WorkListApiClient().getUserInformation(-999, workListData!.sELECTEDEMPLOYEENUMBER!); apiCallCount--; if (apiCallCount == 0) { @@ -759,6 +774,7 @@ class _WorkListDetailScreenState extends State { try { if (apiCallCount == 0) Utils.showLoading(context); apiCallCount++; + getPhonesNotificationBodyList!.clear(); getPhonesNotificationBodyList = await WorkListApiClient().getPhonesNotificationBodyList(workListData!.nOTIFICATIONID); apiCallCount--; if (apiCallCount == 0) { @@ -776,6 +792,7 @@ class _WorkListDetailScreenState extends State { try { if (apiCallCount == 0) Utils.showLoading(context); apiCallCount++; + getBasicDetNtfBodyList!.clear(); getBasicDetNtfBodyList = await WorkListApiClient().getBasicDetNtfBodyList(workListData!.nOTIFICATIONID); apiCallCount--; if (apiCallCount == 0) { @@ -793,6 +810,7 @@ class _WorkListDetailScreenState extends State { try { if (apiCallCount == 0) Utils.showLoading(context); apiCallCount++; + getAbsenceCollectionNotificationBodyList!.clear(); getAbsenceCollectionNotificationBodyList = await WorkListApiClient().getAbsenceNotificationBody(workListData!.nOTIFICATIONID); apiCallCount--; if (apiCallCount == 0) { @@ -916,6 +934,7 @@ class _WorkListDetailScreenState extends State { try { if (apiCallCount == 0) Utils.showLoading(context); apiCallCount++; + getNotificationRespondAttributes.clear(); getNotificationRespondAttributes = await WorkListApiClient().notificationGetRespondAttributes(workListData!.nOTIFICATIONID!); if (getNotificationRespondAttributes.isNotEmpty) { notificationNoteInput = getNotificationRespondAttributes.first; @@ -936,6 +955,7 @@ class _WorkListDetailScreenState extends State { try { if (apiCallCount == 0) Utils.showLoading(context); apiCallCount++; + notificationButtonsList.clear(); notificationButtonsList = await WorkListApiClient().getNotificationButtons(workListData!.nOTIFICATIONID!); if (notificationButtonsList.isNotEmpty) { isCloseAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "CLOSE"); From 67c4970897bb1d0493392ee32672b07d2482a62b Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 13 Dec 2022 11:11:40 +0300 Subject: [PATCH 20/23] fixes --- lib/ui/chat/chat_home.dart | 27 +++++++++++++-------------- lib/ui/landing/dashboard_screen.dart | 2 +- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 807af1a..330242a 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -38,23 +38,22 @@ class _ChatHomeState extends State { data.clearAll(); } - // void fetchAgain() { - // print("Fetch Triggered"); - // if (chatHubConnection.state != HubConnectionState.Connected) { - // data.getUserAutoLoginToken().whenComplete(() async { - // await data.buildHubConnection(); - // data.getUserRecentChats(); - // }); - // return; - // } - // if (data.searchedChats == null || data.searchedChats!.isEmpty) { - // data.getUserRecentChats(); - // } - // } + void fetchAgain() { + if (chatHubConnection.state != HubConnectionState.Connected) { + data.getUserAutoLoginToken().whenComplete(() async { + await data.buildHubConnection(); + data.getUserRecentChats(); + }); + return; + } + if (data.searchedChats == null || data.searchedChats!.isEmpty) { + data.getUserRecentChats(); + } + } @override Widget build(BuildContext context) { - // fetchAgain(); + fetchAgain(); return Scaffold( backgroundColor: MyColors.white, appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true), diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 2d7de09..b423ebd 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -58,7 +58,6 @@ class _DashboardScreenState extends State { data = Provider.of(context, listen: false); marathonProvider = Provider.of(context, listen: false); cProvider = Provider.of(context, listen: false); - _bHubCon(); _onRefresh(); }); } @@ -80,6 +79,7 @@ class _DashboardScreenState extends State { void _onRefresh() async { data.initProvider(); + _bHubCon(); // data.getITGNotification().then((value) { // print("--------------------detail_1-----------------"); // print(value!.result!.data!.notificationMasterId); From 86d25d3ecce835a6d71a377579d931fb3594d79c Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Tue, 13 Dec 2022 11:13:37 +0300 Subject: [PATCH 21/23] Added Privileged logic for Marathon --- assets/langs/ar-SA.json | 3 +- assets/langs/en-US.json | 3 +- lib/app_state/app_state.dart | 1 + lib/classes/colors.dart | 1 + lib/generated/locale_keys.g.dart | 1 + lib/ui/login/verify_login_screen.dart | 1 + lib/ui/marathon/marathon_provider.dart | 59 ++- lib/ui/marathon/marathon_screen.dart | 141 +++-- lib/ui/marathon/widgets/marathon_banner.dart | 514 ++++++++++++------- 9 files changed, 478 insertions(+), 246 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index d51e724..2adb2ba 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -512,5 +512,6 @@ "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", "ourSponsor": "راعينا:", "startingIn": "يبدأ في", - "youAreOutOfContest": "أنت خارج المسابقة." + "youAreOutOfContest": "أنت خارج المسابقة.", + "winners": "الفائزين!!!" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 97e8c5c..46ede79 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -512,6 +512,7 @@ "youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.", "ourSponsor": "Our Sponsor:", "startingIn": "Starting in", - "youAreOutOfContest": "You are out of the contest." + "youAreOutOfContest": "You are out of the contest.", + "winners": "WINNERS!!!" } \ No newline at end of file diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index b0620ad..5060195 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -38,6 +38,7 @@ class AppState { String? get getForgetPasswordTokenID => forgetPasswordTokenID; + //Wifi info String? _mohemmWifiSSID; diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart index 4394279..5c9b30e 100644 --- a/lib/classes/colors.dart +++ b/lib/classes/colors.dart @@ -63,4 +63,5 @@ class MyColors { static const Color darkDigitColor = Color(0xff2D2F39); static const Color grey71Color = Color(0xff717171); static const Color darkGrey3BColor = Color(0xff3B3B3B); + static const Color lightGreyIconColor = Color(0xff919191); } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index c862385..8960278 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -499,5 +499,6 @@ abstract class LocaleKeys { static const ourSponsor = 'ourSponsor'; static const startingIn = 'startingIn'; static const youAreOutOfContest = 'youAreOutOfContest'; + static const winners = 'winners'; } diff --git a/lib/ui/login/verify_login_screen.dart b/lib/ui/login/verify_login_screen.dart index ce21b63..b5eb7df 100644 --- a/lib/ui/login/verify_login_screen.dart +++ b/lib/ui/login/verify_login_screen.dart @@ -642,6 +642,7 @@ class _VerifyLoginScreenState extends State { PrivilegeListModel.saveToPrefs(genericResponseModel.privilegeList ?? []); AppState().setMohemmWifiSSID = genericResponseModel.mohemmWifiSSID; AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword; + AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword; Utils.saveStringFromPrefs(SharedPrefsConsts.username, AppState().getUserName!); Utils.saveStringFromPrefs(SharedPrefsConsts.password, AppState().password!); Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiSSID, genericResponseModel.mohemmWifiSSID!); diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index 2d778b9..175b7be 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -5,11 +5,13 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/marathon/marathon_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; import 'package:mohem_flutter_app/models/marathon/question_model.dart'; import 'package:mohem_flutter_app/models/marathon/winner_model.dart'; +import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; import 'package:video_player/video_player.dart'; @@ -28,6 +30,9 @@ class MarathonProvider extends ChangeNotifier { String? selectedOptionId; int? totalQualifiers; + bool iAmWinner = false; + bool isPrivilegedWithMarathon = false; + bool _isLoading = false; bool get isLoading => _isLoading; @@ -164,7 +169,7 @@ class MarathonProvider extends ChangeNotifier { oneSec, (Timer timer) async { // This 2 is just to show the color of answer tile for 2 seconds and then update card status - if (totalCurrentQuestionTime - currentGapTime == currentQuestion.questionTime! - 2) { + if (totalCurrentQuestionTime - currentGapTime == 1) { getCorrectAnswerAndUpdateAnswerColor(); } @@ -182,7 +187,7 @@ class MarathonProvider extends ChangeNotifier { if (totalCurrentQuestionTime == 0) { updateCardData(); - if (currentQuestionNumber == marathonDetailModel.totalQuestions! - 1) { + if (currentQuestionNumber == marathonDetailModel.totalQuestions! ) { callGetQualifiersApi(); updateQuestionCardStatus(QuestionCardStatus.findingWinner); timer.cancel(); @@ -235,6 +240,19 @@ class MarathonProvider extends ChangeNotifier { Future callGetSelectedWinnersApi() async { selectedWinners = await MarathonApiClient().getSelectedWinner(marathonId: marathonDetailModel.id!); + if (selectedWinners != null) { + selectedWinners!.removeWhere((WinnerModel element) { + print("matching : ${AppState().memberInformationList!.eMPLOYEENUMBER} with ${element.employeeId}"); + if (element.employeeId == AppState().memberInformationList!.eMPLOYEENUMBER) { + iAmWinner = true; + return true; + } else { + return false; + } + }); + } + print("selectedWinners Length : ${selectedWinners!.length}"); + notifyListeners(); } @@ -361,20 +379,35 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); } + bool checkIfPrivilegedForMarathon() { + for (PrivilegeListModel element in AppState().privilegeListModel!) { + if (element.serviceName == "Marathon") { + if (element.previlege != null) { + return element.previlege!; + } + } + } + return false; + } + Future getMarathonDetailsFromApi() async { isLoading = true; notifyListeners(); - await MarathonApiClient().getMarathonToken().whenComplete(() async { - marathonDetailModel = await MarathonApiClient().getMarathonDetails(); - if (marathonDetailModel.id == null) { - isUpComingMarathon = false; - notifyListeners(); - return; - } - populateQuestionStatusesList(); - isLoading = false; - notifyListeners(); - }); + isPrivilegedWithMarathon = checkIfPrivilegedForMarathon(); + if (isPrivilegedWithMarathon) { + await MarathonApiClient().getMarathonToken().whenComplete(() async { + marathonDetailModel = await MarathonApiClient().getMarathonDetails(); + if (marathonDetailModel.id == null) { + isUpComingMarathon = false; + isLoading = false; + notifyListeners(); + return; + } + populateQuestionStatusesList(); + }); + } + isLoading = false; + notifyListeners(); } Future onJoinMarathonPressed(BuildContext context) async { diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index 2ae3f64..71ae3d6 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -43,71 +43,102 @@ class MarathonScreen extends StatelessWidget { return Image.asset(MyLottieConsts.congratsGif, height: 200); } + // SizedBox( + // height: 200, + // child: Stack( + // fit: StackFit.expand, + // children: [ + // Lottie.asset(MyLottieConsts.celebrate1Lottie, height: 200), + // // Lottie.asset(MyLottieConsts.celebrate2Lottie, height: 200), + // ], + // ), + // ), + Widget getWinnerWidget(BuildContext context, {required MarathonProvider provider}) { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox( - height: 200, - child: Stack( - children: [ - Lottie.asset(MyLottieConsts.celebrate1Lottie, height: 200), - Lottie.asset(MyLottieConsts.celebrate2Lottie, height: 200), + child: Stack( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + 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: LocaleKeys.winners.tr().toText32(color: MyColors.white, isBold: true, isCentered: true).paddingOnly(top: 07), + ) + ], + ), + ), + 16.height, + !provider.iAmWinner + ? Column( + children: [ + (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22( + color: MyColors.grey3AColor, + isCentered: true, + ), + 8.height, + AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color), + ], + ) + : const SizedBox(), + 36.height, + if (provider.selectedWinners != null) ...[ + ListView.separated( + shrinkWrap: true, + itemCount: provider.selectedWinners!.length, + separatorBuilder: (BuildContext context, int index) { + return const Divider(); + }, + itemBuilder: (BuildContext context, int index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (AppState().isArabic(context) ? provider.selectedWinners![index].nameEn : provider.selectedWinners![index].nameEn)!.toText16( + color: MyColors.grey3AColor, + ), + provider.selectedWinners!.first.employeeId!.toText16(color: MyColors.grey57Color), + ], + ); + }, + ), ], - ), - ), - 26.height, - SizedBox( - height: 50, - child: Stack( - children: [ - Align( - alignment: Alignment.center, - child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50), + 60.height, + if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...[ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + "${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color), + (AppState().isArabic(context) ? provider.marathonDetailModel.sponsors!.first.nameAr ?? "" : provider.marathonDetailModel.sponsors!.first.nameEn ?? "").toText14( + color: MyColors.darkTextColor, + isBold: true, + ), + ], ), - Align( - alignment: Alignment.center, - child: LocaleKeys.winner.tr().toText32(color: MyColors.white, isBold: true, isCentered: true).paddingOnly(top: 07), + 5.height, + Image.network( + provider.marathonDetailModel.sponsors!.first.image!, + height: 40, + width: 150, + fit: BoxFit.fill, + errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { + return const Center(); + }, ) ], - ), + ], ), - 12.height, - if (provider.selectedWinners != null) ...[ - (AppState().isArabic(context) ? provider.selectedWinners!.first.nameEn : provider.selectedWinners!.first.nameEn)!.toText22( - color: MyColors.grey3AColor, - isCentered: true, - ), - 8.height, - provider.selectedWinners!.first.employeeId!.toText22(color: MyColors.grey57Color), - ], - 60.height, - if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...[ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - "${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color), - (AppState().isArabic(context) ? provider.marathonDetailModel.sponsors!.first.nameAr ?? "" : provider.marathonDetailModel.sponsors!.first.nameEn ?? "").toText14( - color: MyColors.darkTextColor, - isBold: true, - ), - ], - ), - 5.height, - Image.network( - provider.marathonDetailModel.sponsors!.first.image!, - height: 40, - width: 150, - fit: BoxFit.fill, - errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { - return const Center(); - }, - ) - ], + Lottie.asset(MyLottieConsts.celebrate1Lottie), ], ), ); diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index 2be08a9..0487c74 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -22,200 +22,362 @@ class MarathonBanner extends StatelessWidget { const MarathonBanner({Key? key, required this.isMarathonUpcoming}) : super(key: key); - @override - Widget build(BuildContext context) { - MarathonProvider provider = context.read(); - return provider.marathonDetailModel.startTime != null - ? Container( - decoration: MyDecorations.shadowDecoration, - height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11, - clipBehavior: Clip.antiAlias, - child: Stack( + Widget getUnPrivilegedMarathon(BuildContext context) { + return Container( + decoration: MyDecorations.shadowDecoration, + height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11, + clipBehavior: Clip.antiAlias, + child: Stack( + children: [ + Transform( + alignment: Alignment.center, + transform: Matrix4.rotationY( + AppState().isArabic(context) ? math.pi : 0, + ), + child: SvgPicture.asset( + "assets/images/marathon_banner_bg.svg", + fit: BoxFit.fill, + width: double.infinity, + ), + ), + AppState().isArabic(context) + ? Positioned( + right: -15, + top: -10, + child: Transform.rotate( + angle: 10, + child: Container( + width: isTablet ? 70 : 65, + height: isTablet ? 40 : 32, + color: MyColors.darkDigitColor, + ), + ), + ) + : Positioned( + left: -20, + top: -10, + child: Transform.rotate( + angle: 15, + child: Container( + width: isTablet ? 70 : 65, + height: isTablet ? 40 : 32, + color: MyColors.darkDigitColor, + ), + ), + ), + SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( children: [ - Transform( - alignment: Alignment.center, - transform: Matrix4.rotationY( - AppState().isArabic(context) ? math.pi : 0, + const Expanded( + flex: 3, + child: SizedBox( + width: double.infinity, + height: double.infinity, ), - child: SvgPicture.asset( - "assets/images/marathon_banner_bg.svg", - fit: BoxFit.fill, + ), + Expanded( + flex: AppState().isArabic(context) ? 4 : 5, + child: SizedBox( width: double.infinity, + height: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + AppState().isArabic(context) ? 0.height : 5.height, + Text( + LocaleKeys.getReadyForContest.tr(), + style: TextStyle( + fontSize: isTablet ? 20 : 11, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w600, + color: MyColors.white.withOpacity(0.83), + letterSpacing: -0.4, + ), + ), + Text( + LocaleKeys.brainMarathon.tr(), + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: isTablet ? 30 : 19, + fontWeight: FontWeight.bold, + color: MyColors.white.withOpacity(0.83), + height: 32 / 22, + ), + ), + ], + ).paddingOnly( + left: AppState().isArabic(context) ? 12 : 3, + right: AppState().isArabic(context) ? 3 : 12, + ) + ], + ), ), ), - AppState().isArabic(context) - ? Positioned( - right: -15, - top: -10, - child: Transform.rotate( - angle: 10, - child: Container( - width: isTablet ? 70 : 65, - height: isTablet ? 40 : 32, - color: MyColors.darkDigitColor, - ), - ), - ) - : Positioned( - left: -20, - top: -10, - child: Transform.rotate( - angle: 15, - child: Container( - width: isTablet ? 70 : 65, - height: isTablet ? 40 : 32, - color: MyColors.darkDigitColor, - ), + ], + ), + ), + AppState().isArabic(context) + ? Align( + alignment: Alignment.topRight, + child: SizedBox( + height: isTablet ? 30 : 20, + width: isTablet ? 45 : 35, + child: Transform.rotate( + angle: math.pi / 4.5, + child: Text( + LocaleKeys.brainMarathon.tr(), + textAlign: TextAlign.center, + maxLines: 2, + style: TextStyle( + color: MyColors.white, + fontWeight: FontWeight.bold, + fontSize: isTablet ? 8 : 6, + height: 1.2, ), ), - SizedBox( - width: double.infinity, - height: double.infinity, - child: Row( - children: [ - const Expanded( - flex: 3, - child: SizedBox( - width: double.infinity, - height: double.infinity, + ), + ), + ).paddingOnly(top: 5) + : Align( + alignment: Alignment.topLeft, + child: SizedBox( + height: isTablet ? 30 : 20, + width: isTablet ? 45 : 35, + child: Transform.rotate( + angle: -math.pi / 4.5, + child: Text( + LocaleKeys.brainMarathon.tr(), + textAlign: TextAlign.center, + maxLines: 2, + style: TextStyle( + color: MyColors.kWhiteColor, + fontWeight: FontWeight.bold, + fontSize: isTablet ? 8 : 6, + height: 1.2, ), ), - Expanded( - flex: AppState().isArabic(context) ? 4 : 5, - child: SizedBox( - width: double.infinity, - height: double.infinity, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + ), + ), + ).paddingOnly(top: 5), + Container( + height: double.infinity, + width: double.infinity, + color: Colors.black.withOpacity(0.6), + child: const Icon( + Icons.lock_rounded, + color: MyColors.lightGreyIconColor, + ), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + MarathonProvider provider = context.read(); + + return !provider.isPrivilegedWithMarathon + ? getUnPrivilegedMarathon(context) + : provider.marathonDetailModel.startTime != null + ? Container( + decoration: MyDecorations.shadowDecoration, + height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11, + clipBehavior: Clip.antiAlias, + child: Stack( + children: [ + Transform( + alignment: Alignment.center, + transform: Matrix4.rotationY( + AppState().isArabic(context) ? math.pi : 0, + ), + child: SvgPicture.asset( + "assets/images/marathon_banner_bg.svg", + fit: BoxFit.fill, + width: double.infinity, + ), + ), + AppState().isArabic(context) + ? Positioned( + right: -15, + top: -10, + child: Transform.rotate( + angle: 10, + child: Container( + width: isTablet ? 70 : 65, + height: isTablet ? 40 : 32, + color: MyColors.darkDigitColor, + ), + ), + ) + : Positioned( + left: -20, + top: -10, + child: Transform.rotate( + angle: 15, + child: Container( + width: isTablet ? 70 : 65, + height: isTablet ? 40 : 32, + color: MyColors.darkDigitColor, + ), + ), + ), + SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( + children: [ + const Expanded( + flex: 3, + child: SizedBox( + width: double.infinity, + height: double.infinity, + ), + ), + Expanded( + flex: AppState().isArabic(context) ? 4 : 5, + child: SizedBox( + width: double.infinity, + height: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - AppState().isArabic(context) ? 0.height : 5.height, - Text( - LocaleKeys.getReadyForContest.tr(), - style: TextStyle( - fontSize: isTablet ? 20 : 11, - fontStyle: FontStyle.italic, - fontWeight: FontWeight.w600, - color: MyColors.white.withOpacity(0.83), - letterSpacing: -0.4, - ), - ), - Text( - AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "", - style: TextStyle( - fontStyle: FontStyle.italic, - fontSize: isTablet ? 30 : 19, - fontWeight: FontWeight.bold, - color: MyColors.white.withOpacity(0.83), - height: 32 / 22, - ), - ), - isTablet ? 10.height : 3.height, - BuildCountdownTimer( - timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, - provider: provider, - screenFlag: 0, - ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + AppState().isArabic(context) ? 0.height : 5.height, + Text( + LocaleKeys.getReadyForContest.tr(), + style: TextStyle( + fontSize: isTablet ? 20 : 11, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w600, + color: MyColors.white.withOpacity(0.83), + letterSpacing: -0.4, + ), + ), + Text( + AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "", + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: isTablet ? 30 : 19, + fontWeight: FontWeight.bold, + color: MyColors.white.withOpacity(0.83), + height: 32 / 22, + ), + ), + isTablet ? 10.height : 3.height, + BuildCountdownTimer( + timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, + provider: provider, + screenFlag: 0, + ), + ], + ).paddingOnly( + left: AppState().isArabic(context) ? 12 : 3, + right: AppState().isArabic(context) ? 3 : 12, + ) ], - ).paddingOnly( - left: AppState().isArabic(context) ? 12 : 3, - right: AppState().isArabic(context) ? 3 : 12, - ) - ], + ), + ), ), - ), + ], ), - ], - ), - ), - AppState().isArabic(context) - ? Align( - alignment: Alignment.topRight, - child: SizedBox( - height: isTablet ? 30 : 20, - width: isTablet ? 45 : 35, - child: Transform.rotate( - angle: math.pi / 4.5, - child: Text( - LocaleKeys.brainMarathon.tr(), - textAlign: TextAlign.center, - maxLines: 2, - style: TextStyle( - color: MyColors.white, - fontWeight: FontWeight.bold, - fontSize: isTablet ? 8 : 6, - height: 1.2, + ), + AppState().isArabic(context) + ? Align( + alignment: Alignment.topRight, + child: SizedBox( + height: isTablet ? 30 : 20, + width: isTablet ? 45 : 35, + child: Transform.rotate( + angle: math.pi / 4.5, + child: Text( + LocaleKeys.brainMarathon.tr(), + textAlign: TextAlign.center, + maxLines: 2, + style: TextStyle( + color: MyColors.white, + fontWeight: FontWeight.bold, + fontSize: isTablet ? 8 : 6, + height: 1.2, + ), + ), ), ), - ), - ), - ).paddingOnly(top: 5) - : Align( - alignment: Alignment.topLeft, - child: SizedBox( - height: isTablet ? 30 : 20, - width: isTablet ? 45 : 35, - child: Transform.rotate( - angle: -math.pi / 4.5, - child: Text( - LocaleKeys.brainMarathon.tr(), - textAlign: TextAlign.center, - maxLines: 2, - style: TextStyle( - color: MyColors.kWhiteColor, - fontWeight: FontWeight.bold, - fontSize: isTablet ? 8 : 6, - height: 1.2, + ).paddingOnly(top: 5) + : Align( + alignment: Alignment.topLeft, + child: SizedBox( + height: isTablet ? 30 : 20, + width: isTablet ? 45 : 35, + child: Transform.rotate( + angle: -math.pi / 4.5, + child: Text( + LocaleKeys.brainMarathon.tr(), + textAlign: TextAlign.center, + maxLines: 2, + style: TextStyle( + color: MyColors.kWhiteColor, + fontWeight: FontWeight.bold, + fontSize: isTablet ? 8 : 6, + height: 1.2, + ), + ), ), ), + ).paddingOnly(top: 5), + !AppState().isArabic(context) + ? Positioned( + right: 0, + bottom: 0, + child: RotatedBox( + quarterTurns: 4, + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), + ).paddingAll(isTablet ? 20 : 15), + ) + : Positioned( + bottom: 0, + left: 0, + child: RotatedBox( + quarterTurns: 2, + child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), + ).paddingAll(isTablet ? 20 : 15), ), - ), - ).paddingOnly(top: 5), - !AppState().isArabic(context) - ? Positioned( - right: 0, - bottom: 0, - child: RotatedBox( - quarterTurns: 4, - child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), - ).paddingAll(isTablet ? 20 : 15), - ) - : Positioned( - bottom: 0, - left: 0, - child: RotatedBox( - quarterTurns: 2, - child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), - ).paddingAll(isTablet ? 20 : 15), - ), - ], - ).onPress(() async { - int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes; - if (remainingTimeInMinutes > 2) { - Utils.showLoading(context); - try { - await provider.initializeVideoPlayer().then((_) { - Utils.hideLoading(context); - provider.startTimerForSponsorVideo(); - Navigator.pushNamed(context, AppRoutes.marathonSponsorVideoScreen); - }); - } catch (e, s) { - if (kDebugMode) { - print("Error in VideoPlayer: ${e.toString()}"); - } - Utils.hideLoading(context); - Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); - } - } else { - Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); - } - }), - ) - : const SizedBox(); + ], + ).onPress(() async { + int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes; + + if (remainingTimeInMinutes > 2) { + Utils.showLoading(context); + try { + await provider.initializeVideoPlayer().then((_) { + Utils.hideLoading(context); + provider.startTimerForSponsorVideo(); + Navigator.pushNamed(context, AppRoutes.marathonSponsorVideoScreen); + }); + } catch (e) { + if (kDebugMode) { + print("Error in VideoPlayer: ${e.toString()}"); + } + Utils.hideLoading(context); + Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); + } + } else { + Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); + } + }), + ) + : const SizedBox(); } } From 76239d0077b1ca46d0b1526d82f67cd211eca314 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 13 Dec 2022 11:36:38 +0300 Subject: [PATCH 22/23] Fixes --- .../chat/get_single_user_chat_list_model.dart | 2 ++ lib/provider/chat_provider_model.dart | 36 ++++++++++++------- lib/ui/chat/chat_detailed_screen.dart | 6 +++- lib/ui/chat/chat_home.dart | 27 +++++++------- lib/ui/landing/dashboard_screen.dart | 3 +- 5 files changed, 45 insertions(+), 29 deletions(-) diff --git a/lib/models/chat/get_single_user_chat_list_model.dart b/lib/models/chat/get_single_user_chat_list_model.dart index 80ffa5a..ee4f210 100644 --- a/lib/models/chat/get_single_user_chat_list_model.dart +++ b/lib/models/chat/get_single_user_chat_list_model.dart @@ -38,8 +38,10 @@ class SingleUserChatModel { String? contantNo; int? currentUserId; String? currentUserName; + String? currentUserEmail; int? targetUserId; String? targetUserName; + String? targetUserEmail; String? encryptedTargetUserId; String? encryptedTargetUserName; int? chatEventId; diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 3a4e70b..67899c5 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -330,8 +330,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { temp = getSingleUserChatModel(jsonEncode(msg)); data.first.targetUserId = temp.first.currentUserId; data.first.targetUserName = temp.first.currentUserName; + data.first.targetUserEmail = temp.first.currentUserEmail; data.first.currentUserId = temp.first.targetUserId; data.first.currentUserName = temp.first.targetUserName; + data.first.currentUserEmail = temp.first.targetUserEmail; + if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) { data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg"); } @@ -349,21 +352,24 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (searchedChats != null) { dynamic contain = searchedChats!.where((ChatUser element) => element.id == data.first.currentUserId); if (contain.isEmpty) { + List emails = []; + emails.add(await EmailImageEncryption().encrypt(val: data.first.currentUserEmail!)); + List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); searchedChats!.add( ChatUser( - id: data.first.currentUserId, - userName: data.first.currentUserName, - unreadMessageCount: 0, - isImageLoading: false, - image: "", - isImageLoaded: true, - userStatus: 1, - isTyping: false, - userLocalDownlaodedImage: null), + id: data.first.currentUserId, + userName: data.first.currentUserName, + unreadMessageCount: 0, + isImageLoading: false, + image: chatImages!.first.profilePicture ?? "", + isImageLoaded: true, + userStatus: 1, + isTyping: false, + userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, data.first.currentUserId.toString()), + ), ); } } - setMsgTune(); userChatHistory.insert(0, data.first); @@ -526,21 +532,25 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await chatHubConnection.invoke("AddChatUserAsync", args: [json.decode(chatData)]); } - void sendChatMessage(int targetUserId, int userStatus, String targetUserName, BuildContext context) async { + void sendChatMessage(BuildContext context, {required int targetUserId, required int userStatus, required String userEmail, required String targetUserName}) async { dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId); if (contain.isEmpty) { + List emails = []; + emails.add(await EmailImageEncryption().encrypt(val: userEmail)); + List chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); searchedChats!.add( ChatUser( id: targetUserId, userName: targetUserName, unreadMessageCount: 0, + email: userEmail, isImageLoading: false, - image: "", + image: chatImages.first.profilePicture ?? "", isImageLoaded: true, isTyping: false, isFav: false, userStatus: userStatus, - userLocalDownlaodedImage: null, + userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()), ), ); notifyListeners(); diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 05e674a..be685df 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -223,7 +223,11 @@ class _ChatDetailScreenState extends State { ), ).paddingOnly(right: 25), SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26).onPress( - () => m.sendChatMessage(params!.chatUser!.id!, params!.chatUser!.userStatus ?? 0, params!.chatUser!.userName!, context), + () => m.sendChatMessage(context, + targetUserId: params!.chatUser!.id!, + userStatus: params!.chatUser!.userStatus ?? 0, + userEmail: params!.chatUser!.email!, + targetUserName: params!.chatUser!.userName!), ), ], ), diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 807af1a..330242a 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -38,23 +38,22 @@ class _ChatHomeState extends State { data.clearAll(); } - // void fetchAgain() { - // print("Fetch Triggered"); - // if (chatHubConnection.state != HubConnectionState.Connected) { - // data.getUserAutoLoginToken().whenComplete(() async { - // await data.buildHubConnection(); - // data.getUserRecentChats(); - // }); - // return; - // } - // if (data.searchedChats == null || data.searchedChats!.isEmpty) { - // data.getUserRecentChats(); - // } - // } + void fetchAgain() { + if (chatHubConnection.state != HubConnectionState.Connected) { + data.getUserAutoLoginToken().whenComplete(() async { + await data.buildHubConnection(); + data.getUserRecentChats(); + }); + return; + } + if (data.searchedChats == null || data.searchedChats!.isEmpty) { + data.getUserRecentChats(); + } + } @override Widget build(BuildContext context) { - // fetchAgain(); + fetchAgain(); return Scaffold( backgroundColor: MyColors.white, appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true), diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 1800aa3..b1dac53 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -58,7 +58,7 @@ class _DashboardScreenState extends State { data = Provider.of(context, listen: false); marathonProvider = Provider.of(context, listen: false); cProvider = Provider.of(context, listen: false); - _bHubCon(); + _onRefresh(); }); } @@ -80,6 +80,7 @@ class _DashboardScreenState extends State { void _onRefresh() async { data.initProvider(); + _bHubCon(); // data.getITGNotification().then((value) { // print("--------------------detail_1-----------------"); // print(value!.result!.data!.notificationMasterId); From 1144664d6457b56882c2683e5cb2a2cbe647e35c Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 13 Dec 2022 11:52:38 +0300 Subject: [PATCH 23/23] Images Fixes --- lib/models/chat/get_single_user_chat_list_model.dart | 6 ++++++ lib/ui/chat/favorite_users_screen.dart | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/models/chat/get_single_user_chat_list_model.dart b/lib/models/chat/get_single_user_chat_list_model.dart index ee4f210..246a515 100644 --- a/lib/models/chat/get_single_user_chat_list_model.dart +++ b/lib/models/chat/get_single_user_chat_list_model.dart @@ -19,6 +19,8 @@ class SingleUserChatModel { this.targetUserName, this.encryptedTargetUserId, this.encryptedTargetUserName, + this.currentUserEmail, + this.targetUserEmail, this.chatEventId, this.fileTypeId, this.isSeen, @@ -66,6 +68,8 @@ class SingleUserChatModel { currentUserName: json["currentUserName"] == null ? null : json["currentUserName"], targetUserId: json["targetUserId"] == null ? null : json["targetUserId"], targetUserName: json["targetUserName"] == null ? null : json["targetUserName"], + targetUserEmail: json["targetUserEmail"] == null ? null : json["targetUserEmail"], + currentUserEmail: json["currentUserEmail"] == null ? null : json["currentUserEmail"], encryptedTargetUserId: json["encryptedTargetUserId"] == null ? null : json["encryptedTargetUserId"], encryptedTargetUserName: json["encryptedTargetUserName"] == null ? null : json["encryptedTargetUserName"], chatEventId: json["chatEventId"] == null ? null : json["chatEventId"], @@ -92,6 +96,8 @@ class SingleUserChatModel { "targetUserName": targetUserName == null ? null : targetUserName, "encryptedTargetUserId": encryptedTargetUserId == null ? null : encryptedTargetUserId, "encryptedTargetUserName": encryptedTargetUserName == null ? null : encryptedTargetUserName, + "currentUserEmail": currentUserEmail == null ? null : currentUserEmail, + "targetUserEmail": targetUserEmail == null ? null : targetUserEmail, "chatEventId": chatEventId == null ? null : chatEventId, "fileTypeId": fileTypeId, "isSeen": isSeen == null ? null : isSeen, diff --git a/lib/ui/chat/favorite_users_screen.dart b/lib/ui/chat/favorite_users_screen.dart index 157a884..a978ccb 100644 --- a/lib/ui/chat/favorite_users_screen.dart +++ b/lib/ui/chat/favorite_users_screen.dart @@ -111,7 +111,7 @@ class ChatFavoriteUsersScreen extends StatelessWidget { Navigator.pushNamed( context, AppRoutes.chatDetailed, - arguments: ChatDetailedScreenParams(m.favUsersList![index], false), + arguments: ChatDetailedScreenParams(m.favUsersList![index], true), ).then( (Object? value) { m.clearSelections();