diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 2adb2ba..ac320f7 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -513,5 +513,6 @@ "ourSponsor": "راعينا:", "startingIn": "يبدأ في", "youAreOutOfContest": "أنت خارج المسابقة.", - "winners": "الفائزين!!!" + "winners": "الفائزين!!!", + "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 46ede79..1e6025c 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -513,6 +513,6 @@ "ourSponsor": "Our Sponsor:", "startingIn": "Starting in", "youAreOutOfContest": "You are out of the contest.", - "winners": "WINNERS!!!" - + "winners": "WINNERS!!!", + "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified." } \ No newline at end of file diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index ace0881..5f2ad7e 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -133,6 +133,28 @@ class DashboardApiClient { }, url, postParams); } + //Mark Fake Location + Future markFakeLocation({String lat = "0", String? long = "0", required String sourceName}) async { + String url = "${ApiConsts.swpRest}CreateIssueInfo"; + var uuid = Uuid(); + // Generate a v4 (random) id + + Map postParams = { + "UID": uuid.v4(), //Mobile Id + "Latitude": lat, + "Longitude": long, + "QRValue": '', + "NFCValue": sourceName == 'NFC' ? sourceName : '', + "WifiValue": sourceName == 'WIFI' ? sourceName : '', + "EmployeeID": AppState().memberInformationList!.eMPLOYEENUMBER, + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, url, postParams); + } + //Check ITG Type Future getITGPageNotification() async { String url = "${ApiConsts.cocRest}Mohemm_ITG_GetPageNotification"; diff --git a/lib/api/marathon/marathon_api_client.dart b/lib/api/marathon/marathon_api_client.dart index 26a0363..9fcdc68 100644 --- a/lib/api/marathon/marathon_api_client.dart +++ b/lib/api/marathon/marathon_api_client.dart @@ -97,6 +97,7 @@ class MarathonApiClient { if (marathonModel.statusCode == 208) { // means participant is already in the marathon i.e already joined + //TODO: NEED TO LOOK UPON THIS return marathonModel.data["remainingTime"]; } @@ -116,13 +117,13 @@ class MarathonApiClient { Map jsonObject = { "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"]; diff --git a/lib/api/worklist/worklist_api_client.dart b/lib/api/worklist/worklist_api_client.dart index 75992e7..dcbb415 100644 --- a/lib/api/worklist/worklist_api_client.dart +++ b/lib/api/worklist/worklist_api_client.dart @@ -26,6 +26,7 @@ import 'package:mohem_flutter_app/models/update_user_item_type_list.dart'; import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; +import 'package:mohem_flutter_app/models/worklist/hr/get_address_notification_body_list.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; @@ -509,6 +510,20 @@ class WorkListApiClient { }, url, postParams); } + Future?> getAddressNotificationBodyList(int? notificationId) async { + String url = "${ApiConsts.erpRest}GET_ADDRESS_NOTIFICATION_BODY"; + Map postParams = { + "P_NOTIFICATION_ID": notificationId, + "P_PAGE_LIMIT": 100, + "P_PAGE_NUM": 1, + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData.getAddressNotificationBodyList; + }, url, postParams); + } + Future?> getFavoriteReplacementWithoutImage() async { String url = "${ApiConsts.erpRest}Mohemm_GetFavoriteReplacementsWithoutImage"; Map postParams = {}; diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 3d58efd..0559996 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -2,9 +2,9 @@ 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 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/"; @@ -28,6 +28,7 @@ class ApiConsts { //Brain Marathon Constants static String marathonBaseUrl = "https://marathoon.com/service/api/"; + static String marathonBaseUrlServices = "https://marathoon.com/service/"; static String marathonParticipantLoginUrl = marathonBaseUrl + "auth/participantlogin"; static String marathonProjectGetUrl = marathonBaseUrl + "Project/Project_Get"; static String marathonUpcomingUrl = marathonBaseUrl + "marathon/upcoming/"; diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index fbdc6ce..57bb888 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -9,7 +9,6 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; -import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/exceptions/api_exception.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -66,6 +65,7 @@ class Utils { showDialog( context: context, barrierColor: Colors.black.withOpacity(0.5), + useRootNavigator: false, builder: (BuildContext context) => LoadingDialog(), ).then((value) { _isLoadingVisible = false; @@ -121,8 +121,11 @@ class Utils { ), ); } else { - showToast(errorMessage); - // confirmDialog(cxt, errorMessage); + if (cxt != null) { + confirmDialog(cxt, errorMessage); + } else { + showToast(errorMessage); + } } } } diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index b2a92ad..67408b3 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -528,7 +528,9 @@ class CodegenLoader extends AssetLoader{ "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", "ourSponsor": "راعينا:", "startingIn": "يبدأ في", - "youAreOutOfContest": "أنت خارج المسابقة." + "youAreOutOfContest": "أنت خارج المسابقة.", + "winners": "الفائزين!!!", + "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية" }; static const Map en_US = { "mohemm": "Mohemm", @@ -1044,7 +1046,9 @@ static const Map en_US = { "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!!!", + "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified." }; 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 8960278..e4c6ffb 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -500,5 +500,6 @@ abstract class LocaleKeys { static const startingIn = 'startingIn'; static const youAreOutOfContest = 'youAreOutOfContest'; static const winners = 'winners'; + static const fakeLocation = 'fakeLocation'; } diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index cd7043c..ed00de4 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -102,6 +102,7 @@ import 'package:mohem_flutter_app/models/validate_eit_transaction_list_model.dar import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; import 'package:mohem_flutter_app/models/worklist/get_favorite_replacements_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; +import 'package:mohem_flutter_app/models/worklist/hr/get_address_notification_body_list.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; @@ -163,12 +164,12 @@ class GenericResponseModel { List? getAbsenceAttachmentsList; List? getAbsenceAttendanceTypesList; List? getAbsenceCollectionNotificationBodyList; + List? getAddressNotificationBodyList; List? getAbsenceDffStructureList; List? getAbsenceTransactionList; List? getAccrualBalancesList; List? getActionHistoryList; List? getAddressDffStructureList; - List? getAddressNotificationBodyList; List? getApprovesList; List? getAttachementList; GetAttendanceTracking? getAttendanceTrackingList; @@ -717,6 +718,13 @@ class GenericResponseModel { }); } + if (json['GetAddressNotificationBodyList'] != null) { + getAddressNotificationBodyList = []; + json['GetAddressNotificationBodyList'].forEach((v) { + getAddressNotificationBodyList!.add(GetAddressNotificationBodyList.fromJson(v)); + }); + } + if (json['GetAbsenceDffStructureList'] != null) { getAbsenceDffStructureList = []; json['GetAbsenceDffStructureList'].forEach((v) { @@ -746,7 +754,7 @@ class GenericResponseModel { getAddressDffStructureList!.add(GetAddressDffStructureList.fromJson(v)); }); } - getAddressNotificationBodyList = json['GetAddressNotificationBodyList']; + // getAddressNotificationBodyList = json['GetAddressNotificationBodyList']; if (json['GetApprovesList'] != null) { getApprovesList = []; diff --git a/lib/models/get_po_Item_history_list_model.dart b/lib/models/get_po_Item_history_list_model.dart index 35e81d6..28a4f28 100644 --- a/lib/models/get_po_Item_history_list_model.dart +++ b/lib/models/get_po_Item_history_list_model.dart @@ -4,7 +4,7 @@ class GetPoItemHistoryList { String? bUYER; String? cLOSEDCODE; String? cREATIONDATE; - int? dISCOUNTPERCENTAGE; + num? dISCOUNTPERCENTAGE; int? fROMROWNUM; int? iTEMID; num? nETPRICE; diff --git a/lib/models/get_quotation_analysis_list_model.dart b/lib/models/get_quotation_analysis_list_model.dart index e041f95..e1926f0 100644 --- a/lib/models/get_quotation_analysis_list_model.dart +++ b/lib/models/get_quotation_analysis_list_model.dart @@ -5,7 +5,7 @@ class GetQuotationAnalysisList { int? nOOFROWS; String? qUOTBONUSQTY; String? qUOTDELIVERYDATE; - int? qUOTLINETOTAL; + num? qUOTLINETOTAL; String? qUOTMFGPARTNUM; String? qUOTNUM; num? qUOTQTY; diff --git a/lib/models/worklist/hr/get_address_notification_body_list.dart b/lib/models/worklist/hr/get_address_notification_body_list.dart new file mode 100644 index 0000000..28ee516 --- /dev/null +++ b/lib/models/worklist/hr/get_address_notification_body_list.dart @@ -0,0 +1,28 @@ +class GetAddressNotificationBodyList { + String? pREVSEGMENTVALUEDSP; + String? sEGMENTPROMPT; + String? sEGMENTVALUEDSP; + String? uPDATEDFLAG; + + GetAddressNotificationBodyList( + {this.pREVSEGMENTVALUEDSP, + this.sEGMENTPROMPT, + this.sEGMENTVALUEDSP, + this.uPDATEDFLAG}); + + GetAddressNotificationBodyList.fromJson(Map json) { + pREVSEGMENTVALUEDSP = json['PREV_SEGMENT_VALUE_DSP']; + sEGMENTPROMPT = json['SEGMENT_PROMPT']; + sEGMENTVALUEDSP = json['SEGMENT_VALUE_DSP']; + uPDATEDFLAG = json['UPDATED_FLAG']; + } + + Map toJson() { + Map data = new Map(); + data['PREV_SEGMENT_VALUE_DSP'] = this.pREVSEGMENTVALUEDSP; + data['SEGMENT_PROMPT'] = this.sEGMENTPROMPT; + data['SEGMENT_VALUE_DSP'] = this.sEGMENTVALUEDSP; + data['UPDATED_FLAG'] = this.uPDATEDFLAG; + return data; + } +} diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 876737f..a62016f 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -48,7 +48,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { bool currentUserTyping = false; int? cTypingUserId = 0; - //Chat + //Chat Home Page Counter int chatUConvCounter = 0; Future getUserAutoLoginToken() async { @@ -291,14 +291,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void chatNotDelivered(List? args) { dynamic items = args!.toList(); for (dynamic item in items[0]) { - searchedChats!.forEach( - (ChatUser element) { - if (element.id == item["currentUserId"]) { - int? val = element.unreadMessageCount ?? 0; - element.unreadMessageCount = val! + 1; - } - }, - ); + for (ChatUser element in searchedChats!) { + if (element.id == item["currentUserId"]) { + int? val = element.unreadMessageCount ?? 0; + element.unreadMessageCount = val! + 1; + } + } } notifyListeners(); } @@ -378,20 +376,25 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { setMsgTune(); if (isChatScreenActive && data.first.currentUserId == receiverID) { userChatHistory.insert(0, data.first); - } - - if (searchedChats != null) { - for (ChatUser user in searchedChats!) { - if (user.id == data.first.currentUserId) { - int tempCount = user.unreadMessageCount ?? 0; - user.unreadMessageCount = tempCount + 1; + } else { + if (searchedChats != null) { + for (ChatUser user in searchedChats!) { + if (user.id == data.first.currentUserId) { + int tempCount = user.unreadMessageCount ?? 0; + user.unreadMessageCount = tempCount + 1; + } } + sort(); } - sort(); } - List list = [ - {"userChatHistoryId": data.first.userChatHistoryId, "TargetUserId": temp.first.targetUserId, "isDelivered": true, "isSeen": isChatScreenActive && data.first.currentUserId == receiverID ? true : false} + List list = [ + { + "userChatHistoryId": data.first.userChatHistoryId, + "TargetUserId": temp.first.targetUserId, + "isDelivered": true, + "isSeen": isChatScreenActive && data.first.currentUserId == receiverID ? true : false + } ]; updateUserChatHistoryOnMsg(list); invokeChatCounter(userId: AppState().chatDetails!.response!.id!); @@ -400,9 +403,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void sort() { searchedChats!.sort( - (ChatUser a, ChatUser b) => b.unreadMessageCount!.compareTo( - a.unreadMessageCount!, - ), + (ChatUser a, ChatUser b) => b.unreadMessageCount!.compareTo(a.unreadMessageCount!), ); } @@ -540,28 +541,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } 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: chatImages.first.profilePicture ?? "", - isImageLoaded: true, - isTyping: false, - isFav: false, - userStatus: userStatus, - userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()), - ), - ); - notifyListeners(); - } if (!isFileSelected && !isMsgReply) { print("Normal Text Msg"); if (message.text == null || message.text.isEmpty) { @@ -621,6 +600,51 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isImageLoaded: true, image: selectedFile.readAsBytesSync()); } + + if (searchedChats != null) { + 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: chatImages.first.profilePicture ?? "", + isImageLoaded: true, + isTyping: false, + isFav: false, + userStatus: userStatus, + userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()), + ), + ); + notifyListeners(); + } + } else { + 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: chatImages.first.profilePicture ?? "", + isImageLoaded: true, + isTyping: false, + isFav: false, + userStatus: userStatus, + userLocalDownlaodedImage: await downloadImageLocal(chatImages.first.profilePicture, targetUserId.toString()), + ), + ); + notifyListeners(); + } } void selectImageToUpload(BuildContext context) { @@ -725,7 +749,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { for (ChatUser user in searchedChats!) { if (user.id == favoriteChatUser.response!.targetUserId!) { user.isFav = favoriteChatUser.response!.isFav; - favUsersList.add(user); + dynamic contain = favUsersList!.where((ChatUser element) => element.id == favoriteChatUser.response!.targetUserId!); + if (contain.isEmpty) { + favUsersList.add(user); + } } } } @@ -764,6 +791,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void clearAll() { + print("----------------- Disposed ---------------------------"); searchedChats = pChatHistory; search.clear(); isChatScreenActive = false; @@ -775,6 +803,37 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { sFileType = ""; } + void disposeData() { + search.clear(); + isChatScreenActive = false; + receiverID = 0; + paginationVal = 0; + message.text = ''; + isFileSelected = false; + repliedMsg = []; + sFileType = ""; + deleteData(); + favUsersList.clear(); + searchedChats!.clear(); + pChatHistory!.clear(); + chatHubConnection.stop(); + AppState().chatDetails = null; + } + + void deleteData() { + 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!) { + deleteFile(element.id.toString()); + } + } + void getUserImages() async { List emails = []; List exists = [], unique = []; @@ -885,4 +944,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await chatHubConnection.invoke("GetChatCounversationCount", args: [userId]); return ""; } + + void userTypingInvoke({required int currentUser, required int reciptUser}) async { + logger.d([reciptUser, currentUser]); + await chatHubConnection.invoke("UserTypingAsync", args: [reciptUser, currentUser]); + } } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 03a41e4..8978ff1 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -123,6 +123,7 @@ class ChatBubble extends StatelessWidget { 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().expanded, + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) const Icon(Icons.remove_red_eye, size: 16) ], ), Align( @@ -217,11 +218,9 @@ class ChatBubble extends StatelessWidget { 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, - ), + 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).expanded, + if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2) const Icon(Icons.remove_red_eye, color: Colors.white, size: 16) ], ), Align( diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 5cad3fa..379fe2b 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -233,6 +233,9 @@ class _ChatDetailScreenState extends State { ), ).paddingOnly(right: 21), ), + onChanged: (val) { + m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!); + }, ), ], )); diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 330242a..af243e5 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -47,6 +47,7 @@ class _ChatHomeState extends State { return; } if (data.searchedChats == null || data.searchedChats!.isEmpty) { + data.isLoading = true; data.getUserRecentChats(); } } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index b1dac53..22768e6 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -200,7 +200,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/landing/widget/app_drawer.dart b/lib/ui/landing/widget/app_drawer.dart index 4160fde..4b4219d 100644 --- a/lib/ui/landing/widget/app_drawer.dart +++ b/lib/ui/landing/widget/app_drawer.dart @@ -11,6 +11,7 @@ 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/dashboard/drawer_menu_item_model.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/ui/dialogs/id/business_card_dialog.dart'; import 'package:mohem_flutter_app/ui/dialogs/id/employee_digital_id_dialog.dart'; @@ -28,6 +29,13 @@ class AppDrawer extends StatefulWidget { class _AppDrawerState extends State { List drawerMenuItemList = []; + late ChatProviderModel chatData; + + @override + void initState() { + super.initState(); + chatData = Provider.of(context, listen: false); + } @override Widget build(BuildContext context) { @@ -171,6 +179,7 @@ class _AppDrawerState extends State { AppState().isAuthenticated = false; AppState().isLogged = false; AppState().setPostParamsInitConfig(); + chatData.disposeData(); // SharedPreferences prefs = await SharedPreferences.getInstance(); // await prefs.clear(); Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: null); diff --git a/lib/ui/leave_balance/leave_balance_screen.dart b/lib/ui/leave_balance/leave_balance_screen.dart index d1a64c6..8c346bc 100644 --- a/lib/ui/leave_balance/leave_balance_screen.dart +++ b/lib/ui/leave_balance/leave_balance_screen.dart @@ -43,9 +43,9 @@ class _LeaveBalanceState extends State { void getAbsenceTransactions() async { try { - // Utils.showLoading(context); + Utils.showLoading(context); absenceTransList = await LeaveBalanceApiClient().getAbsenceTransactions(-999, empID: selectedEmp); - //Utils.hideLoading(context); + Utils.hideLoading(context); setState(() {}); } catch (ex) { Utils.hideLoading(context); diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index a0ab3c9..04c3077 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -58,9 +58,9 @@ class _LoginScreenState extends State { void initState() { super.initState(); // checkFirebaseToken(); - if (kReleaseMode) { - checkDeviceSafety(); - } + // if (kReleaseMode) { + // checkDeviceSafety(); + // } } void checkDeviceSafety() async { diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index c5b1cd7..bde62aa 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -6,6 +6,7 @@ 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/consts.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'; @@ -30,6 +31,11 @@ class MarathonProvider extends ChangeNotifier { String? selectedOptionId; int? totalQualifiers; + //TODO: THIS BUG NEEDS TO BE FIXED. NOT DONE YET + String? gapTimeImage; + String? gapTimeText; + int? gapTimeType; + bool iAmWinner = false; bool isPrivilegedWithMarathon = false; @@ -99,8 +105,7 @@ class MarathonProvider extends ChangeNotifier { late VideoPlayerController videoController; Future initializeVideoPlayer() async { - // videoController = VideoPlayerController.network(marathonDetailModel.sponsors!.first.video!)..initialize(); - videoController = VideoPlayerController.network("http://clips.vorwaerts-gmbh.de/VfE_html5.mp4"); + videoController = VideoPlayerController.network(ApiConsts.marathonBaseUrlServices + marathonDetailModel.sponsors!.first.video!); await videoController.initialize(); await videoController.play(); await videoController.setVolume(1.0); @@ -178,16 +183,21 @@ class MarathonProvider extends ChangeNotifier { updateCardStatusToAnswer(); - await callSubmitOptionApi().then((bool value) async { - if (value) { - await callNextQuestionApi(); - } + scheduleMicrotask(() async { + await callSubmitOptionApi().then((bool value) async { + if (value) { + await callNextQuestionApi(); + } + }); }); } if (totalCurrentQuestionTime == 0) { + gapTimeImage = currentQuestion.gapImage; + gapTimeText = currentQuestion.gapText; + gapTimeType = currentQuestion.gapType; updateCardData(); - if (currentQuestionNumber == marathonDetailModel.totalQuestions! ) { + if (currentQuestionNumber - 1 == marathonDetailModel.totalQuestions!) { callGetQualifiersApi(); updateQuestionCardStatus(QuestionCardStatus.findingWinner); timer.cancel(); @@ -254,13 +264,14 @@ class MarathonProvider extends ChangeNotifier { 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 - // TODO: Verify the callings!!! Future callNextQuestionApi() async { if (currentQuestionNumber < marathonDetailModel.totalQuestions!) { if (currentQuestionNumber == 0) { Utils.showLoading(AppRoutes.navigatorKey.currentContext!); currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!))!; + gapTimeImage = currentQuestion.gapImage; + gapTimeText = currentQuestion.gapText; + gapTimeType = currentQuestion.gapType; if (Utils.isLoading) { Utils.hideLoading(AppRoutes.navigatorKey.currentContext!); } @@ -281,6 +292,7 @@ class MarathonProvider extends ChangeNotifier { } selectedOptionIndex = null; currentQuestionNumber++; + cardContentList.add(const CardContent()); totalCurrentQuestionTime = currentQuestion.questionTime! + currentQuestion.nextQuestGap!; currentGapTime = currentQuestion.nextQuestGap!; @@ -291,7 +303,7 @@ class MarathonProvider extends ChangeNotifier { void populateQuestionStatusesList() { if (marathonDetailModel.totalQuestions != null) { - for (int i = 0; i < marathonDetailModel.totalQuestions! - 1; i++) { + for (int i = 0; i < marathonDetailModel.totalQuestions!; i++) { answerStatusesList.add(QuestionCardStatus.question); } notifyListeners(); @@ -378,6 +390,7 @@ class MarathonProvider extends ChangeNotifier { } bool checkIfPrivilegedForMarathon() { + return true; for (PrivilegeListModel element in AppState().privilegeListModel!) { if (element.serviceName == "Marathon") { if (element.previlege != null) { @@ -420,9 +433,6 @@ class MarathonProvider extends ChangeNotifier { Navigator.pushReplacementNamed(context, AppRoutes.marathonWaitingScreen); } } catch (e) { - if (kDebugMode) { - print("error in onJoinMarathonPressed: ${e.toString()}"); - } 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 71ae3d6..c032823 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -6,6 +6,7 @@ import 'package:flutter_svg/svg.dart'; import 'package:lottie/lottie.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/consts.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/classes/lottie_consts.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -21,6 +22,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/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:provider/provider.dart'; @@ -43,24 +45,13 @@ 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: Stack( - children: [ + children: [ Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -80,7 +71,7 @@ class MarathonScreen extends StatelessWidget { ), ), 16.height, - !provider.iAmWinner + provider.iAmWinner ? Column( children: [ (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22( @@ -103,7 +94,7 @@ class MarathonScreen extends StatelessWidget { itemBuilder: (BuildContext context, int index) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ (AppState().isArabic(context) ? provider.selectedWinners![index].nameEn : provider.selectedWinners![index].nameEn)!.toText16( color: MyColors.grey3AColor, ), @@ -127,10 +118,10 @@ class MarathonScreen extends StatelessWidget { ), 5.height, Image.network( - provider.marathonDetailModel.sponsors!.first.image!, - height: 40, + ApiConsts.marathonBaseUrlServices + provider.marathonDetailModel.sponsors!.first.image!, + height: 50, width: 150, - fit: BoxFit.fill, + fit: BoxFit.contain, errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return const Center(); }, @@ -207,57 +198,74 @@ class MarathonScreen extends StatelessWidget { } }, ), - body: SingleChildScrollView( - child: Column( - children: [ - 20.height, - if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...[ - QualifiersContainer(provider: provider).paddingOnly(left: 21, right: 21), - ] else if (provider.questionCardStatus == QuestionCardStatus.winnerFound) - ...[] - else ...[ - MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21), - ], - if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...[ - getNameContainer(context), + body: Column( + children: [ + ListView( + children: [ + 20.height, + if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...[ + QualifiersContainer(provider: provider).paddingOnly(left: 21, right: 21), + ] else if (provider.questionCardStatus == QuestionCardStatus.winnerFound) + ...[] + else ...[ + MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21), + ], + if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...[ + getNameContainer(context), + ], + QuestionCardBuilder( + onQuestion: (BuildContext context) => const QuestionCard(), + onCompleted: (BuildContext context) => CustomStatusWidget( + asset: Lottie.asset(MyLottieConsts.allQuestions, height: 200), + title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor), + subTitle: LocaleKeys.allQuestionsCorrect.toText18(color: MyColors.darkTextColor, isCentered: true), + ), + onCorrectAnswer: (BuildContext context) => CustomStatusWidget( + asset: getSuccessWidget(gapType: provider.gapTimeType, gapImage: provider.gapTimeImage, gapText: provider.gapTimeText), + title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor), + subTitle: LocaleKeys.yourAnswerCorrect.tr().toText18(color: MyColors.darkTextColor, isCentered: true), + ), + onWinner: (BuildContext context) => getWinnerWidget(context, provider: provider), + onWrongAnswer: (BuildContext context) => CustomStatusWidget( + asset: Image.asset(MyLottieConsts.wrongAnswerGif, height: 200), + title: LocaleKeys.oops.tr().toText22(color: MyColors.redColor), + subTitle: LocaleKeys.wrongAnswer.tr().toText18(color: MyColors.darkTextColor, isCentered: true), + ), + onSkippedAnswer: (BuildContext context) => CustomStatusWidget( + asset: Image.asset(MyLottieConsts.wrongAnswerGif, height: 200), + title: LocaleKeys.oops.tr().toText22(color: MyColors.redColor), + subTitle: LocaleKeys.youMissedTheQuestion.tr().toText18(color: MyColors.darkTextColor, isCentered: true), + ), + onFindingWinner: (BuildContext context) => CustomStatusWidget( + asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168), + title: LocaleKeys.fingersCrossed.tr().toText22(color: MyColors.greenColor), + subTitle: LocaleKeys.winnerSelectedRandomly.tr().toText18(color: MyColors.darkTextColor, isCentered: true), + ), + questionCardStatus: provider.questionCardStatus, + ).paddingOnly(top: 12, left: 21, right: 21), ], - QuestionCardBuilder( - onQuestion: (BuildContext context) => const QuestionCard(), - onCompleted: (BuildContext context) => CustomStatusWidget( - asset: Lottie.asset(MyLottieConsts.allQuestions, height: 200), - title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor), - subTitle: LocaleKeys.allQuestionsCorrect.toText18(color: MyColors.darkTextColor, isCentered: true), - ), - onCorrectAnswer: (BuildContext context) => CustomStatusWidget( - asset: getSuccessWidget(gapType: provider.currentQuestion.gapType, gapImage: provider.currentQuestion.gapImage, gapText: provider.currentQuestion.gapText), - title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor), - subTitle: LocaleKeys.yourAnswerCorrect.toText18(color: MyColors.darkTextColor, isCentered: true), - ), - onWinner: (BuildContext context) => getWinnerWidget(context, provider: provider), - onWrongAnswer: (BuildContext context) => CustomStatusWidget( - asset: Image.asset(MyLottieConsts.wrongAnswerGif, height: 200), - title: LocaleKeys.oops.tr().toText22(color: MyColors.redColor), - subTitle: LocaleKeys.wrongAnswer.tr().toText18(color: MyColors.darkTextColor, isCentered: true), - ), - onSkippedAnswer: (BuildContext context) => CustomStatusWidget( - asset: Image.asset(MyLottieConsts.wrongAnswerGif, height: 200), - title: LocaleKeys.oops.tr().toText22(color: MyColors.redColor), - subTitle: LocaleKeys.youMissedTheQuestion.tr().toText18(color: MyColors.darkTextColor, isCentered: true), - ), - onFindingWinner: (BuildContext context) => CustomStatusWidget( - asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168), - title: LocaleKeys.fingersCrossed.tr().toText22(color: MyColors.greenColor), - subTitle: LocaleKeys.winnerSelectedRandomly.tr().toText18(color: MyColors.darkTextColor, isCentered: true), - ), - questionCardStatus: provider.questionCardStatus, - ).paddingOnly(top: 12, left: 21, right: 21), - ], - ), + ).expanded, + provider.questionCardStatus == QuestionCardStatus.winnerFound + ? DefaultButton(LocaleKeys.ok.tr(), () { + provider.resetValues(); + Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard)); + }).insideContainer + : const SizedBox() + ], ), ), onWillPop: () { - provider.resetValues(); - return Future.value(true); + 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); }, ); } diff --git a/lib/ui/marathon/marathon_sponsor_video_screen.dart b/lib/ui/marathon/marathon_sponsor_video_screen.dart index 12d5949..88c66f9 100644 --- a/lib/ui/marathon/marathon_sponsor_video_screen.dart +++ b/lib/ui/marathon/marathon_sponsor_video_screen.dart @@ -15,9 +15,6 @@ import 'package:video_player/video_player.dart'; class SponsorVideoScreen extends StatelessWidget { const SponsorVideoScreen({Key? key}) : super(key: key); - Future onSponsorVideoClosed(BuildContext context) async { - Navigator.pop(context); - } @override Widget build(BuildContext context) { diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index 0487c74..1b5533b 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -184,200 +184,202 @@ class MarathonBanner extends StatelessWidget { 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, - ), + 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, ), - 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: [ + 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, ), ), - ) - : Positioned( - left: -20, - top: -10, - child: Transform.rotate( - angle: 15, - child: Container( - width: isTablet ? 70 : 65, - height: isTablet ? 40 : 32, - color: MyColors.darkDigitColor, + 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, ), ), - ), - 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: [ - 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, - ) - ], - ), + 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, + ) + ], + ), + ), + ), + ], + ), + ), + 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), - !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; + ), + ).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), + ), + ], + ).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(); + 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(); } } diff --git a/lib/ui/marathon/widgets/marathon_details_card.dart b/lib/ui/marathon/widgets/marathon_details_card.dart index b74b78b..e8b37a0 100644 --- a/lib/ui/marathon/widgets/marathon_details_card.dart +++ b/lib/ui/marathon/widgets/marathon_details_card.dart @@ -1,16 +1,14 @@ - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; - - class MarathonDetailsCard extends StatelessWidget { final MarathonProvider provider; @@ -38,16 +36,16 @@ class MarathonDetailsCard extends StatelessWidget { ) ], ), - if (provider.itsMarathonTime && provider.marathonDetailModel.sponsors != null) ...[ + if (provider.marathonDetailModel.sponsors != null) ...[ 5.height, provider.marathonDetailModel.sponsors?.first.sponsorPrizes != null ? Row( - children: [ - "${LocaleKeys.prize.tr()} ".toText16(color: MyColors.grey77Color, isBold: true), - "${AppState().isArabic(context) ? provider.marathonDetailModel.sponsors?.first.sponsorPrizes?.first.marathonPrizeAr : provider.marathonDetailModel.sponsors?.first.sponsorPrizes?.first.marathonPrizeAr}" - .toText16(color: MyColors.greenColor, isBold: true), - ], - ) + children: [ + "${LocaleKeys.prize.tr()} ".toText16(color: MyColors.grey77Color, isBold: true), + "${AppState().isArabic(context) ? provider.marathonDetailModel.sponsors?.first.sponsorPrizes?.first.marathonPrizeAr : provider.marathonDetailModel.sponsors?.first.sponsorPrizes?.first.marathonPrizeAr}" + .toText16(color: MyColors.greenColor, isBold: true), + ], + ) : const SizedBox(), Row( children: [ @@ -61,10 +59,10 @@ class MarathonDetailsCard extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Image.network( - provider.marathonDetailModel.sponsors!.first.image!, - height: 40, + ApiConsts.marathonBaseUrlServices + provider.marathonDetailModel.sponsors!.first.image!, + height: 50, width: 150, - fit: BoxFit.fill, + fit: BoxFit.contain, errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return const Center(); }, @@ -79,4 +77,3 @@ class MarathonDetailsCard extends StatelessWidget { ); } } - diff --git a/lib/ui/marathon/widgets/marathon_footer.dart b/lib/ui/marathon/widgets/marathon_footer.dart index b5083c0..fea076e 100644 --- a/lib/ui/marathon/widgets/marathon_footer.dart +++ b/lib/ui/marathon/widgets/marathon_footer.dart @@ -47,20 +47,3 @@ class MarathonFooter extends StatelessWidget { ).insideContainer; } } - -//Container( -// color: Colors.white, -// child: Column( -// mainAxisSize: MainAxisSize.min, -// children: [ -// buildNoteForDemo(), -// DefaultButton( -// LocaleKeys.joinDemoMarathon.tr(), -// () { -// provider.connectSignalrAndJoinMarathon(context); -// }, -// color: MyColors.yellowColorII, -// ).insideContainer, -// ], -// ), -// ); diff --git a/lib/ui/marathon/widgets/marathon_progress_container.dart b/lib/ui/marathon/widgets/marathon_progress_container.dart index c0dae6c..5015f25 100644 --- a/lib/ui/marathon/widgets/marathon_progress_container.dart +++ b/lib/ui/marathon/widgets/marathon_progress_container.dart @@ -43,7 +43,8 @@ class MarathonProgressContainer extends StatelessWidget { 8.height, Row( children: [ - "${((provider.currentQuestionNumber / provider.marathonDetailModel.totalQuestions!) * 100).toInt()}% ${LocaleKeys.completed.tr()}".toText14(), + "${provider.currentQuestionNumber == 1 ? 0 : (((provider.currentQuestionNumber - 1) / provider.marathonDetailModel.totalQuestions!) * 100).toInt()}% ${LocaleKeys.completed.tr()}" + .toText14(), ], ), ], @@ -52,9 +53,6 @@ class MarathonProgressContainer extends StatelessWidget { } Color getStepColor(QuestionCardStatus status, bool isOutOfGame) { - if (isOutOfGame) { - return MyColors.redColor; - } switch (status) { case QuestionCardStatus.question: return MyColors.yellowColorII; @@ -79,7 +77,7 @@ class MarathonProgressContainer extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - for (int i = 0; i < totalQuestions - 1; i++) + for (int i = 0; i < totalQuestions; i++) if (value <= i) roundContainer(MyColors.lightGreyDeColor, i != 0) else diff --git a/lib/ui/marathon/widgets/marathon_qualifiers_container.dart b/lib/ui/marathon/widgets/marathon_qualifiers_container.dart index dc9d7e4..7463f37 100644 --- a/lib/ui/marathon/widgets/marathon_qualifiers_container.dart +++ b/lib/ui/marathon/widgets/marathon_qualifiers_container.dart @@ -43,6 +43,7 @@ class _QualifiersContainerState extends State { ), 10.height, Row( + crossAxisAlignment: CrossAxisAlignment.end, children: [ widget.provider.totalQualifiers != null ? widget.provider.totalQualifiers.toString().toText30(color: MyColors.greenColor, isBold: true) : const SizedBox(), 2.width, diff --git a/lib/ui/work_list/item_history_screen.dart b/lib/ui/work_list/item_history_screen.dart index 562b59f..a3c34a9 100644 --- a/lib/ui/work_list/item_history_screen.dart +++ b/lib/ui/work_list/item_history_screen.dart @@ -88,7 +88,8 @@ class _ItemHistoryScreenState extends State { children: [ if (moItemHistoryList.isNotEmpty) loadMoItemHistoryData(), if (poItemHistoryList.isNotEmpty) loadPoItemHistoryData(), - if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData() + if (quotationAnalysisList.isNotEmpty) loadQuotationAnalysisData(), + if (moItemHistoryList.isEmpty && poItemHistoryList.isEmpty && quotationAnalysisList.isEmpty) Utils.getNoDataWidget(context), ], ), ); diff --git a/lib/ui/work_list/worklist_detail_screen.dart b/lib/ui/work_list/worklist_detail_screen.dart index b5129a5..1f62d4e 100644 --- a/lib/ui/work_list/worklist_detail_screen.dart +++ b/lib/ui/work_list/worklist_detail_screen.dart @@ -25,6 +25,7 @@ import 'package:mohem_flutter_app/models/member_information_list_model.dart'; import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/GetRFCEmployeeList.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; +import 'package:mohem_flutter_app/models/worklist/hr/get_address_notification_body_list.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; @@ -78,6 +79,8 @@ class _WorkListDetailScreenState extends State { List? getBasicDetNtfBodyList = []; List? getAbsenceCollectionNotificationBodyList = []; GetContactNotificationBodyList? getContactNotificationBodyList; + List? getAddressNotificationBodyList = []; + GenericResponseModel? getBasicNTFBody; GenericResponseModel? getICBody; @@ -118,6 +121,7 @@ class _WorkListDetailScreenState extends State { getBasicDetNtfBodyList!.clear(); getAbsenceCollectionNotificationBodyList!.clear(); getContactNotificationBodyList = null; + getAddressNotificationBodyList!.clear(); if (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") { getUserInformation(); @@ -139,6 +143,8 @@ class _WorkListDetailScreenState extends State { getAbsenceNotificationBody(); } else if (workListData!.rEQUESTTYPE == "CONTACT") { getContactNotificationBody(); + } else if (workListData!.rEQUESTTYPE == "ADDRESS") { + getAddressNotificationBody(); } // getBasicNTFBody = await WorkListApiClient().getBasicDetNTFBody(workListData!.nOTIFICATIONID!, -999); // getAbsenceCollectionNotifications = await WorkListApiClient().getAbsenceNotificationBody(workListData!.nOTIFICATIONID!, -999); @@ -271,6 +277,7 @@ class _WorkListDetailScreenState extends State { getEitCollectionNotificationBodyList: getEitCollectionNotificationBodyList, getPhonesNotificationBodyList: getPhonesNotificationBodyList, getBasicDetNtfBodyList: getBasicDetNtfBodyList, + getAddressNotificationBodyList: getAddressNotificationBodyList, getAbsenceCollectionNotificationBodyList: getAbsenceCollectionNotificationBodyList, getContactNotificationBodyList: getContactNotificationBodyList, getPrNotificationBodyList: getPrNotificationBody, @@ -429,6 +436,12 @@ class _WorkListDetailScreenState extends State { case "DELEGATE": returnActionImage = "assets/images/delegate.svg"; break; + case "APPROVE": + returnActionImage = "assets/images/worklist/approve.svg"; + break; + case "REJECT": + returnActionImage = "assets/images/worklist/reject.svg"; + break; case "REQUEST_INFO": returnActionImage = "assets/images/request_info.svg"; break; @@ -841,6 +854,23 @@ class _WorkListDetailScreenState extends State { } } + void getAddressNotificationBody() async { + try { + if (apiCallCount == 0) Utils.showLoading(context); + apiCallCount++; + getAddressNotificationBodyList = await WorkListApiClient().getAddressNotificationBodyList(workListData!.nOTIFICATIONID); + apiCallCount--; + if (apiCallCount == 0) { + Utils.hideLoading(context); + setState(() {}); + } + } catch (ex) { + apiCallCount--; + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + void getStampNotificationBody() async { try { if (apiCallCount == 0) Utils.showLoading(context); diff --git a/lib/ui/work_list/worklist_fragments/info_fragments.dart b/lib/ui/work_list/worklist_fragments/info_fragments.dart index 7cf8aa9..d2c64f3 100644 --- a/lib/ui/work_list/worklist_fragments/info_fragments.dart +++ b/lib/ui/work_list/worklist_fragments/info_fragments.dart @@ -13,6 +13,7 @@ import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dar import 'package:mohem_flutter_app/models/get_stamp_ms_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/get_stamp_ns_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/eit_otification_body_model.dart'; +import 'package:mohem_flutter_app/models/worklist/hr/get_address_notification_body_list.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_basic_det_ntf_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_contact_notification_body_list_model.dart'; import 'package:mohem_flutter_app/models/worklist/hr/get_phones_notification_body_list_model.dart'; @@ -31,6 +32,7 @@ class InfoFragment extends StatelessWidget { List? getAbsenceCollectionNotificationBodyList; GetContactNotificationBodyList? getContactNotificationBodyList; GetPrNotificationBodyList? getPrNotificationBodyList; + List? getAddressNotificationBodyList = []; InfoFragment( {this.workListData, @@ -43,7 +45,8 @@ class InfoFragment extends StatelessWidget { this.getBasicDetNtfBodyList, this.getAbsenceCollectionNotificationBodyList, this.getContactNotificationBodyList, - this.getPrNotificationBodyList}); + this.getPrNotificationBodyList, + this.getAddressNotificationBodyList}); double itemHeight = 0; double itemWidth = 0; @@ -89,6 +92,7 @@ class InfoFragment extends StatelessWidget { if (getBasicDetNtfBodyList?.isNotEmpty ?? false) getBasicDetNtfBodyListWidget(getBasicDetNtfBodyList ?? []).objectContainerView(title: "Basic Information"), if (getAbsenceCollectionNotificationBodyList?.isNotEmpty ?? false) getAbsenceCollectionNotificationBodyListWidget(getAbsenceCollectionNotificationBodyList ?? []), if (getContactNotificationBodyList != null) getContactNotificationBodyListWidget(getContactNotificationBodyList ?? GetContactNotificationBodyList()).objectContainerView(), + if (getAddressNotificationBodyList?.isNotEmpty ?? false) getAddressNotificationBodyListWidget(getAddressNotificationBodyList!), ]; return Container( width: double.infinity, @@ -160,7 +164,7 @@ class InfoFragment extends StatelessWidget { ), ItemDetailGrid( ItemDetailViewCol(LocaleKeys.otherCharges.tr(), poHeaderList[index].oTHERCHARGES?.toString() ?? ""), - ItemDetailViewCol(LocaleKeys.totalPOAmountWithVAT.tr(), poHeaderList[index].qUOTATIONDATE ?? ""), + ItemDetailViewCol(LocaleKeys.totalPOAmountWithVAT.tr(), poHeaderList[index].tOTPOAMT.toString() ?? ""), ), ItemDetailGrid( ItemDetailViewCol(LocaleKeys.totalPOAmountInWords.tr(), poHeaderList[index].tOTPOAMTWORD ?? ""), @@ -465,6 +469,36 @@ class InfoFragment extends StatelessWidget { ); } + Widget getAddressNotificationBodyListWidget(List getAddressNotificationBodyList) { + bool isOdd = false; + try { + if (getAddressNotificationBodyList.length % 2 != 0) { + isOdd = true; + getAddressNotificationBodyList.add(GetAddressNotificationBodyList(sEGMENTPROMPT: "--", sEGMENTVALUEDSP: "--")); + } + } catch (e) {} + + return GridView.builder( + itemCount: getAddressNotificationBodyList!.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) => ItemDetailViewGridItem( + index, + getAddressNotificationBodyList[index].sEGMENTPROMPT, + getAddressNotificationBodyList[index].sEGMENTVALUEDSP, + isNeedToShowEmptyDivider: (getAddressNotificationBodyList.length == index + 1) + ? isOdd + ? true + : false + : false, + ), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: (itemWidth / itemHeight), + ), + ).objectContainerView(); + } + List getPRHeaderValues() { List pRHeaders = []; getPrNotificationBodyList!.pRHeader!.forEach((element) { @@ -478,7 +512,7 @@ class InfoFragment extends StatelessWidget { try { if (data.contactNotificationBody!.length % 2 != 0) { isOdd = true; - data.contactNotificationBody!.add(new ContactNotificationBody()); + data.contactNotificationBody!.add(ContactNotificationBody(segmentPrompt: "--", segmentValueDsp: "--")); } } catch (e) {} diff --git a/lib/ui/work_list/worklist_fragments/request_fragment.dart b/lib/ui/work_list/worklist_fragments/request_fragment.dart index b86bb1a..a13f91f 100644 --- a/lib/ui/work_list/worklist_fragments/request_fragment.dart +++ b/lib/ui/work_list/worklist_fragments/request_fragment.dart @@ -58,10 +58,10 @@ class RequestFragment extends StatelessWidget { children: [ ItemDetailGrid( ItemDetailViewCol(LocaleKeys.code.tr(), poLinesList[index].iTEMCODE ?? ""), - ItemDetailViewCol(LocaleKeys.mfg.tr(), poLinesList[index].uOM ?? ""), + ItemDetailViewCol(LocaleKeys.mfg.tr(), poLinesList[index].mFG ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.lineType.tr(), poLinesList[index].qUANTITY?.toString() ?? ""), + ItemDetailViewCol(LocaleKeys.lineType.tr(), poLinesList[index].lINETYPE?.toString() ?? ""), ItemDetailViewCol(LocaleKeys.unit.tr(), poLinesList[index].uOM ?? ""), ), ItemDetailGrid( @@ -78,10 +78,10 @@ class RequestFragment extends StatelessWidget { ), ItemDetailGrid( ItemDetailViewCol(LocaleKeys.deliverToLocation.tr(), poLinesList[index].dELIVERTOLOCATION ?? ""), - ItemDetailViewCol(LocaleKeys.requisitionNumber.tr(), poLinesList[index].rEQUESTOR ?? ""), + ItemDetailViewCol(LocaleKeys.requisitionNumber.tr(), poLinesList[index].pRNUM ?? ""), ), ItemDetailGrid( - ItemDetailViewCol(LocaleKeys.requester.tr(), poLinesList[index].pRNUM ?? ""), + ItemDetailViewCol(LocaleKeys.requester.tr(), poLinesList[index].rEQUESTOR ?? ""), Container(), ), 12.height, diff --git a/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart b/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart index 299ef7a..ec4146b 100644 --- a/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart +++ b/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart @@ -68,11 +68,7 @@ class DynamicTextFieldWidget extends StatelessWidget { enabled: isEnable, scrollPadding: EdgeInsets.zero, readOnly: isReadOnly, - keyboardType: (isInputTypeNum) - ? isInputTypeNumSigned - ? const TextInputType.numberWithOptions(signed: true) - : TextInputType.number - : TextInputType.text, + keyboardType: (isInputTypeNum) ? (isInputTypeNumSigned ? const TextInputType.numberWithOptions(signed: true, decimal: true) : TextInputType.numberWithOptions(signed: true, decimal: true)) : TextInputType.text, textInputAction: TextInputAction.done, //controller: controller, maxLines: lines, diff --git a/lib/widgets/location/Location.dart b/lib/widgets/location/Location.dart index 0ddca1c..d407c1c 100644 --- a/lib/widgets/location/Location.dart +++ b/lib/widgets/location/Location.dart @@ -46,12 +46,12 @@ class Location { }); } - static void getCurrentLocation(Function(LatLng?) callback, BuildContext context) { + static void getCurrentLocation(Function(LatLng?, bool isMocked) callback, BuildContext context) { void done(Position position) { //AppStorage.sp.saveLocation(position); - + bool isMocked = position.isMocked; LatLng? myCurrentLocation = LatLng(position.latitude, position.longitude); - callback(myCurrentLocation); + callback(myCurrentLocation, isMocked); } AppPermissions.location((granted) { diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 9840700..cbf70ad 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -94,8 +94,12 @@ class _MarkAttendanceWidgetState extends State { // if (isNfcEnabled) attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () { if (isNfcLocationEnabled) { - Location.getCurrentLocation((LatLng? latlng) { - performNfcAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + Location.getCurrentLocation((LatLng? latlng, bool isMocked) { + if (isMocked) { + markFakeAttendance("NFC", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? ""); + } else { + performNfcAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + } }, context); } else { performNfcAttendance(widget.model); @@ -104,8 +108,12 @@ class _MarkAttendanceWidgetState extends State { if (isWifiEnabled) attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () { if (isWifiLocationEnabled) { - Location.getCurrentLocation((LatLng? latlng) { - performWifiAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + Location.getCurrentLocation((LatLng? latlng, bool isMocked) { + if (isMocked) { + markFakeAttendance("WIFI", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? ""); + } else { + performWifiAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + } }, context); } else { performWifiAttendance(widget.model); @@ -115,8 +123,12 @@ class _MarkAttendanceWidgetState extends State { if (isQrEnabled) attendanceMethod("QR", "assets/images/ic_qr.svg", isQrEnabled, () async { if (isQrLocationEnabled) { - Location.getCurrentLocation((LatLng? latlng) { - performQrCodeAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + Location.getCurrentLocation((LatLng? latlng, bool isMocked) { + if (isMocked) { + markFakeAttendance("QR", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? ""); + } else { + performQrCodeAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? ""); + } }, context); } else { performQrCodeAttendance(widget.model); @@ -136,7 +148,7 @@ class _MarkAttendanceWidgetState extends State { Utils.showLoading(context); try { GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId, isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); - if(g?.messageStatus != 1) { + if (g?.messageStatus != 1) { Utils.hideLoading(context); showDialog( context: context, @@ -157,7 +169,6 @@ class _MarkAttendanceWidgetState extends State { child: SuccessDialog(widget.isFromDashboard), ); } - } catch (ex) { print(ex); Utils.hideLoading(context); @@ -171,7 +182,7 @@ class _MarkAttendanceWidgetState extends State { Utils.showLoading(context); try { GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng); - if(g?.messageStatus != 1) { + if (g?.messageStatus != 1) { Utils.hideLoading(context); showDialog( context: context, @@ -276,6 +287,21 @@ class _MarkAttendanceWidgetState extends State { } } + void markFakeAttendance(String sourceName, String lat, String long) async { + Utils.showLoading(context); + try { + await DashboardApiClient().markFakeLocation(sourceName: sourceName, lat: lat, long: long); + Utils.hideLoading(context); + Utils.confirmDialog(context, LocaleKeys.fakeLocation.tr()); + } catch (ex) { + print(ex); + Utils.hideLoading(context); + Utils.handleException(ex, context, (msg) { + Utils.confirmDialog(context, msg); + }); + } + } + Widget attendanceMethod(String title, String image, bool isEnabled, VoidCallback onPress) => Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15),