merge-requests/105/head
Sultan khan 3 years ago
commit 5384d0e59c

@ -11,6 +11,7 @@
<application <application
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="Mohemm" android:label="Mohemm"
android:allowBackup="false"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"> android:roundIcon="@mipmap/ic_launcher_round">
<activity <activity

@ -424,6 +424,9 @@
"typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه",
"currentPassword": "كلمة المرور الحاليه", "currentPassword": "كلمة المرور الحاليه",
"concurrentReports": "التقارير المتزامنه", "concurrentReports": "التقارير المتزامنه",
"EnterNewAddressMoved" : "أدخل عنوان جديد إذا كنت قد انتقلت",
"CorrectAddress": "تصحيح أو تعديل هذا العنوان",
"SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.",
"profile": { "profile": {
"reset_password": { "reset_password": {
"label": "Reset Password", "label": "Reset Password",
@ -509,5 +512,6 @@
"youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.",
"ourSponsor": "راعينا:", "ourSponsor": "راعينا:",
"startingIn": "يبدأ في", "startingIn": "يبدأ في",
"youAreOutOfContest": "أنت خارج المسابقة." "youAreOutOfContest": "أنت خارج المسابقة.",
"winners": "الفائزين!!!"
} }

@ -424,6 +424,9 @@
"typeCurrentPasswordBelow": "Type Your Current password below", "typeCurrentPasswordBelow": "Type Your Current password below",
"currentPassword": "Current password", "currentPassword": "Current password",
"concurrentReports": "Concurrent Reports", "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": { "profile": {
"reset_password": { "reset_password": {
"label": "Reset Password", "label": "Reset Password",
@ -509,6 +512,7 @@
"youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.", "youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.",
"ourSponsor": "Our Sponsor:", "ourSponsor": "Our Sponsor:",
"startingIn": "Starting in", "startingIn": "Starting in",
"youAreOutOfContest": "You are out of the contest." "youAreOutOfContest": "You are out of the contest.",
"winners": "WINNERS!!!"
} }

@ -69,6 +69,10 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>TAG</string>
</array>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key> <key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array> <array>
<string>0000</string> <string>0000</string>

@ -2,11 +2,11 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:mohem_flutter_app/api/api_client.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/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/consts.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/exceptions/api_exception.dart';
import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart'; import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart';
@ -29,6 +29,9 @@ class ChatApiClient {
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
}, },
); );
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
user.UserAutoLoginModel userLoginResponse = user.userAutoLoginModelFromJson(response.body); user.UserAutoLoginModel userLoginResponse = user.userAutoLoginModelFromJson(response.body);
return userLoginResponse; return userLoginResponse;
} }
@ -38,10 +41,11 @@ class ChatApiClient {
"${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync/$sName/$cUserId", "${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync/$sName/$cUserId",
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
return searchUserJsonModel(response.body); if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return List<ChatUser>.from(json.decode(response.body).map((x) => ChatUser.fromJson(x)));
} }
List<ChatUser> searchUserJsonModel(String str) => List<ChatUser>.from(json.decode(str).map((x) => ChatUser.fromJson(x)));
Future<ChatUserModel> getRecentChats() async { Future<ChatUserModel> getRecentChats() async {
try { try {
@ -49,22 +53,24 @@ class ChatApiClient {
"${ApiConsts.chatRecentUrl}getchathistorybyuserid", "${ApiConsts.chatRecentUrl}getchathistorybyuserid",
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return ChatUserModel.fromJson( return ChatUserModel.fromJson(
json.decode(response.body), json.decode(response.body),
); );
} catch (e) { } catch (e) {
e as APIException; // if (e.message == "api_common_unauthorized") {
if (e.message == "api_common_unauthorized") { // user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken();
user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); // if (userLoginResponse.response != null) {
if (userLoginResponse.response != null) { // AppState().setchatUserDetails = userLoginResponse;
AppState().setchatUserDetails = userLoginResponse; // getRecentChats();
getRecentChats(); // } else {
} else { // Utils.showToast(
Utils.showToast( // userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr",
userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr", // );
); // }
} // }
}
throw e; throw e;
} }
} }
@ -74,9 +80,10 @@ class ChatApiClient {
"${ApiConsts.chatFavUser}getFavUserById/${AppState().chatDetails!.response!.id}", "${ApiConsts.chatFavUser}getFavUserById/${AppState().chatDetails!.response!.id}",
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
return ChatUserModel.fromJson( if (!kReleaseMode) {
json.decode(favRes.body), logger.i("res: " + favRes.body);
); }
return ChatUserModel.fromJson(json.decode(favRes.body));
} }
Future<Response> getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false, required int paginationVal}) async { Future<Response> 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", "${ApiConsts.chatSingleUserHistoryUrl}GetUserChatHistory/$senderUID/$receiverUID/$paginationVal",
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return response; return response;
} catch (e) { } catch (e) {
e as APIException; // e as APIException;
if (e.message == "api_common_unauthorized") { // if (e.message == "api_common_unauthorized") {
user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); // user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken();
if (userLoginResponse.response != null) { // if (userLoginResponse.response != null) {
AppState().setchatUserDetails = userLoginResponse; // AppState().setchatUserDetails = userLoginResponse;
getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal); // getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal);
} else { // } else {
Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); // Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr");
} // }
} // }
throw e; throw e;
} }
} }
Future<fav.FavoriteChatUser> favUser({required int userID, required int targetUserID}) async { Future<fav.FavoriteChatUser> 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); 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); fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
return favoriteChatUser; return favoriteChatUser;
} }
@ -114,20 +127,23 @@ class ChatApiClient {
{"targetUserId": targetUserID, "userId": userID}, {"targetUserId": targetUserID, "userId": userID},
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body); fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
return favoriteChatUser; return favoriteChatUser;
} catch (e) { } catch (e) {
e as APIException; e as APIException;
if (e.message == "api_common_unauthorized") { // if (e.message == "api_common_unauthorized") {
logger.d("Token Generated On APIIIIII"); // user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken();
user.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); // if (userLoginResponse.response != null) {
if (userLoginResponse.response != null) { // AppState().setchatUserDetails = userLoginResponse;
AppState().setchatUserDetails = userLoginResponse; // unFavUser(userID: userID, targetUserID: targetUserID);
unFavUser(userID: userID, targetUserID: targetUserID); // } else {
} else { // Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr");
Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr"); // }
} // }
}
throw e; throw e;
} }
} }
@ -138,6 +154,7 @@ class ChatApiClient {
request.files.add(await MultipartFile.fromPath('files', file.path)); request.files.add(await MultipartFile.fromPath('files', file.path));
request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'}); request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'});
StreamedResponse response = await request.send(); StreamedResponse response = await request.send();
if (!kReleaseMode) {}
return response; return response;
} }
@ -159,6 +176,9 @@ class ChatApiClient {
{"encryptedEmails": encryptedEmails, "fromClient": false}, {"encryptedEmails": encryptedEmails, "fromClient": false},
token: AppState().chatDetails!.response!.token, token: AppState().chatDetails!.response!.token,
); );
if (!kReleaseMode) {
logger.i("res: " + response.body);
}
return chatUserImageModelFromJson(response.body); return chatUserImageModelFromJson(response.body);
} }
} }

@ -65,10 +65,13 @@ class DashboardApiClient {
}, url, postParams); }, url, postParams);
} }
Future<List<GetAccrualBalancesList>> getAccrualBalances(String effectiveDate) async { Future<List<GetAccrualBalancesList>> getAccrualBalances(String effectiveDate, {String? empID}) async {
String url = "${ApiConsts.erpRest}GET_ACCRUAL_BALANCES"; String url = "${ApiConsts.erpRest}GET_ACCRUAL_BALANCES";
Map<String, dynamic> postParams = {"P_EFFECTIVE_DATE": effectiveDate}; Map<String, dynamic> postParams = {"P_EFFECTIVE_DATE": effectiveDate};
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
if (empID != null && empID.isNotEmpty) {
postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID;
}
return await ApiClient().postJsonForObject((json) { return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json); GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData.getAccrualBalancesList ?? []; return responseData.getAccrualBalancesList ?? [];
@ -180,12 +183,7 @@ class DashboardApiClient {
}, url, postParams); }, url, postParams);
} }
Future<ChatUnreadCovnCountModel> getChatCount() async {
Response response = await ApiClient().getJsonForResponse(
"${ApiConsts.chatLoginTokenUrl}unreadconversationcount/${AppState().getUserName}",
);
return chatUnreadCovnCountModelFromJson(response.body);
}
// Future setAdvertisementViewed(String masterID, int advertisementId) async { // Future setAdvertisementViewed(String masterID, int advertisementId) async {
// String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed"; // String url = "${ApiConsts.cocRest}Mohemm_ITG_UpdateAdvertisementAsViewed";

