Merge branch 'master' of http://34.17.52.79/Haroon6138/mohemm-flutter-app into sultan-dev

# Conflicts:
#	assets/langs/ar-SA.json
#	assets/langs/en-US.json
#	lib/app_state/app_state.dart
#	lib/generated/codegen_loader.g.dart
#	lib/generated/locale_keys.g.dart
pull/9/head
Sultan khan 2 years ago
commit 608a8fcb97

@ -43,6 +43,7 @@
"newString": "جديد",
"setTheNewPassword": "قم بتعيين كلمة المرور الجديدة",
"typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه",
"typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه",
"confirmPassword": "تأكيد كلمة المرور",
"update": "تحديث",
"title": "عنوان",
@ -524,28 +525,12 @@
"noUpcoming": "لا يوجد قادم",
"fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية",
"noWinner": "حزين! لم يفز أحد اليوم.",
"myTeam" : "فريقي",
"myTeam": "فريقي",
"youCanPlayDemo": "لكن يمكنك لعب العرض",
"group" : "مجموعة",
"searchGroup": "مجموعة البحث",
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI",
"manage":"يدير",
"members":"أعضاء",
"areYouSureWantTodelete": "هل أنت متأكد من أنك تريد الحذف؟",
"groupMembers": "أعضاء المجموعة",
"manageGroup": "إدارة المجموعة",
"admin": "مسؤل",
"addUsers": "أضف المستخدمين إلى المجموعة",
"editGroups": "تحرير المجموعة",
"groupNameshouldbe": "يجب ألا يقل اسم المجموعة عن 10 أحرف",
"groupName": "أسم المجموعة",
"enterGroupNamePlease": "الرجاء إدخال اسم المجموعة",
"audioCall": "مكالمة صوتية",
"videoCall": "مكالمة فيديو",
"shareScreen": "شاشة المشاركة",
"searchByUserName": "البحث باسم المستخدم",
"userSearch": "بحث المستخدم",
"userName":"اسم المستخدم",
"userId":"معرف المستخدم"
"itgForms": "نماذج (ITG)",
"resetAdPassword": "إعادة تعيين كلمة مرور AD"
}

@ -43,6 +43,7 @@
"newString": "New",
"setTheNewPassword": "Set the new password",
"typeYourNewPasswordBelow": "Type your new password below",
"typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below",
"confirmPassword": "Confirm Password",
"update": "Update",
"title": "Title",
@ -425,7 +426,7 @@
"typeCurrentPasswordBelow": "Type Your Current password below",
"currentPassword": "Current password",
"concurrentReports": "Concurrent Reports",
"EnterNewAddressMoved" : "Enter a new address if you have moved",
"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": {
@ -518,17 +519,20 @@
"startingIn": "Starting in",
"youAreOutOfContest": "You are out of the contest.",
"winners": "WINNERS!!!",
"expireAfter":"Expires After",
"oneWeek":"1 Week",
"twoWeek":"2 Week",
"expireAfter": "Expires After",
"oneWeek": "1 Week",
"twoWeek": "2 Week",
"noUpcoming": "There is no upcoming",
"fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.",
"noWinner": "Sad! No one won today.",
"myTeam" : "My Team",
"myTeam": "My Team",
"youCanPlayDemo": "But you can play demo",
"group": "Groups",
"searchGroup": "Search Group",
"connectHmgWifi": "Connect HMG WIFI",
"connectedHmgWifi": "Connected HMG WIFI",
"itgForms": "ITG Forms",
"resetAdPassword": "Reset AD Password"
"manage": "Manage",
"members": "Members",
"areYouSureWantTodelete": "Are you sure want to delete?",
@ -548,4 +552,4 @@
"userSearch": "User Search",
"userName": "User Name",
"userId": "UserID"
}
}

@ -145,4 +145,15 @@ class LoginApiClient {
return responseData;
}, url, postParams);
}
Future<GenericResponseModel> changePasswordFromActiveDirectorySession(String password, String email) async {
String url = "${ApiConsts.authenticationRest}SetPassword";
Map<String, dynamic> postParams = {"EmailAddress": email, "Password": password, "generalid": "Cs2020@2016\$2958"};
postParams.addAll(AppState().postParamsJson);
postParams["LogInTokenID"] = "@acT!V3D!r3Ct0rY"; // hard code token for active directory
return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData;
}, url, postParams);
}
}

@ -14,6 +14,7 @@ import 'package:mohem_flutter_app/models/get_mo_notification_body_list_model.dar
import 'package:mohem_flutter_app/models/get_notification_buttons_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
@ -91,6 +92,16 @@ class WorkListApiClient {
}, url, postParams);
}
Future<List<GetAttachementList>> getPRAttachments(String pOLineID) async {
String url = "${ApiConsts.erpRest}GET_PR_ATTACHMENTS";
Map<String, dynamic> postParams = {"P_PO_LINE_ID": pOLineID};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData.getPRAttachmentList ?? [];
}, url, postParams);
}
Future<List<GetRFCEmployeeList>> getRFCEmployeeeList(int pNotificationID) async {
String url = "${ApiConsts.erpRest}GET_RFC_EMPLOYEE_LIST";
Map<String, dynamic> postParams = {"P_NOTIFICATION_ID": pNotificationID, "P_PAGE_NUM": 1, "P_PAGE_LIMIT": 10};
@ -115,6 +126,20 @@ class WorkListApiClient {
}, url, postParams);
}
Future<List<GetPRActionHistoryList>> getActionHistoryForPR(String pOLineID) async {
String url = "${ApiConsts.erpRest}GET_PR_ACTION_HISTORY";
Map<String, dynamic> postParams = {
"P_PO_LINE_ID": pOLineID,
"P_PAGE_LIMIT": 100,
"P_PAGE_NUM": 1,
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData.getPRActionHistoryList?.reversed.toList() ?? [];
}, url, postParams);
}
Future<List<GetNotificationButtonsList>> getNotificationButtons(int pNotificationID) async {
String url = "${ApiConsts.erpRest}GET_NOTIFICATION_BUTTONS";
Map<String, dynamic> postParams = {"P_NOTIFICATION_ID": pNotificationID};

@ -90,7 +90,7 @@ class AppState {
String get getHuaweiPushToken => _huaweiPushToken;
final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.6, mobileType: Platform.isAndroid ? "android" : "ios");
final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.8, mobileType: Platform.isAndroid ? "android" : "ios");
void setPostParamsInitConfig() {
isAuthenticated = false;

@ -8,6 +8,7 @@ class ApiConsts {
static String baseUrlServices = baseUrl + "/Services/"; // server
// static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server
static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/";
static String authenticationRest = baseUrlServices + "Authentication.svc/REST/";
static String erpRest = baseUrlServices + "ERP.svc/REST/";
static String swpRest = baseUrlServices + "SWP.svc/REST/";
static String user = baseUrlServices + "api/User/";

@ -4,6 +4,7 @@ import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
import 'package:huawei_push/huawei_push.dart' as huawei_push;
import 'package:mohem_flutter_app/app_state/app_state.dart';
@ -70,18 +71,17 @@ class AppNotifications {
if (Platform.isAndroid) {
// await hmsApiAvailability.isHMSAvailable().then((value) async {
if (!(await Utils.isGoogleServicesAvailable())) {
huawei_push.Push.enableLogger();
var result = await huawei_push.Push.setAutoInitEnabled(true);
var result = await huawei_push.Push.setAutoInitEnabled(true);
huawei_push.Push.onNotificationOpenedApp.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
huawei_push.Push.onNotificationOpenedApp.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
huawei_push.Push.onMessageReceivedStream.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
}
huawei_push.Push.onMessageReceivedStream.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
}
// }).catchError((err) {
// print(err);
// });
@ -116,8 +116,10 @@ class AppNotifications {
}
void _handleOpenApp(RemoteMessage message) {
Utils.saveStringFromPrefs("isAppOpendByChat", "true");
Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString());
if (message.data.isNotEmpty && message.data["type"] == 'chat') {
Utils.saveStringFromPrefs("isAppOpendByChat", "true");
Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString());
}
}
}
@ -131,4 +133,7 @@ Future<dynamic> backgroundMessageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
Utils.saveStringFromPrefs("isAppOpendByChat", "false");
Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString());
if (message.data.isNotEmpty && message.data["type"] == 'call') {
// ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message);
}
}

