diff --git a/assets/images/cancel_button.svg b/assets/images/cancel_button.svg
new file mode 100644
index 0000000..2aba62a
--- /dev/null
+++ b/assets/images/cancel_button.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/images/document.svg b/assets/images/document.svg
new file mode 100644
index 0000000..ca0e83f
--- /dev/null
+++ b/assets/images/document.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index 4b7acc9..48f443e 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -530,5 +530,12 @@
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI",
"itgForms": "نماذج (ITG)",
- "resetAdPassword": "إعادة تعيين كلمة مرور AD"
+ "resetAdPassword": "إعادة تعيين كلمة مرور AD",
+ "myDocuments": "مستنداتي",
+ "requiredDocuments": "المستندات المطلوبة",
+ "optionalDocuments": "المستندات الاختيارية",
+ "allDocuments": "كافة المستندات",
+ "expiredDocuments": "المستندات منتهية الصلاحية",
+ "missingDocuments": "مستندات مفقودة",
+ "uploadedDocuments": "المستندات التي تم تحميلها"
}
\ No newline at end of file
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index 3f460a1..b005710 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -530,5 +530,12 @@
"connectHmgWifi": "Connect HMG WIFI",
"connectedHmgWifi": "Connected HMG WIFI",
"itgForms": "ITG Forms",
- "resetAdPassword": "Reset AD Password"
+ "resetAdPassword": "Reset AD Password",
+ "myDocuments": "My Documents",
+ "requiredDocuments": "Required Documents",
+ "optionalDocuments": "Optional Documents",
+ "allDocuments": "All\nDocuments",
+ "expiredDocuments": "Expired\nDocuments",
+ "missingDocuments": "Missing\nDocuments",
+ "uploadedDocuments": "Uploaded\nDocuments"
}
\ No newline at end of file
diff --git a/lib/api/profile_api_client.dart b/lib/api/profile_api_client.dart
index 6a8cfb0..030a949 100644
--- a/lib/api/profile_api_client.dart
+++ b/lib/api/profile_api_client.dart
@@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/models/get_employee_address_model.dart';
import 'package:mohem_flutter_app/models/get_employee_basic_details.model.dart';
import 'package:mohem_flutter_app/models/get_employee_contacts.model.dart';
import 'package:mohem_flutter_app/models/get_employee_phones_model.dart';
+import 'package:mohem_flutter_app/models/my_documents/employee_documents_list_model.dart';
import 'package:mohem_flutter_app/models/performance.dart';
import 'package:mohem_flutter_app/models/profile/basic_details_dff_structure.dart';
import 'package:mohem_flutter_app/models/profile/get_contact_clos_structure_list.dart';
@@ -84,6 +85,19 @@ class ProfileApiClient {
}, url, postParams);
}
+ Future> getEmployeeDocuments() async {
+ String url = "${ApiConsts.erpRest}GET_EMPLOYEE_DOCUMENTS";
+ Map postParams = {
+ "P_MENU_TYPE": "E",
+ "P_SELECTED_RESP_ID": -999,
+ };
+ postParams.addAll(AppState().postParamsJson);
+ return await ApiClient().postJsonForObject((json) {
+ GenericResponseModel? responseData = GenericResponseModel.fromJson(json);
+ return responseData.employeeDocumentsList ?? [];
+ }, url, postParams);
+ }
+
Future updateEmpImage(img) async {
String url = "${ApiConsts.erpRest}UPDATE_EMPLOYEE_IMAGE";
Map postParams = {"P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": -999, "P_IMAGE": img};
diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart
index 5c9b30e..915f35d 100644
--- a/lib/classes/colors.dart
+++ b/lib/classes/colors.dart
@@ -35,6 +35,7 @@ class MyColors {
static const Color orange = Color(0xFFCC9B14);
static const Color yellowFavColor = Color(0xffEAC321);
static const Color yellowColorII = Color(0xffEAA118);
+ static const Color yellowColor00 = Color(0xffE6AA00);
static const Color backgroundBlackColor = Color(0xff202529);
static const Color black = Color(0xff000000);
static const Color white = Color(0xffffffff);
@@ -64,4 +65,5 @@ class MyColors {
static const Color grey71Color = Color(0xff717171);
static const Color darkGrey3BColor = Color(0xff3B3B3B);
static const Color lightGreyIconColor = Color(0xff919191);
+ static const Color selectedBorderColor = Color(0xff37A4BE);
}
diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart
index 1838cb8..7885fad 100644
--- a/lib/classes/utils.dart
+++ b/lib/classes/utils.dart
@@ -349,7 +349,7 @@ class Utils {
}
static Future selectDate(BuildContext context, DateTime selectedDate) async {
- if (!Platform.isIOS) {
+ if (Platform.isIOS) {
await showCupertinoModalPopup(
context: context,
builder: (BuildContext cxt) => Container(
diff --git a/lib/config/routes.dart b/lib/config/routes.dart
index 7ccb6ce..705e40d 100644
--- a/lib/config/routes.dart
+++ b/lib/config/routes.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import 'package:mohem_flutter_app/models/my_documents/employee_documents_list_model.dart';
import 'package:mohem_flutter_app/ui/app_update_screen.dart';
import 'package:mohem_flutter_app/ui/attendance/add_vacation_rule_screen.dart';
import 'package:mohem_flutter_app/ui/attendance/monthly_attendance_screen.dart';
@@ -59,6 +60,8 @@ import 'package:mohem_flutter_app/ui/screens/items_for_sale/items_for_sale_home.
import 'package:mohem_flutter_app/ui/screens/mowadhafhi/mowadhafhi_home.dart';
import 'package:mohem_flutter_app/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart';
import 'package:mohem_flutter_app/ui/screens/mowadhafhi/request_details.dart';
+import 'package:mohem_flutter_app/ui/screens/my_documents/my_document_detail_screen.dart';
+import 'package:mohem_flutter_app/ui/screens/my_documents/my_documents_screen.dart';
import 'package:mohem_flutter_app/ui/screens/my_requests/my_requests.dart';
import 'package:mohem_flutter_app/ui/screens/my_requests/new_request.dart';
import 'package:mohem_flutter_app/ui/screens/offers_and_discounts/offers_and_discounts_details.dart';
@@ -149,6 +152,8 @@ class AppRoutes {
// My Requests
static const String myRequests = "/myRequests";
static const String newRequest = "/newRequests";
+ static const String myDocuments = "/myDocuments";
+ static const String myDocumentDetail = "/myDocumentDetail";
// Items For Sale
static const String itemsForSale = "/itemsForSale";
@@ -265,7 +270,7 @@ class AppRoutes {
//My Requests
myRequests: (BuildContext context) => MyRequests(),
newRequest: (BuildContext context) => NewRequest(),
-
+ myDocuments: (BuildContext context) => MyDocumentsScreen(),
// Items for sale
itemsForSale: (BuildContext context) => ItemsForSale(),
itemsForSaleDetail: (BuildContext context) => ItemForSaleDetailPage(),
diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart
index ba21c29..c8bfdfa 100644
--- a/lib/generated/codegen_loader.g.dart
+++ b/lib/generated/codegen_loader.g.dart
@@ -546,7 +546,14 @@ class CodegenLoader extends AssetLoader{
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI",
"itgForms": "نماذج (ITG)",
- "resetAdPassword": "إعادة تعيين كلمة مرور AD"
+ "resetAdPassword": "إعادة تعيين كلمة مرور AD",
+ "myDocuments": "مستنداتي",
+ "requiredDocuments": "المستندات المطلوبة",
+ "optionalDocuments": "المستندات الاختيارية",
+ "allDocuments": "كافة المستندات",
+ "expiredDocuments": "المستندات منتهية الصلاحية",
+ "missingDocuments": "مستندات مفقودة",
+ "uploadedDocuments": "المستندات التي تم تحميلها"
};
static const Map en_US = {
"mohemm": "Mohemm",
@@ -1080,7 +1087,14 @@ static const Map en_US = {
"connectHmgWifi": "Connect HMG WIFI",
"connectedHmgWifi": "Connected HMG WIFI",
"itgForms": "ITG Forms",
- "resetAdPassword": "Reset AD Password"
+ "resetAdPassword": "Reset AD Password",
+ "myDocuments": "My Documents",
+ "requiredDocuments": "Required Documents",
+ "optionalDocuments": "Optional Documents",
+ "allDocuments": "All\nDocuments",
+ "expiredDocuments": "Expired\nDocuments",
+ "missingDocuments": "Missing\nDocuments",
+ "uploadedDocuments": "Uploaded\nDocuments"
};
static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}
diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart
index 343bf38..3a4921f 100644
--- a/lib/generated/locale_keys.g.dart
+++ b/lib/generated/locale_keys.g.dart
@@ -517,5 +517,12 @@ abstract class LocaleKeys {
static const connectedHmgWifi = 'connectedHmgWifi';
static const itgForms = 'itgForms';
static const resetAdPassword = 'resetAdPassword';
+ static const myDocuments = 'myDocuments';
+ static const requiredDocuments = 'requiredDocuments';
+ static const optionalDocuments = 'optionalDocuments';
+ static const allDocuments = 'allDocuments';
+ static const expiredDocuments = 'expiredDocuments';
+ static const missingDocuments = 'missingDocuments';
+ static const uploadedDocuments = 'uploadedDocuments';
}
diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart
index a9006eb..5188b2c 100644
--- a/lib/models/generic_response_model.dart
+++ b/lib/models/generic_response_model.dart
@@ -60,6 +60,7 @@ import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_details.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_types.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_tickets_list.dart';
+import 'package:mohem_flutter_app/models/my_documents/employee_documents_list_model.dart';
import 'package:mohem_flutter_app/models/my_requests/get_ccp_dff_structure_model.dart';
import 'package:mohem_flutter_app/models/my_requests/get_ccp_output_model.dart';
import 'package:mohem_flutter_app/models/my_requests/get_ccp_transactions_model.dart';
@@ -160,6 +161,7 @@ class GenericResponseModel {
String? deleteVacationRuleList;
String? disableSessionList;
String? employeeQR;
+ List? employeeDocumentsList;
String? forgetPasswordTokenID;
List? getCcpTransactionsListNew;
List? getConcurrentProgramsList;
@@ -431,6 +433,7 @@ class GenericResponseModel {
this.deleteVacationRuleList,
this.disableSessionList,
this.employeeQR,
+ this.employeeDocumentsList,
this.forgetPasswordTokenID,
this.getAbsenceAttachmentsList,
this.getAbsenceAttendanceTypesList,
@@ -709,6 +712,14 @@ class GenericResponseModel {
deleteVacationRuleList = json['DeleteVacationRuleList'];
disableSessionList = json['DisableSessionList'];
employeeQR = json['EmployeeQR'];
+
+ if (json['Employee_Documents_List'] != null) {
+ employeeDocumentsList = [];
+ json['Employee_Documents_List'].forEach((v) {
+ employeeDocumentsList!.add(EmployeeDocumentsList.fromJson(v));
+ });
+ }
+
forgetPasswordTokenID = json['ForgetPasswordTokenID'];
getAbsenceAttachmentsList = json['GetAbsenceAttachmentsList'];
@@ -1315,7 +1326,7 @@ class GenericResponseModel {
if (json['RespondRolesList'] != null) {
respondRolesList = [];
json['RespondRolesList'].forEach((v) {
- // respondRolesList!.add(v);
+ // respondRolesList!.add(v);
});
}
resubmitAbsenceTransactionList = json['ResubmitAbsenceTransactionList'];
@@ -1341,10 +1352,7 @@ class GenericResponseModel {
submitAddressTransactionList = json['SubmitAddressTransactionList'] != null ? SubmitAddressTransaction.fromJson(json['SubmitAddressTransactionList']) : null;
submitBasicDetTransactionList = json['SubmitBasicDetTransactionList'] != null ? SubmitBasicDetailsTransactionList.fromJson(json['SubmitBasicDetTransactionList']) : null;
submitCEITransactionList = json['SubmitCEITransactionList'];
- submitCcpTransactionList = json['SubmitCcpTransactionList'] != null
- ? new SubmitCcpTransactionList.fromJson(
- json['SubmitCcpTransactionList'])
- : null;
+ submitCcpTransactionList = json['SubmitCcpTransactionList'] != null ? new SubmitCcpTransactionList.fromJson(json['SubmitCcpTransactionList']) : null;
submitContactTransactionList = json['SubmitContactTransactionList'] != null ? SubmitContactTransactionList.fromJson(json['SubmitContactTransactionList']) : null;
submitEITTransactionList = json['SubmitEITTransactionList'] != null ? SubmitEITTransactionList.fromJson(json['SubmitEITTransactionList']) : null;
@@ -1471,6 +1479,11 @@ class GenericResponseModel {
data['DeleteVacationRuleList'] = this.deleteVacationRuleList;
data['DisableSessionList'] = this.disableSessionList;
data['EmployeeQR'] = this.employeeQR;
+
+ if (this.employeeDocumentsList != null) {
+ data['Employee_Documents_List'] = this.employeeDocumentsList!.map((v) => v.toJson()).toList();
+ }
+
data['ForgetPasswordTokenID'] = this.forgetPasswordTokenID;
data['GetAbsenceAttachmentsList'] = this.getAbsenceAttachmentsList;
@@ -1804,8 +1817,7 @@ class GenericResponseModel {
data['SubmitCEITransactionList'] = this.submitCEITransactionList;
if (this.submitCcpTransactionList != null) {
- data['SubmitCcpTransactionList'] =
- this.submitCcpTransactionList!.toJson();
+ data['SubmitCcpTransactionList'] = this.submitCcpTransactionList!.toJson();
}
data['SubmitContactTransactionList'] = this.submitContactTransactionList;
diff --git a/lib/models/my_documents/employee_documents_list_model.dart b/lib/models/my_documents/employee_documents_list_model.dart
new file mode 100644
index 0000000..97ef785
--- /dev/null
+++ b/lib/models/my_documents/employee_documents_list_model.dart
@@ -0,0 +1,29 @@
+class EmployeeDocumentsList {
+ String? dOCUMENTREQUIREDSTATUS;
+ String? dOCUMENTSTATUS;
+ String? dOCUMENTTYPE;
+ String? fUNCTIONNAME;
+
+ EmployeeDocumentsList({
+ this.dOCUMENTREQUIREDSTATUS,
+ this.dOCUMENTSTATUS,
+ this.dOCUMENTTYPE,
+ this.fUNCTIONNAME,
+ });
+
+ EmployeeDocumentsList.fromJson(Map json) {
+ dOCUMENTREQUIREDSTATUS = json['DOCUMENT_REQUIRED_STATUS'];
+ dOCUMENTSTATUS = json['DOCUMENT_STATUS'];
+ dOCUMENTTYPE = json['DOCUMENT_TYPE'];
+ fUNCTIONNAME = json['FUNCTION_NAME'];
+ }
+
+ Map toJson() {
+ Map data = Map();
+ data['DOCUMENT_REQUIRED_STATUS'] = dOCUMENTREQUIREDSTATUS;
+ data['DOCUMENT_STATUS'] = dOCUMENTSTATUS;
+ data['DOCUMENT_TYPE'] = dOCUMENTTYPE;
+ data['FUNCTION_NAME'] = fUNCTIONNAME;
+ return data;
+ }
+}
diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart
index 0e18544..5eac532 100644
--- a/lib/provider/dashboard_provider_model.dart
+++ b/lib/provider/dashboard_provider_model.dart
@@ -278,6 +278,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
getMenuEntriesList.add(activeDirectoryEntry);
list.add(GetMenuEntriesList(requestType: "ITG_FORMS", prompt: LocaleKeys.itgForms.tr(), menuName: 'ITG_FORMS'));
+ list.add(GetMenuEntriesList(requestType: "MY_DOCUMENTS", prompt: LocaleKeys.myDocuments.tr(), menuName: 'MY_DOCUMENTS'));
}
menus.add(Menus(getMenuEntriesList[i], list));
diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart
index 2333c18..7dabb0c 100644
--- a/lib/ui/landing/widget/services_widget.dart
+++ b/lib/ui/landing/widget/services_widget.dart
@@ -69,7 +69,9 @@ class ServicesWidget extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- SvgPicture.asset(AppState().isArabic(context) ? getMenuIconAr(data.homeMenus![parentIndex].menuEntiesList[index].prompt!) : getMenuIconEn(data.homeMenus![parentIndex].menuEntiesList[index].prompt!)),
+ SvgPicture.asset(AppState().isArabic(context)
+ ? getMenuIconAr(data.homeMenus![parentIndex].menuEntiesList[index].prompt!)
+ : getMenuIconEn(data.homeMenus![parentIndex].menuEntiesList[index].prompt!)),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
@@ -138,6 +140,9 @@ class ServicesWidget extends StatelessWidget {
case "قاعدة الاجازات":
returnImage = "assets/images/services_icons/vacation_rule.svg";
break;
+ case "مستنداتي":
+ returnImage = "assets/images/document.svg";
+ break;
default:
returnImage = "assets/images/monthly_attendance.svg";
break;
@@ -181,6 +186,9 @@ class ServicesWidget extends StatelessWidget {
case "Vacation Rule":
returnImage = "assets/images/services_icons/vacation_rule.svg";
break;
+ case "My Documents":
+ returnImage = "assets/images/document.svg";
+ break;
default:
returnImage = "assets/images/monthly_attendance.svg";
break;
@@ -199,6 +207,9 @@ class ServicesWidget extends StatelessWidget {
} else if (menuEntry.menuName == "MBL_PERINFO_SS") {
Navigator.of(context).pushNamed(AppRoutes.profile);
return;
+ } else if (menuEntry.menuName == "MY_DOCUMENTS") {
+ Navigator.pushNamed(context, AppRoutes.myDocuments);
+ return;
}
List menuList = pro.getMenuEntriesList?.where((element) => element.parentMenuName == menuEntry.menuName && (element.menuEntryType == "FUNCTION")).toList() ?? [];
menuEntry.icon = "";
diff --git a/lib/ui/misc/request_submit_screen.dart b/lib/ui/misc/request_submit_screen.dart
index 3611241..6fa0ef8 100644
--- a/lib/ui/misc/request_submit_screen.dart
+++ b/lib/ui/misc/request_submit_screen.dart
@@ -31,8 +31,9 @@ class RequestSubmitScreenParams {
String pItemId;
String approvalFlag;
String? selectedEmployeeID;
+ String? popNavigateToSpecificRoute;
- RequestSubmitScreenParams(this.title, this.transactionId, this.pItemId, this.approvalFlag, {this.selectedEmployeeID});
+ RequestSubmitScreenParams(this.title, this.transactionId, this.pItemId, this.approvalFlag, {this.selectedEmployeeID, this.popNavigateToSpecificRoute});
}
class RequestSubmitScreen extends StatefulWidget {
@@ -145,8 +146,13 @@ class _RequestSubmitScreenState extends State {
Utils.hideLoading(context);
Utils.showToast(LocaleKeys.yourRequestHasBeenSubmittedForApprovals.tr(), longDuration: true);
AppState().cancelRequestTrancsection = false;
- Navigator.of(context).popUntil((route) => route.settings.name == AppRoutes.dashboard);
- Navigator.pushNamed(context, AppRoutes.workList);
+
+ if (params?.popNavigateToSpecificRoute == null) {
+ Navigator.of(context).popUntil((route) => route.settings.name == AppRoutes.dashboard);
+ Navigator.pushNamed(context, AppRoutes.workList);
+ } else {
+ Navigator.of(context).popUntil((route) => route.settings.name == params!.popNavigateToSpecificRoute);
+ }
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart
index 3e75813..8d595bf 100644
--- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart
+++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart
@@ -94,8 +94,17 @@ class _DynamicInputScreenState extends State {
genericResponseModel = await MyAttendanceApiClient().validateEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp);
SubmitEITTransactionList submitEITTransactionList = await MyAttendanceApiClient().submitEitTransaction(dESCFLEXCONTEXTCODE, dynamicParams!.dynamicId, values, empID: dynamicParams!.selectedEmp);
Utils.hideLoading(context);
- await Navigator.pushNamed(context, AppRoutes.requestSubmitScreen,
- arguments: RequestSubmitScreenParams(LocaleKeys.submit.tr(), submitEITTransactionList.pTRANSACTIONID!, submitEITTransactionList.pITEMKEY!, 'eit'));
+ await Navigator.pushNamed(
+ context,
+ AppRoutes.requestSubmitScreen,
+ arguments: RequestSubmitScreenParams(
+ LocaleKeys.submit.tr(),
+ submitEITTransactionList.pTRANSACTIONID!,
+ submitEITTransactionList.pITEMKEY!,
+ 'eit',
+ popNavigateToSpecificRoute: dynamicParams!.popUntilRoute,
+ ),
+ );
if (!AppState().cancelRequestTrancsection) {
return;
}
diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart
index a9c9694..9294159 100644
--- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart
+++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart
@@ -19,12 +19,13 @@ class DynamicListViewParams {
String requestID;
String colsURL;
bool isUpdate;
+ String? popUntilRoute;
List? collectionNotificationList;
final String? selectedEmp;
DynamicListViewParams(this.title, this.dynamicId,
- {this.selectedEmp, this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = '', this.colsURL = '', this.isUpdate = false, this.collectionNotificationList});
+ {this.selectedEmp, this.uRL = 'GET_EIT_DFF_STRUCTURE', this.requestID = '', this.colsURL = '', this.isUpdate = false, this.collectionNotificationList, this.popUntilRoute});
}
class DynamicListViewScreen extends StatefulWidget {
diff --git a/lib/ui/screens/my_documents/my_document_detail_screen.dart b/lib/ui/screens/my_documents/my_document_detail_screen.dart
new file mode 100644
index 0000000..ec97586
--- /dev/null
+++ b/lib/ui/screens/my_documents/my_document_detail_screen.dart
@@ -0,0 +1,174 @@
+import 'dart:io';
+
+import 'package:dotted_border/dotted_border.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:image_picker/image_picker.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/my_documents/employee_documents_list_model.dart';
+import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
+import 'package:mohem_flutter_app/widgets/button/default_button.dart';
+import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart';
+import 'package:mohem_flutter_app/widgets/my_document_item.dart';
+import 'package:sizer/sizer.dart';
+
+class MyDocumentDetailScreen extends StatefulWidget {
+ EmployeeDocumentsList document;
+ final Color color;
+
+ MyDocumentDetailScreen(this.document, this.color, {Key? key}) : super(key: key);
+
+ @override
+ _MyDocumentDetailScreenState createState() {
+ return _MyDocumentDetailScreenState();
+ }
+}
+
+class _MyDocumentDetailScreenState extends State {
+ DateTime? expiryDate;
+ List imagesList = [];
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ backgroundColor: Colors.white,
+ appBar: AppBarWidget(context, title: widget.document.dOCUMENTTYPE!, showHomeButton: true),
+ body: Column(
+ children: [
+ ListView(
+ padding: const EdgeInsets.all(21),
+ children: [
+ MyDocumentItem(widget.document, widget.color,isNotInDetailView: false),
+ 20.height,
+ DynamicTextFieldWidget(
+ LocaleKeys.employeeNumber.tr(),
+ AppState().getUserName!,
+ isInputTypeNum: true,
+ isReadOnly: true,
+ ),
+ 12.height,
+ PopupMenuButton(
+ child: DynamicTextFieldWidget(
+ "Document Type*",
+ "National ID",
+ isEnable: false,
+ isPopup: true,
+ isInputTypeNum: true,
+ // isReadOnly: true,
+ ),
+ itemBuilder: (_) => >[],
+ onSelected: (int popipIndex) async {}),
+ 12.height,
+ DynamicTextFieldWidget(
+ "Expiry Date",
+ expiryDate == null ? LocaleKeys.dateRequired.tr() : Utils.getMonthNamedFormat(expiryDate!).replaceAll("-", " "),
+ suffixIconData: Icons.calendar_today,
+ isEnable: false,
+ onTap: () async {
+ DateTime date = await Utils.selectDate(context, expiryDate ?? DateTime.now());
+ String dateString = date.toString().split(' ').first;
+ if (date != expiryDate) {
+ expiryDate = date;
+ setState(() {});
+ }
+ },
+ ),
+ 12.height,
+ DottedBorder(
+ borderType: BorderType.RRect,
+ radius: const Radius.circular(10),
+ padding: const EdgeInsets.all(12),
+ dashPattern: const [2, 1],
+ color: MyColors.selectedBorderColor,
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Transform.rotate(
+ angle: 45,
+ child: const Icon(Icons.attach_file_rounded, size: 16, color: MyColors.selectedBorderColor),
+ ),
+ 4.width,
+ "Attach Image".toText14(color: MyColors.selectedBorderColor),
+ ],
+ ).center,
+ ).onPress(() async {
+ ImagePicker picker = ImagePicker();
+ List list = await picker.pickMultiImage();
+ if (list.isNotEmpty) {
+ imagesList.addAll(list);
+ var seen = {};
+ imagesList = imagesList.where((image) => seen.add(image.name)).toList();
+ setState(() {});
+ }
+ }),
+ 12.height,
+ GridView.builder(
+ padding: EdgeInsets.zero,
+ itemCount: imagesList.length,
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ itemBuilder: (context, index) {
+ return Stack(
+ alignment: Alignment.topRight,
+ children: [
+ AspectRatio(
+ aspectRatio: 1,
+ child: Image.file(
+ File(imagesList[index].path),
+ fit: BoxFit.cover,
+ errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) {
+ return const Center(child: Text('This image type is not supported'));
+ },
+ ),
+ ).paddingOnly(top: 6, right: 6),
+ Container(
+ height: 16,
+ width: 16,
+ decoration: const BoxDecoration(
+ shape: BoxShape.circle,
+ color: Color(0xffd85323),
+ ),
+ child: const Icon(Icons.clear, color: Colors.white, size: 12),
+ ).onPress(() {
+ imagesList.removeAt(index);
+ setState(() {});
+ }),
+ ],
+ );
+ },
+ gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
+ crossAxisCount: 4,
+ mainAxisSpacing: 8,
+ crossAxisSpacing: 8,
+ childAspectRatio: 1,
+ ),
+ )
+ ],
+ ).expanded,
+ const Divider(height: 1, color: MyColors.lightGreyEFColor),
+ DefaultButton(
+ LocaleKeys.submit.tr(),
+ widget.document.dOCUMENTSTATUS == "Exist" ? null : () {},
+ ).paddingOnly(left: 21, right: 21, bottom: 21, top: 14),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/ui/screens/my_documents/my_documents_fragment.dart b/lib/ui/screens/my_documents/my_documents_fragment.dart
new file mode 100644
index 0000000..89ad69d
--- /dev/null
+++ b/lib/ui/screens/my_documents/my_documents_fragment.dart
@@ -0,0 +1,157 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:mohem_flutter_app/api/profile_api_client.dart';
+import 'package:mohem_flutter_app/app_state/app_state.dart';
+import 'package:mohem_flutter_app/classes/colors.dart';
+import 'package:mohem_flutter_app/classes/utils.dart';
+import 'package:mohem_flutter_app/config/routes.dart';
+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/my_documents/employee_documents_list_model.dart';
+import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart';
+import 'package:mohem_flutter_app/ui/screens/my_documents/my_document_detail_screen.dart';
+import 'package:mohem_flutter_app/widgets/my_document_item.dart';
+
+class MyDocumentsFragment extends StatefulWidget {
+ List? list;
+
+ MyDocumentsFragment(this.list, {Key? key}) : super(key: key);
+
+ @override
+ _MyDocumentsFragmentState createState() {
+ return _MyDocumentsFragmentState();
+ }
+}
+
+class _MyDocumentsFragmentState extends State {
+ int selectedIndex = 0;
+ List? documentsList;
+
+ @override
+ void initState() {
+ super.initState();
+ documentsList = widget.list;
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ void didUpdateWidget(covariant MyDocumentsFragment oldWidget) {
+ super.didUpdateWidget(oldWidget);
+ if (oldWidget.list != widget.list) {
+ documentsList = widget.list;
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ List documentfilteredList = getTagBySelectedTab(selectedIndex);
+ return Column(
+ children: [
+ GridView.count(
+ crossAxisSpacing: 6,
+ crossAxisCount: 4,
+ childAspectRatio: 79 / 79,
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ padding: const EdgeInsets.only(left: 21, right: 21, bottom: 11, top: 21),
+ children: [
+ gridViewItem(LocaleKeys.allDocuments.tr(), getTagBySelectedTab(0).length.toString(), 0, MyColors.darkTextColor),
+ gridViewItem(LocaleKeys.expiredDocuments.tr(), getTagBySelectedTab(1).length.toString(), 1, MyColors.redA3Color),
+ gridViewItem(LocaleKeys.missingDocuments.tr(), getTagBySelectedTab(2).length.toString(), 2, MyColors.yellowColor00),
+ gridViewItem(LocaleKeys.uploadedDocuments.tr(), getTagBySelectedTab(3).length.toString(), 3, MyColors.greenColor),
+ ],
+ ),
+ documentsList == null
+ ? const SizedBox()
+ : (documentfilteredList.isNotEmpty
+ ? ListView.separated(
+ physics: const BouncingScrollPhysics(),
+ padding: const EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 11),
+ itemBuilder: (cxt, index) {
+ return MyDocumentItem(documentfilteredList[index], getColorByDocumentStatus(documentfilteredList[index].dOCUMENTSTATUS!)).onPress(() {
+ Navigator.pushNamed(context, AppRoutes.addDynamicInput,
+ arguments: DynamicListViewParams(documentfilteredList[index].dOCUMENTTYPE!, documentfilteredList[index].fUNCTIONNAME!, selectedEmp: AppState().getUserName, popUntilRoute: AppRoutes.myDocuments));
+ });
+ },
+ separatorBuilder: (cxt, index) => 12.height,
+ itemCount: documentfilteredList.length)
+ : Utils.getNoDataWidget(context).center)
+ .expanded,
+ ],
+ );
+ }
+
+ Widget gridViewItem(String title, String value, int index, Color color) {
+ return Container(
+ padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8),
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(15),
+ boxShadow: [
+ BoxShadow(
+ color: const Color(0xff000000).withOpacity(.05),
+ blurRadius: 26,
+ offset: const Offset(0, 0),
+ ),
+ ],
+ border: Border.all(color: selectedIndex == index ? MyColors.selectedBorderColor : Colors.white, width: 2),
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ title.toText10(),
+ value.toText20(isBold: true, color: color),
+ ],
+ ),
+ ).onPress(() {
+ setState(() {
+ selectedIndex = index;
+ });
+ });
+ }
+
+ Color getColorByDocumentStatus(String status) {
+ Color _color;
+ switch (status) {
+ case "Exist":
+ _color = MyColors.greenColor;
+ break;
+ case "Missing":
+ _color = MyColors.yellowColor00;
+ break;
+ case "Not Exist":
+ _color = MyColors.redA3Color;
+ break;
+ default:
+ _color = MyColors.darkTextColor;
+ break;
+ }
+ return _color;
+ }
+
+ List getTagBySelectedTab(int index) {
+ List list = [];
+ switch (index) {
+ case 1:
+ list = documentsList?.where((element) => element.dOCUMENTSTATUS == "Not Exist").toList() ?? [];
+ break;
+ case 2:
+ list = documentsList?.where((element) => element.dOCUMENTSTATUS == "Missing").toList() ?? [];
+ break;
+ case 3:
+ list = documentsList?.where((element) => element.dOCUMENTSTATUS == "Exist").toList() ?? [];
+ break;
+ default:
+ list = documentsList ?? [];
+ break;
+ }
+ return list;
+ }
+}
diff --git a/lib/ui/screens/my_documents/my_documents_screen.dart b/lib/ui/screens/my_documents/my_documents_screen.dart
new file mode 100644
index 0000000..ffddd36
--- /dev/null
+++ b/lib/ui/screens/my_documents/my_documents_screen.dart
@@ -0,0 +1,132 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:mohem_flutter_app/api/profile_api_client.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/my_documents/employee_documents_list_model.dart';
+import 'package:mohem_flutter_app/ui/screens/my_documents/my_documents_fragment.dart';
+import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
+
+class MyDocumentsScreen extends StatefulWidget {
+ MyDocumentsScreen({Key? key}) : super(key: key);
+
+ @override
+ _MyDocumentsScreenState createState() {
+ return _MyDocumentsScreenState();
+ }
+}
+
+class _MyDocumentsScreenState extends State {
+ int tabIndex = 0;
+ PageController controller = PageController();
+
+ List? documentsList;
+
+ @override
+ void initState() {
+ super.initState();
+ getDocuments();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ void getDocuments() async {
+ try {
+ documentsList?.clear();
+ Utils.showLoading(context);
+ documentsList = await ProfileApiClient().getEmployeeDocuments();
+ Utils.hideLoading(context);
+ setState(() {});
+ } catch (ex) {
+ Utils.hideLoading(context);
+ Utils.handleException(ex, context, null);
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ var requiredDocumentsList;
+ var optionalDocumentsList;
+
+ if (documentsList?.isNotEmpty ?? false) {
+ requiredDocumentsList = [];
+ optionalDocumentsList = [];
+ documentsList!.forEach((element) {
+ if (element.dOCUMENTREQUIREDSTATUS == "Required") {
+ requiredDocumentsList.add(element);
+ } else {
+ optionalDocumentsList.add(element);
+ }
+ });
+ }
+
+ return Scaffold(
+ backgroundColor: Colors.white,
+ appBar: AppBarWidget(context, title: LocaleKeys.myDocuments.tr(), showHomeButton: true),
+ body: 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.requiredDocuments.tr(), 0), myTab(LocaleKeys.optionalDocuments.tr(), 1)],
+ ),
+ ),
+ PageView(
+ controller: controller,
+ physics: const NeverScrollableScrollPhysics(),
+ onPageChanged: (int pageIndex) {
+ setState(() {
+ tabIndex = pageIndex;
+ });
+ },
+ children: [MyDocumentsFragment(requiredDocumentsList), MyDocumentsFragment(optionalDocumentsList)],
+ ).expanded,
+ ],
+ ),
+ );
+ }
+
+ 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(() {
+ controller.jumpToPage(index);
+ }).expanded;
+ }
+}
diff --git a/lib/widgets/my_document_item.dart b/lib/widgets/my_document_item.dart
new file mode 100644
index 0000000..b0d4b51
--- /dev/null
+++ b/lib/widgets/my_document_item.dart
@@ -0,0 +1,76 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.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/my_documents/employee_documents_list_model.dart';
+import 'package:sizer/sizer.dart';
+
+class MyDocumentItem extends StatelessWidget {
+ EmployeeDocumentsList document;
+ final Color color;
+ final bool isNotInDetailView;
+
+ MyDocumentItem(this.document, this.color, {Key? key,this.isNotInDetailView = true}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(10),
+ boxShadow: [
+ BoxShadow(
+ color: const Color(0xff000000).withOpacity(.05),
+ blurRadius: 26,
+ offset: const Offset(0, -3),
+ ),
+ ],
+ ),
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(10.0),
+ child: Stack(
+ children: [
+ Positioned(
+ top: -35,
+ child: Container(
+ width: 45,
+ height: 45,
+ transform: Matrix4.rotationZ(0.8),
+ color: color,
+ ),
+ ),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ SvgPicture.asset('assets/images/document.svg').paddingOnly(top: 6),
+ 12.width,
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ document.dOCUMENTTYPE!.toText16(),
+ document.dOCUMENTSTATUS!.toText10(color: color),
+ ],
+ ).expanded,
+ ],
+ ).expanded,
+ if(isNotInDetailView)
+ const Icon(
+ Icons.arrow_forward,
+ size: 20,
+ color: Color(0xff2E303A),
+ )
+ ],
+ ).paddingOnly(top: 14, bottom: 18, right: 14, left: 24),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index bc70be9..aae7196 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -117,6 +117,9 @@ dependencies:
# store_checker: ^1.1.0
google_api_availability: ^3.0.1
+ #todo its for temporary purpose, later will remove this.
+ dotted_border: ^2.0.0+3
+
dependency_overrides:
firebase_core_platform_interface: 4.5.1