Merge branch 'master' into development_haroon

master
haroon amjad 1 year ago
commit 0fd1c8c96b

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22.015" height="22.015" viewBox="0 0 22.015 22.015">
<g id="Button" transform="translate(-75.66 64.04) rotate(-45)">
<rect id="Rectangle_5860" data-name="Rectangle 5860" width="15.567" height="15.567" rx="7.783" transform="translate(91 16)" fill="#d85323"/>
<g id="plus_1" data-name="plus 1" transform="translate(95.001 20.001)">
<path id="Vector" d="M0,0V7.756" transform="translate(3.878)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2"/>
<path id="Vector-2" data-name="Vector" d="M0,0H7.756" transform="translate(0 3.878)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 757 B

@ -0,0 +1,4 @@
<svg id="google-docs" xmlns="http://www.w3.org/2000/svg" width="18.402" height="24.158" viewBox="0 0 18.402 24.158">
<path id="Path_4955" data-name="Path 4955" d="M63.123,24.158H77.278A2.126,2.126,0,0,0,79.4,22.035V7.078H74.447a2.126,2.126,0,0,1-2.123-2.123V0h-9.2A2.126,2.126,0,0,0,61,2.123V22.035A2.126,2.126,0,0,0,63.123,24.158Zm2.831-14.2h8.493a.708.708,0,0,1,0,1.416H65.954a.708.708,0,1,1,0-1.416Zm0,2.831h8.493a.708.708,0,0,1,0,1.416H65.954a.708.708,0,1,1,0-1.416Zm0,2.831h8.493a.708.708,0,0,1,0,1.416H65.954a.708.708,0,1,1,0-1.416Zm0,2.831h5.662a.708.708,0,0,1,0,1.416H65.954a.708.708,0,1,1,0-1.416Z" transform="translate(-61)" fill="#125765"/>
<path id="Path_4956" data-name="Path 4956" d="M331.708,14.036h4.54L331,8.789v4.54A.708.708,0,0,0,331.708,14.036Z" transform="translate(-318.26 -8.374)" fill="#2bb8a6"/>
</svg>

After

Width:  |  Height:  |  Size: 832 B

@ -530,5 +530,12 @@
"connectHmgWifi": "قم بتوصيل HMG WIFI",
"connectedHmgWifi": "اتصال HMG WIFI",
"itgForms": "نماذج (ITG)",
"resetAdPassword": "إعادة تعيين كلمة مرور AD"
"resetAdPassword": "إعادة تعيين كلمة مرور AD",
"myDocuments": "مستنداتي",
"requiredDocuments": "المستندات المطلوبة",
"optionalDocuments": "المستندات الاختيارية",
"allDocuments": "كافة المستندات",
"expiredDocuments": "المستندات منتهية الصلاحية",
"missingDocuments": "مستندات مفقودة",
"uploadedDocuments": "المستندات التي تم تحميلها"
}

@ -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"
}

@ -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<List<EmployeeDocumentsList>> getEmployeeDocuments() async {
String url = "${ApiConsts.erpRest}GET_EMPLOYEE_DOCUMENTS";
Map<String, dynamic> 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<String, dynamic> postParams = {"P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": -999, "P_IMAGE": img};

@ -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);
}

@ -349,7 +349,7 @@ class Utils {
}
static Future<DateTime> selectDate(BuildContext context, DateTime selectedDate) async {
if (!Platform.isIOS) {
if (Platform.isIOS) {
await showCupertinoModalPopup(
context: context,
builder: (BuildContext cxt) => Container(

@ -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(),

@ -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<String,dynamic> en_US = {
"mohemm": "Mohemm",
@ -1080,7 +1087,14 @@ static const Map<String,dynamic> 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<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -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';
}

@ -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>? employeeDocumentsList;
String? forgetPasswordTokenID;
List<String>? getCcpTransactionsListNew;
List<String>? 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 = <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 = <String>[];
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;

@ -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<String, dynamic> json) {
dOCUMENTREQUIREDSTATUS = json['DOCUMENT_REQUIRED_STATUS'];
dOCUMENTSTATUS = json['DOCUMENT_STATUS'];
dOCUMENTTYPE = json['DOCUMENT_TYPE'];
fUNCTIONNAME = json['FUNCTION_NAME'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = Map<String, dynamic>();
data['DOCUMENT_REQUIRED_STATUS'] = dOCUMENTREQUIREDSTATUS;
data['DOCUMENT_STATUS'] = dOCUMENTSTATUS;
data['DOCUMENT_TYPE'] = dOCUMENTTYPE;
data['FUNCTION_NAME'] = fUNCTIONNAME;
return data;
}
}

@ -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));

@ -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<GetMenuEntriesList> menuList = pro.getMenuEntriesList?.where((element) => element.parentMenuName == menuEntry.menuName && (element.menuEntryType == "FUNCTION")).toList() ?? [];
menuEntry.icon = "";

@ -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<RequestSubmitScreen> {
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);

@ -94,8 +94,17 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
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;
}

@ -19,12 +19,13 @@ class DynamicListViewParams {
String requestID;
String colsURL;
bool isUpdate;
String? popUntilRoute;
List<CollectionNotificationEit>? 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 {

@ -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<MyDocumentDetailScreen> {
DateTime? expiryDate;
List<XFile> 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: (_) => <PopupMenuItem<int>>[],
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 <double>[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<XFile> list = await picker.pickMultiImage();
if (list.isNotEmpty) {
imagesList.addAll(list);
var seen = <String>{};
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),
],
),
);
}
}

@ -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<EmployeeDocumentsList>? list;
MyDocumentsFragment(this.list, {Key? key}) : super(key: key);
@override
_MyDocumentsFragmentState createState() {
return _MyDocumentsFragmentState();
}
}
class _MyDocumentsFragmentState extends State<MyDocumentsFragment> {
int selectedIndex = 0;
List<EmployeeDocumentsList>? 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<EmployeeDocumentsList> 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<EmployeeDocumentsList> getTagBySelectedTab(int index) {
List<EmployeeDocumentsList> 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;
}
}

@ -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<MyDocumentsScreen> {
int tabIndex = 0;
PageController controller = PageController();
List<EmployeeDocumentsList>? 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 = <EmployeeDocumentsList>[];
optionalDocumentsList = <EmployeeDocumentsList>[];
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;
}
}

@ -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),
],
),
),
);
}
}

@ -118,6 +118,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

Loading…
Cancel
Save