@ -17,27 +17,33 @@ class LeaveBalanceApiClient {
factory LeaveBalanceApiClient() => _instance; factory LeaveBalanceApiClient() => _instance;
Future<List<GetAbsenceTransactionList>> getAbsenceTransactions(int pSelectedResopID) async { Future<List<GetAbsenceTransactionList>> getAbsenceTransactions(int pSelectedResopID, {String? empID}) async {
String url = "${ApiConsts.erpRest}GET_ABSENCE_TRANSACTIONS"; String url = "${ApiConsts.erpRest}GET_ABSENCE_TRANSACTIONS";
Map<String, dynamic> postParams = {"P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1, "P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": pSelectedResopID}; Map<String, dynamic> postParams = {"P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1, "P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": pSelectedResopID};
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
if (empID!.isNotEmpty) {
postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID;
}
return await ApiClient().postJsonForObject((json) { return await ApiClient().postJsonForObject((json) {
GenericResponseModel? responseData = GenericResponseModel.fromJson(json); GenericResponseModel? responseData = GenericResponseModel.fromJson(json);
return responseData.getAbsenceTransactionList ?? []; return responseData.getAbsenceTransactionList ?? [];
}, url, postParams); }, url, postParams);
} }
Future<List<GetAbsenceAttendanceTypesList>> getAbsenceAttendanceTypes() async { Future<List<GetAbsenceAttendanceTypesList>> getAbsenceAttendanceTypes({String? empID}) async {
String url = "${ApiConsts.erpRest}GET_ABSENCE_ATTENDANCE_TYPES"; String url = "${ApiConsts.erpRest}GET_ABSENCE_ATTENDANCE_TYPES";
Map<String, dynamic> postParams = {}; Map<String, dynamic> postParams = {};
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
if (empID!.isNotEmpty) {
postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID;
}
return await ApiClient().postJsonForObject((json) { return await ApiClient().postJsonForObject((json) {
GenericResponseModel? responseData = GenericResponseModel.fromJson(json); GenericResponseModel? responseData = GenericResponseModel.fromJson(json);
return responseData.getAbsenceAttendanceTypesList ?? []; return responseData.getAbsenceAttendanceTypesList ?? [];
}, url, postParams); }, url, postParams);
} }
Future<CalculateAbsenceDuration> calculateAbsenceDuration(int pAbsenceAttendanceTypeID, String pDateStart, String pDateEnd, int pSelectedResopID) async { Future<CalculateAbsenceDuration> calculateAbsenceDuration(int pAbsenceAttendanceTypeID, String pDateStart, String pDateEnd, int pSelectedResopID, {String? empID}) async {
String url = "${ApiConsts.erpRest}CALCULATE_ABSENCE_DURATION"; String url = "${ApiConsts.erpRest}CALCULATE_ABSENCE_DURATION";
Map<String, dynamic> postParams = { Map<String, dynamic> postParams = {
"P_ABSENCE_ATTENDANCE_TYPE_ID": pAbsenceAttendanceTypeID, "P_ABSENCE_ATTENDANCE_TYPE_ID": pAbsenceAttendanceTypeID,
@ -49,16 +55,22 @@ class LeaveBalanceApiClient {
"P_TIME_START": null, "P_TIME_START": null,
}; };
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
if (empID!.isNotEmpty) {
postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID;
}
return await ApiClient().postJsonForObject((json) { return await ApiClient().postJsonForObject((json) {
GenericResponseModel? responseData = GenericResponseModel.fromJson(json); GenericResponseModel? responseData = GenericResponseModel.fromJson(json);
return responseData.calculateAbsenceDuration!; return responseData.calculateAbsenceDuration!;
}, url, postParams); }, url, postParams);
} }
Future<List<GetAbsenceDffStructureList>> getAbsenceDffStructure(String pDescFlexContextCode, String pFunctionName, int pSelectedResopID) async { Future<List<GetAbsenceDffStructureList>> getAbsenceDffStructure(String pDescFlexContextCode, String pFunctionName, int pSelectedResopID, {String? empID}) async {
String url = "${ApiConsts.erpRest}GET_ABSENCE_DFF_STRUCTURE"; String url = "${ApiConsts.erpRest}GET_ABSENCE_DFF_STRUCTURE";
Map<String, dynamic> postParams = {"P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, "P_FUNCTION_NAME": pFunctionName, "P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": pSelectedResopID}; Map<String, dynamic> postParams = {"P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, "P_FUNCTION_NAME": pFunctionName, "P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": pSelectedResopID};
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
if (empID!.isNotEmpty) {
postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID;
}
return await ApiClient().postJsonForObject((json) { return await ApiClient().postJsonForObject((json) {
GenericResponseModel? responseData = GenericResponseModel.fromJson(json); GenericResponseModel? responseData = GenericResponseModel.fromJson(json);
return responseData.getAbsenceDffStructureList ?? []; return responseData.getAbsenceDffStructureList ?? [];
@ -67,7 +79,7 @@ class LeaveBalanceApiClient {
Future<GenericResponseModel> validateAbsenceTransaction( Future<GenericResponseModel> validateAbsenceTransaction(
String pDescFlexContextCode, String pFunctionName, int pAbsenceAttendanceTypeID, String pReplacementUserName, String pDateStart, String pDateEnd, int pSelectedResopID, Map<String, String?> data, String pDescFlexContextCode, String pFunctionName, int pAbsenceAttendanceTypeID, String pReplacementUserName, String pDateStart, String pDateEnd, int pSelectedResopID, Map<String, String?> data,
{String comments = ""}) async { {String comments = "", String? empID}) async {
String url = "${ApiConsts.erpRest}VALIDATE_ABSENCE_TRANSACTION"; String url = "${ApiConsts.erpRest}VALIDATE_ABSENCE_TRANSACTION";
Map<String, dynamic> postParams = { Map<String, dynamic> postParams = {
"P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode,
@ -86,6 +98,9 @@ class LeaveBalanceApiClient {
}; };
postParams.addAll(data); postParams.addAll(data);
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
if (empID!.isNotEmpty) {
postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID;
}
return await ApiClient().postJsonForObject((json) { return await ApiClient().postJsonForObject((json) {
GenericResponseModel? responseData = GenericResponseModel.fromJson(json); GenericResponseModel? responseData = GenericResponseModel.fromJson(json);
return responseData; return responseData;
@ -94,7 +109,7 @@ class LeaveBalanceApiClient {
Future<SumbitAbsenceTransactionList> submitAbsenceTransaction( Future<SumbitAbsenceTransactionList> submitAbsenceTransaction(
String pDescFlexContextCode, String pFunctionName, int pAbsenceAttendanceTypeID, String pReplacementUserName, String pDateStart, String pDateEnd, int pSelectedResopID, Map<String, String?> data, String pDescFlexContextCode, String pFunctionName, int pAbsenceAttendanceTypeID, String pReplacementUserName, String pDateStart, String pDateEnd, int pSelectedResopID, Map<String, String?> data,
{String comments = ""}) async { {String comments = "", String? empID}) async {
String url = "${ApiConsts.erpRest}SUBMIT_ABSENCE_TRANSACTION"; String url = "${ApiConsts.erpRest}SUBMIT_ABSENCE_TRANSACTION";
Map<String, dynamic> postParams = { Map<String, dynamic> postParams = {
"P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode,
@ -113,6 +128,9 @@ class LeaveBalanceApiClient {
}; };
postParams.addAll(data); postParams.addAll(data);
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
if (empID!.isNotEmpty) {
postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID;
}
return await ApiClient().postJsonForObject((json) { return await ApiClient().postJsonForObject((json) {
GenericResponseModel? responseData = GenericResponseModel.fromJson(json); GenericResponseModel? responseData = GenericResponseModel.fromJson(json);
return responseData.sumbitAbsenceTransactionList!; return responseData.sumbitAbsenceTransactionList!;
@ -129,7 +147,7 @@ class LeaveBalanceApiClient {
}, url, postParams); }, url, postParams);
} }
Future<StartAbsenceApprovalProccess> startAbsenceApprovalProcess(int pTransactionID, String comments, int pSelectedResopID) async { Future<StartAbsenceApprovalProccess> startAbsenceApprovalProcess(int pTransactionID, String comments, int pSelectedResopID,{String? empID}) async {
String url = "${ApiConsts.erpRest}START_ABSENCE_APPROVAL_PROCESS"; String url = "${ApiConsts.erpRest}START_ABSENCE_APPROVAL_PROCESS";
Map<String, dynamic> postParams = { Map<String, dynamic> postParams = {
"P_TRANSACTION_ID": pTransactionID, "P_TRANSACTION_ID": pTransactionID,
@ -138,6 +156,9 @@ class LeaveBalanceApiClient {
"P_MENU_TYPE": "E", "P_MENU_TYPE": "E",
}; };
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
if (empID!.isNotEmpty) {
postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID;
}
return await ApiClient().postJsonForObject((json) { return await ApiClient().postJsonForObject((json) {
GenericResponseModel? responseData = GenericResponseModel.fromJson(json); GenericResponseModel? responseData = GenericResponseModel.fromJson(json);
return responseData.startAbsenceApprovalProccess!; return responseData.startAbsenceApprovalProccess!;

@ -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_generic_model.dart';
import 'package:mohem_flutter_app/models/marathon/marathon_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/question_model.dart';
import 'package:mohem_flutter_app/models/marathon/winner_model.dart';
import 'package:signalr_netcore/hub_connection.dart'; import 'package:signalr_netcore/hub_connection.dart';
class MarathonApiClient { class MarathonApiClient {
@ -19,6 +20,7 @@ class MarathonApiClient {
String employeeSession = AppState().postParamsObject?.pSessionId.toString() ?? ""; String employeeSession = AppState().postParamsObject?.pSessionId.toString() ?? "";
Map<String, String> jsonObject = <String, String>{"userName": employeeUserName, "password": employeeSession}; Map<String, String> jsonObject = <String, String>{"userName": employeeUserName, "password": employeeSession};
Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonParticipantLoginUrl, jsonObject); Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonParticipantLoginUrl, jsonObject);
var json = jsonDecode(response.body); var json = jsonDecode(response.body);
@ -80,10 +82,11 @@ class MarathonApiClient {
return marathonDetailModel; return marathonDetailModel;
} }
Future<bool> joinMarathonAsParticipant() async { Future<int?> joinMarathonAsParticipant() async {
Map<String, String> jsonObject = <String, String>{ Map<String, String> jsonObject = <String, String>{
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "", "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "",
"employeeName": AppState().memberInformationList!.eMPLOYEENAME ?? "", "employeeNameAr": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr ?? "",
"employeeNameEn": AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn ?? "",
"marathonId": AppState().getMarathonProjectId!, "marathonId": AppState().getMarathonProjectId!,
}; };
@ -95,24 +98,24 @@ class MarathonApiClient {
if (marathonModel.statusCode == 208) { if (marathonModel.statusCode == 208) {
// means participant is already in the marathon i.e already joined // means participant is already in the marathon i.e already joined
return true; return marathonModel.data["remainingTime"];
} }
if (marathonModel.statusCode == 200) { if (marathonModel.statusCode == 200) {
if (marathonModel.data != null && marathonModel.isSuccessful == true) { if (marathonModel.data != null && marathonModel.isSuccessful == true) {
logger.i("joinMarathonAsParticipant: ${marathonModel.data}"); logger.i("joinMarathonAsParticipant: ${marathonModel.data}");
return true; return marathonModel.data["remainingTime"];
} else { } else {
return false; return null;
} }
} else { } else {
return false; return null;
} }
} }
Future<QuestionModel?> getNextQuestion({required String? questionId, required String marathonId}) async { Future<QuestionModel?> getNextQuestion({required String? questionId, required String marathonId}) async {
Map<String, String?> jsonObject = <String, String?>{ Map<String, String?> jsonObject = <String, String?>{
"questionId": questionId, "previousQuestionId": questionId,
"marathonId": marathonId, "marathonId": marathonId,
}; };
@ -120,6 +123,8 @@ class MarathonApiClient {
var json = jsonDecode(response.body); var json = jsonDecode(response.body);
logger.i("json in NextQuestion: $json");
var data = json["data"]; var data = json["data"];
if (data != null) { if (data != null) {
@ -130,13 +135,13 @@ class MarathonApiClient {
} }
} }
Future<bool> submitSelectedOption({required String? selectedAnswerId}) async { Future<bool> submitSelectedOption({required String marathonId, required String? questionId, required String? selectedAnswerId}) async {
Map<String, String?> jsonObject = <String, String?>{"selectedOptionId": selectedAnswerId}; Map<String, String?> jsonObject = <String, String?>{"marathonId": marathonId, "questionId": questionId, "selectedOptionId" : selectedAnswerId};
Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonSubmitAnswerUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken()); Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonSubmitAnswerUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken());
var json = jsonDecode(response.body); var json = jsonDecode(response.body);
logger.i("json: $json"); logger.i("json in submitSelectedOption : $json");
MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json); MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json);
@ -147,6 +152,42 @@ class MarathonApiClient {
return marathonModel.isSuccessful!; return marathonModel.isSuccessful!;
} }
Future<int?> getQualifiers({required String marathonId}) async {
Map<String, String> params = <String, String>{"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<List<WinnerModel>?> getSelectedWinner({required String marathonId}) async {
Map<String, String> params = <String, String>{"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<WinnerModel> winners = <WinnerModel>[];
List data = marathonGenericModel.data as List;
for (Map<String, dynamic> winner in data) {
winners.add(WinnerModel.fromJson(winner));
}
return winners;
}
return null;
}
// Future<void> buildHubConnection(BuildContext context, String prizeId) async { // Future<void> buildHubConnection(BuildContext context, String prizeId) async {
// HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); // HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
// hubConnection = HubConnectionBuilder() // hubConnection = HubConnectionBuilder()

@ -38,6 +38,7 @@ class AppState {
String? get getForgetPasswordTokenID => forgetPasswordTokenID; String? get getForgetPasswordTokenID => forgetPasswordTokenID;
//Wifi info //Wifi info
String? _mohemmWifiSSID; String? _mohemmWifiSSID;

@ -63,4 +63,5 @@ class MyColors {
static const Color darkDigitColor = Color(0xff2D2F39); static const Color darkDigitColor = Color(0xff2D2F39);
static const Color grey71Color = Color(0xff717171); static const Color grey71Color = Color(0xff717171);
static const Color darkGrey3BColor = Color(0xff3B3B3B); static const Color darkGrey3BColor = Color(0xff3B3B3B);
static const Color lightGreyIconColor = Color(0xff919191);
} }

@ -3,6 +3,7 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart';
class ApiConsts { class ApiConsts {
//static String baseUrl = "http://10.200.204.20:2801/"; // Local server //static String baseUrl = "http://10.200.204.20:2801/"; // Local server
// static String baseUrl = "https://uat.hmgwebservices.com"; // UAT 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://hmgwebservices.com"; // Live server
static String baseUrlServices = baseUrl + "/Services/"; // server static String baseUrlServices = baseUrl + "/Services/"; // server
// static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server
@ -30,15 +31,16 @@ class ApiConsts {
static String marathonParticipantLoginUrl = marathonBaseUrl + "auth/participantlogin"; static String marathonParticipantLoginUrl = marathonBaseUrl + "auth/participantlogin";
static String marathonProjectGetUrl = marathonBaseUrl + "Project/Project_Get"; static String marathonProjectGetUrl = marathonBaseUrl + "Project/Project_Get";
static String marathonUpcomingUrl = marathonBaseUrl + "marathon/upcoming/"; 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 marathonNextQuestionUrl = marathonBaseUrl + "question/next";
static String marathonSubmitAnswerUrl = marathonBaseUrl + "question/submit"; static String marathonSubmitAnswerUrl = marathonBaseUrl + "question/submit";
static String marathonQualifiersUrl = marathonBaseUrl + "winner/getWinner/"; static String marathonQualifiersUrl = marathonBaseUrl + "winner/getWinner/";
static String marathonSelectedWinner = marathonBaseUrl + "winner/getSelectedWinner/"; static String marathonSelectedWinner = marathonBaseUrl + "winner/getSelectedWinner/";
//DummyCards for the UI //DummyCards for the UI
static CardContent dummyQuestion = const CardContent(); static CardContent dummyQuestion = const CardContent();
static int tabletMinLength = 500;
} }
class SharedPrefsConsts { class SharedPrefsConsts {

@ -37,7 +37,7 @@ class Utils {
timeInSecForIosWeb: 1, timeInSecForIosWeb: 1,
backgroundColor: Colors.black54, backgroundColor: Colors.black54,
textColor: Colors.white, textColor: Colors.white,
fontSize: 16.0); fontSize: 13.0);
} }
static dynamic getNotNullValue(List<dynamic> list, int index) { static dynamic getNotNullValue(List<dynamic> list, int index) {
@ -122,6 +122,7 @@ class Utils {
); );
} else { } else {
showToast(errorMessage); showToast(errorMessage);
// confirmDialog(cxt, errorMessage);
} }
} }
} }

@ -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_screen.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_sponsor_video_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_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/marathon/winner_screen.dart';
import 'package:mohem_flutter_app/ui/misc/request_submit_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'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart';
@ -187,7 +186,6 @@ class AppRoutes {
//Marathon //Marathon
static const String marathonIntroScreen = "/marathonIntroScreen"; static const String marathonIntroScreen = "/marathonIntroScreen";
static const String marathonScreen = "/marathonScreen"; static const String marathonScreen = "/marathonScreen";
static const String marathonWinnerSelection = "/marathonWinnerSelection";
static const String marathonWinnerScreen = "/marathonWinnerScreen"; static const String marathonWinnerScreen = "/marathonWinnerScreen";
static const String marathonSponsorVideoScreen = "/marathonSponsorVideoScreen"; static const String marathonSponsorVideoScreen = "/marathonSponsorVideoScreen";
static const String marathonWaitingScreen = "/marathonWaitingScreen"; static const String marathonWaitingScreen = "/marathonWaitingScreen";
@ -299,7 +297,6 @@ class AppRoutes {
// Marathon // Marathon
marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(), marathonIntroScreen: (BuildContext context) => MarathonIntroScreen(),
marathonScreen: (BuildContext context) => MarathonScreen(), marathonScreen: (BuildContext context) => MarathonScreen(),
marathonWinnerSelection: (BuildContext context) => MarathonWinnerSelection(),
marathonWinnerScreen: (BuildContext context) => WinnerScreen(), marathonWinnerScreen: (BuildContext context) => WinnerScreen(),
marathonSponsorVideoScreen: (BuildContext context) => const SponsorVideoScreen(), marathonSponsorVideoScreen: (BuildContext context) => const SponsorVideoScreen(),
marathonWaitingScreen: (BuildContext context) => const MarathonWaitingScreen(), marathonWaitingScreen: (BuildContext context) => const MarathonWaitingScreen(),

@ -141,8 +141,9 @@ extension EmailValidator on String {
style: TextStyle(color: color ?? MyColors.grey3AColor, fontSize: 21, letterSpacing: -0.84, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.w600)), 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, 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), style: TextStyle(height: 1, color: color ?? MyColors.darkTextColor, fontSize: 22, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
); );
@ -156,8 +157,9 @@ extension EmailValidator on String {
style: TextStyle(height: 20 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.2, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), 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, 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), style: TextStyle(height: 32 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.92, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
); );

@ -440,6 +440,9 @@ class CodegenLoader extends AssetLoader{
"typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه", "typeCurrentPasswordBelow": "اكتب كلمة المرور الحاليه",
"currentPassword": "كلمة المرور الحاليه", "currentPassword": "كلمة المرور الحاليه",
"concurrentReports": "التقارير المتزامنه", "concurrentReports": "التقارير المتزامنه",
"EnterNewAddressMoved": "أدخل عنوان جديد إذا كنت قد انتقلت",
"CorrectAddress": "تصحيح أو تعديل هذا العنوان",
"SelectChangeWantToMake": " حدد نوع التغيير الذي تريد القيام به.",
"profile": { "profile": {
"reset_password": { "reset_password": {
"label": "Reset Password", "label": "Reset Password",
@ -516,7 +519,16 @@ class CodegenLoader extends AssetLoader{
"codeExpire": "انتهت صلاحية رمز التحقق", "codeExpire": "انتهت صلاحية رمز التحقق",
"typeheretoreply": "اكتب هنا للرد", "typeheretoreply": "اكتب هنا للرد",
"favorite": "مفضلتي", "favorite": "مفضلتي",
"searchfromchat": "البحث من الدردشة" "searchfromchat": "البحث من الدردشة",
"yourAnswerCorrect": "إجابتك صحيحة",
"youMissedTheQuestion": "نفد منك الوقت. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.",
"wrongAnswer": "إجابتك غير صحيحة. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.",
"oops": "أوه!!!",
"winner": "الفائز",
"youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.",
"ourSponsor": "راعينا:",
"startingIn": "يبدأ في",
"youAreOutOfContest": "أنت خارج المسابقة."
}; };
static const Map<String,dynamic> en_US = { static const Map<String,dynamic> en_US = {
"mohemm": "Mohemm", "mohemm": "Mohemm",
@ -944,6 +956,9 @@ static const Map<String,dynamic> en_US = {
"typeCurrentPasswordBelow": "Type Your Current password below", "typeCurrentPasswordBelow": "Type Your Current password below",
"currentPassword": "Current password", "currentPassword": "Current password",
"concurrentReports": "Concurrent Reports", "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": { "profile": {
"reset_password": { "reset_password": {
"label": "Reset Password", "label": "Reset Password",
@ -1020,7 +1035,16 @@ static const Map<String,dynamic> en_US = {
"allQuestionsCorrect": "You have answered all questions correct", "allQuestionsCorrect": "You have answered all questions correct",
"typeheretoreply": "Type here to reply", "typeheretoreply": "Type here to reply",
"favorite": "My Favorites", "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<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
} }

@ -425,6 +425,9 @@ abstract class LocaleKeys {
static const typeCurrentPasswordBelow = 'typeCurrentPasswordBelow'; static const typeCurrentPasswordBelow = 'typeCurrentPasswordBelow';
static const currentPassword = 'currentPassword'; static const currentPassword = 'currentPassword';
static const concurrentReports = 'concurrentReports'; 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_label = 'profile.reset_password.label';
static const profile_reset_password_username = 'profile.reset_password.username'; 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_password = 'profile.reset_password.password';
@ -496,5 +499,6 @@ abstract class LocaleKeys {
static const ourSponsor = 'ourSponsor'; static const ourSponsor = 'ourSponsor';
static const startingIn = 'startingIn'; static const startingIn = 'startingIn';
static const youAreOutOfContest = 'youAreOutOfContest'; static const youAreOutOfContest = 'youAreOutOfContest';
static const winners = 'winners';
} }

@ -2,8 +2,10 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
import 'package:mohem_flutter_app/app_state/app_state.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/config/routes.dart';
import 'package:mohem_flutter_app/generated/codegen_loader.g.dart'; import 'package:mohem_flutter_app/generated/codegen_loader.g.dart';
import 'package:mohem_flutter_app/models/post_params_model.dart'; import 'package:mohem_flutter_app/models/post_params_model.dart';
@ -32,11 +34,19 @@ class MyHttpOverrides extends HttpOverrides {
} }
} }
bool isTablet = false;
Future<void> main() async { Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
await EasyLocalization.ensureInitialized(); await EasyLocalization.ensureInitialized();
AppState().setPostParamsInitConfig(); AppState().setPostParamsInitConfig();
HttpOverrides.global = MyHttpOverrides(); HttpOverrides.global = MyHttpOverrides();
isTablet = MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.shortestSide >= ApiConsts.tabletMinLength;
runApp( runApp(
EasyLocalization( EasyLocalization(
supportedLocales: const <Locale>[ supportedLocales: const <Locale>[

@ -1,8 +1,8 @@
import 'dart:convert'; // To parse this JSON data, do
//
ChatUnreadCovnCountModel chatUnreadCovnCountModelFromJson(String str) => ChatUnreadCovnCountModel.fromJson(json.decode(str)); // final chatUnreadCovnCountModel = chatUnreadCovnCountModelFromMap(jsonString);
String chatUnreadCovnCountModelToJson(ChatUnreadCovnCountModel data) => json.encode(data.toJson()); import 'dart:convert';
class ChatUnreadCovnCountModel { class ChatUnreadCovnCountModel {
ChatUnreadCovnCountModel({ ChatUnreadCovnCountModel({
@ -13,12 +13,16 @@ class ChatUnreadCovnCountModel {
int? singleChatCount; int? singleChatCount;
int? groupChatCount; int? groupChatCount;
factory ChatUnreadCovnCountModel.fromJson(Map<String, dynamic> json) => ChatUnreadCovnCountModel( factory ChatUnreadCovnCountModel.fromJson(String str) => ChatUnreadCovnCountModel.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory ChatUnreadCovnCountModel.fromMap(Map<String, dynamic> json) => ChatUnreadCovnCountModel(
singleChatCount: json["singleChatCount"] == null ? null : json["singleChatCount"], singleChatCount: json["singleChatCount"] == null ? null : json["singleChatCount"],
groupChatCount: json["groupChatCount"] == null ? null : json["groupChatCount"], groupChatCount: json["groupChatCount"] == null ? null : json["groupChatCount"],
); );
Map<String, dynamic> toJson() => { Map<String, dynamic> toMap() => {
"singleChatCount": singleChatCount == null ? null : singleChatCount, "singleChatCount": singleChatCount == null ? null : singleChatCount,
"groupChatCount": groupChatCount == null ? null : groupChatCount, "groupChatCount": groupChatCount == null ? null : groupChatCount,
}; };

@ -1,3 +1,5 @@
import 'dart:io';
class ChatUserModel { class ChatUserModel {
ChatUserModel({ ChatUserModel({
this.response, this.response,
@ -35,6 +37,7 @@ class ChatUser {
this.isTyping, this.isTyping,
this.isImageLoaded, this.isImageLoaded,
this.isImageLoading, this.isImageLoading,
this.userLocalDownlaodedImage,
}); });
int? id; int? id;
@ -52,6 +55,7 @@ class ChatUser {
bool? isTyping; bool? isTyping;
bool? isImageLoaded; bool? isImageLoaded;
bool? isImageLoading; bool? isImageLoading;
File? userLocalDownlaodedImage;
factory ChatUser.fromJson(Map<String, dynamic> json) => ChatUser( factory ChatUser.fromJson(Map<String, dynamic> json) => ChatUser(
id: json["id"] == null ? null : json["id"], id: json["id"] == null ? null : json["id"],
@ -69,7 +73,7 @@ class ChatUser {
isTyping: false, isTyping: false,
isImageLoaded: false, isImageLoaded: false,
isImageLoading: true, isImageLoading: true,
); userLocalDownlaodedImage: null);
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
"id": id == null ? null : id, "id": id == null ? null : id,

@ -19,6 +19,8 @@ class SingleUserChatModel {
this.targetUserName, this.targetUserName,
this.encryptedTargetUserId, this.encryptedTargetUserId,
this.encryptedTargetUserName, this.encryptedTargetUserName,
this.currentUserEmail,
this.targetUserEmail,
this.chatEventId, this.chatEventId,
this.fileTypeId, this.fileTypeId,
this.isSeen, this.isSeen,
@ -38,8 +40,10 @@ class SingleUserChatModel {
String? contantNo; String? contantNo;
int? currentUserId; int? currentUserId;
String? currentUserName; String? currentUserName;
String? currentUserEmail;
int? targetUserId; int? targetUserId;
String? targetUserName; String? targetUserName;
String? targetUserEmail;
String? encryptedTargetUserId; String? encryptedTargetUserId;
String? encryptedTargetUserName; String? encryptedTargetUserName;
int? chatEventId; int? chatEventId;
@ -64,6 +68,8 @@ class SingleUserChatModel {
currentUserName: json["currentUserName"] == null ? null : json["currentUserName"], currentUserName: json["currentUserName"] == null ? null : json["currentUserName"],
targetUserId: json["targetUserId"] == null ? null : json["targetUserId"], targetUserId: json["targetUserId"] == null ? null : json["targetUserId"],
targetUserName: json["targetUserName"] == null ? null : json["targetUserName"], 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"], encryptedTargetUserId: json["encryptedTargetUserId"] == null ? null : json["encryptedTargetUserId"],
encryptedTargetUserName: json["encryptedTargetUserName"] == null ? null : json["encryptedTargetUserName"], encryptedTargetUserName: json["encryptedTargetUserName"] == null ? null : json["encryptedTargetUserName"],
chatEventId: json["chatEventId"] == null ? null : json["chatEventId"], chatEventId: json["chatEventId"] == null ? null : json["chatEventId"],
@ -90,6 +96,8 @@ class SingleUserChatModel {
"targetUserName": targetUserName == null ? null : targetUserName, "targetUserName": targetUserName == null ? null : targetUserName,
"encryptedTargetUserId": encryptedTargetUserId == null ? null : encryptedTargetUserId, "encryptedTargetUserId": encryptedTargetUserId == null ? null : encryptedTargetUserId,
"encryptedTargetUserName": encryptedTargetUserName == null ? null : encryptedTargetUserName, "encryptedTargetUserName": encryptedTargetUserName == null ? null : encryptedTargetUserName,
"currentUserEmail": currentUserEmail == null ? null : currentUserEmail,
"targetUserEmail": targetUserEmail == null ? null : targetUserEmail,
"chatEventId": chatEventId == null ? null : chatEventId, "chatEventId": chatEventId == null ? null : chatEventId,
"fileTypeId": fileTypeId, "fileTypeId": fileTypeId,
"isSeen": isSeen == null ? null : isSeen, "isSeen": isSeen == null ? null : isSeen,

@ -1,41 +1,41 @@
class GetTimeCardSummaryList { class GetTimeCardSummaryList {
int? aBSENTDAYS; num? aBSENTDAYS;
dynamic? aCTUALHRS; dynamic? aCTUALHRS;
dynamic? aPPROVEDTIMEBACKHRS; dynamic? aPPROVEDTIMEBACKHRS;
int? aSSIGNMENTID; num? aSSIGNMENTID;
int? aTTENDEDDAYS; num? aTTENDEDDAYS;
int? bUSINESSTRIP; num? bUSINESSTRIP;
dynamic? cOMPOFFHHRS; dynamic? cOMPOFFHHRS;
dynamic? cOMPOFFNHRS; dynamic? cOMPOFFNHRS;
dynamic? cOMPOFFWHRS; dynamic? cOMPOFFWHRS;
dynamic? dESIREDSCHEDULEDHRS; dynamic? dESIREDSCHEDULEDHRS;
dynamic? eARLYOUTHRS; dynamic? eARLYOUTHRS;
dynamic? eXCESSHRS; dynamic? eXCESSHRS;
int? hALFDAYLEAVE; num? hALFDAYLEAVE;
dynamic? lATEINHRS; dynamic? lATEINHRS;
dynamic? lEAVESHOLIDAYSHRS; dynamic? lEAVESHOLIDAYSHRS;
dynamic? nONSCHEDULEDAYS; dynamic? nONSCHEDULEDAYS;
dynamic? nOTANALYZEDDAYS; dynamic? nOTANALYZEDDAYS;
int? oFFDAYS; num? oFFDAYS;
dynamic? oNCALLHRS; dynamic? oNCALLHRS;
dynamic? pAIDLEAVE; dynamic? pAIDLEAVE;
int? pERIODDAYS; num? pERIODDAYS;
dynamic? pLANNEDOTHRS; dynamic? pLANNEDOTHRS;
int? pUBLICHOLIDAY; num? pUBLICHOLIDAY;
dynamic? sCHEDULEDHRS; dynamic? sCHEDULEDHRS;
dynamic? sCHEDULEDONCALLHRS; dynamic? sCHEDULEDONCALLHRS;
dynamic? sCHEDULEDPLANNEDOTHRS; dynamic? sCHEDULEDPLANNEDOTHRS;
int? sCHEDULEDAYS; num? sCHEDULEDAYS;
dynamic? sHORTAGEHRS; dynamic? sHORTAGEHRS;
dynamic? sHORTAGESCHEDULEHRS; dynamic? sHORTAGESCHEDULEHRS;
int? sICKLEAVE; num? sICKLEAVE;
dynamic? tIMEBACKHRS; dynamic? tIMEBACKHRS;
dynamic? tIMEBACKBALANCE; dynamic? tIMEBACKBALANCE;
int? uNAUTHORIZEDLEAVE; num? uNAUTHORIZEDLEAVE;
dynamic? uNCOVERDSHORTAGEHRS; dynamic? uNCOVERDSHORTAGEHRS;
int? uNPAIDLEAVE; num? uNPAIDLEAVE;
GetTimeCardSummaryList( GetTimeCardSummaryList(
{this.aBSENTDAYS, {this.aBSENTDAYS,

@ -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<String, dynamic> json) {
id = json['id'];
marathoneId = json['marathoneId'];
employeeId = json['employeeId'];
nameEn = json['nameEn'];
nameAr = json['nameAr'];
}
}

@ -48,7 +48,7 @@ class MemberInformationListModel {
String? nATIONALITYCODE; String? nATIONALITYCODE;
String? nATIONALITYMEANING; String? nATIONALITYMEANING;
String? nATIONALIDENTIFIER; String? nATIONALIDENTIFIER;
String? nORMALHOURS; dynamic? nORMALHOURS;
int? nOOFROWS; int? nOOFROWS;
int? oRGANIZATIONID; int? oRGANIZATIONID;
String? oRGANIZATIONNAME; String? oRGANIZATIONNAME;

@ -13,6 +13,7 @@ import 'package:mohem_flutter_app/classes/consts.dart';
import 'package:mohem_flutter_app/classes/encryption.dart'; import 'package:mohem_flutter_app/classes/encryption.dart';
import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/main.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/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_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart';
@ -20,6 +21,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/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/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/widgets/image_picker.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/hub_connection.dart';
import 'package:signalr_netcore/signalr_client.dart'; import 'package:signalr_netcore/signalr_client.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
@ -40,6 +43,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List<SingleUserChatModel> repliedMsg = []; List<SingleUserChatModel> repliedMsg = [];
List<ChatUser> favUsersList = []; List<ChatUser> favUsersList = [];
int paginationVal = 0; int paginationVal = 0;
bool currentUserTyping = false;
int? cTypingUserId = 0;
//Chat
int chatUConvCounter = 0;
Future<void> getUserAutoLoginToken() async { Future<void> getUserAutoLoginToken() async {
userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken(); userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken();
@ -57,30 +65,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
await chatHubConnection.start(); await chatHubConnection.start();
print("Startedddddddd"); print("Startedddddddd");
chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
chatHubConnection.on("OnGetChatConversationCount", onNewChatConversion);
} }
Future<HubConnection> getHubConnection() async { Future<HubConnection> getHubConnection() async {
HubConnection hub; HubConnection hub;
// try {
HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
hub = HubConnectionBuilder() hub = HubConnectionBuilder()
.withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
.withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build(); .withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
// isChatHubLoding = false;
return hub; return hub;
// } catch (e) {
// getUserAutoLoginToken().whenComplete(() {
// getHubConnection();
// });
// throw e;
// }
} }
void registerEvents() { void registerEvents() {
chatHubConnection.on("OnUpdateUserStatusAsync", changeStatus); chatHubConnection.on("OnUpdateUserStatusAsync", changeStatus);
// chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived); // chatHubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
// hubConnection.on("OnSeenChatUserAsync", onChatSeen); // hubConnection.on("OnSeenChatUserAsync", onChatSeen);
//hubConnection.on("OnUserTypingAsync", onUserTyping); chatHubConnection.on("OnUserTypingAsync", onUserTyping);
chatHubConnection.on("OnUserCountAsync", userCountAsync); chatHubConnection.on("OnUserCountAsync", userCountAsync);
// hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow); // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered); chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
@ -124,8 +125,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
AppState().chatDetails!.response!.id.toString(), AppState().chatDetails!.response!.id.toString(),
), ),
); );
sort();
notifyListeners(); notifyListeners();
if (searchedChats!.isNotEmpty) { if (searchedChats!.isNotEmpty || favUsersList.isNotEmpty) {
getUserImages(); getUserImages();
} }
} }
@ -140,19 +142,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
if (isNewChat) userChatHistory = []; if (isNewChat) userChatHistory = [];
if (!loadMore) paginationVal = 0; if (!loadMore) paginationVal = 0;
isChatScreenActive = true; 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); Response response = await ChatApiClient().getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal);
if (response.statusCode == 204) { if (response.statusCode == 204) {
if (isNewChat) { if (isNewChat) {
userChatHistory = []; userChatHistory = [];
} else if (loadMore) { } else if (loadMore) {
// userChatHistory = [];
Utils.showToast("No More Data To Load"); Utils.showToast("No More Data To Load");
} }
} else { } else {
@ -165,7 +159,9 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} }
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();
markRead(userChatHistory, receiverUID); markRead(userChatHistory, receiverUID);
generateConvId(); generateConvId();
} }
@ -177,6 +173,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void markRead(List<SingleUserChatModel> data, int receiverID) { void markRead(List<SingleUserChatModel> data, int receiverID) {
if (data != null) { if (data != null) {
for (SingleUserChatModel element in data!) { for (SingleUserChatModel element in data!) {
if (AppState().chatDetails!.response!.id! == element.targetUserId) {
if (element.isSeen != null) { if (element.isSeen != null) {
if (!element.isSeen!) { if (!element.isSeen!) {
element.isSeen = true; element.isSeen = true;
@ -192,11 +189,12 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
notifyListeners(); notifyListeners();
} }
} }
}
for (ChatUser element in searchedChats!) { for (ChatUser element in searchedChats!) {
if (element.id == receiverID) { if (element.id == receiverID) {
element.unreadMessageCount = 0; element.unreadMessageCount = 0;
// notifyListeners(); chatUConvCounter = 0;
}
}
} }
} }
notifyListeners(); notifyListeners();
@ -332,8 +330,11 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
temp = getSingleUserChatModel(jsonEncode(msg)); temp = getSingleUserChatModel(jsonEncode(msg));
data.first.targetUserId = temp.first.currentUserId; data.first.targetUserId = temp.first.currentUserId;
data.first.targetUserName = temp.first.currentUserName; data.first.targetUserName = temp.first.currentUserName;
data.first.targetUserEmail = temp.first.currentUserEmail;
data.first.currentUserId = temp.first.targetUserId; data.first.currentUserId = temp.first.targetUserId;
data.first.currentUserName = temp.first.targetUserName; 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) { 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"); data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg");
} }
@ -347,11 +348,28 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} }
} }
} }
if (searchedChats != null) {
dynamic contain = searchedChats!.where((ChatUser element) => element.id == data.first.currentUserId); dynamic contain = searchedChats!.where((ChatUser element) => element.id == data.first.currentUserId);
if (contain.isEmpty) { if (contain.isEmpty) {
searchedChats!.add(ChatUser(id: data.first.currentUserId, userName: data.first.currentUserName, unreadMessageCount: 0, isImageLoading: false, image: "", isImageLoaded: true, userStatus: 1)); List<String> emails = [];
emails.add(await EmailImageEncryption().encrypt(val: data.first.currentUserEmail!));
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
searchedChats!.add(
ChatUser(
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(); setMsgTune();
userChatHistory.insert(0, data.first); userChatHistory.insert(0, data.first);
@ -369,6 +387,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
{"userChatHistoryId": data.first.userChatHistoryId, "TargetUserId": temp.first.targetUserId, "isDelivered": true, "isSeen": isChatScreenActive ? true : false} {"userChatHistoryId": data.first.userChatHistoryId, "TargetUserId": temp.first.targetUserId, "isDelivered": true, "isSeen": isChatScreenActive ? true : false}
]; ];
updateUserChatHistoryOnMsg(list); updateUserChatHistoryOnMsg(list);
invokeChatCounter(userId: AppState().chatDetails!.response!.id!);
notifyListeners(); notifyListeners();
} }
@ -474,7 +493,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
required bool isImageLoaded}) async { required bool isImageLoaded}) async {
Uuid uuid = const Uuid(); Uuid uuid = const Uuid();
String contentNo = uuid.v4(); String contentNo = uuid.v4();
String msg = message.text; String msg = message.text;
SingleUserChatModel data = SingleUserChatModel( SingleUserChatModel data = SingleUserChatModel(
chatEventId: chatEventId, chatEventId: chatEventId,
@ -493,8 +511,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
fileTypeResponse: isAttachment fileTypeResponse: isAttachment
? FileTypeResponse( ? FileTypeResponse(
fileTypeId: fileTypeId, fileTypeId: fileTypeId,
fileTypeName: getFileType(getFileExtension(selectedFile.path).toString()), fileTypeName: getFileExtension(selectedFile.path).toString(),
fileKind: getFileExtension(selectedFile.path), fileKind: "file",
fileName: selectedFile.path.split("/").last, fileName: selectedFile.path.split("/").last,
fileTypeDescription: getFileTypeDescription(getFileExtension(selectedFile.path).toString()), fileTypeDescription: getFileTypeDescription(getFileExtension(selectedFile.path).toString()),
) )
@ -514,11 +532,26 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
await chatHubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]); await chatHubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]);
} }
void sendChatMessage(int targetUserId, 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); dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId);
if (contain.isEmpty) { if (contain.isEmpty) {
List<String> emails = [];
emails.add(await EmailImageEncryption().encrypt(val: userEmail));
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
searchedChats!.add( searchedChats!.add(
ChatUser(id: targetUserId, userName: targetUserName, unreadMessageCount: 0, isImageLoading: false, image: "", isImageLoaded: true), 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(); notifyListeners();
} }
@ -531,6 +564,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: false, chatReplyId: null, isReply: false, isImageLoaded: false, image: null); chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: false, chatReplyId: null, isReply: false, isImageLoaded: false, image: null);
} // normal Text msg } // normal Text msg
if (isFileSelected && !isMsgReply) { if (isFileSelected && !isMsgReply) {
bool isImage = false;
print("Normal Attachment Msg"); print("Normal Attachment Msg");
Utils.showLoading(context); Utils.showLoading(context);
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile); dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile);
@ -606,6 +640,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
String? getFileExtension(String fileName) { String? getFileExtension(String fileName) {
try { try {
print("Ext: " + "." + fileName.split('.').last);
return "." + fileName.split('.').last; return "." + fileName.split('.').last;
} catch (e) { } catch (e) {
return null; return null;
@ -733,14 +768,24 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void getUserImages() async { void getUserImages() async {
List<String> emails = []; List<String> emails = [];
for (ChatUser element in searchedChats!) { List<ChatUser> exists = [], unique = [];
exists.addAll(searchedChats!);
exists.addAll(favUsersList!);
Map<String, ChatUser> 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!)); emails.add(await EmailImageEncryption().encrypt(val: element.email!));
} }
List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails); List<ChatUserImageModel> chatImages = await ChatApiClient().getUsersImages(encryptedEmails: emails);
for (ChatUser user in searchedChats!) { for (ChatUser user in searchedChats!) {
for (ChatUserImageModel uImage in chatImages) { for (ChatUserImageModel uImage in chatImages) {
if (user.email == uImage.email) { if (user.email == uImage.email) {
user.image = uImage.profilePicture ?? ""; user.image = uImage.profilePicture ?? "";
user.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, user.id.toString());
user.isImageLoading = false; user.isImageLoading = false;
user.isImageLoaded = true; user.isImageLoaded = true;
} }
@ -750,6 +795,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
for (ChatUserImageModel uImage in chatImages) { for (ChatUserImageModel uImage in chatImages) {
if (favUser.email == uImage.email) { if (favUser.email == uImage.email) {
favUser.image = uImage.profilePicture ?? ""; favUser.image = uImage.profilePicture ?? "";
favUser.userLocalDownlaodedImage = await downloadImageLocal(uImage.profilePicture, favUser.id.toString());
favUser.isImageLoading = false; favUser.isImageLoading = false;
favUser.isImageLoaded = true; favUser.isImageLoaded = true;
} }
@ -759,6 +805,35 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
notifyListeners(); notifyListeners();
} }
Future<File?> 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<String> 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 { void setMsgTune() async {
AudioPlayer player = AudioPlayer(); AudioPlayer player = AudioPlayer();
await player.setVolume(1.0); await player.setVolume(1.0);
@ -776,4 +851,30 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
print("Error: $e"); print("Error: $e");
} }
} }
Future<void> 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.");
}
}
}
void onNewChatConversion(List<Object?>? params) {
dynamic items = params!.toList();
logger.d(items);
chatUConvCounter = items[0]["singleChatCount"] ?? 0;
notifyListeners();
}
Future invokeChatCounter({required int userId}) async {
await chatHubConnection.invoke("GetChatCounversationCount", args: [userId]);
return "";
}
} }

@ -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/config/routes.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.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/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_accrual_balances_list_model.dart';
import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_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/generic_response_model.dart';
import 'package:mohem_flutter_app/models/itg/itg_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/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'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';
/// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool /// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool
@ -35,9 +35,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
bool isWorkListLoading = true; bool isWorkListLoading = true;
int workListCounter = 0; int workListCounter = 0;
//Chat
bool isChatCounterLoding = true;
int chatUConvCounter = 0;
//Misssing Swipe //Misssing Swipe
bool isMissingSwipeLoading = true; bool isMissingSwipeLoading = true;
@ -96,8 +94,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
accrualList = null; accrualList = null;
leaveBalanceAccrual = null; leaveBalanceAccrual = null;
isChatCounterLoding = true;
chatUConvCounter = 0;
ticketBalance = 0; ticketBalance = 0;
isServicesMenusLoading = true; isServicesMenusLoading = true;
@ -273,21 +269,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification(); MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification();
return res; 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() { void notify() {
notifyListeners(); notifyListeners();
} }

@ -1,17 +1,23 @@
import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/material.dart'; 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/api_client.dart';
import 'package:mohem_flutter_app/api/chat/chat_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/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.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/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_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/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/main.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/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/ui/chat/chat_full_image_preview.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheet.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. // 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); ChatBubble({Key? key, required this.dateTime, required this.cItem}) : super(key: key);
final String dateTime; final String dateTime;
final SingleUserChatModel cItem; final SingleUserChatModel cItem;
bool isCurrentUser = false; bool isCurrentUser = false;
bool isSeen = false; bool isSeen = false;
bool isReplied = false; bool isReplied = false;
int? fileTypeID; int? fileTypeID;
String? fileTypeName;
late ChatProviderModel data;
String? fileTypeDescription; String? fileTypeDescription;
bool isDelivered = false; bool isDelivered = false;
@ -35,6 +42,7 @@ class ChatBubble extends StatelessWidget {
isSeen = cItem.isSeen == true ? true : false; isSeen = cItem.isSeen == true ? true : false;
isReplied = cItem.userChatReplyResponse != null ? true : false; isReplied = cItem.userChatReplyResponse != null ? true : false;
fileTypeID = cItem.fileTypeId; fileTypeID = cItem.fileTypeId;
fileTypeName = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeName : "";
fileTypeDescription = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeDescription : ""; fileTypeDescription = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeDescription : "";
isDelivered = cItem.currentUserId == AppState().chatDetails!.response!.id && cItem.isDelivered == true ? true : false; isDelivered = cItem.currentUserId == AppState().chatDetails!.response!.id && cItem.isDelivered == true ? true : false;
userName = AppState().chatDetails!.response!.userName == cItem.currentUserName.toString() ? "You" : cItem.currentUserName.toString(); userName = AppState().chatDetails!.response!.userName == cItem.currentUserName.toString() ? "You" : cItem.currentUserName.toString();
@ -45,10 +53,11 @@ class ChatBubble extends StatelessWidget {
Size windowSize = MediaQuery.of(context).size; Size windowSize = MediaQuery.of(context).size;
screenOffset = Offset(windowSize.width / 2, windowSize.height / 2); screenOffset = Offset(windowSize.width / 2, windowSize.height / 2);
makeAssign(); makeAssign();
data = Provider.of<ChatProviderModel>(context, listen: false);
return isCurrentUser ? currentUser(context) : receiptUser(context); return isCurrentUser ? currentUser(context) : receiptUser(context);
} }
Widget currentUser(context) { Widget currentUser(BuildContext context) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -77,22 +86,6 @@ class ChatBubble extends StatelessWidget {
if (cItem.userChatReplyResponse != null && cItem.userChatReplyResponse!.fileTypeId == 12 || if (cItem.userChatReplyResponse != null && cItem.userChatReplyResponse!.fileTypeId == 12 ||
cItem.userChatReplyResponse!.fileTypeId == 3 || cItem.userChatReplyResponse!.fileTypeId == 3 ||
cItem.userChatReplyResponse!.fileTypeId == 4) 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( ClipRRect(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
child: SizedBox( child: SizedBox(
@ -116,8 +109,15 @@ class ChatBubble extends StatelessWidget {
anchorPoint: screenOffset, anchorPoint: screenOffset,
builder: (BuildContext context) => ChatImagePreviewScreen(imgTitle: cItem.contant!, img: cItem.image!), 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().expanded,
],
),
Align( Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: Row( child: Row(
@ -200,10 +200,19 @@ class ChatBubble extends StatelessWidget {
); );
}) })
else 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).expanded,
],
),
Align( Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: dateTime.toText10(color: Colors.white.withOpacity(.71)), child: dateTime.toText10(color: Colors.white.withOpacity(.71),),
), ),
], ],
), ),

@ -12,20 +12,28 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/call.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/models/chat/get_single_user_chat_list_model.dart';
import 'package:mohem_flutter_app/provider/chat_provider_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'; 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/ui/chat/chat_bubble.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.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:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:signalr_netcore/signalr_client.dart'; import 'package:signalr_netcore/signalr_client.dart';
import 'package:swipe_to/swipe_to.dart'; import 'package:swipe_to/swipe_to.dart';
class ChatDetailedScreenParams {
ChatUser? chatUser;
bool? isNewChat;
ChatDetailedScreenParams(this.chatUser, this.isNewChat);
}
class ChatDetailScreen extends StatefulWidget { class ChatDetailScreen extends StatefulWidget {
// ignore: prefer_const_constructors_in_immutables const ChatDetailScreen({Key? key}) : super(key: key);
ChatDetailScreen({Key? key}) : super(key: key);
@override @override
State<ChatDetailScreen> createState() => _ChatDetailScreenState(); State<ChatDetailScreen> createState() => _ChatDetailScreenState();
@ -33,16 +41,16 @@ class ChatDetailScreen extends StatefulWidget {
class _ChatDetailScreenState extends State<ChatDetailScreen> { class _ChatDetailScreenState extends State<ChatDetailScreen> {
final RefreshController _rc = RefreshController(initialRefresh: false); final RefreshController _rc = RefreshController(initialRefresh: false);
dynamic userDetails;
late ChatProviderModel data; late ChatProviderModel data;
ChatDetailedScreenParams? params;
void getMoreChat() async { void getMoreChat() async {
if (userDetails != null) { if (params != null) {
data.paginationVal = data.paginationVal + 10; data.paginationVal = data.paginationVal + 10;
if (userDetails != null) { if (params != null) {
data.getSingleUserChatHistory( data.getSingleUserChatHistory(
senderUID: AppState().chatDetails!.response!.id!.toInt(), senderUID: AppState().chatDetails!.response!.id!.toInt(),
receiverUID: userDetails["targetUser"].id, receiverUID: params!.chatUser!.id!,
loadMore: true, loadMore: true,
isNewChat: false, isNewChat: false,
); );
@ -56,24 +64,26 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
userDetails = ModalRoute.of(context)!.settings.arguments; params = ModalRoute.of(context)!.settings.arguments as ChatDetailedScreenParams;
data = Provider.of<ChatProviderModel>(context, listen: false); data = Provider.of<ChatProviderModel>(context, listen: false);
if (userDetails != null) { if (params != null) {
data.getSingleUserChatHistory( data.getSingleUserChatHistory(
senderUID: AppState().chatDetails!.response!.id!.toInt(), senderUID: AppState().chatDetails!.response!.id!.toInt(),
receiverUID: userDetails["targetUser"].id, receiverUID: params!.chatUser!.id!,
loadMore: false, loadMore: false,
isNewChat: userDetails["isNewChat"], isNewChat: params!.isNewChat!,
); );
} }
return Scaffold( return Scaffold(
backgroundColor: MyColors.backgroundColor, backgroundColor: MyColors.backgroundColor,
appBar: AppBarWidget( appBar: ChatAppBarWidget(
context, context,
title: userDetails["targetUser"].userName.toString().replaceAll(".", " ").capitalizeFirstofEach, title: params!.chatUser!.userName.toString().replaceAll(".", " ").capitalizeFirstofEach,
showHomeButton: false, 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,
chatUser: params!.chatUser,
actions: [ actions: [
SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() { SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() {
// makeCall(callType: "AUDIO", con: hubConnection); // makeCall(callType: "AUDIO", con: hubConnection);
@ -85,7 +95,8 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
21.width, 21.width,
], ],
), ),
body: Consumer<ChatProviderModel>( body: SafeArea(
child: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) { builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return (m.isLoading return (m.isLoading
? ChatHomeShimmer( ? ChatHomeShimmer(
@ -124,8 +135,11 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
m.userChatHistory[i], m.userChatHistory[i],
); );
}, },
).onPress(() { ).onPress(() async {
logger.d(jsonEncode(m.userChatHistory[i])); if (m.userChatHistory[i].fileTypeResponse != null) {
m.getChatMedia(context,
fileTypeName: m.userChatHistory[i].fileTypeResponse!.fileTypeName ?? "", fileTypeID: m.userChatHistory[i].fileTypeId!, fileName: m.userChatHistory[i].contant!);
}
}); });
}, },
), ),
@ -152,7 +166,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
], ],
).expanded, ).expanded,
12.width, 12.width,
if (m.isMsgReply && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg), if (m.isMsgReply && m.repliedMsg.isNotEmpty) showReplyImage(m.repliedMsg, m),
12.width, 12.width,
const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe), const Icon(Icons.cancel, size: 23, color: MyColors.grey7BColor).onPress(m.closeMe),
], ],
@ -209,7 +223,11 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
), ),
).paddingOnly(right: 25), ).paddingOnly(right: 25),
SvgPicture.asset("assets/icons/chat/chat_send_icon.svg", height: 26, width: 26).onPress( 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(context,
targetUserId: params!.chatUser!.id!,
userStatus: params!.chatUser!.userStatus ?? 0,
userEmail: params!.chatUser!.email!,
targetUserName: params!.chatUser!.userName!),
), ),
], ],
), ),
@ -220,10 +238,11 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
)); ));
}, },
), ),
),
); );
} }
Widget showReplyImage(List<SingleUserChatModel> data) { Widget showReplyImage(List<SingleUserChatModel> data, ChatProviderModel m) {
if (data.first.isImageLoaded! && data.first.image != null) { if (data.first.isImageLoaded! && data.first.image != null) {
return Container( return Container(
width: 43, width: 43,
@ -232,7 +251,14 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), image: DecorationImage(image: MemoryImage(data.first.image!), fit: BoxFit.cover)), border: Border.all(color: MyColors.darkGrey3BColor, width: 1), borderRadius: BorderRadius.circular(10.0), image: DecorationImage(image: MemoryImage(data.first.image!), fit: BoxFit.cover)),
); );
} else { } else {
return const SizedBox(); return data.first.fileTypeResponse != null && data.first.fileTypeResponse!.fileTypeName != null
? Container(
width: 43,
height: 43,
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))
: const SizedBox();
} }
} }
@ -240,7 +266,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
print("================== Make call Triggered ============================"); print("================== Make call Triggered ============================");
Map<String, dynamic> json = { Map<String, dynamic> json = {
"callerID": AppState().chatDetails!.response!.id!.toString(), "callerID": AppState().chatDetails!.response!.id!.toString(),
"callReceiverID": userDetails["targetUser"].id.toString(), "callReceiverID": params!.chatUser!.id.toString(),
"notification_foreground": "true", "notification_foreground": "true",
"message": "Aamir is calling", "message": "Aamir is calling",
"title": "Video Call", "title": "Video Call",
@ -259,7 +285,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
{ {
"isSeen": false, "isSeen": false,
"isDelivered": false, "isDelivered": false,
"targetUserId": userDetails["targetUser"].id, "targetUserId": params!.chatUser!.id!,
"targetUserStatus": 4, "targetUserStatus": 4,
} }
], ],

@ -30,6 +30,15 @@ class _ChatHomeState extends State<ChatHome> {
super.initState(); super.initState();
data = Provider.of<ChatProviderModel>(context, listen: false); data = Provider.of<ChatProviderModel>(context, listen: false);
data.registerEvents(); data.registerEvents();
}
@override
void dispose() {
super.dispose();
data.clearAll();
}
void fetchAgain() {
if (chatHubConnection.state != HubConnectionState.Connected) { if (chatHubConnection.state != HubConnectionState.Connected) {
data.getUserAutoLoginToken().whenComplete(() async { data.getUserAutoLoginToken().whenComplete(() async {
await data.buildHubConnection(); await data.buildHubConnection();
@ -42,14 +51,9 @@ class _ChatHomeState extends State<ChatHome> {
} }
} }
@override
void dispose() {
super.dispose();
data.clearAll();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
fetchAgain();
return Scaffold( return Scaffold(
backgroundColor: MyColors.white, backgroundColor: MyColors.white,
appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true), appBar: AppBarWidget(context, title: LocaleKeys.chat.tr(), showHomeButton: true),
@ -85,7 +89,6 @@ class _ChatHomeState extends State<ChatHome> {
onPageChanged: (int pageIndex) { onPageChanged: (int pageIndex) {
setState(() { setState(() {
tabIndex = pageIndex; tabIndex = pageIndex;
}); });
}, },
children: <Widget>[ children: <Widget>[

@ -1,22 +1,20 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data'; import 'package:animated_text_kit/animated_text_kit.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_des/flutter_des.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/app_state/app_state.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/colors.dart';
import 'package:mohem_flutter_app/classes/encryption.dart';
import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/string_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/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.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/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_sheet.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_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:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart';
@ -53,7 +51,9 @@ class _ChatHomeScreenState extends State<ChatHomeScreen> {
body: Consumer<ChatProviderModel>( body: Consumer<ChatProviderModel>(
builder: (BuildContext context, ChatProviderModel m, Widget? child) { builder: (BuildContext context, ChatProviderModel m, Widget? child) {
return m.isLoading return m.isLoading
? ChatHomeShimmer(isDetailedScreen: false,) ? ChatHomeShimmer(
isDetailedScreen: false,
)
: Column( : Column(
children: <Widget>[ children: <Widget>[
TextField( TextField(
@ -102,20 +102,24 @@ class _ChatHomeScreenState extends State<ChatHomeScreen> {
height: 48, height: 48,
width: 48, width: 48,
).toShimmer().circle(30), ).toShimmer().circle(30),
if (m.searchedChats![index].isImageLoaded! && m.searchedChats![index].image.isNotEmpty) if (!m.searchedChats![index].isImageLoading! && m.searchedChats![index].userLocalDownlaodedImage == null)
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)
SvgPicture.asset( SvgPicture.asset(
"assets/images/user.svg", "assets/images/user.svg",
height: 48, height: 48,
width: 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( Positioned(
right: 5, right: 5,
bottom: 1, bottom: 1,
@ -128,14 +132,20 @@ class _ChatHomeScreenState extends State<ChatHomeScreen> {
).circle(10), ).circle(10),
) )
], ],
).onPress(() { ),
print(jsonEncode(m.searchedChats![index]));
}),
Column( Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
(m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 13), (m.searchedChats![index].userName!.replaceFirst(".", " ").capitalizeFirstofEach ?? "").toText14(color: MyColors.darkTextColor).paddingOnly(left: 11, top: 13),
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, ).expanded,
SizedBox( SizedBox(
@ -194,7 +204,7 @@ class _ChatHomeScreenState extends State<ChatHomeScreen> {
Navigator.pushNamed( Navigator.pushNamed(
context, context,
AppRoutes.chatDetailed, AppRoutes.chatDetailed,
arguments: {"targetUser": m.searchedChats![index], "isNewChat": false}, arguments: ChatDetailedScreenParams(m.searchedChats![index], false),
).then((Object? value) { ).then((Object? value) {
m.clearSelections(); m.clearSelections();
m.notifyListeners(); m.notifyListeners();

@ -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/config/routes.dart';
import 'package:mohem_flutter_app/extensions/string_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/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/circular_avatar.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -45,20 +46,24 @@ class ChatFavoriteUsersScreen extends StatelessWidget {
height: 48, height: 48,
width: 48, width: 48,
).toShimmer().circle(30), ).toShimmer().circle(30),
if (m.favUsersList![index].isImageLoaded! && m.favUsersList![index].image != null && m.favUsersList![index].image.isNotEmpty) if (!m.favUsersList![index].isImageLoading! && m.favUsersList![index].userLocalDownlaodedImage == null)
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)
SvgPicture.asset( SvgPicture.asset(
"assets/images/user.svg", "assets/images/user.svg",
height: 48, height: 48,
width: 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( Positioned(
right: 5, right: 5,
bottom: 1, bottom: 1,
@ -106,7 +111,7 @@ class ChatFavoriteUsersScreen extends StatelessWidget {
Navigator.pushNamed( Navigator.pushNamed(
context, context,
AppRoutes.chatDetailed, AppRoutes.chatDetailed,
arguments: {"targetUser": m.favUsersList![index], "isNewChat": false}, arguments: ChatDetailedScreenParams(m.favUsersList![index], true),
).then( ).then(
(Object? value) { (Object? value) {
m.clearSelections(); m.clearSelections();

@ -58,7 +58,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
data = Provider.of<DashboardProviderModel>(context, listen: false); data = Provider.of<DashboardProviderModel>(context, listen: false);
marathonProvider = Provider.of<MarathonProvider>(context, listen: false); marathonProvider = Provider.of<MarathonProvider>(context, listen: false);
cProvider = Provider.of<ChatProviderModel>(context, listen: false); cProvider = Provider.of<ChatProviderModel>(context, listen: false);
_bHubCon();
_onRefresh(); _onRefresh();
}); });
} }
@ -72,11 +72,15 @@ class _DashboardScreenState extends State<DashboardScreen> {
void _bHubCon() { void _bHubCon() {
cProvider.getUserAutoLoginToken().whenComplete(() { cProvider.getUserAutoLoginToken().whenComplete(() {
cProvider.buildHubConnection(); cProvider.buildHubConnection();
Future.delayed(const Duration(seconds: 2), () {
cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!);
});
}); });
} }
void _onRefresh() async { void _onRefresh() async {
data.initProvider(); data.initProvider();
_bHubCon();
// data.getITGNotification().then((value) { // data.getITGNotification().then((value) {
// print("--------------------detail_1-----------------"); // print("--------------------detail_1-----------------");
// print(value!.result!.data!.notificationMasterId); // print(value!.result!.data!.notificationMasterId);
@ -90,7 +94,6 @@ class _DashboardScreenState extends State<DashboardScreen> {
data.fetchMenuEntries(); data.fetchMenuEntries();
data.getCategoryOffersListAPI(context); data.getCategoryOffersListAPI(context);
marathonProvider.getMarathonDetailsFromApi(); marathonProvider.getMarathonDetailsFromApi();
data.fetchChatCounts();
_refreshController.refreshCompleted(); _refreshController.refreshCompleted();
} }
@ -503,8 +506,8 @@ class _DashboardScreenState extends State<DashboardScreen> {
"assets/icons/chat/chat.svg", "assets/icons/chat/chat.svg",
color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color, color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4), ).paddingAll(4),
Consumer<DashboardProviderModel>( Consumer<ChatProviderModel>(
builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) { builder: (BuildContext cxt, ChatProviderModel data, Widget? child) {
return Positioned( return Positioned(
right: 0, right: 0,
top: 0, top: 0,
@ -538,9 +541,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
} else if (index == 3) { } else if (index == 3) {
Navigator.pushNamed(context, AppRoutes.itemsForSale); Navigator.pushNamed(context, AppRoutes.itemsForSale);
} else if (index == 4) { } else if (index == 4) {
Navigator.pushNamed(context, AppRoutes.chat).then((Object? value) { Navigator.pushNamed(context, AppRoutes.chat);
data.fetchChatCounts();
});
} }
}, },
), ),

@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/leave_balance_api_client.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/date_uitl.dart';
import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.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'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
class AddLeaveBalanceScreen extends StatefulWidget { class AddLeaveBalanceScreen extends StatefulWidget {
AddLeaveBalanceScreen({Key? key}) : super(key: key); final String selectedEmp;
AddLeaveBalanceScreen({this.selectedEmp = '', Key? key}) : super(key: key);
@override @override
_AddLeaveBalanceScreenState createState() { _AddLeaveBalanceScreenState createState() {
@ -42,19 +44,21 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
int? totalDays; int? totalDays;
String comment = ""; String comment = "";
ReplacementList? selectedReplacementEmployee; ReplacementList? selectedReplacementEmployee;
dynamic dynamicParams;
String selectedEmp = "";
DateTime selectedDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day); DateTime selectedDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day);
@override @override
void initState() { void initState() {
super.initState(); super.initState();
getAbsenceAttendanceTypes(); //getAbsenceAttendanceTypes();
} }
void getAbsenceAttendanceTypes() async { void getAbsenceAttendanceTypes() async {
try { try {
Utils.showLoading(context); Utils.showLoading(context);
absenceList = await LeaveBalanceApiClient().getAbsenceAttendanceTypes(); absenceList = await LeaveBalanceApiClient().getAbsenceAttendanceTypes(empID: selectedEmp);
Utils.hideLoading(context); Utils.hideLoading(context);
setState(() {}); setState(() {});
} catch (ex) { } catch (ex) {
@ -67,7 +71,7 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
try { try {
Utils.showLoading(context); Utils.showLoading(context);
getabsenceDffStructureList.clear(); 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); Utils.hideLoading(context);
setState(() {}); setState(() {});
} catch (ex) { } catch (ex) {
@ -80,7 +84,7 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
try { try {
Utils.showLoading(context); Utils.showLoading(context);
CalculateAbsenceDuration duration = await LeaveBalanceApiClient() 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(); totalDays = duration.pABSENCEDAYS?.toInt();
Utils.hideLoading(context); Utils.hideLoading(context);
@ -91,7 +95,7 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
} }
} }
void validateAbsenceTransaction() async { void validateAbsenceTransaction(selectedID) async {
try { try {
Utils.showLoading(context); Utils.showLoading(context);
Map<String, String?> dffDataMap = {}; Map<String, String?> dffDataMap = {};
@ -118,7 +122,8 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"),
-999, -999,
dffDataMap, dffDataMap,
comments: comment); comments: comment,
empID: selectedEmp);
SumbitAbsenceTransactionList submit = await LeaveBalanceApiClient().submitAbsenceTransaction( SumbitAbsenceTransactionList submit = await LeaveBalanceApiClient().submitAbsenceTransaction(
selectedAbsenceType!.dESCFLEXCONTEXTCODE!, selectedAbsenceType!.dESCFLEXCONTEXTCODE!,
@ -129,7 +134,8 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"),
-999, -999,
dffDataMap, dffDataMap,
comments: comment); comments: comment,
empID: selectedEmp);
Utils.hideLoading(context); Utils.hideLoading(context);
@ -152,6 +158,16 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (dynamicParams == null) {
dynamicParams = ModalRoute.of(context)!.settings.arguments;
if (dynamicParams!= null && dynamicParams.isNotEmpty) {
AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams;
selectedEmp = dynamicParams;
getAbsenceAttendanceTypes();
} else {
getAbsenceAttendanceTypes();
}
}
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: AppBarWidget( appBar: AppBarWidget(
@ -269,7 +285,7 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
validateFieldData() validateFieldData()
? null ? null
: () { : () {
validateAbsenceTransaction(); validateAbsenceTransaction(selectedEmp);
}, },
).insideContainer ).insideContainer
], ],

@ -1,6 +1,7 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/leave_balance_api_client.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/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.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'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart';
class LeaveBalance extends StatefulWidget { class LeaveBalance extends StatefulWidget {
LeaveBalance({Key? key}) : super(key: key); final String selectedEmp;
LeaveBalance({this.selectedEmp = '', Key? key}) : super(key: key);
@override @override
_LeaveBalanceState createState() { _LeaveBalanceState createState() {
@ -25,12 +27,13 @@ class _LeaveBalanceState extends State<LeaveBalance> {
List<GetAbsenceTransactionList>? absenceTransList; List<GetAbsenceTransactionList>? absenceTransList;
DateTime accrualDateTime = DateTime.now(); DateTime accrualDateTime = DateTime.now();
dynamic dynamicParams;
String selectedEmp = "";
@override @override
void initState() { void initState() {
super.initState(); super.initState();
absenceTransList = [];
getAbsenceTransactions();
} }
@override @override
@ -40,9 +43,9 @@ class _LeaveBalanceState extends State<LeaveBalance> {
void getAbsenceTransactions() async { void getAbsenceTransactions() async {
try { try {
Utils.showLoading(context); // Utils.showLoading(context);
absenceTransList = await LeaveBalanceApiClient().getAbsenceTransactions(-999); absenceTransList = await LeaveBalanceApiClient().getAbsenceTransactions(-999, empID: selectedEmp);
Utils.hideLoading(context); //Utils.hideLoading(context);
setState(() {}); setState(() {});
} catch (ex) { } catch (ex) {
Utils.hideLoading(context); Utils.hideLoading(context);
@ -52,6 +55,16 @@ class _LeaveBalanceState extends State<LeaveBalance> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (dynamicParams == null) {
dynamicParams = ModalRoute.of(context)!.settings.arguments;
if (dynamicParams!= null && dynamicParams.isNotEmpty) {
AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams;
selectedEmp = dynamicParams;
getAbsenceTransactions();
} else {
getAbsenceTransactions();
}
}
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: AppBarWidget( appBar: AppBarWidget(
@ -62,7 +75,7 @@ class _LeaveBalanceState extends State<LeaveBalance> {
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(21), padding: const EdgeInsets.all(21),
children: [ children: [
BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true), BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true, selectedEmp),
12.height, 12.height,
absenceTransList == null absenceTransList == null
? const SizedBox() ? const SizedBox()
@ -111,7 +124,7 @@ class _LeaveBalanceState extends State<LeaveBalance> {
), ),
child: const Icon(Icons.add, color: Colors.white, size: 30), child: const Icon(Icons.add, color: Colors.white, size: 30),
).onPress(() { ).onPress(() {
Navigator.pushNamed(context, AppRoutes.addLeaveBalance); Navigator.pushNamed(context, AppRoutes.addLeaveBalance, arguments: selectedEmp ?? '');
}), }),
); );
} }

@ -642,6 +642,7 @@ class _VerifyLoginScreenState extends State<VerifyLoginScreen> {
PrivilegeListModel.saveToPrefs(genericResponseModel.privilegeList ?? []); PrivilegeListModel.saveToPrefs(genericResponseModel.privilegeList ?? []);
AppState().setMohemmWifiSSID = genericResponseModel.mohemmWifiSSID; AppState().setMohemmWifiSSID = genericResponseModel.mohemmWifiSSID;
AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword; AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword;
AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword;
Utils.saveStringFromPrefs(SharedPrefsConsts.username, AppState().getUserName!); Utils.saveStringFromPrefs(SharedPrefsConsts.username, AppState().getUserName!);
Utils.saveStringFromPrefs(SharedPrefsConsts.password, AppState().password!); Utils.saveStringFromPrefs(SharedPrefsConsts.password, AppState().password!);
Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiSSID, genericResponseModel.mohemmWifiSSID!); Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiSSID, genericResponseModel.mohemmWifiSSID!);

@ -5,10 +5,13 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/marathon/marathon_api_client.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/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.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/marathon_model.dart';
import 'package:mohem_flutter_app/models/marathon/question_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:mohem_flutter_app/ui/marathon/widgets/question_card.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
@ -22,10 +25,13 @@ class MarathonProvider extends ChangeNotifier {
QuestionModel currentQuestion = QuestionModel(); QuestionModel currentQuestion = QuestionModel();
List<QuestionCardStatus> answerStatusesList = <QuestionCardStatus>[]; List<QuestionCardStatus> answerStatusesList = <QuestionCardStatus>[];
QuestionCardStatus questionCardStatus = QuestionCardStatus.question; QuestionCardStatus questionCardStatus = QuestionCardStatus.question;
List<WinnerModel>? selectedWinners;
int? selectedOptionIndex; int? selectedOptionIndex;
String? selectedOptionId; String? selectedOptionId;
int totalQualifiers = 0; int? totalQualifiers;
bool iAmWinner = false;
bool isPrivilegedWithMarathon = false;
bool _isLoading = false; bool _isLoading = false;
@ -110,6 +116,7 @@ class MarathonProvider extends ChangeNotifier {
//****************TIMERS********** //****************TIMERS**********
int sponsorsSecondsCounter = 0;
int totalSponsorVideoSeconds = 0; int totalSponsorVideoSeconds = 0;
Timer timerForSponsorVideo = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); Timer timerForSponsorVideo = Timer.periodic(const Duration(seconds: 1), (Timer timer) {});
@ -118,6 +125,7 @@ class MarathonProvider extends ChangeNotifier {
timerForSponsorVideo = Timer.periodic( timerForSponsorVideo = Timer.periodic(
oneSec, oneSec,
(Timer timer) async { (Timer timer) async {
sponsorsSecondsCounter++;
if (totalSponsorVideoSeconds == 0) { if (totalSponsorVideoSeconds == 0) {
timer.cancel(); timer.cancel();
notifyListeners(); notifyListeners();
@ -134,12 +142,15 @@ class MarathonProvider extends ChangeNotifier {
int totalSecondsToWaitForMarathon = 20; int totalSecondsToWaitForMarathon = 20;
Timer timerToWaitForMarathon = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); Timer timerToWaitForMarathon = Timer.periodic(const Duration(seconds: 1), (Timer timer) {});
void startTimerToMarathon(BuildContext context) { void startTimerToWaitForMarathon() {
const Duration oneSec = Duration(seconds: 1); const Duration oneSec = Duration(seconds: 1);
timerToWaitForMarathon = Timer.periodic( timerToWaitForMarathon = Timer.periodic(
oneSec, oneSec,
(Timer timer) async { (Timer timer) async {
if (totalSecondsToWaitForMarathon == 0) { if (totalSecondsToWaitForMarathon == 0) {
callNextQuestionApi();
timer.cancel();
return;
} else { } else {
totalSecondsToWaitForMarathon--; totalSecondsToWaitForMarathon--;
} }
@ -158,11 +169,13 @@ class MarathonProvider extends ChangeNotifier {
oneSec, oneSec,
(Timer timer) async { (Timer timer) async {
// This 2 is just to show the color of answer tile for 2 seconds and then update card status // 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(); getCorrectAnswerAndUpdateAnswerColor();
} }
if (totalCurrentQuestionTime == currentGapTime) { if (totalCurrentQuestionTime == currentGapTime) {
totalCurrentQuestionTime--;
updateCardStatusToAnswer(); updateCardStatusToAnswer();
await callSubmitOptionApi().then((bool value) async { await callSubmitOptionApi().then((bool value) async {
@ -174,7 +187,8 @@ class MarathonProvider extends ChangeNotifier {
if (totalCurrentQuestionTime == 0) { if (totalCurrentQuestionTime == 0) {
updateCardData(); updateCardData();
if (currentQuestionNumber == marathonDetailModel.totalQuestions! - 1) { if (currentQuestionNumber == marathonDetailModel.totalQuestions! ) {
callGetQualifiersApi();
updateQuestionCardStatus(QuestionCardStatus.findingWinner); updateQuestionCardStatus(QuestionCardStatus.findingWinner);
timer.cancel(); timer.cancel();
cancelTimer(); cancelTimer();
@ -182,8 +196,10 @@ class MarathonProvider extends ChangeNotifier {
} }
return; return;
} else { } else {
if (totalCurrentQuestionTime != currentGapTime) {
totalCurrentQuestionTime--; totalCurrentQuestionTime--;
} }
}
notifyListeners(); notifyListeners();
}, },
@ -214,7 +230,30 @@ class MarathonProvider extends ChangeNotifier {
//****************FUNCTIONS********* //****************FUNCTIONS*********
Future<bool> callSubmitOptionApi() async { Future<bool> callSubmitOptionApi() async {
return await MarathonApiClient().submitSelectedOption(selectedAnswerId: selectedOptionId); return await MarathonApiClient().submitSelectedOption(marathonId: marathonDetailModel.id!, questionId: currentQuestion.id, selectedAnswerId: selectedOptionId);
}
Future<void> callGetQualifiersApi() async {
totalQualifiers = await MarathonApiClient().getQualifiers(marathonId: marathonDetailModel.id!);
notifyListeners();
}
Future<void> 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();
} }
// 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: 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 +261,7 @@ class MarathonProvider extends ChangeNotifier {
Future<void> callNextQuestionApi() async { Future<void> callNextQuestionApi() async {
if (currentQuestionNumber < marathonDetailModel.totalQuestions!) { if (currentQuestionNumber < marathonDetailModel.totalQuestions!) {
if (currentQuestionNumber == 0) { if (currentQuestionNumber == 0) {
Utils.showLoading(AppRoutes.navigatorKey.currentContext!);
currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!))!; currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!))!;
if (Utils.isLoading) { if (Utils.isLoading) {
Utils.hideLoading(AppRoutes.navigatorKey.currentContext!); Utils.hideLoading(AppRoutes.navigatorKey.currentContext!);
@ -239,8 +279,7 @@ class MarathonProvider extends ChangeNotifier {
void updateCardData() { void updateCardData() {
if (currentQuestionNumber > 0) { if (currentQuestionNumber > 0) {
print("swiped it away!!"); swiperController.swipeLeft();
swipeCardLeft();
} }
selectedOptionIndex = null; selectedOptionIndex = null;
currentQuestionNumber++; currentQuestionNumber++;
@ -249,6 +288,7 @@ class MarathonProvider extends ChangeNotifier {
currentGapTime = currentQuestion.nextQuestGap!; currentGapTime = currentQuestion.nextQuestGap!;
totalMarathoners = currentQuestion.remainingParticipantCount!; totalMarathoners = currentQuestion.remainingParticipantCount!;
questionCardStatus = QuestionCardStatus.question; questionCardStatus = QuestionCardStatus.question;
notifyListeners();
} }
void populateQuestionStatusesList() { void populateQuestionStatusesList() {
@ -316,20 +356,21 @@ class MarathonProvider extends ChangeNotifier {
} }
} }
void swipeCardLeft() {
swiperController.swipeLeft();
notifyListeners();
}
void resetValues() async { void resetValues() async {
_currentQuestionNumber = 0; _currentQuestionNumber = 0;
cardContentList.clear(); cardContentList.clear();
timerForWinnerSelection.cancel(); timerForWinnerSelection.cancel();
timerForSponsorVideo.cancel();
timerToWaitForMarathon.cancel();
timerForQuestion.cancel(); timerForQuestion.cancel();
_isMarathonCompleted = false; _isMarathonCompleted = false;
isUserOutOfGame = false;
totalCurrentQuestionTime = 0; totalCurrentQuestionTime = 0;
sponsorsSecondsCounter = 0;
totalSponsorVideoSeconds = 0;
totalSecondsToWaitForMarathon = 20;
currentGapTime = 0;
currentQuestion = QuestionModel(); currentQuestion = QuestionModel();
notifyListeners(); notifyListeners();
} }
@ -338,56 +379,54 @@ class MarathonProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
bool checkIfPrivilegedForMarathon() {
for (PrivilegeListModel element in AppState().privilegeListModel!) {
if (element.serviceName == "Marathon") {
if (element.previlege != null) {
return element.previlege!;
}
}
}
return false;
}
Future<void> getMarathonDetailsFromApi() async { Future<void> getMarathonDetailsFromApi() async {
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
isPrivilegedWithMarathon = checkIfPrivilegedForMarathon();
if (isPrivilegedWithMarathon) {
await MarathonApiClient().getMarathonToken().whenComplete(() async { await MarathonApiClient().getMarathonToken().whenComplete(() async {
marathonDetailModel = await MarathonApiClient().getMarathonDetails(); marathonDetailModel = await MarathonApiClient().getMarathonDetails();
if (marathonDetailModel.id == null) { if (marathonDetailModel.id == null) {
isUpComingMarathon = false; isUpComingMarathon = false;
isLoading = false;
notifyListeners(); notifyListeners();
return; return;
} }
populateQuestionStatusesList(); populateQuestionStatusesList();
});
}
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();
});
} }
Future<void> buildConnectionWithSignalR(BuildContext context) async { Future<void> onJoinMarathonPressed(BuildContext context) async {
Utils.showLoading(context);
try { try {
Utils.showLoading(context);
resetValues(); 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) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print("error in buildConnectionWithSignalR: ${e.toString()}"); print("error in onJoinMarathonPressed: ${e.toString()}");
} }
Utils.hideLoading(context); Utils.hideLoading(context);
Utils.confirmDialog(context, e.toString()); Utils.confirmDialog(context, e.toString());
} }
} }
Future<void> 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());
}
}
}
} }

@ -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/colors.dart';
import 'package:mohem_flutter_app/classes/decorations_helper.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/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/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_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/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.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/question_card_builder.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/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class MarathonScreen extends StatelessWidget { class MarathonScreen extends StatelessWidget {
@ -42,43 +43,77 @@ class MarathonScreen extends StatelessWidget {
return Image.asset(MyLottieConsts.congratsGif, height: 200); return Image.asset(MyLottieConsts.congratsGif, height: 200);
} }
// SizedBox(
// height: 200,
// child: Stack(
// fit: StackFit.expand,
// children: <Widget>[
// Lottie.asset(MyLottieConsts.celebrate1Lottie, height: 200),
// // Lottie.asset(MyLottieConsts.celebrate2Lottie, height: 200),
// ],
// ),
// ),
Widget getWinnerWidget(BuildContext context, {required MarathonProvider provider}) { Widget getWinnerWidget(BuildContext context, {required MarathonProvider provider}) {
return Container( return Container(
width: double.infinity, width: double.infinity,
decoration: MyDecorations.shadowDecoration, decoration: MyDecorations.shadowDecoration,
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 200,
child: Stack( child: Stack(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Lottie.asset(MyLottieConsts.celebrate1Lottie, height: 200),
Lottie.asset(MyLottieConsts.celebrate2Lottie, height: 200),
],
),
),
26.height,
SizedBox( SizedBox(
height: 50, height: 50,
child: Stack( child: Stack(
children: [ children: <Widget>[
Align( Align(
alignment: Alignment.center, alignment: Alignment.center,
child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50), child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50),
), ),
Align( Align(
alignment: Alignment.center, alignment: Alignment.center,
child: LocaleKeys.winner.tr().toText32(color: MyColors.white, isBold: true).paddingOnly(top: 07), child: LocaleKeys.winners.tr().toText32(color: MyColors.white, isBold: true, isCentered: true).paddingOnly(top: 07),
) )
], ],
), ),
), ),
12.height, 16.height,
"Muhammad Shrouff".toText22(color: MyColors.grey3AColor), !provider.iAmWinner
"837436".toText22(color: MyColors.grey57Color), ? Column(
80.height, children: <Widget>[
(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) ...<Widget>[
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),
],
);
},
),
],
60.height,
if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...<Widget>[ if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...<Widget>[
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -103,6 +138,9 @@ class MarathonScreen extends StatelessWidget {
], ],
], ],
), ),
Lottie.asset(MyLottieConsts.celebrate1Lottie),
],
),
); );
} }
@ -118,12 +156,12 @@ class MarathonScreen extends StatelessWidget {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
(AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr!) (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!)
.toText17(isBold: true, color: MyColors.white), .toText17(isBold: true, color: MyColors.white),
AppState().memberInformationList!.eMPLOYEENUMBER!.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 @override
@ -135,10 +173,38 @@ class MarathonScreen extends StatelessWidget {
context, context,
title: LocaleKeys.brainMarathon.tr(), title: LocaleKeys.brainMarathon.tr(),
onHomeTapped: () { 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: () { 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( body: SingleChildScrollView(
@ -156,7 +222,7 @@ class MarathonScreen extends StatelessWidget {
getNameContainer(context), getNameContainer(context),
], ],
QuestionCardBuilder( QuestionCardBuilder(
onQuestion: (BuildContext context) => QuestionCard(provider: provider), onQuestion: (BuildContext context) => const QuestionCard(),
onCompleted: (BuildContext context) => CustomStatusWidget( onCompleted: (BuildContext context) => CustomStatusWidget(
asset: Lottie.asset(MyLottieConsts.allQuestions, height: 200), asset: Lottie.asset(MyLottieConsts.allQuestions, height: 200),
title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor), title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor),

@ -25,6 +25,9 @@ class SponsorVideoScreen extends StatelessWidget {
return WillPopScope( return WillPopScope(
onWillPop: () { onWillPop: () {
provider.videoController.dispose(); provider.videoController.dispose();
provider.sponsorsSecondsCounter = 0;
provider.totalSponsorVideoSeconds = 0;
provider.timerForSponsorVideo.cancel();
return Future<bool>.value(true); return Future<bool>.value(true);
}, },
child: Scaffold( child: Scaffold(
@ -52,9 +55,11 @@ class SponsorVideoScreen extends StatelessWidget {
child: provider.totalSponsorVideoSeconds == 0 child: provider.totalSponsorVideoSeconds == 0
? InkWell( ? InkWell(
onTap: () { onTap: () {
Navigator.pop(context);
provider.videoController.dispose(); 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), child: const Icon(Icons.close, size: 12),
) )
@ -64,13 +69,18 @@ class SponsorVideoScreen extends StatelessWidget {
), ),
), ),
).paddingOnly(top: 20, right: 18), ).paddingOnly(top: 20, right: 18),
Align(
//TODO: WE WILL INCREASE THIS 2 BEFORE GOING LIVE
provider.sponsorsSecondsCounter >= 2
? Align(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
Navigator.pop(context);
provider.videoController.dispose(); 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: Container( child: Container(
decoration: BoxDecoration(color: MyColors.white, borderRadius: BorderRadius.circular(15)), decoration: BoxDecoration(color: MyColors.white, borderRadius: BorderRadius.circular(15)),
@ -81,7 +91,8 @@ class SponsorVideoScreen extends StatelessWidget {
), ),
), ),
), ),
).paddingOnly(top: 20, left: 18), ).paddingOnly(top: 20, left: 18)
: const SizedBox(),
], ],
), ),
), ),

@ -4,12 +4,13 @@ import 'package:lottie/lottie.dart';
import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/decorations_helper.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/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/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_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/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.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/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class MarathonWaitingScreen extends StatelessWidget { class MarathonWaitingScreen extends StatelessWidget {
@ -18,15 +19,47 @@ class MarathonWaitingScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
MarathonProvider provider = context.watch<MarathonProvider>(); MarathonProvider provider = context.watch<MarathonProvider>();
return Scaffold( 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<bool>.value(false);
},
child: Scaffold(
appBar: AppBarWidget( appBar: AppBarWidget(
context, context,
title: LocaleKeys.brainMarathon.tr(), title: LocaleKeys.brainMarathon.tr(),
onHomeTapped: () { onHomeTapped: () {
Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); showDialog(
context: context,
builder: (BuildContext context) => ConfirmDialog(
message: LocaleKeys.youWantToLeaveMarathon.tr(),
onTap: () {
provider.resetValues();
Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard));
},
),
);
}, },
onBackTapped: () { onBackTapped: () {
Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); showDialog(
context: context,
builder: (BuildContext context) => ConfirmDialog(
message: LocaleKeys.youWantToLeaveMarathon.tr(),
onTap: () {
provider.resetValues();
Navigator.of(context).popUntil(ModalRoute.withName(AppRoutes.dashboard));
},
),
);
}, },
), ),
body: Column( body: Column(
@ -47,8 +80,21 @@ class MarathonWaitingScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
LocaleKeys.startingIn.tr().toText16(), LocaleKeys.startingIn.tr().toText16(),
"00:${provider.totalSecondsToWaitForMarathon < 10 ? "0${provider.totalSecondsToWaitForMarathon}" : provider.totalSecondsToWaitForMarathon}" provider.totalSecondsToWaitForMarathon.toString().toText18(color: provider.totalSecondsToWaitForMarathon < 5 ? MyColors.redColor : MyColors.black),
.toText18(color: provider.totalSecondsToWaitForMarathon < 5 ? MyColors.redColor : MyColors.black), ],
),
),
Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
InkWell(
onTap: () {
provider.callNextQuestionApi();
provider.timerToWaitForMarathon.cancel();
},
child: "Join Now".toText16(),
).paddingOnly(bottom: 20),
], ],
), ),
), ),
@ -57,6 +103,7 @@ class MarathonWaitingScreen extends StatelessWidget {
).expanded, ).expanded,
], ],
), ),
),
); );
} }
} }

@ -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<MarathonProvider>();
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: <Widget>[
"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),
],
),
),
);
}
}

@ -8,6 +8,7 @@ import 'package:flutter_countdown_timer/current_remaining_time.dart';
import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.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/marathon_provider.dart';
class BuildCountdownTimer extends StatelessWidget { class BuildCountdownTimer extends StatelessWidget {
@ -29,9 +30,10 @@ class BuildCountdownTimer extends StatelessWidget {
letterSpacing: -0.4, letterSpacing: -0.4,
); );
final TextStyle styleDigitHome = const TextStyle( final TextStyle styleDigitHome = TextStyle(
height: 22 / 27, height: 22 / 27,
color: MyColors.white, color: MyColors.white,
fontSize: isTablet ? 30 : 15,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
letterSpacing: -1.44, letterSpacing: -1.44,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -53,6 +55,33 @@ class BuildCountdownTimer extends StatelessWidget {
fontWeight: FontWeight.bold, 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() { Widget buildEmptyWidget() {
return Directionality( return Directionality(
textDirection: ui.TextDirection.ltr, textDirection: ui.TextDirection.ltr,
@ -63,70 +92,29 @@ class BuildCountdownTimer extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Column( Column(
children: <Widget>[ children: <Widget>[
// todo @faiz: Make a separate method and pass string , so we can minimize code replication getTimeDigit("00"),
AutoSizeText( getTimeText(LocaleKeys.days.tr()),
"00",
maxFontSize: 24,
minFontSize: 20,
style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon,
),
AutoSizeText(
LocaleKeys.days.tr(),
minFontSize: 7,
maxFontSize: 8,
style: screenFlag == 0 ? styleTextHome : styleTextMarathon,
),
], ],
), ),
buildSeparator(), buildSeparator(),
Column( Column(
children: <Widget>[ children: <Widget>[
AutoSizeText( getTimeDigit("00"),
"00", getTimeText(LocaleKeys.hours.tr()),
maxFontSize: 24,
minFontSize: 20,
style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon,
),
AutoSizeText(
LocaleKeys.hours.tr(),
minFontSize: 7,
maxFontSize: 8,
style: screenFlag == 0 ? styleTextHome : styleTextMarathon,
),
], ],
), ),
buildSeparator(), buildSeparator(),
Column( Column(
children: <Widget>[ children: <Widget>[
AutoSizeText( getTimeDigit("00"),
"00", getTimeText(LocaleKeys.minutes.tr()),
maxFontSize: 24,
minFontSize: 20,
style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon,
),
AutoSizeText(
LocaleKeys.minutes.tr(),
minFontSize: 7,
maxFontSize: 8,
style: screenFlag == 0 ? styleTextHome : styleTextMarathon,
),
], ],
), ),
buildSeparator(), buildSeparator(),
Column( Column(
children: <Widget>[ children: <Widget>[
AutoSizeText( getTimeDigit("00"),
"00", getTimeText(LocaleKeys.seconds.tr()),
maxFontSize: 24,
minFontSize: 20,
style: screenFlag == 0 ? styleDigitHome : styleDigitMarathon,
),
AutoSizeText(
LocaleKeys.seconds.tr(),
minFontSize: 7,
maxFontSize: 8,
style: screenFlag == 0 ? styleTextHome : styleTextMarathon,
),
], ],
), ),
], ],
@ -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) { Widget buildCountdownTimer(CurrentRemainingTime? time) {
if (time == null) { if (time == null) {
if (!provider.itsMarathonTime) { if (!provider.itsMarathonTime) {
@ -162,98 +141,29 @@ class BuildCountdownTimer extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Column( Column(
children: <Widget>[ children: <Widget>[
// todo @faiz: Make a separate method and pass value and string , so we can minimize code replication time.days == null ? getTimeDigit("00") : getTimeDigit(time.days! < 10 ? "0${time.days.toString()}" : time.days.toString()),
time.days == null getTimeText(LocaleKeys.days.tr()),
? 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,
),
], ],
), ),
buildSeparator(), buildSeparator(),
Column( Column(
children: <Widget>[ children: <Widget>[
time.hours == null time.hours == null ? getTimeDigit("00") : getTimeDigit(time.hours! < 10 ? "0${time.hours.toString()}" : time.hours.toString()),
? AutoSizeText( getTimeText(LocaleKeys.hours.tr()),
"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,
),
], ],
), ),
buildSeparator(), buildSeparator(),
Column( Column(
children: <Widget>[ children: <Widget>[
time.min == null time.min == null ? getTimeDigit("00") : getTimeDigit(time.min! < 10 ? "0${time.min.toString()}" : time.min.toString()),
? AutoSizeText( getTimeText(LocaleKeys.minutes.tr()),
"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,
),
], ],
), ),
buildSeparator(), buildSeparator(),
Column( Column(
children: <Widget>[ children: <Widget>[
time.sec == null time.sec == null ? getTimeDigit("00") : getTimeDigit(time.sec! < 10 ? "0${time.sec.toString()}" : time.sec.toString()),
? AutoSizeText( getTimeText(LocaleKeys.seconds.tr()),
"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,
),
], ],
), ),
], ],

@ -1,16 +1,18 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:auto_size_text/auto_size_text.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/app_state/app_state.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/colors.dart';
import 'package:mohem_flutter_app/classes/decorations_helper.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/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_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/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/marathon_provider.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -20,16 +22,177 @@ class MarathonBanner extends StatelessWidget {
const MarathonBanner({Key? key, required this.isMarathonUpcoming}) : super(key: key); const MarathonBanner({Key? key, required this.isMarathonUpcoming}) : super(key: key);
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: <Widget>[
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: <Widget>[
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: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
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)
? 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),
Container(
height: double.infinity,
width: double.infinity,
color: Colors.black.withOpacity(0.6),
child: const Icon(
Icons.lock_rounded,
color: MyColors.lightGreyIconColor,
),
),
],
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
MarathonProvider provider = context.read<MarathonProvider>(); MarathonProvider provider = context.read<MarathonProvider>();
return provider.marathonDetailModel.startTime != null
return !provider.isPrivilegedWithMarathon
? getUnPrivilegedMarathon(context)
: provider.marathonDetailModel.startTime != null
? Container( ? Container(
decoration: MyDecorations.shadowDecoration, 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, clipBehavior: Clip.antiAlias,
child: Stack( child: Stack(
children: [ children: <Widget>[
Transform( Transform(
alignment: Alignment.center, alignment: Alignment.center,
transform: Matrix4.rotationY( transform: Matrix4.rotationY(
@ -48,8 +211,8 @@ class MarathonBanner extends StatelessWidget {
child: Transform.rotate( child: Transform.rotate(
angle: 10, angle: 10,
child: Container( child: Container(
width: 65, width: isTablet ? 70 : 65,
height: 32, height: isTablet ? 40 : 32,
color: MyColors.darkDigitColor, color: MyColors.darkDigitColor,
), ),
), ),
@ -60,8 +223,8 @@ class MarathonBanner extends StatelessWidget {
child: Transform.rotate( child: Transform.rotate(
angle: 15, angle: 15,
child: Container( child: Container(
width: 65, width: isTablet ? 70 : 65,
height: 32, height: isTablet ? 40 : 32,
color: MyColors.darkDigitColor, color: MyColors.darkDigitColor,
), ),
), ),
@ -70,7 +233,7 @@ class MarathonBanner extends StatelessWidget {
width: double.infinity, width: double.infinity,
height: double.infinity, height: double.infinity,
child: Row( child: Row(
children: [ children: <Widget>[
const Expanded( const Expanded(
flex: 3, flex: 3,
child: SizedBox( child: SizedBox(
@ -92,28 +255,27 @@ class MarathonBanner extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
AppState().isArabic(context) ? 0.height : 5.height, AppState().isArabic(context) ? 0.height : 5.height,
AutoSizeText( Text(
LocaleKeys.getReadyForContest.tr(), LocaleKeys.getReadyForContest.tr(),
minFontSize: 08,
maxFontSize: 11,
style: TextStyle( style: TextStyle(
fontSize: isTablet ? 20 : 11,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: MyColors.white.withOpacity(0.83), color: MyColors.white.withOpacity(0.83),
letterSpacing: -0.4, letterSpacing: -0.4,
), ),
), ),
AutoSizeText( Text(
AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "", AppState().isArabic(context) ? provider.marathonDetailModel.titleAr ?? "" : provider.marathonDetailModel.titleEn ?? "",
style: TextStyle( style: TextStyle(
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
fontSize: 19, fontSize: isTablet ? 30 : 19,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: MyColors.white.withOpacity(0.83), color: MyColors.white.withOpacity(0.83),
height: 32 / 22, height: 32 / 22,
), ),
), ),
3.height, isTablet ? 10.height : 3.height,
BuildCountdownTimer( BuildCountdownTimer(
timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch,
provider: provider, provider: provider,
@ -135,18 +297,18 @@ class MarathonBanner extends StatelessWidget {
? Align( ? Align(
alignment: Alignment.topRight, alignment: Alignment.topRight,
child: SizedBox( child: SizedBox(
height: 20, height: isTablet ? 30 : 20,
width: 35, width: isTablet ? 45 : 35,
child: Transform.rotate( child: Transform.rotate(
angle: math.pi / 4.5, angle: math.pi / 4.5,
child: Text( child: Text(
LocaleKeys.brainMarathon.tr(), LocaleKeys.brainMarathon.tr(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 2, maxLines: 2,
style: const TextStyle( style: TextStyle(
color: MyColors.white, color: MyColors.white,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 6, fontSize: isTablet ? 8 : 6,
height: 1.2, height: 1.2,
), ),
), ),
@ -156,18 +318,18 @@ class MarathonBanner extends StatelessWidget {
: Align( : Align(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: SizedBox( child: SizedBox(
height: 20, height: isTablet ? 30 : 20,
width: 35, width: isTablet ? 45 : 35,
child: Transform.rotate( child: Transform.rotate(
angle: -math.pi / 4.5, angle: -math.pi / 4.5,
child: Text( child: Text(
LocaleKeys.brainMarathon.tr(), LocaleKeys.brainMarathon.tr(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 2, maxLines: 2,
style: const TextStyle( style: TextStyle(
color: MyColors.kWhiteColor, color: MyColors.kWhiteColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 6, fontSize: isTablet ? 8 : 6,
height: 1.2, height: 1.2,
), ),
), ),
@ -181,7 +343,7 @@ class MarathonBanner extends StatelessWidget {
child: RotatedBox( child: RotatedBox(
quarterTurns: 4, quarterTurns: 4,
child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor),
).paddingAll(15), ).paddingAll(isTablet ? 20 : 15),
) )
: Positioned( : Positioned(
bottom: 0, bottom: 0,
@ -189,12 +351,32 @@ class MarathonBanner extends StatelessWidget {
child: RotatedBox( child: RotatedBox(
quarterTurns: 2, quarterTurns: 2,
child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor), child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.whiteColor),
).paddingAll(15), ).paddingAll(isTablet ? 20 : 15),
), ),
], ],
).onPress( ).onPress(() async {
() => Navigator.pushNamed(context, AppRoutes.marathonIntroScreen), 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(); : const SizedBox();
} }

@ -20,6 +20,7 @@ class _QualifiersContainerState extends State<QualifiersContainer> {
@override @override
void initState() { void initState() {
widget.provider.startTimerForWinnerSelection(); widget.provider.startTimerForWinnerSelection();
widget.provider.callGetSelectedWinnersApi();
super.initState(); super.initState();
} }
@ -36,13 +37,14 @@ class _QualifiersContainerState extends State<QualifiersContainer> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
LocaleKeys.winnerSelection.tr().toText21(color: MyColors.grey3AColor), 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, 10.height,
Row( Row(
children: <Widget>[ children: <Widget>[
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, 2.width,
LocaleKeys.qualifiers.tr().toText16(color: MyColors.greenColor), LocaleKeys.qualifiers.tr().toText16(color: MyColors.greenColor),
], ],

@ -1,4 +1,5 @@
import 'package:appinio_swiper/appinio_swiper.dart'; import 'package:appinio_swiper/appinio_swiper.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart'; import 'package:lottie/lottie.dart';
@ -6,29 +7,28 @@ import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/decorations_helper.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/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/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_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/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/models/marathon/question_model.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class QuestionCard extends StatelessWidget { class QuestionCard extends StatelessWidget {
final MarathonProvider provider; const QuestionCard({Key? key}) : super(key: key);
const QuestionCard({Key? key, required this.provider}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
MarathonProvider provider = context.read<MarathonProvider>();
return CupertinoPageScaffold( return CupertinoPageScaffold(
child: provider.cardContentList.isEmpty child: provider.cardContentList.isEmpty
? Lottie.asset(MyLottieConsts.hourGlassLottie, height: 250).paddingOnly(top: 50) ? Lottie.asset(MyLottieConsts.hourGlassLottie, height: 250).paddingOnly(top: 50)
: SizedBox( : SizedBox(
height: 440, height: 440,
width: double.infinity, width: double.infinity,
child: Consumer<MarathonProvider>( child: AppinioSwiper(
builder: (BuildContext context, MarathonProvider provider, _) {
return AppinioSwiper(
duration: const Duration(milliseconds: 400), duration: const Duration(milliseconds: 400),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
isDisabled: true, isDisabled: true,
@ -36,8 +36,6 @@ class QuestionCard extends StatelessWidget {
unswipe: (int index, AppinioSwiperDirection direction) {}, unswipe: (int index, AppinioSwiperDirection direction) {},
onSwipe: (int index, AppinioSwiperDirection direction) {}, onSwipe: (int index, AppinioSwiperDirection direction) {},
cards: provider.cardContentList, cards: provider.cardContentList,
);
},
), ),
), ),
); );
@ -163,7 +161,7 @@ class AnswerTileForText extends StatelessWidget {
MarathonProvider provider = context.watch<MarathonProvider>(); MarathonProvider provider = context.watch<MarathonProvider>();
return InkWell( return InkWell(
onTap: () { onTap: () {
provider.isUserOutOfGame ? null : onAnswerTapped() ; provider.isUserOutOfGame ? Utils.showToast(LocaleKeys.youAreOutOfContest.tr()) : onAnswerTapped();
}, },
child: Container( child: Container(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,

@ -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/my_attendance_api_client.dart';
import 'package:mohem_flutter_app/api/profile_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/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/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/config/routes.dart';
@ -35,7 +36,8 @@ class RequestSubmitScreenParams {
} }
class RequestSubmitScreen extends StatefulWidget { class RequestSubmitScreen extends StatefulWidget {
RequestSubmitScreen({Key? key}) : super(key: key); final String selectedEmp;
RequestSubmitScreen({this.selectedEmp ='',Key? key}) : super(key: key);
@override @override
_RequestSubmitScreenState createState() { _RequestSubmitScreenState createState() {
@ -50,6 +52,8 @@ class _RequestSubmitScreenState extends State<RequestSubmitScreen> {
List<GetApprovesList> approverList = []; List<GetApprovesList> approverList = [];
List<File> attachmentFiles = []; List<File> attachmentFiles = [];
List<String> attachments = []; List<String> attachments = [];
dynamic dynamicParams;
String selectedEmp ="";
@override @override
void initState() { void initState() {
@ -123,6 +127,7 @@ class _RequestSubmitScreenState extends State<RequestSubmitScreen> {
params!.transactionId, params!.transactionId,
comments.text, comments.text,
-999, -999,
empID: widget.selectedEmp
); );
} else if (params!.approvalFlag == 'eit') { } else if (params!.approvalFlag == 'eit') {
await MyAttendanceApiClient().startEitApprovalProcess( await MyAttendanceApiClient().startEitApprovalProcess(

@ -627,7 +627,12 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
).paddingOnly(bottom: 12), ).paddingOnly(bottom: 12),
itemBuilder: (_) => <PopupMenuItem<int>>[ itemBuilder: (_) => <PopupMenuItem<int>>[
if (model.rEADONLY != "Y") if (model.rEADONLY != "Y")
for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem<int>(child: Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), value: i), for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem<int>(value: i, child: Column(
children: [
Text(model.eSERVICESVS![i].vALUECOLUMNNAME!),
const PopupMenuDivider(),
],
)),
], ],
onSelected: (int popipIndex) async { onSelected: (int popipIndex) async {
ESERVICESDV eservicesdv = ESERVICESDV( ESERVICESDV eservicesdv = ESERVICESDV(

@ -91,7 +91,7 @@ class _DynamicListViewScreenState extends State<DynamicListViewScreen> {
padding: const EdgeInsets.all(21), padding: const EdgeInsets.all(21),
children: [ children: [
// HMG_TKT_NEW_EIT_SS Id used for ticket balance dashboard // 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 getEITTransactionList == null
? const SizedBox() ? const SizedBox()
: (getEITTransactionList!.isEmpty : (getEITTransactionList!.isEmpty
@ -102,8 +102,8 @@ class _DynamicListViewScreenState extends State<DynamicListViewScreen> {
itemBuilder: (cxt, int parentIndex) => getEITTransactionList![parentIndex].collectionTransaction!.isEmpty itemBuilder: (cxt, int parentIndex) => getEITTransactionList![parentIndex].collectionTransaction!.isEmpty
? const SizedBox() ? const SizedBox()
: GridView( : GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 1.9 / 0.75), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 1.0 / 0.75),
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.only(left: 12,right: 21,top: 12),
shrinkWrap: true, shrinkWrap: true,
primary: false, primary: false,
physics: const ScrollPhysics(), physics: const ScrollPhysics(),

@ -54,7 +54,7 @@ class ServicesMenuListScreen extends StatelessWidget {
} }
return; return;
} else if (servicesMenuData.list[index].requestType == "ABSENCE") { } else if (servicesMenuData.list[index].requestType == "ABSENCE") {
Navigator.pushNamed(context, AppRoutes.leaveBalance); Navigator.pushNamed(context, AppRoutes.leaveBalance, arguments: servicesMenuData?.selectedEmp ??'');
return; return;
} }
if (servicesMenuData.list[index].requestType == "EIT") { if (servicesMenuData.list[index].requestType == "EIT") {

@ -66,13 +66,13 @@ class _CreateRequestState extends State<CreateRequest> {
} }
void handleOnPress(context, Menus menu) { void handleOnPress(context, Menus menu) {
if (menu.menuEntry.menuEntryType == "FUNCTION") { if (menu.menuEntry.menuEntryType == "FUNCTION") {
if (menu.menuEntry.requestType == "EIT") { 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 {}
} 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; return;
} }

@ -160,7 +160,7 @@ class _ContactDetailsState extends State<ContactDetails> {
right: 1, right: 1,
child: const Icon(Icons.add_location_alt_outlined, size: 20).onPress(continueDynamicForms), child: const Icon(Icons.add_location_alt_outlined, size: 20).onPress(continueDynamicForms),
), ),
Utils.getNoDataWidget(context).expanded, Utils.getNoDataWidget(context),
], ],
).objectContainerView() ).objectContainerView()
], ],
@ -177,13 +177,13 @@ class _ContactDetailsState extends State<ContactDetails> {
void addUpdateAddress() { void addUpdateAddress() {
Widget cancelButton = TextButton( Widget cancelButton = TextButton(
child: Text("Cancel"), child: Text(LocaleKeys.cancel.tr()),
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
}, },
); );
Widget continueButton = TextButton( Widget continueButton = TextButton(
child: Text("Next"), child: Text(LocaleKeys.next.tr()),
onPressed: () { onPressed: () {
continueDynamicForms(); continueDynamicForms();
}, },
@ -191,7 +191,7 @@ class _ContactDetailsState extends State<ContactDetails> {
StatefulBuilder alert = StatefulBuilder(builder: (context, setState) { StatefulBuilder alert = StatefulBuilder(builder: (context, setState) {
return AlertDialog( return AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))), shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))),
title: Text("Confirm"), title: Text(LocaleKeys.confirm.tr()),
content: Builder(builder: (context) { content: Builder(builder: (context) {
// Get available height and width of the build area of this widget. Make a choice depending on the size. // 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; var height = MediaQuery.of(context).size.height * .5;
@ -199,14 +199,14 @@ class _ContactDetailsState extends State<ContactDetails> {
height: height, height: height,
child: Column(children: [ child: Column(children: [
Text( Text(
"Select the type of change you want to make.", LocaleKeys.SelectChangeWantToMake.tr(),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
), ),
Divider(), Divider(),
Column( Column(
children: [ children: [
ListTile( ListTile(
title: Text("Correct or amend this address"), title: Text(LocaleKeys.CorrectAddress.tr()),
leading: Radio( leading: Radio(
value: 1, value: 1,
groupValue: correctOrNew, groupValue: correctOrNew,
@ -219,7 +219,7 @@ class _ContactDetailsState extends State<ContactDetails> {
), ),
), ),
ListTile( ListTile(
title: Text("Enter a new address if you have moved"), title: Text(LocaleKeys.EnterNewAddressMoved.tr()),
leading: Radio( leading: Radio(
value: 2, value: 2,
groupValue: correctOrNew, groupValue: correctOrNew,

@ -60,7 +60,7 @@ class _AnnouncementDetailsState extends State<AnnouncementDetails> {
), ),
), ),
Html( Html(
data: getAnnouncementDetailsObj?.bodyEN, data: AppState().isArabic(context) ? getAnnouncementDetailsObj?.bodyAR : getAnnouncementDetailsObj?.bodyEN,
).paddingOnly(top: 12), ).paddingOnly(top: 12),
], ],
).objectContainerView().paddingAll(21), ).objectContainerView().paddingAll(21),

@ -106,6 +106,19 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
void getData() async { void getData() async {
// try { // try {
// Utils.showLoading(context); // 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") { if (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") {
getUserInformation(); getUserInformation();
} }
@ -233,9 +246,9 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
), ),
child: Row( child: Row(
children: [ children: [
(workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") ? myTab(LocaleKeys.details.tr(), 0) : myTab(LocaleKeys.request.tr(), 0), myTab(LocaleKeys.info.tr(), 0),
myTab(LocaleKeys.actions.tr(), 1), (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP") ? myTab(LocaleKeys.details.tr(), 1) : myTab(LocaleKeys.request.tr(), 1),
myTab(LocaleKeys.info.tr(), 2), myTab(LocaleKeys.actions.tr(), 2),
myTab(LocaleKeys.attachments.tr(), 3), myTab(LocaleKeys.attachments.tr(), 3),
], ],
), ),
@ -249,6 +262,19 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
}); });
}, },
children: [ 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") (workListData!.iTEMTYPE == "HRSSA" || workListData!.iTEMTYPE == "STAMP")
? DetailFragment(workListData, memberInformationListModel) ? DetailFragment(workListData, memberInformationListModel)
: RequestFragment( : RequestFragment(
@ -266,19 +292,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
voidCallback: reloadWorkList, voidCallback: reloadWorkList,
) )
: showLoadingAnimation(), : 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 isAttachmentLoaded
? getAttachmentList.isEmpty ? getAttachmentList.isEmpty
? Utils.getNoDataWidget(context) ? Utils.getNoDataWidget(context)
@ -688,7 +701,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
GenericResponseModel model = await WorkListApiClient().postNotificationActions(payload); GenericResponseModel model = await WorkListApiClient().postNotificationActions(payload);
Utils.hideLoading(context); Utils.hideLoading(context);
Utils.showToast(LocaleKeys.yourChangeHasBeenSavedSuccessfully.tr()); Utils.showToast(LocaleKeys.yourChangeHasBeenSavedSuccessfully.tr());
animationIndex=animationIndex+1; animationIndex = animationIndex + 1;
AppState().workList!.removeAt(AppState().workListIndex!); AppState().workList!.removeAt(AppState().workListIndex!);
if (AppState().workList!.isEmpty) { if (AppState().workList!.isEmpty) {
Navigator.pop(context, "delegate_reload"); Navigator.pop(context, "delegate_reload");
@ -725,6 +738,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try { try {
if (apiCallCount == 0) Utils.showLoading(context); if (apiCallCount == 0) Utils.showLoading(context);
apiCallCount++; apiCallCount++;
getEitCollectionNotificationBodyList!.clear();
getEitCollectionNotificationBodyList = await WorkListApiClient().GetEitNotificationBody(workListData!.nOTIFICATIONID); getEitCollectionNotificationBodyList = await WorkListApiClient().GetEitNotificationBody(workListData!.nOTIFICATIONID);
apiCallCount--; apiCallCount--;
if (apiCallCount == 0) { if (apiCallCount == 0) {
@ -742,6 +756,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try { try {
if (apiCallCount == 0) Utils.showLoading(context); if (apiCallCount == 0) Utils.showLoading(context);
apiCallCount++; apiCallCount++;
memberInformationListModel = null;
memberInformationListModel = await WorkListApiClient().getUserInformation(-999, workListData!.sELECTEDEMPLOYEENUMBER!); memberInformationListModel = await WorkListApiClient().getUserInformation(-999, workListData!.sELECTEDEMPLOYEENUMBER!);
apiCallCount--; apiCallCount--;
if (apiCallCount == 0) { if (apiCallCount == 0) {
@ -759,6 +774,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try { try {
if (apiCallCount == 0) Utils.showLoading(context); if (apiCallCount == 0) Utils.showLoading(context);
apiCallCount++; apiCallCount++;
getPhonesNotificationBodyList!.clear();
getPhonesNotificationBodyList = await WorkListApiClient().getPhonesNotificationBodyList(workListData!.nOTIFICATIONID); getPhonesNotificationBodyList = await WorkListApiClient().getPhonesNotificationBodyList(workListData!.nOTIFICATIONID);
apiCallCount--; apiCallCount--;
if (apiCallCount == 0) { if (apiCallCount == 0) {
@ -776,6 +792,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try { try {
if (apiCallCount == 0) Utils.showLoading(context); if (apiCallCount == 0) Utils.showLoading(context);
apiCallCount++; apiCallCount++;
getBasicDetNtfBodyList!.clear();
getBasicDetNtfBodyList = await WorkListApiClient().getBasicDetNtfBodyList(workListData!.nOTIFICATIONID); getBasicDetNtfBodyList = await WorkListApiClient().getBasicDetNtfBodyList(workListData!.nOTIFICATIONID);
apiCallCount--; apiCallCount--;
if (apiCallCount == 0) { if (apiCallCount == 0) {
@ -793,6 +810,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try { try {
if (apiCallCount == 0) Utils.showLoading(context); if (apiCallCount == 0) Utils.showLoading(context);
apiCallCount++; apiCallCount++;
getAbsenceCollectionNotificationBodyList!.clear();
getAbsenceCollectionNotificationBodyList = await WorkListApiClient().getAbsenceNotificationBody(workListData!.nOTIFICATIONID); getAbsenceCollectionNotificationBodyList = await WorkListApiClient().getAbsenceNotificationBody(workListData!.nOTIFICATIONID);
apiCallCount--; apiCallCount--;
if (apiCallCount == 0) { if (apiCallCount == 0) {
@ -916,6 +934,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try { try {
if (apiCallCount == 0) Utils.showLoading(context); if (apiCallCount == 0) Utils.showLoading(context);
apiCallCount++; apiCallCount++;
getNotificationRespondAttributes.clear();
getNotificationRespondAttributes = await WorkListApiClient().notificationGetRespondAttributes(workListData!.nOTIFICATIONID!); getNotificationRespondAttributes = await WorkListApiClient().notificationGetRespondAttributes(workListData!.nOTIFICATIONID!);
if (getNotificationRespondAttributes.isNotEmpty) { if (getNotificationRespondAttributes.isNotEmpty) {
notificationNoteInput = getNotificationRespondAttributes.first; notificationNoteInput = getNotificationRespondAttributes.first;
@ -936,6 +955,7 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
try { try {
if (apiCallCount == 0) Utils.showLoading(context); if (apiCallCount == 0) Utils.showLoading(context);
apiCallCount++; apiCallCount++;
notificationButtonsList.clear();
notificationButtonsList = await WorkListApiClient().getNotificationButtons(workListData!.nOTIFICATIONID!); notificationButtonsList = await WorkListApiClient().getNotificationButtons(workListData!.nOTIFICATIONID!);
if (notificationButtonsList.isNotEmpty) { if (notificationButtonsList.isNotEmpty) {
isCloseAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "CLOSE"); isCloseAvailable = notificationButtonsList.any((element) => element.bUTTONACTION == "CLOSE");

@ -5,25 +5,20 @@ import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.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/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_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:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:provider/provider.dart';
AppBar AppBarWidget(BuildContext context, AppBar AppBarWidget(BuildContext context,
{required String title, {required String title,
bool showHomeButton = true, bool showHomeButton = true,
bool showNotificationButton = false, bool showNotificationButton = false,
bool showMemberButton = false, bool showMemberButton = false,
String? image,
List<Widget>? actions, List<Widget>? actions,
void Function()? onHomeTapped, void Function()? onHomeTapped,
void Function()? onBackTapped}) { void Function()? onBackTapped}) {
return AppBar( return AppBar(
leadingWidth: 0, 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( title: Row(
children: [ children: [
GestureDetector( GestureDetector(
@ -34,14 +29,6 @@ AppBar AppBarWidget(BuildContext context,
child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
), ),
4.width, 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, title.toText24(color: MyColors.darkTextColor, isBold: true).expanded,
], ],
), ),

@ -31,8 +31,9 @@ class BalancesDashboardWidget extends StatefulWidget {
final String title; final String title;
final List<PieChartModel> chartModelList; final List<PieChartModel> chartModelList;
final bool isLeaveBalance; 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 @override
_BalancesDashboardWidgetState createState() { _BalancesDashboardWidgetState createState() {
@ -45,11 +46,14 @@ class _BalancesDashboardWidgetState extends State<BalancesDashboardWidget> {
late DateTime accrualDateTime; late DateTime accrualDateTime;
GetAccrualBalancesList? leaveBalanceAccrual; GetAccrualBalancesList? leaveBalanceAccrual;
List<GetAccrualBalancesList>? ticketBalanceAccrualList; List<GetAccrualBalancesList>? ticketBalanceAccrualList;
dynamic dynamicParams;
String selectedEmp = "";
@override @override
void initState() { void initState() {
super.initState(); super.initState();
accrualDateTime = DateTime.now(); accrualDateTime = DateTime.now();
changeAccrualDate();
} }
@override @override
@ -59,8 +63,8 @@ class _BalancesDashboardWidgetState extends State<BalancesDashboardWidget> {
void changeAccrualDate() async { void changeAccrualDate() async {
try { try {
Utils.showLoading(context); // Utils.showLoading(context);
List<GetAccrualBalancesList> accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime)); List<GetAccrualBalancesList> accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime), empID: widget.selectedEmp);
if (accrualList.isNotEmpty) { if (accrualList.isNotEmpty) {
if (widget.isLeaveBalance) { if (widget.isLeaveBalance) {
leaveBalanceAccrual = accrualList[0]; leaveBalanceAccrual = accrualList[0];
@ -76,7 +80,7 @@ class _BalancesDashboardWidgetState extends State<BalancesDashboardWidget> {
]; ];
} }
} }
Utils.hideLoading(context); // Utils.hideLoading(context);
setState(() {}); setState(() {});
} catch (ex) { } catch (ex) {
Utils.hideLoading(context); Utils.hideLoading(context);

@ -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/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/get_favorite_replacements_model.dart';
import 'package:mohem_flutter_app/models/worklist/replacement_list_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/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
@ -238,7 +239,7 @@ class _SearchEmployeeBottomSheetState extends State<SearchEmployeeBottomSheet> {
Navigator.pushNamed( Navigator.pushNamed(
context, context,
AppRoutes.chatDetailed, AppRoutes.chatDetailed,
arguments: {"targetUser": chatUsersList![index], "isNewChat": true}, arguments: ChatDetailedScreenParams(chatUsersList![index], true),
); );
}, },
), ),

@ -0,0 +1,84 @@
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';
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<Widget>? 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<ChatProviderModel>(
builder: (BuildContext cxt, ChatProviderModel data, Widget? child) {
if (chatUser!.isTyping!) {
// 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();
}
},
),
],
),
)
],
),
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 ?? []
],
);
}

@ -45,7 +45,7 @@ class ImageOptions {
onFilesTap: () async { onFilesTap: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles( FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom, 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<File> files = result!.paths.map((path) => File(path!)).toList(); List<File> files = result!.paths.map((path) => File(path!)).toList();
image(result.files.first.path.toString(), files.first); image(result.files.first.path.toString(), files.first);

@ -92,12 +92,14 @@ dependencies:
swipe_to: ^1.0.2 swipe_to: ^1.0.2
flutter_webrtc: ^0.9.16 flutter_webrtc: ^0.9.16
camera: ^0.10.0+4 camera: ^0.10.0+4
animated_text_kit: ^4.2.2
#Encryption #Encryption
flutter_des: ^2.1.0 flutter_des: ^2.1.0
video_player: ^2.4.7 video_player: ^2.4.7
just_audio: ^0.9.30 just_audio: ^0.9.30
safe_device: ^1.1.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save