@ -11,6 +11,7 @@ import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart';
import 'package:mohem_flutter_app/ui/chat/group_members.dart';
import 'package:mohem_flutter_app/ui/chat/manage_group.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart';
import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart';
import 'package:mohem_flutter_app/ui/landing/today_attendance_screen2.dart';
@ -180,6 +181,7 @@ class AppRoutes {
static const String subordinateLeave = "/subordinateLeave";
static const String changePassword = "/changePassword";
static const String changeItgAdPasswordScreen = "/changeItgAdPasswordScreen";
//Chat
static const String chat = "/chat";
@ -296,7 +298,7 @@ class AppRoutes {
subordinateLeave: (BuildContext context) => SubordinateLeave(),
changePassword: (BuildContext context) => ChangePasswordScreen(),
changeItgAdPasswordScreen: (BuildContext context) => ChangeItgAdPasswordScreen(),
//Chat
chat: (BuildContext context) => ChatHome(),
chatDetailed: (BuildContext context) => ChatDetailScreen(),

@ -59,6 +59,7 @@ class CodegenLoader extends AssetLoader{
"newString": "جديد",
"setTheNewPassword": "قم بتعيين كلمة المرور الجديدة",
"typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه",
"typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه",
"confirmPassword": "تأكيد كلمة المرور",
"update": "تحديث",
"title": "عنوان",
@ -546,24 +547,8 @@ class CodegenLoader extends AssetLoader{
"searchGroup": "مجموعة البحث",
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI",
"manage": "يدير",
"members": "أعضاء",
"areYouSureWantTodelete": "هل أنت متأكد من أنك تريد الحذف؟",
"groupMembers": "أعضاء المجموعة",
"manageGroup": "إدارة المجموعة",
"admin": "مسؤل",
"addUsers": "أضف المستخدمين إلى المجموعة",
"editGroups": "تحرير المجموعة",
"groupNameshouldbe": "يجب ألا يقل اسم المجموعة عن 10 أحرف",
"groupName": "أسم المجموعة",
"enterGroupNamePlease": "الرجاء إدخال اسم المجموعة",
"audioCall": "مكالمة صوتية",
"videoCall": "مكالمة فيديو",
"shareScreen": "شاشة المشاركة",
"searchByUserName": "البحث باسم المستخدم",
"userSearch": "بحث المستخدم",
"userName": "اسم المستخدم",
"userId": "معرف المستخدم"
"itgForms": "نماذج (ITG)",
"resetAdPassword": "إعادة تعيين كلمة مرور AD"
};
static const Map<String,dynamic> en_US = {
"mohemm": "Mohemm",
@ -610,6 +595,7 @@ static const Map<String,dynamic> en_US = {
"newString": "New",
"setTheNewPassword": "Set the new password",
"typeYourNewPasswordBelow": "Type your new password below",
"typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below",
"confirmPassword": "Confirm Password",
"update": "Update",
"title": "Title",
@ -1096,6 +1082,9 @@ static const Map<String,dynamic> en_US = {
"group": "Groups",
"searchGroup": "Search Group",
"connectHmgWifi": "Connect HMG WIFI",
"connectedHmgWifi": "Connected HMG WIFI",
"itgForms": "ITG Forms",
"resetAdPassword": "Reset AD Password",
"manage": "Manage",
"members": "Members",
"areYouSureWantTodelete": "Are you sure want to delete?",

@ -44,6 +44,7 @@ abstract class LocaleKeys {
static const newString = 'newString';
static const setTheNewPassword = 'setTheNewPassword';
static const typeYourNewPasswordBelow = 'typeYourNewPasswordBelow';
static const typeYourNewActiveDirectoryPasswordBelow = 'typeYourNewActiveDirectoryPasswordBelow';
static const confirmPassword = 'confirmPassword';
static const update = 'update';
static const title = 'title';
@ -516,6 +517,9 @@ abstract class LocaleKeys {
static const searchGroup = 'searchGroup';
static const connectHmgWifi = 'connectHmgWifi';
static const connectedHmgWifi = 'connectedHmgWifi';
static const itgForms = 'itgForms';
static const resetAdPassword = 'resetAdPassword';
static const manage = 'manage';
static const members = 'members';
static const areYouSureWantTodelete = 'areYouSureWantTodelete';

@ -28,6 +28,7 @@ import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart';
import 'package:mohem_flutter_app/models/get_notification_buttons_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_pr_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
@ -170,9 +171,11 @@ class GenericResponseModel {
List<GetAbsenceTransactionList>? getAbsenceTransactionList;
List<GetAccrualBalancesList>? getAccrualBalancesList;
List<GetActionHistoryList>? getActionHistoryList;
List<GetPRActionHistoryList>? getPRActionHistoryList;
List<GetAddressDffStructureList>? getAddressDffStructureList;
List<GetApprovesList>? getApprovesList;
List<GetAttachementList>? getAttachementList;
List<GetAttachementList>? getPRAttachmentList;
GetAttendanceTracking? getAttendanceTrackingList;
List<GetBasicDetColsStructureList>? getBasicDetColsStructureList;
List<GetBasicDetDffStructureList>? getBasicDetDffStructureList;
@ -436,10 +439,12 @@ class GenericResponseModel {
this.getAbsenceTransactionList,
this.getAccrualBalancesList,
this.getActionHistoryList,
this.getPRActionHistoryList,
this.getAddressDffStructureList,
this.getAddressNotificationBodyList,
this.getApprovesList,
this.getAttachementList,
this.getPRAttachmentList,
this.getAttendanceTrackingList,
this.getBasicDetColsStructureList,
this.getBasicDetDffStructureList,
@ -751,6 +756,13 @@ class GenericResponseModel {
});
}
if (json['PR_Action_History_List'] != null) {
getPRActionHistoryList = <GetPRActionHistoryList>[];
json['PR_Action_History_List'].forEach((v) {
getPRActionHistoryList!.add(GetPRActionHistoryList.fromJson(v));
});
}
if (json['GetAddressDffStructureList'] != null) {
getAddressDffStructureList = <GetAddressDffStructureList>[];
json['GetAddressDffStructureList'].forEach((v) {
@ -772,6 +784,14 @@ class GenericResponseModel {
getAttachementList!.add(GetAttachementList.fromJson(v));
});
}
if (json['PR_Attachments_List'] != null) {
getPRAttachmentList = <GetAttachementList>[];
json['PR_Attachments_List'].forEach((v) {
getPRAttachmentList!.add(GetAttachementList.fromJson(v));
});
}
getAttendanceTrackingList = json["GetAttendanceTrackingList"] == null ? null : GetAttendanceTracking.fromMap(json["GetAttendanceTrackingList"]);
if (json['GetBasicDetColsStructureList'] != null) {
getBasicDetColsStructureList = <GetBasicDetColsStructureList>[];

@ -0,0 +1,68 @@
class GetPRActionHistoryList {
String? aCTION;
String? aCTIONCODE;
String? aPPROVALDATE;
String? eMAILADDRESS;
String? eMPLOYEEIMAGE;
int? fROMROWNUM;
String? nAME;
String? nOTE;
int? nOOFROWS;
String? pOSITIONTITLE;
int? rOWNUM;
int? sEQUENCE;
int? tOROWNUM;
Null? uSERNAME;
GetPRActionHistoryList(
{this.aCTION,
this.aCTIONCODE,
this.aPPROVALDATE,
this.eMAILADDRESS,
this.eMPLOYEEIMAGE,
this.fROMROWNUM,
this.nAME,
this.nOTE,
this.nOOFROWS,
this.pOSITIONTITLE,
this.rOWNUM,
this.sEQUENCE,
this.tOROWNUM,
this.uSERNAME});
GetPRActionHistoryList.fromJson(Map<String, dynamic> json) {
aCTION = json['ACTION'];
aCTIONCODE = json['ACTION_CODE'];
aPPROVALDATE = json['APPROVAL_DATE'];
eMAILADDRESS = json['EMAIL_ADDRESS'];
eMPLOYEEIMAGE = json['EMPLOYEE_IMAGE'];
fROMROWNUM = json['FROM_ROW_NUM'];
nAME = json['NAME'];
nOTE = json['NOTE'];
nOOFROWS = json['NO_OF_ROWS'];
pOSITIONTITLE = json['POSITION_TITLE'];
rOWNUM = json['ROW_NUM'];
sEQUENCE = json['SEQUENCE'];
tOROWNUM = json['TO_ROW_NUM'];
uSERNAME = json['USER_NAME'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['ACTION'] = this.aCTION;
data['ACTION_CODE'] = this.aCTIONCODE;
data['APPROVAL_DATE'] = this.aPPROVALDATE;
data['EMAIL_ADDRESS'] = this.eMAILADDRESS;
data['EMPLOYEE_IMAGE'] = this.eMPLOYEEIMAGE;
data['FROM_ROW_NUM'] = this.fROMROWNUM;
data['NAME'] = this.nAME;
data['NOTE'] = this.nOTE;
data['NO_OF_ROWS'] = this.nOOFROWS;
data['POSITION_TITLE'] = this.pOSITIONTITLE;
data['ROW_NUM'] = this.rOWNUM;
data['SEQUENCE'] = this.sEQUENCE;
data['TO_ROW_NUM'] = this.tOROWNUM;
data['USER_NAME'] = this.uSERNAME;
return data;
}
}

@ -5,6 +5,7 @@
import 'dart:convert';
import 'package:mohem_flutter_app/models/itg/advertisement.dart';
import 'package:mohem_flutter_app/models/itg/survey_model.dart';
MohemmItgResponseItem mohemmItgResponseItemFromJson(String str) => MohemmItgResponseItem.fromJson(json.decode(str));
@ -103,7 +104,7 @@ class ItgResponseData {
final bool? isDeleted;
final bool? showDelete;
final Advertisement? advertisement;
final dynamic survey;
final SurveyModel? survey;
final dynamic isActive;
final dynamic pageSize;
final dynamic pageNo;
@ -126,7 +127,7 @@ class ItgResponseData {
isDeleted: json["isDeleted"] == null ? null : json["isDeleted"],
showDelete: json["showDelete"] == null ? null : json["showDelete"],
advertisement: json["advertisement"] == null ? null : Advertisement.fromJson(json["advertisement"]),
survey: json["survey"],
survey: json["survey"] == null ? null : SurveyModel.fromJson(json["survey"]),
isActive: json["isActive"],
pageSize: json["pageSize"],
pageNo: json["pageNo"],

@ -0,0 +1,148 @@
class SurveyModel {
int? surveyId;
String? referenceNo;
String? title;
String? description;
List<Questions>? questions;
bool? isActive;
Null? pageSize;
Null? pageNo;
Null? languageId;
SurveyModel({this.surveyId, this.referenceNo, this.title, this.description, this.questions, this.isActive, this.pageSize, this.pageNo, this.languageId});
SurveyModel.fromJson(Map<String, dynamic> json) {
surveyId = json['surveyId'];
referenceNo = json['referenceNo'];
title = json['title'];
description = json['description'];
if (json['questions'] != null) {
questions = <Questions>[];
json['questions'].forEach((v) {
questions!.add(new Questions.fromJson(v));
});
}
isActive = json['isActive'];
pageSize = json['pageSize'];
pageNo = json['pageNo'];
languageId = json['languageId'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['surveyId'] = this.surveyId;
data['referenceNo'] = this.referenceNo;
data['title'] = this.title;
data['description'] = this.description;
if (this.questions != null) {
data['questions'] = this.questions!.map((v) => v.toJson()).toList();
}
data['isActive'] = this.isActive;
data['pageSize'] = this.pageSize;
data['pageNo'] = this.pageNo;
data['languageId'] = this.languageId;
return data;
}
}
class Questions {
int? questionId;
String? title;
bool? isRequired;
String? type;
int? sequenceNo;
Null? surveyId;
List<Options>? options;
Null? rspPercentage;
Null? isActive;
Null? pageSize;
Null? pageNo;
Null? languageId;
Questions({this.questionId, this.title, this.isRequired, this.type, this.sequenceNo, this.surveyId, this.options, this.rspPercentage, this.isActive, this.pageSize, this.pageNo, this.languageId});
Questions.fromJson(Map<String, dynamic> json) {
questionId = json['questionId'];
title = json['title'];
isRequired = json['isRequired'];
type = json['type'];
sequenceNo = json['sequenceNo'];
surveyId = json['surveyId'];
if (json['options'] != null) {
options = <Options>[];
json['options'].forEach((v) {
options!.add(new Options.fromJson(v));
});
}
rspPercentage = json['rspPercentage'];
isActive = json['isActive'];
pageSize = json['pageSize'];
pageNo = json['pageNo'];
languageId = json['languageId'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['questionId'] = this.questionId;
data['title'] = this.title;
data['isRequired'] = this.isRequired;
data['type'] = this.type;
data['sequenceNo'] = this.sequenceNo;
data['surveyId'] = this.surveyId;
if (this.options != null) {
data['options'] = this.options!.map((v) => v.toJson()).toList();
}
data['rspPercentage'] = this.rspPercentage;
data['isActive'] = this.isActive;
data['pageSize'] = this.pageSize;
data['pageNo'] = this.pageNo;
data['languageId'] = this.languageId;
return data;
}
}
class Options {
int? optionId;
String? title;
bool? isCommentsRequired;
int? sequenceNo;
int? questionId;
Null? rspPercentage;
Null? count;
Null? isActive;
Null? pageSize;
Null? pageNo;
Null? languageId;
Options({this.optionId, this.title, this.isCommentsRequired, this.sequenceNo, this.questionId, this.rspPercentage, this.count, this.isActive, this.pageSize, this.pageNo, this.languageId});
Options.fromJson(Map<String, dynamic> json) {
optionId = json['optionId'];
title = json['title'];
isCommentsRequired = json['isCommentsRequired'];
sequenceNo = json['sequenceNo'];
questionId = json['questionId'];
rspPercentage = json['rspPercentage'];
count = json['count'];
isActive = json['isActive'];
pageSize = json['pageSize'];
pageNo = json['pageNo'];
languageId = json['languageId'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['optionId'] = this.optionId;
data['title'] = this.title;
data['isCommentsRequired'] = this.isCommentsRequired;
data['sequenceNo'] = this.sequenceNo;
data['questionId'] = this.questionId;
data['rspPercentage'] = this.rspPercentage;
data['count'] = this.count;
data['isActive'] = this.isActive;
data['pageSize'] = this.pageSize;
data['pageNo'] = this.pageNo;
data['languageId'] = this.languageId;
return data;
}
}

@ -66,7 +66,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
if (attendanceTracking?.pSwipeIn != null) {
isTimeRemainingInSeconds = calculateSeconds(attendanceTracking!.pRemainingHours ?? "00:00:00");
int totalShiftTimeInSeconds = calculateSeconds(attendanceTracking!.pScheduledHours ?? "00:00:00");
if(isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) {
if (isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) {
progress = 0;
} else {
progress = (isTimeRemainingInSeconds / totalShiftTimeInSeconds);
@ -245,7 +245,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
}
void getCategoryOffersListAPI(BuildContext context) async {
void getCategoryOffersListAPI(BuildContext context) async {
try {
// Utils.showLoading(context);
getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 10);
@ -262,7 +262,25 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List<Menus> menus = [];
for (int i = 0; i < getMenuEntriesList.length; i++) {
if (getMenuEntriesList[i].parentMenuName!.isEmpty) {
menus.add(Menus(getMenuEntriesList[i], getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList()));
GetMenuEntriesList abc = GetMenuEntriesList(requestType: "itg_forms", prompt: LocaleKeys.itgForms.tr());
List<GetMenuEntriesList> list = getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList();
if (getMenuEntriesList[i].menuName == "MBL_E_PROFESSIONALS_01") {
// hard coding this check to add change password for Active Directory
GetMenuEntriesList activeDirectoryEntry = GetMenuEntriesList(
requestType: "RESET_ITG_AD_PASSWORD",
prompt: LocaleKeys.resetAdPassword.tr(),
parentMenuName: 'ITG_FORMS',
menuName: LocaleKeys.itgForms.tr(),
menuEntryType: "FUNCTION", //Reset AD Password
);
getMenuEntriesList.add(activeDirectoryEntry);
list.add(GetMenuEntriesList(requestType: "ITG_FORMS", prompt: LocaleKeys.itgForms.tr(), menuName: 'ITG_FORMS'));
}
menus.add(Menus(getMenuEntriesList[i], list));
}
}
return menus;
@ -272,6 +290,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification();
return res;
}
void notify() {
notifyListeners();
}

@ -26,7 +26,6 @@ import 'package:mohem_flutter_app/ui/landing/widget/services_widget.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_banner.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/dialogs/dialogs.dart';
import 'package:mohem_flutter_app/widgets/mark_attendance_widget.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart';
@ -98,7 +97,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
cProvider.getUserAutoLoginToken().whenComplete(() async {
if (!cProvider.disbaleChatForThisUser) {
String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat");
if (isAppOpendByChat != null && isAppOpendByChat == "true") {
if (isAppOpendByChat != "null" && isAppOpendByChat == "true") {
Utils.showLoading(context);
cProvider.buildHubConnection();
Future.delayed(const Duration(seconds: 2), () async {
@ -128,6 +127,11 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
if (chatHubConnection.state == HubConnectionState.Connected) {
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.chat);
String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat");
if (isAppOpendByChat != "null" || isAppOpendByChat == "true") {
Utils.saveStringFromPrefs("isAppOpendByChat", "false");
Utils.saveStringFromPrefs("notificationData", "null");
}
}
}
@ -158,7 +162,20 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
if (val!.result!.data != null) {
print("-------------------- Survey ----------------------------");
if (val.result!.data!.notificationType == "Survey") {
Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data);
DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then(
(value) {
if (value!.mohemmItgResponseItem!.statusCode == 200) {
if (value.mohemmItgResponseItem!.result!.data != null) {
// Navigator.pushNamed(context, AppRoutes.survey, arguments: val.result!.data);
Navigator.pushNamed(context, AppRoutes.survey, arguments: value.mohemmItgResponseItem!.result!.data);
// Navigator.pushNamed(context, AppRoutes.advertisement, arguments: {
// "masterId": val.result!.data!.notificationMasterId,
// "advertisement": value.mohemmItgResponseItem!.result!.data!.advertisement,
// });
}
}
},
);
} else {
print("------------------------------------------- Ads --------------------");
DashboardApiClient().getAdvertisementDetail(val.result!.data!.notificationMasterId ?? "").then(

@ -0,0 +1,166 @@
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/login_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/input_widget.dart';
class ChangeItgAdPasswordScreen extends StatefulWidget {
ChangeItgAdPasswordScreen({Key? key}) : super(key: key);
@override
_ChangeItgAdPasswordScreenState createState() {
return _ChangeItgAdPasswordScreenState();
}
}
class _ChangeItgAdPasswordScreenState extends State<ChangeItgAdPasswordScreen> {
TextEditingController password = TextEditingController();
TextEditingController confirmPassword = TextEditingController();
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
void setNewPassword() async {
Utils.showLoading(context);
try {
GenericResponseModel response = await LoginApiClient().changePasswordFromActiveDirectorySession(password.text, AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!);
Utils.hideLoading(context);
if ((response.messageStatus ?? 0) == 1) {
Utils.showToast(LocaleKeys.passwordChangedSuccessfully.tr());
Navigator.pop(context);
}
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, (msg) {
Utils.confirmDialog(context, msg);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
onPressed: () => Navigator.pop(context),
),
),
body: Column(
children: [
ListView(
padding: const EdgeInsets.all(21),
children: [
LocaleKeys.changePassword.tr().toText24(isBold: true),
LocaleKeys.typeYourNewActiveDirectoryPasswordBelow.tr().toText16(),
16.height,
InputWidget(
LocaleKeys.password.tr(),
"**********",
password,
onChange: (value) {
setState(() {});
},
),
12.height,
InputWidget(
LocaleKeys.confirmPassword.tr(),
"**********",
confirmPassword,
isTextIsPassword: true,
onChange: (value) {
setState(() {});
},
),
16.height,
passwordConstraintsUI(LocaleKeys.doNotUseRecentPassword.tr(), true),
8.height,
passwordConstraintsUI(LocaleKeys.atLeastOneLowercase.tr(), checkRegEx(r'[a-z]')),
// 8.height,
// passwordConstraintsUI(LocaleKeys.atLeastOneUppercase.tr(), checkRegEx(r'[A-Z]')),
8.height,
passwordConstraintsUI(LocaleKeys.atLeastOneNumeric.tr(), checkRegEx(r'[0-9]')),
8.height,
passwordConstraintsUI(LocaleKeys.minimum8Characters.tr(), password.text.length >= 8),
8.height,
passwordConstraintsUI(LocaleKeys.doNotAddRepeatingLetters.tr(), checkRepeatedChars(password.text)),
// 8.height,
// passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')),
8.height,
passwordConstraintsUI(LocaleKeys.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text),
],
).expanded,
DefaultButton(LocaleKeys.changePassword.tr(), (!isPasswordCompliant(password.text, 8)) ? null : setNewPassword).insideContainer
],
),
);
}
bool checkRegEx(String pattern) {
return RegExp(pattern).hasMatch(password.text);
}
String recentPassword = "";
bool isPasswordCompliant(String? password, int minLength) {
if (password == null || password.isEmpty) {
return false;
}
// bool hasUppercase = password.contains(RegExp(r'[A-Z]'));
bool hasDigits = password.contains(RegExp(r'[0-9]'));
bool hasLowercase = password.contains(RegExp(r'[a-z]'));
// bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'));
bool hasMinLength = password.length >= minLength;
bool isMatched = password == confirmPassword.text;
return hasDigits && hasLowercase && hasMinLength && isMatched && checkRepeatedChars(password);
}
bool checkRepeatedChars(String password) {
bool isNonRepeatedLetters = true;
if (password.length > 2) {
for (int i = 0; i < password.length; i++) {
String char = password[i];
try {
if (char == password[i + 1]) {
isNonRepeatedLetters = false;
break;
}
} catch (ex) {}
}
}
return isNonRepeatedLetters;
}
Widget passwordConstraintsUI(String description, bool check) {
return Row(
children: [
4.width,
SizedBox(
width: 12,
height: 12,
child: Checkbox(fillColor: MaterialStateProperty.all(MyColors.gradiantEndColor), shape: const CircleBorder(), value: check, onChanged: null),
),
8.width,
description.toText14()
],
);
}
}

@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
@ -7,15 +5,14 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/itg/itg_main_response.dart';
import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:mohem_flutter_app/models/itg/survey_model.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
class SurveyScreen extends StatefulWidget {
const SurveyScreen({Key? key}) : super(key: key);
@ -27,78 +24,50 @@ class SurveyScreen extends StatefulWidget {
class _SurveyScreenState extends State<SurveyScreen> {
String reviewText = "";
double starRating = 1;
int _selectedIndex = 5;
int _selectedIndex = 0;
ItgResponseData? itgResponseData;
List<String> answeredQuestions = [];
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(
(_) => initAnswersList(),
);
super.initState();
}
@override
Widget build(BuildContext context) {
if (itgResponseData == null) itgResponseData = ModalRoute.of(context)!.settings.arguments as ItgResponseData;
itgResponseData ??= ModalRoute.of(context)!.settings.arguments as ItgResponseData;
return Scaffold(
backgroundColor: MyColors.backgroundColor,
body: Column(
children: [
Expanded(
child: ListView(
scrollDirection: Axis.vertical,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
124.height,
LocaleKeys.feedbackUserExperience.tr().toText19(),
27.height,
LocaleKeys.rateUI.tr().toText16(),
22.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
RatingBar.builder(
initialRating: 3,
minRating: starRating,
direction: Axis.horizontal,
allowHalfRating: false,
itemCount: 5,
itemPadding: EdgeInsets.symmetric(horizontal: 8),
itemBuilder: (context, _) => Icon(
Icons.star,
color: Colors.amber,
),
onRatingUpdate: (rating) {
starRating = rating;
},
)
],
).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true),
39.height,
LocaleKeys.rateUI2.tr().toText16(),
10.height,
GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7),
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.only(top: 0),
shrinkWrap: true,
children: [
optionUI("poor.svg", 1),
optionUI("bad.svg", 2),
optionUI("normal.svg", 3),
optionUI("good.svg", 4),
optionUI("xcellent.svg", 5),
],
),
27.height,
DynamicTextFieldWidget(
LocaleKeys.description.tr(),
LocaleKeys.typeHere.tr(),
lines: 3,
onChange: (v) {
reviewText = v;
},
),
150.height
],
).paddingOnly(left: 21, right: 21),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
32.height,
itgResponseData?.survey?.title?.toText24() ?? const Text(""),
8.height,
itgResponseData?.survey?.description?.toText16() ?? const Text(""),
ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: itgResponseData?.survey?.questions?.length,
itemBuilder: (cxt, index) {
return answeredQuestions.isNotEmpty ? getSurveyWidget(itgResponseData?.survey?.questions![index], index) : Container();
},
),
],
).paddingOnly(left: 21, right: 21),
),
],
)),
DefaultButton(
@ -111,7 +80,7 @@ class _SurveyScreenState extends State<SurveyScreen> {
));
}
Widget optionUI(String icon, int index) {
Widget optionUI(String icon, int? index, int answerIndex) {
return (_selectedIndex == index
? SvgPicture.asset(
'assets/images/' + icon,
@ -126,22 +95,121 @@ class _SurveyScreenState extends State<SurveyScreen> {
disablePadding: true,
))
.onPress(() {
_selectedIndex = index;
_selectedIndex = index!;
answeredQuestions[answerIndex] = _selectedIndex.toString();
setState(() {});
});
}
void initAnswersList() {
answeredQuestions.clear();
itgResponseData?.survey?.questions?.forEach((element) {
if (element.type != "Stars") {
if(element.type == "Faces") {
_selectedIndex = element.options![0].optionId!;
}
answeredQuestions.add(element.options![0].optionId.toString());
} else {
answeredQuestions.add("4");
}
});
setState(() {});
}
Widget getSurveyWidget(Questions? question, int parentIndex) {
if (question?.type == "Expressions") {
// Expressions = radio buttons
return Column(
children: [
24.height,
question?.title?.toText18() ?? const Text(""),
16.height,
GridView.builder(
padding: EdgeInsets.zero,
itemCount: question?.options?.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return radioOption(question?.options?[index].title ?? "", question?.options?[index].optionId.toString() ?? "", answeredQuestions[parentIndex], parentIndex);
},
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: (4.0),
),
).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true),
],
);
} else if (question?.type == "Stars") {
// Stars = star rating
return Column(
mainAxisSize: MainAxisSize.min,
children: [
24.height,
question?.title?.toText18() ?? Text(""),
16.height,
RatingBar.builder(
initialRating: 3,
minRating: starRating,
direction: Axis.horizontal,
allowHalfRating: false,
itemCount: 5,
itemPadding: const EdgeInsets.symmetric(horizontal: 8),
itemBuilder: (context, _) => const Icon(
Icons.star,
color: Colors.amber,
),
onRatingUpdate: (rating) {
starRating = rating;
answeredQuestions[parentIndex] = rating.toInt().toString();
},
).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true),
],
);
} else if (question?.type == "Faces") {
// Faces = face rating
return Column(
mainAxisSize: MainAxisSize.min,
children: [
24.height,
question?.title?.toText18() ?? Text("asdasdasdasd"),
16.height,
GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7),
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.only(top: 0),
shrinkWrap: true,
children: [
optionUI("poor.svg", question?.options?[0].optionId, parentIndex),
optionUI("bad.svg", question?.options?[1].optionId, parentIndex),
optionUI("normal.svg", question?.options?[2].optionId, parentIndex),
optionUI("good.svg", question?.options?[3].optionId, parentIndex),
optionUI("xcellent.svg", question?.options?[4].optionId, parentIndex),
],
),
],
);
} else {
return Container();
}
return Container();
}
void performAPI() async {
Utils.showLoading(context);
List<Map<String, dynamic>> itgAnswersList = [];
int index = 0;
try {
ItgMainRes? res = await DashboardApiClient().submitItgForm(
comment: reviewText,
masterId: itgResponseData!.notificationMasterId ?? "",
itgList: [
{"questionId": "1", "optionId": null, "starRating": starRating},
{"questionId": "2", "optionId": "4", "starRating": _selectedIndex}
],
serviceId: itgResponseData!.serviceId ?? 0);
answeredQuestions.forEach((element) {
itgAnswersList.add({
"questionId": itgResponseData?.survey?.questions![index].questionId,
"optionId": itgResponseData?.survey?.questions![index].type != "Stars" ? answeredQuestions[index] : null,
"starRating": itgResponseData?.survey?.questions![index].type == "Stars" ? answeredQuestions[index] : null
});
index++;
});
ItgMainRes? res = await DashboardApiClient()
.submitItgForm(comment: reviewText, masterId: itgResponseData!.notificationMasterId ?? "", itgList: itgAnswersList, serviceId: itgResponseData!.survey!.surveyId ?? 0);
Utils.hideLoading(context);
if (res!.mohemmItgResponseItem!.statusCode == 200) {
@ -157,4 +225,41 @@ class _SurveyScreenState extends State<SurveyScreen> {
});
}
}
Widget radioOption(String title, String value, String groupValue, int answerIndex) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(color: MyColors.borderColor, width: 1),
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
),
padding: const EdgeInsets.all(4),
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: value == answeredQuestions[answerIndex] ? MyColors.greenColor : Colors.transparent,
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
),
),
),
6.width,
title.toText12(color: MyColors.grey57Color),
12.width
],
).onPress(() {
answeredQuestions[answerIndex] = value;
setState(() {});
});
}
}

@ -57,6 +57,9 @@ class ServicesMenuListScreen extends StatelessWidget {
} else if (servicesMenuData.list[index].requestType == "ABSENCE") {
Navigator.pushNamed(context, AppRoutes.leaveBalance, arguments: servicesMenuData.selectedEmp);
return;
} else if (servicesMenuData.list[index].requestType == "RESET_ITG_AD_PASSWORD") {
Navigator.pushNamed(context, AppRoutes.changeItgAdPasswordScreen);
return;
}
if (servicesMenuData.list[index].requestType == "EIT") {
Navigator.pushNamed(context, AppRoutes.dynamicScreen,

@ -142,6 +142,7 @@ class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
}
List<Widget> getItemImages() {
int index = 0;
List<Widget> itemImages = [];
getItemsForSaleList.itemAttachments!.forEach((element) {
itemImages.add(
@ -150,12 +151,13 @@ class _ItemForSaleDetailPageState extends State<ItemForSaleDetailPage> {
child: ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.network(
getItemsForSaleList.itemAttachments![0].filePath!,
getItemsForSaleList.itemAttachments![index].filePath!,
fit: BoxFit.cover,
),
),
),
);
index++;
});
return itemImages;
}

@ -1,16 +1,29 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/date_uitl.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_attachement_list_model.dart';
import 'package:mohem_flutter_app/models/get_mo_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_po_Item_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/get_pr_information_list.dart';
import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/circular_avatar.dart';
import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
class ItemHistoryScreenParams {
String? title;
@ -21,8 +34,10 @@ class ItemHistoryScreenParams {
int? pOrgId;
bool isPRInfo;
GetPRInformationList? getPRInformationList;
String pOLineID;
ItemHistoryScreenParams({@required this.title, this.isItemHistory = true, this.isMO = true, this.isPRInfo = false, this.getPRInformationList, this.pItemId, this.pPoHeaderId, this.pOrgId});
ItemHistoryScreenParams(
{@required this.title, this.isItemHistory = true, this.isMO = true, this.isPRInfo = false, this.getPRInformationList, this.pItemId, this.pPoHeaderId, this.pOrgId, this.pOLineID = ""});
}
class ItemHistoryScreen extends StatefulWidget {
@ -40,6 +55,9 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
List<GetMoItemHistoryList> moItemHistoryList = [];
List<GetPoItemHistoryList> poItemHistoryList = [];
List<GetQuotationAnalysisList> quotationAnalysisList = [];
List<GetPRActionHistoryList> actionHistoryList = [];
List<GetAttachementList> getAttachmentList = [];
int tabIndex = 0;
@override
void initState() {
@ -49,6 +67,7 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
@override
void dispose() {
super.dispose();
actionHistoryList.clear();
}
void loadData() {
@ -60,6 +79,34 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
}
}
void getActionsDataFromApi() async {
if (actionHistoryList.isEmpty) {
try {
Utils.showLoading(context);
actionHistoryList = await WorkListApiClient().getActionHistoryForPR(_screenParams!.pOLineID);
Utils.hideLoading(context);
setState(() {});
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
}
void getAttachmentsDataFromApi() async {
if (getAttachmentList.isEmpty) {
try {
Utils.showLoading(context);
getAttachmentList = await WorkListApiClient().getPRAttachments(_screenParams!.pOLineID!);
Utils.hideLoading(context);
setState(() {});
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
}
void getDataFromApi() async {
try {
Utils.showLoading(context);
@ -88,7 +135,7 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
appBar: AppBarWidget(context, title: _screenParams?.title ?? ""),
backgroundColor: Colors.white,
body: ListView(
padding: const EdgeInsets.all(21),
padding: _screenParams!.isPRInfo ? const EdgeInsets.all(0) : const EdgeInsets.all(21),
physics: const BouncingScrollPhysics(),
children: [
if (_screenParams!.isPRInfo) prLinesDataView(),
@ -102,32 +149,243 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
}
Widget prLinesDataView() {
return Column(
children: [
Container(
padding: const EdgeInsets.only(left: 21, right: 21, top: 16, bottom: 16),
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
gradient: LinearGradient(
transform: GradientRotation(.83),
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
],
),
),
child: Row(
children: [
myTab(LocaleKeys.info.tr(), 0),
myTab(LocaleKeys.actions.tr(), 1),
myTab(LocaleKeys.attachments.tr(), 2),
],
),
),
if (tabIndex == 0) _screenParams!.getPRInformationList!.pRHeader![0].dESCRIPTION!.toText14().paddingOnly(top: 20, right: 21, left: 21),
if (tabIndex == 0)
ListView.separated(
padding: const EdgeInsets.all(21),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (cxt, index) => Column(
children: [
ItemDetailGrid(
ItemDetailViewCol("Cost Center", _screenParams!.getPRInformationList!.pRLines![index].cOSTCENTER ?? ""),
ItemDetailViewCol("Code", _screenParams!.getPRInformationList!.pRLines![index].iTEMCODE ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("Unit", _screenParams!.getPRInformationList!.pRLines![index].uOM ?? ""),
ItemDetailViewCol("Price (SAR)", _screenParams!.getPRInformationList!.pRLines![index].uNITPRICE.toString() ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("Amount (SAR)", _screenParams!.getPRInformationList!.pRLines![index].lINEAMOUNT.toString() ?? ""),
ItemDetailViewCol("Quantity", _screenParams!.getPRInformationList!.pRLines![index].qUANTITY.toString() ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("AMU (Last 3 months)", _screenParams!.getPRInformationList!.pRLines![index].iTEMAMU.toString() ?? ""),
ItemDetailViewCol("PR Number", _screenParams!.getPRInformationList!.pRHeader![0].pRNUMBER!.toString() ?? ""),
isItLast: true,
),
],
).objectContainerView(),
separatorBuilder: (cxt, index) => 12.height,
itemCount: _screenParams!.getPRInformationList!.pRLines!.length),
if (tabIndex == 1) getPRActionsHistory(), //"ACTIONS".toText14().paddingOnly(top: 20, right: 21, left: 21),
if (tabIndex == 2) getPRAttachments(),
],
);
}
String determineFileIcon(String fileContentType) {
String icon = "";
switch (fileContentType) {
case "pdf":
icon = "assets/images/pdf.svg";
break;
case "xls":
icon = "assets/images/xls.svg";
break;
case "xlsx":
icon = "assets/images/xls.svg";
break;
case "png":
icon = "assets/images/png.svg";
break;
case "jpg":
icon = "assets/images/jpg.svg";
break;
case "jpeg":
icon = "assets/images/jpg.svg";
break;
}
return icon;
}
Future<String> _createFileFromString(String encodedStr, String ext) async {
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getApplicationDocumentsDirectory()).path;
File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
await file.writeAsBytes(bytes);
return file.path;
}
Widget getPRAttachments() {
return ListView.separated(
itemCount: getAttachmentList.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Row(
children: [
SvgPicture.asset(determineFileIcon(getAttachmentList[index].fILECONTENTTYPE ?? "")),
12.width,
(getAttachmentList[index].fILENAME ?? "").toText16().expanded,
],
).objectContainerView().onPress(() async {
try {
String path = await _createFileFromString(getAttachmentList[index].fILEDATA ?? "", getAttachmentList[index].fILECONTENTTYPE ?? "");
OpenFile.open(path);
} catch (ex) {
Utils.showToast("Cannot open file.");
}
});
},
separatorBuilder: (BuildContext context, int index) => 12.height,
).paddingAll(21);
}
Widget getPRActionsHistory() {
return SingleChildScrollView(
child: ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (cxt, index) => Column(
children: [
ItemDetailGrid(
ItemDetailViewCol("Cost Center", _screenParams!.getPRInformationList!.pRLines![index].cOSTCENTER ?? ""),
ItemDetailViewCol("Code", _screenParams!.getPRInformationList!.pRLines![index].iTEMCODE ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("Unit", _screenParams!.getPRInformationList!.pRLines![index].uOM ?? ""),
ItemDetailViewCol("Price (SAR)", _screenParams!.getPRInformationList!.pRLines![index].uNITPRICE.toString() ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("Amount (SAR)", _screenParams!.getPRInformationList!.pRLines![index].lINEAMOUNT.toString() ?? ""),
ItemDetailViewCol("Quantity", _screenParams!.getPRInformationList!.pRLines![index].qUANTITY.toString() ?? ""),
),
ItemDetailGrid(
ItemDetailViewCol("AMU (Last 3 months)", _screenParams!.getPRInformationList!.pRLines![index].iTEMAMU.toString() ?? ""),
Container(),
isItLast: true,
),
],
).objectContainerView(),
separatorBuilder: (cxt, index) => 12.height,
itemCount: _screenParams!.getPRInformationList!.pRLines!.length);
itemCount: actionHistoryList.length,
padding: EdgeInsets.all(21),
itemBuilder: (context, index) {
return showItem(context, actionHistoryList[index], index);
},
separatorBuilder: (BuildContext context, int index) {
return 12.height;
},
),
);
}
Widget showItem(BuildContext context, GetPRActionHistoryList actionHistory, int index) {
return Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: const Color(0xff000000).withOpacity(.05),
blurRadius: 26,
offset: const Offset(0, -3),
),
],
),
clipBehavior: Clip.antiAlias,
child: Stack(
clipBehavior: Clip.antiAlias,
children: [
Positioned(
left: -20,
top: -10,
child: Transform.rotate(
angle: 15,
child: Container(
width: 50,
height: 30,
color: getStatusColor(actionHistory.aCTIONCODE!),
),
),
),
Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
actionHistory.eMPLOYEEIMAGE != null
? CircularAvatar(url: actionHistory.eMPLOYEEIMAGE ?? "", isImageBase64: true, height: 34, width: 34)
: CircularAvatar(url: "https://cdn4.iconfinder.com/data/icons/professions-2-2/151/89-512.png", isImageBase64: false, height: 34, width: 34),
9.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
actionHistory.nAME!.toText16(),
if ((actionHistory.nOTE ?? "").isNotEmpty)
SelectableText(
actionHistory.nOTE!,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: MyColors.grey57Color,
letterSpacing: -0.72,
),
),
// "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color),
4.height,
Row(
children: [
actionHistory.aCTION!.toText10(color: getStatusColor(actionHistory.aCTIONCODE!)),
8.width,
if (actionHistory.aPPROVALDATE!.isNotEmpty)
DateUtil.formatDateToDate(DateUtil.convertSimpleStringDateToDateddMMyyyy(actionHistory.aPPROVALDATE!), false).toText12(color: MyColors.lightTextColor),
],
),
10.height,
// getActionDuration(index).toText11(maxLine: 1, color: const Color(0xff1FA269))
],
),
)
],
).paddingOnly(top: 19, left: 16, right: 16, bottom: 12),
],
),
],
),
);
}
Color getStatusColor(String code) {
if (code == "SUBMIT") {
return const Color(0xff2E303A);
} else if (code == "REJECTED") {
return MyColors.redColor;
} else if (code == "REJECT") {
return MyColors.redColor;
} else if (code == "PENDING") {
return MyColors.orange;
} else if (code == "APPROVED" || code == "APPROVE" || code == "ANSWER_INFO") {
return const Color(0xff1FA269);
} else if (code == "REQUEST_INFO" || code == "FORWARD") {
return const Color(0xff2E303A);
} else if (code != "SUBMIT" && code != "REJECT" && code != "PENDING") {
return MyColors.orange;
} else {
return const Color(0xff2E303A);
}
}
Widget getActionHistory() {
return Container();
}
Widget loadMoItemHistoryData() {
@ -266,4 +524,34 @@ class _ItemHistoryScreenState extends State<ItemHistoryScreen> {
separatorBuilder: (cxt, index) => 12.height,
itemCount: quotationAnalysisList.length);
}
Widget myTab(String title, int index) {
bool isSelected = (index == tabIndex);
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
title.toText12(color: isSelected ? Colors.white : Colors.white.withOpacity(.74), isCenter: true),
4.height,
Container(
height: 8,
width: 8,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isSelected ? Colors.white : Colors.transparent,
),
)
],
).onPress(() {
setState(() {
if (index == 1) {
getActionsDataFromApi();
}
if (index == 2) {
getAttachmentsDataFromApi();
}
tabIndex = index;
});
}).expanded;
}
}

@ -6,7 +6,6 @@ import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_action_history_list_model.dart';
import 'package:mohem_flutter_app/models/member_information_list_model.dart';
@ -144,26 +143,30 @@ class SelectedItemSheet extends StatelessWidget {
forwardToUser = filtered.first;
}
showDialog(
context: context,
builder: (cxt) => AcceptRejectInputDialog(
message: title != null ? null : LocaleKeys.requestedItems.tr(),
// title: title,
notificationGetRespond: notificationNoteInput,
actionMode: apiMode,
onTap: (note) {
performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: [
if ((apiMode == "FORWARD" || apiMode == "APPROVE_AND_FORWARD") && forwardToUser != null)
{"ATTRIBUTE_NAME": "FORWARD_TO_USERNAME_RESPONSE", "ATTRIBUTE_TEXT_VALUE": actionHistoryList?.uSERNAME},
if (notificationNoteInput != null)
{
"ATTRIBUTE_NAME": notificationNoteInput.attributeName,
if (notificationNoteInput.attributeType == "number") "ATTRIBUTE_NUMBER_VALUE": note else if (notificationNoteInput.attributeType == "VARCHAR2") "ATTRIBUTE_TEXT_VALUE": note
}
]);
},
),
);
if (notificationNoteInput == null) {
performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: []);
} else {
showDialog(
context: context,
builder: (cxt) => AcceptRejectInputDialog(
message: title != null ? null : LocaleKeys.requestedItems.tr(),
// title: title,
notificationGetRespond: notificationNoteInput,
actionMode: apiMode,
onTap: (note) {
performNetworkCall(context, email: email ?? "", userId: userId ?? "", attributeData: [
if ((apiMode == "FORWARD" || apiMode == "APPROVE_AND_FORWARD") && forwardToUser != null)
{"ATTRIBUTE_NAME": "FORWARD_TO_USERNAME_RESPONSE", "ATTRIBUTE_TEXT_VALUE": actionHistoryList?.uSERNAME},
if (notificationNoteInput != null)
{
"ATTRIBUTE_NAME": notificationNoteInput.attributeName,
if (notificationNoteInput.attributeType == "number") "ATTRIBUTE_NUMBER_VALUE": note else if (notificationNoteInput.attributeType == "VARCHAR2") "ATTRIBUTE_TEXT_VALUE": note
}
]);
},
),
);
}
}
void getUserInformation(BuildContext context) async {

@ -148,9 +148,6 @@ class _WorkListDetailScreenState extends State<WorkListDetailScreen> {
} else if (workListData!.rEQUESTTYPE == "ADDRESS") {
getAddressNotificationBody();
}
// getBasicNTFBody = await WorkListApiClient().getBasicDetNTFBody(workListData!.nOTIFICATIONID!, -999);
// getAbsenceCollectionNotifications = await WorkListApiClient().getAbsenceNotificationBody(workListData!.nOTIFICATIONID!, -999);
// subordinatesLeavesModel = await WorkListApiClient().getSubordinatesLeaves("", "");
}
if (workListData!.iTEMTYPE == "STAMP") {
getStampNotificationBody();

@ -82,7 +82,20 @@ class ActionsFragment extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
actionHistory.nAME!.toText16(),
if ((actionHistory.nOTE ?? "").isNotEmpty) "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color),
if ((actionHistory.nOTE ?? "").isNotEmpty)
SelectableText(
actionHistory.nOTE!,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: MyColors.grey57Color,
letterSpacing: -0.72,
),
),
// if ((actionHistory.nOTE ?? "").isNotEmpty) "Note: ${actionHistory.nOTE!}".toText12(color: MyColors.grey57Color),
4.height,
Row(
children: [

@ -22,7 +22,6 @@ class AttachmentsFragment extends StatelessWidget {
return ListView.separated(
itemCount: getAttachmentList.length,
itemBuilder: (context, index) {
return Row(
children: [
SvgPicture.asset(determineFileIcon(getAttachmentList[index].fILECONTENTTYPE ?? "")),

@ -294,7 +294,7 @@ class RequestFragment extends StatelessWidget {
context,
AppRoutes.itemHistory,
arguments: ItemHistoryScreenParams(
isItemHistory: false, isMO: false, isPRInfo: true, getPRInformationList: getPRInformationList, title: "PR Details", pItemId: 0, pPoHeaderId: 0),
isItemHistory: false, isMO: false, isPRInfo: true, getPRInformationList: getPRInformationList, title: "PR Details", pItemId: 0, pPoHeaderId: 0, pOLineID: poLineID),
);
} catch (ex) {
Utils.hideLoading(context);

@ -26,6 +26,7 @@ import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart';
import 'package:mohem_flutter_app/widgets/qr_scanner_dialog.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:platform_device_id/platform_device_id.dart';
import 'package:wifi_iot/wifi_iot.dart';
class MarkAttendanceWidget extends StatefulWidget {
@ -53,6 +54,8 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
}
void checkAttendanceAvailability() async {
String? deviceID = await PlatformDeviceId.getDeviceId;
print("Platform Device ID: $deviceID");
bool isAvailable = await NfcManager.instance.isAvailable();
setState(() {
AppState().privilegeListModel!.forEach((PrivilegeListModel element) {
@ -131,7 +134,7 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
children: <Widget>[
// if (isNfcEnabled)
attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () {
if (isNfcLocationEnabled) {
// if (isNfcLocationEnabled) {
if (AppState().getIsHuawei) {
checkHuaweiLocationPermission("NFC");
} else {
@ -143,13 +146,13 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
}
}, context);
}
} else {
performNfcAttendance(widget.model);
}
// } else {
// performNfcAttendance(widget.model);
// }
}),
if (isWifiEnabled)
attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () {
if (isWifiLocationEnabled) {
// if (isWifiLocationEnabled) {
if (AppState().getIsHuawei) {
checkHuaweiLocationPermission("WIFI");
} else {
@ -161,13 +164,13 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
}
}, context);
}
} else {
performWifiAttendance(widget.model);
}
// } else {
// performWifiAttendance(widget.model);
// }
}),
if (isQrEnabled)
attendanceMethod("QR", "assets/images/ic_qr.svg", isQrEnabled, () async {
if (isQrLocationEnabled) {
// if (isQrLocationEnabled) {
if (AppState().getIsHuawei) {
checkHuaweiLocationPermission("QR");
} else {
@ -179,9 +182,9 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
}
}, context);
}
} else {
performQrCodeAttendance(widget.model);
}
// } else {
// performQrCodeAttendance(widget.model);
// }
// performQrCodeAttendance(model);
}),
],

Loading…
Cancel
Save