From 4edb19c2bb214f76ed86c3aa70ead8c1cd91958e Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 16 Aug 2022 16:07:51 +0300 Subject: [PATCH 1/3] Vacation rule added cont. --- lib/classes/colors.dart | 3 + lib/extensions/widget_extensions.dart | 3 +- lib/models/generic_response_model.dart | 9 +- .../attendance/add_vacation_rule_screen.dart | 245 +++++++++++++++++- lib/ui/work_list/sheets/delegate_sheet.dart | 34 +-- .../work_list/sheets/selected_item_sheet.dart | 8 +- lib/widgets/bottom_sheet.dart | 12 +- .../search_employee_bottom_sheet.dart | 224 ++++++++++++++++ .../dynamic_textfield_widget.dart | 5 +- 9 files changed, 494 insertions(+), 49 deletions(-) create mode 100644 lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart index 4b34186..e37a049 100644 --- a/lib/classes/colors.dart +++ b/lib/classes/colors.dart @@ -22,11 +22,14 @@ class MyColors { static const Color darkWhiteColor = Color(0xffE0E0E0); static const Color redColor = Color(0xffD02127); static const Color yellowColor = Color(0xffF4E31C); + static const Color yellowFavColor = Color(0xffEAC321); static const Color backgroundBlackColor = Color(0xff202529); static const Color black = Color(0xff000000); static const Color white = Color(0xffffffff); static const Color green = Color(0xffffffff); static const Color borderColor = Color(0xffE8E8E8); + static const Color borderE3Color = Color(0xffE3E3E3); + static const Color borderCEColor = Color(0xffCECECE); //static const Color grey67Color = Color(0xff676767); static const Color whiteColor = Color(0xFFEEEEEE); static const Color greenColor = Color(0xff1FA269); diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index bbe50b4..247cde5 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -41,7 +41,7 @@ extension WidgetExtensions on Widget { child: this, ); - Widget objectContainerView({String title = ""}) { + Widget objectContainerView({String title = "", String note = ""}) { return Container( padding: const EdgeInsets.only(top: 15, bottom: 15, left: 14, right: 14), decoration: BoxDecoration( @@ -62,6 +62,7 @@ extension WidgetExtensions on Widget { if (title.isNotEmpty) title.toText16(), if (title.isNotEmpty) 12.height, this, + if (note.isNotEmpty) note.toText11(), ], ), ); diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 782fb7c..1260d80 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -294,7 +294,7 @@ class GenericResponseModel { String? registerUserNameList; List? replacementList; List? respondAttributesList; - String? respondRolesList; + List? respondRolesList; String? resubmitAbsenceTransactionList; String? resubmitEITTransactionList; String? resubmitHrTransactionList; @@ -1163,7 +1163,12 @@ class GenericResponseModel { respondAttributesList!.add(new RespondAttributesList.fromJson(v)); }); } - respondRolesList = json['RespondRolesList']; + if (json['RespondRolesList'] != null) { + respondRolesList = []; + json['RespondRolesList'].forEach((v) { + respondRolesList!.add(v); + }); + } resubmitAbsenceTransactionList = json['ResubmitAbsenceTransactionList']; resubmitEITTransactionList = json['ResubmitEITTransactionList']; resubmitHrTransactionList = json['ResubmitHrTransactionList']; diff --git a/lib/ui/attendance/add_vacation_rule_screen.dart b/lib/ui/attendance/add_vacation_rule_screen.dart index b3c3780..a76e65a 100644 --- a/lib/ui/attendance/add_vacation_rule_screen.dart +++ b/lib/ui/attendance/add_vacation_rule_screen.dart @@ -1,7 +1,11 @@ +import 'dart:io'; + import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/vacation_rule_api_client.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/int_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/vacation_rule/get_item_type_notifications_list_model.dart'; @@ -9,8 +13,13 @@ import 'package:mohem_flutter_app/models/vacation_rule/get_notification_reassign import 'package:mohem_flutter_app/models/vacation_rule/respond_attributes_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/vr_item_types_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/wf_look_up_list_model.dart'; +import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; +import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; +import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; class AddVacationRuleScreen extends StatefulWidget { AddVacationRuleScreen({Key? key}) : super(key: key); @@ -23,14 +32,24 @@ class AddVacationRuleScreen extends StatefulWidget { class _AddVacationRuleScreenState extends State { List? vrItemTypesList; + VrItemTypesList? selectedItemType; + List? itemTypeNotificationsList; + GetItemTypeNotificationsList? selectedItemTypeNotification; List? notificationReassignModeList; + GetNotificationReassignModeList? notificationReassignMode; + List? respondAttributesList; List? wfLookupList; + ReplacementList? selectedReplacementEmployee; + int currentStage = 0; + DateTime startTime = DateTime.now(); + DateTime? endTime; + @override void initState() { super.initState(); @@ -53,7 +72,8 @@ class _AddVacationRuleScreenState extends State { void getItemTypeNotificationsList() async { try { Utils.showLoading(context); - //itemTypeNotificationsList = await VacationRuleApiClient().getItemTypeNotifications(); + itemTypeNotificationsList = await VacationRuleApiClient().getItemTypeNotifications(selectedItemType!.iTEMTYPE!); + itemTypeNotificationsList!.insert(0, GetItemTypeNotificationsList(nOTIFICATIONDISPLAYNAME: "All", nOTIFICATIONNAME: "*", fYIFLAG: "N")); Utils.hideLoading(context); currentStage = 2; setState(() {}); @@ -67,13 +87,31 @@ class _AddVacationRuleScreenState extends State { try { Utils.showLoading(context); List results = await Future.wait([ - // VacationRuleApiClient().getNotificationReassignMode(), - // VacationRuleApiClient().getRespondAttributes("", ""), + VacationRuleApiClient().getNotificationReassignMode(), + VacationRuleApiClient().getRespondAttributes(selectedItemType!.iTEMTYPE!, selectedItemTypeNotification!.nOTIFICATIONNAME!), // VacationRuleApiClient().getWfLookup(P_LOOKUP_TYPE), ]); notificationReassignModeList = results[0]; + if (selectedItemType!.iTEMTYPE != "*") { + notificationReassignModeList!.add( + GetNotificationReassignModeList( + rADIOBUTTONLABEL: "Deliver notifications to me regardless of any general rules", + rADIOBUTTONACTION: "deliver_notification", + rADIOBUTTONSEQ: 1, + ), + ); + } + if (selectedItemTypeNotification!.fYIFLAG == "Y") { + notificationReassignModeList!.add( + GetNotificationReassignModeList( + rADIOBUTTONLABEL: "Close", + rADIOBUTTONACTION: "close", + rADIOBUTTONSEQ: 1, + ), + ); + } respondAttributesList = results[1]; - wfLookupList = results[2]; + // wfLookupList = results[2]; Utils.hideLoading(context); currentStage = 3; setState(() {}); @@ -94,7 +132,7 @@ class _AddVacationRuleScreenState extends State { backgroundColor: Colors.white, appBar: AppBarWidget( context, - title: LocaleKeys.vacationRule.tr(), + title: LocaleKeys.vacationRule.tr(), // todo @Sikander change title to 'Vacation Type' ), body: vrItemTypesList == null ? const SizedBox() @@ -105,20 +143,199 @@ class _AddVacationRuleScreenState extends State { ListView( padding: const EdgeInsets.all(21), physics: const BouncingScrollPhysics(), - children: [], + children: [ + if (vrItemTypesList!.isNotEmpty) + PopupMenuButton( + child: DynamicTextFieldWidget( + LocaleKeys.itemType.tr(), + selectedItemType == null ? "Select Type" : selectedItemType!.iTEMTYPEDISPLAYNAME!, + isEnable: false, + isPopup: true, + ).paddingOnly(bottom: 12), + itemBuilder: (_) => >[ + for (int i = 0; i < vrItemTypesList!.length; i++) PopupMenuItem(value: i, child: Text(vrItemTypesList![i].iTEMTYPEDISPLAYNAME!)), + ], + onSelected: (int popupIndex) { + if (selectedItemType == vrItemTypesList![popupIndex]) { + return; + } + selectedItemType = vrItemTypesList![popupIndex]; + setState(() {}); + if (selectedItemType!.iTEMTYPE == "*") { + selectedItemTypeNotification = GetItemTypeNotificationsList(nOTIFICATIONDISPLAYNAME: "All", nOTIFICATIONNAME: "*", fYIFLAG: "N"); + itemTypeNotificationsList = null; + notificationReassignMode = null; + callCombineApis(); + } else { + selectedItemTypeNotification = null; + notificationReassignMode = null; + getItemTypeNotificationsList(); + } + }).objectContainerView(title: "Apply for Vacation Rule\nStep 1", note: "*If All is selected, you will skip to step 3"), + if ((itemTypeNotificationsList ?? []).isNotEmpty) ...[ + 12.height, + PopupMenuButton( + child: DynamicTextFieldWidget( + "Notification", + selectedItemTypeNotification == null ? "Select Notification" : selectedItemTypeNotification!.nOTIFICATIONDISPLAYNAME!, + isEnable: false, + isPopup: true, + ).paddingOnly(bottom: 12), + itemBuilder: (_) => >[ + for (int i = 0; i < itemTypeNotificationsList!.length; i++) PopupMenuItem(value: i, child: Text(itemTypeNotificationsList![i].nOTIFICATIONDISPLAYNAME!)), + ], + onSelected: (int popupIndex) { + if (selectedItemTypeNotification == itemTypeNotificationsList![popupIndex]) { + return; + } + selectedItemTypeNotification = itemTypeNotificationsList![popupIndex]; + notificationReassignMode = null; + setState(() {}); + callCombineApis(); + }).objectContainerView(title: "Step 2") + ], + if (selectedItemType != null && selectedItemTypeNotification != null && currentStage == 3) ...[ + 12.height, + Column( + children: [ + ItemDetailView(LocaleKeys.itemType.tr(), selectedItemType!.iTEMTYPEDISPLAYNAME!), + ItemDetailView("Notification", selectedItemTypeNotification!.nOTIFICATIONDISPLAYNAME!), + 12.height, + DynamicTextFieldWidget( + "Start Date", + formattedDate(startTime), + suffixIconData: Icons.calendar_today, + isEnable: false, + onTap: () async { + var start = await _selectDateTime(context, startTime); + if (start != startTime) { + startTime = start; + setState(() {}); + } + }, + ), + 12.height, + DynamicTextFieldWidget( + "End Date", + formattedDate(endTime), + suffixIconData: Icons.calendar_today, + isEnable: false, + onTap: () async { + var end = await _selectDateTime(context, endTime ?? startTime); + if (end != endTime) { + endTime = end; + setState(() {}); + } + }, + ), + 12.height, + DynamicTextFieldWidget( + "Message", + "Write a message", + lines: 2, + onChange: (message) {}, + // isEnable: false, + // isPopup: true, + ).paddingOnly(bottom: 12), + PopupMenuButton( + child: DynamicTextFieldWidget( + "Notification Reassign", + notificationReassignMode == null ? "Select Notification" : notificationReassignMode!.rADIOBUTTONLABEL ?? "", + isEnable: false, + isPopup: true, + ).paddingOnly(bottom: 12), + itemBuilder: (_) => >[ + for (int i = 0; i < notificationReassignModeList!.length; i++) PopupMenuItem(value: i, child: Text(notificationReassignModeList![i].rADIOBUTTONLABEL!)), + ], + onSelected: (int popupIndex) { + if (notificationReassignMode == notificationReassignModeList![popupIndex]) { + return; + } + notificationReassignMode = notificationReassignModeList![popupIndex]; + setState(() {}); + }), + DynamicTextFieldWidget( + "Select Employee", + selectedReplacementEmployee == null ? "Search employee for replacement" : selectedReplacementEmployee!.employeeDisplayName ?? "", + isEnable: false, + onTap: () { + showMyBottomSheet( + context, + child: SearchEmployeeBottomSheet( + title: "Search for Employee", + apiMode: "DELEGATE", + onSelectEmployee: (_selectedEmployee) { + // Navigator.pop(context); + selectedReplacementEmployee = _selectedEmployee; + setState(() {}); + }, + ), + ); + }, + ).paddingOnly(bottom: 12), + ], + ).objectContainerView(title: "Step 3") + ] + ], ).expanded, DefaultButton( - currentStage == 3 ? LocaleKeys.apply.tr() : LocaleKeys.next.tr(), - () { - if (currentStage == 1) { - getItemTypeNotificationsList(); - } else if (currentStage == 2) { - callCombineApis(); - } - }, + LocaleKeys.apply.tr(), + currentStage != 3 + ? null + : () { + if (currentStage == 1) { + getItemTypeNotificationsList(); + } else if (currentStage == 2) { + callCombineApis(); + } + }, ).insideContainer, ], )), ); } + + Future _selectDateTime(BuildContext context, DateTime _time) async { + DateTime time = _time; + if (Platform.isIOS) { + await showCupertinoModalPopup( + context: context, + builder: (cxt) => Container( + height: 250, + color: Colors.white, + child: CupertinoDatePicker( + backgroundColor: Colors.white, + mode: CupertinoDatePickerMode.dateAndTime, + onDateTimeChanged: (value) { + if (value != _time) { + time = value; + } + }, + initialDateTime: _time, + ), + ), + ); + } else { + final DateTime? picked = await showDatePicker(context: context, initialDate: _time, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101)); + final TimeOfDay? timePicked = await showTimePicker( + context: context, + initialTime: TimeOfDay.fromDateTime(picked!), + ); + if (picked != _time || timePicked != TimeOfDay.fromDateTime(picked)) { + time = picked; + time = time.add( + Duration( + hours: timePicked!.hour, + minutes: timePicked.minute, + ), + ); + } + } + return time; + } + + String formattedDate(DateTime? _time) { + if (_time == null) return "Select date and time"; + return DateFormat("MM/dd/yyyy hh:mm:ss a").format(_time); + } } diff --git a/lib/ui/work_list/sheets/delegate_sheet.dart b/lib/ui/work_list/sheets/delegate_sheet.dart index 1923c27..55483bf 100644 --- a/lib/ui/work_list/sheets/delegate_sheet.dart +++ b/lib/ui/work_list/sheets/delegate_sheet.dart @@ -109,14 +109,14 @@ class _DelegateSheetState extends State { Expanded( child: SingleChildScrollView( child: Padding( - padding: EdgeInsets.all(21), + padding: const EdgeInsets.all(21), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - widget.title.toText24(), - 24.height, + widget.title.toText24(isBold: true), + 21.height, "Search".toText16(), - 20.height, + 11.height, Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -148,7 +148,7 @@ class _DelegateSheetState extends State { ), ), Container( - height: 24, + height: 36, width: 1, color: Color(0xffE5E5E5), ), @@ -156,17 +156,9 @@ class _DelegateSheetState extends State { padding: EdgeInsets.all(8), child: Row( children: [ - Text( - selectedType, - style: const TextStyle( - fontSize: 11, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.44, - ), - ), + selectedType.toText12(), 4.width, - Icon( + const Icon( Icons.keyboard_arrow_down, color: Colors.black, size: 16, @@ -269,7 +261,7 @@ class _DelegateSheetState extends State { }, separatorBuilder: (context, index) { return Container( - color: MyColors.borderColor, + color: MyColors.borderE3Color, width: double.infinity, height: 1, margin: EdgeInsets.only(top: 8, bottom: 8), @@ -286,7 +278,7 @@ class _DelegateSheetState extends State { }, separatorBuilder: (context, index) { return Container( - color: MyColors.borderColor, + color: MyColors.borderE3Color, width: double.infinity, height: 1, margin: EdgeInsets.only(top: 8, bottom: 8), @@ -371,11 +363,11 @@ class _DelegateSheetState extends State { width: 30, isImageBase64: true, ), - 16.width, - Expanded( - child: (actionHistory.nAME ?? "").toText12(), - ), + 9.width, + (actionHistory.nAME ?? "").toText12().expanded, IconButton( + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), onPressed: () { actionHistory.isFavorite = true; fetchChangeFav( diff --git a/lib/ui/work_list/sheets/selected_item_sheet.dart b/lib/ui/work_list/sheets/selected_item_sheet.dart index aadec34..2d37d06 100644 --- a/lib/ui/work_list/sheets/selected_item_sheet.dart +++ b/lib/ui/work_list/sheets/selected_item_sheet.dart @@ -37,12 +37,12 @@ class SelectedItemSheet extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - title.toText24(), - 24.height, + title.toText24(isBold: true), + 21.height, if (actionHistoryList != null) showItem(actionHistoryList!.nAME, actionHistoryList!.isFavorite), if (favoriteReplacements != null) showItem(favoriteReplacements!.employeeDisplayName, true), if (replacementList != null) showItem(replacementList!.employeeDisplayName, replacementList!.isFavorite), - 12.height, + 14.height, InputWidget( "Enter a note", "This is simple note", @@ -61,7 +61,7 @@ class SelectedItemSheet extends StatelessWidget { Container( width: double.infinity, height: 1, - color: MyColors.borderColor, + color: MyColors.borderE3Color, ), Row( children: [ diff --git a/lib/widgets/bottom_sheet.dart b/lib/widgets/bottom_sheet.dart index d151afc..206d017 100644 --- a/lib/widgets/bottom_sheet.dart +++ b/lib/widgets/bottom_sheet.dart @@ -8,11 +8,11 @@ void showMyBottomSheet(BuildContext context, {required Widget child}) { backgroundColor: Colors.transparent, builder: (BuildContext context) { return Container( - decoration: BoxDecoration( + decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( - topRight: Radius.circular(24), - topLeft: Radius.circular(24), + topRight: Radius.circular(25), + topLeft: Radius.circular(25), ), ), clipBehavior: Clip.antiAlias, @@ -20,12 +20,12 @@ void showMyBottomSheet(BuildContext context, {required Widget child}) { mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ - 8.height, + 13.height, Container( height: 6, width: 60, - decoration: BoxDecoration( - color: Colors.grey[200], + decoration: const BoxDecoration( + color: Color(0xff9A9A9A), borderRadius: BorderRadius.all( Radius.circular(20), ), diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart new file mode 100644 index 0000000..9aabbb7 --- /dev/null +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -0,0 +1,224 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.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/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/worklist/get_favorite_replacements_model.dart'; +import 'package:mohem_flutter_app/models/worklist/replacement_list_model.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; +import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; + +class SearchEmployeeBottomSheet extends StatefulWidget { + int? notificationID; + String title, apiMode; + List? actionHistoryList; + Function(ReplacementList) onSelectEmployee; + + SearchEmployeeBottomSheet({required this.title, required this.apiMode, this.notificationID, this.actionHistoryList, required this.onSelectEmployee}); + + @override + State createState() => _SearchEmployeeBottomSheetState(); +} + +class _SearchEmployeeBottomSheetState extends State { + TextEditingController username = TextEditingController(); + String searchText = ""; + + List? optionsList = [ + LocaleKeys.fullName.tr(), + LocaleKeys.username.tr(), + LocaleKeys.endDate.tr(), + ]; + List? favUsersList; + + List? replacementList; + List? favouriteUserList; + List? nonFavouriteUserList; + + int _selectedSearchIndex = 0; + + void fetchUserByInput({bool isNeedLoading = true}) async { + try { + Utils.showLoading(context); + replacementList = await WorkListApiClient().searchUserByInput( + userName: _selectedSearchIndex == 0 ? searchText : "", + userId: _selectedSearchIndex == 1 ? searchText : "", + email: _selectedSearchIndex == 2 ? searchText : "", + ); + favouriteUserList = replacementList?.where((element) => element.isFavorite ?? false).toList(); + nonFavouriteUserList = replacementList?.where((element) => !(element.isFavorite ?? false)).toList(); + Utils.hideLoading(context); + setState(() {}); + } catch (e) { + Utils.hideLoading(context); + Utils.handleException(e, context, null); + } + + if (isNeedLoading) Utils.hideLoading(context); + setState(() {}); + return null; + } + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + height: MediaQuery.of(context).size.height - 100, + child: Column( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + widget.title.toText24(isBold: true), + 21.height, + "Search".toText16(), + 11.height, + Row( + children: [ + radioOption("Name", 0, _selectedSearchIndex), + radioOption("User Name", 1, _selectedSearchIndex), + radioOption("Email", 2, _selectedSearchIndex), + ], + ), + 14.height, + Row( + children: [ + DynamicTextFieldWidget( + "Search", + "Search By Username", + inputAction: TextInputAction.done, + suffixIconData: Icons.search, + onChange: (text) { + searchText = text; + setState(() {}); + }, + ).expanded, + IconButton( + constraints: const BoxConstraints(), + onPressed: () async { + await SystemChannels.textInput.invokeMethod('TextInput.hide'); + fetchUserByInput(); + }, + icon: Icon(Icons.search)) + ], + ), + if (replacementList != null) + replacementList!.isEmpty + ? Utils.getNoDataWidget(context).expanded + : ListView( + physics: const BouncingScrollPhysics(), + padding: EdgeInsets.only(top: 21, bottom: 8), + children: [ + if (favouriteUserList?.isNotEmpty ?? false) ...[ + "Favorites".toText16(), + 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (cxt, index) => employeeItemView(favouriteUserList![index]), + separatorBuilder: (cxt, index) => Container( + height: 1, + color: MyColors.borderE3Color, + ), + itemCount: favouriteUserList?.length ?? 0), + 12.height, + ], + if (nonFavouriteUserList?.isNotEmpty ?? false) ...[ + "Related".toText16(), + 12.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (cxt, index) => employeeItemView(nonFavouriteUserList![index]), + separatorBuilder: (cxt, index) => Container( + height: 1, + color: MyColors.borderE3Color, + ), + itemCount: nonFavouriteUserList?.length ?? 0), + ] + ], + ).expanded + ], + ).paddingOnly(left: 21, right: 21, bottom: 0, top: 21).expanded, + Container(width: double.infinity, height: 1, color: MyColors.lightGreyEFColor), + DefaultButton( + LocaleKeys.cancel.tr(), + () { + Navigator.pop(context); + }, + textColor: MyColors.grey3AColor, + colors: const [ + Color(0xffE6E6E6), + Color(0xffE6E6E6), + ], + ).insideContainer + ], + ), + ); + } + + Widget employeeItemView(ReplacementList replacement) { + return InkWell( + onTap: () { + Navigator.pop(context); + widget.onSelectEmployee(replacement); + }, + child: SizedBox( + height: 50, + child: Row( + children: [ + CircularAvatar( + url: replacement.employeeImage ?? "", + height: 30, + width: 30, + isImageBase64: true, + ), + 16.width, + Expanded( + child: (replacement.employeeDisplayName ?? "").toText12(), + ), + Icon(Icons.star, size: 16, color: replacement.isFavorite! ? MyColors.yellowFavColor : MyColors.borderCEColor), + ], + ), + ), + ); + } + + Widget radioOption(String title, int value, int groupValue) { + return Row( + 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 == groupValue ? MyColors.grey3AColor : Colors.transparent, + borderRadius: BorderRadius.all(const Radius.circular(100)), + ), + ), + ), + 9.width, + title.toText12(color: MyColors.grey57Color) + ], + ).onPress(() { + _selectedSearchIndex = value; + setState(() {}); + }).expanded; + } +} diff --git a/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart b/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart index c44be0d..398b746 100644 --- a/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart +++ b/lib/widgets/dynamic_forms/dynamic_textfield_widget.dart @@ -8,6 +8,7 @@ class DynamicTextFieldWidget extends StatelessWidget { final VoidCallback? onTap; final IconData? suffixIconData; final bool isEnable; + final TextInputAction? inputAction; final bool isReadOnly; final bool isPopup; final int? lines; @@ -24,6 +25,7 @@ class DynamicTextFieldWidget extends StatelessWidget { this.isReadOnly = false, this.isPopup = false, this.lines = 1, + this.inputAction, this.onChange, this.isInputTypeNum = false, this.isBackgroundEnable = false}); @@ -62,6 +64,7 @@ class DynamicTextFieldWidget extends StatelessWidget { TextField( enabled: isEnable, scrollPadding: EdgeInsets.zero, readOnly: isReadOnly, + textInputAction: inputAction, keyboardType: isInputTypeNum ? TextInputType.number : TextInputType.text, //controller: controller, maxLines: lines, @@ -99,7 +102,7 @@ class DynamicTextFieldWidget extends StatelessWidget { ), ), if (isPopup) const Icon(Icons.keyboard_arrow_down_outlined, color: MyColors.darkIconColor), - if (onTap != null) Icon(suffixIconData ?? Icons.keyboard_arrow_down_outlined, color: MyColors.darkIconColor,size: 20), + if (onTap != null) Icon(suffixIconData ?? Icons.keyboard_arrow_down_outlined, color: MyColors.darkIconColor), ], ), ), From 3750f2c90455d65667de0a77a7289104b2370f28 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 23 Aug 2022 15:27:47 +0300 Subject: [PATCH 2/3] Vacation rule added complete. --- assets/langs/ar-SA.json | 1 + assets/langs/en-US.json | 1 + lib/api/vacation_rule_api_client.dart | 26 +- lib/extensions/widget_extensions.dart | 25 ++ lib/generated/locale_keys.g.dart | 1 + lib/models/generic_response_model.dart | 15 +- .../create_vacation_rule_list_model.dart | 18 + .../attendance/add_vacation_rule_screen.dart | 338 +++++++++++++++--- lib/ui/attendance/vacation_rule_screen.dart | 2 +- lib/widgets/dialogs/confirm_dialog.dart | 41 +-- 10 files changed, 389 insertions(+), 79 deletions(-) create mode 100644 lib/models/vacation_rule/create_vacation_rule_list_model.dart diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index ecedbdf..6821686 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -31,6 +31,7 @@ "viewAllServices": "عرض جميع الخدمات", "monthlyAttendance": "الحضور الشهري", "vacationRule": "حكم اجازة", + "vacationType": "نوع الاجازة", "startDateT": "تاريخ البدء", "endDateT": "تاريخ الانتهاء", "workFromHome": "العمل من المنزل", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 32a5e43..03ac050 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -31,6 +31,7 @@ "viewAllServices": "View All Services", "monthlyAttendance": "Monthly Attendance", "vacationRule": "Vacation Rule", + "vacationType": "Vacation Type", "startDateT": "Start Date", "endDateT": "End Date", "workFromHome": "Work From Home", diff --git a/lib/api/vacation_rule_api_client.dart b/lib/api/vacation_rule_api_client.dart index d144174..746116a 100644 --- a/lib/api/vacation_rule_api_client.dart +++ b/lib/api/vacation_rule_api_client.dart @@ -2,10 +2,10 @@ import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; +import 'package:mohem_flutter_app/models/vacation_rule/create_vacation_rule_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/get_item_type_notifications_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/get_notification_reassign_mode_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/get_vacation_rules_list_model.dart'; -import 'package:mohem_flutter_app/models/vacation_rule/respond_attributes_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/vr_item_types_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/wf_look_up_list_model.dart'; @@ -56,13 +56,33 @@ class VacationRuleApiClient { }, url, postParams); } - Future> getRespondAttributes(String pItemType, String pNotificationName) async { + Future getRespondAttributes(String pItemType, String pNotificationName) async { String url = "${ApiConsts.erpRest}GET_RESPOND_ATTRIBUTES"; Map postParams = {"P_ITEM_TYPE": pItemType, "P_NOTIFICATION_NAME": pNotificationName}; postParams.addAll(AppState().postParamsJson); return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); - return responseData.respondAttributesList ?? []; + return responseData; + }, url, postParams); + } + + Future createVacationRule(String pBeginDate, String pEndDate, String pItemType, String pNotificationName, String pMessage, String pAction, String pReplacementUserName, + List> respondAttributeList) async { + String url = "${ApiConsts.erpRest}CREATE_VACATION_RULE"; + Map postParams = { + "P_ITEM_TYPE": pItemType, + "P_NOTIFICATION_NAME": pNotificationName, + "P_BEGIN_DATE": pBeginDate, + "P_END_DATE": pEndDate, + "P_MESSAGE": pMessage, + "P_REPLACEMENT_USER_NAME": pReplacementUserName, + "P_ACTION": pAction, + "RespondAttributeList": respondAttributeList, + }; + postParams.addAll(AppState().postParamsJson); + return await ApiClient().postJsonForObject((json) { + GenericResponseModel? responseData = GenericResponseModel.fromJson(json); + return responseData.createVacationRuleList; }, url, postParams); } diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 247cde5..c9a4b49 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:shimmer/shimmer.dart'; @@ -67,4 +68,28 @@ extension WidgetExtensions on Widget { ), ); } + + Widget objectContainerBorderView({String title = "", String note = ""}) { + return Container( + padding: const EdgeInsets.only(top: 15, bottom: 15, left: 14, right: 14), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + border: Border.all( + color: MyColors.lightGreyEFColor, + width: 1, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + if (title.isNotEmpty) title.toText16(), + if (title.isNotEmpty) 12.height, + this, + if (note.isNotEmpty) note.toText11(), + ], + ), + ); + } } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index eac063d..c37b5c8 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -32,6 +32,7 @@ abstract class LocaleKeys { static const viewAllServices = 'viewAllServices'; static const monthlyAttendance = 'monthlyAttendance'; static const vacationRule = 'vacationRule'; + static const vacationType = 'vacationType'; static const startDateT = 'startDateT'; static const endDateT = 'endDateT'; static const workFromHome = 'workFromHome'; diff --git a/lib/models/generic_response_model.dart b/lib/models/generic_response_model.dart index 1260d80..e288d38 100644 --- a/lib/models/generic_response_model.dart +++ b/lib/models/generic_response_model.dart @@ -55,18 +55,19 @@ import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/models/profile/basic_details_cols_structions.dart'; import 'package:mohem_flutter_app/models/profile/basic_details_dff_structure.dart'; import 'package:mohem_flutter_app/models/profile/get_address_dff_structure_list.dart'; +import 'package:mohem_flutter_app/models/profile/get_contact_clos_structure_list.dart'; +import 'package:mohem_flutter_app/models/profile/get_contact_details_list.dart'; import 'package:mohem_flutter_app/models/profile/get_countries_list_model.dart'; import 'package:mohem_flutter_app/models/profile/phone_number_types_model.dart'; import 'package:mohem_flutter_app/models/profile/start_address_approval_process_model.dart'; import 'package:mohem_flutter_app/models/profile/submit_address_transaction.dart'; -import 'package:mohem_flutter_app/models/profile/get_contact_clos_structure_list.dart'; -import 'package:mohem_flutter_app/models/profile/get_contact_details_list.dart'; import 'package:mohem_flutter_app/models/profile/submit_basic_details_transaction_model.dart'; import 'package:mohem_flutter_app/models/profile/submit_contact_transaction_list_model.dart'; import 'package:mohem_flutter_app/models/start_eit_approval_process_model.dart'; import 'package:mohem_flutter_app/models/start_phone_approval_process_model.dart'; import 'package:mohem_flutter_app/models/submit_eit_transaction_list_model.dart'; import 'package:mohem_flutter_app/models/subordinates_on_leaves_model.dart'; +import 'package:mohem_flutter_app/models/vacation_rule/create_vacation_rule_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/get_item_type_notifications_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/get_notification_reassign_mode_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/get_vacation_rules_list_model.dart'; @@ -124,7 +125,7 @@ class GenericResponseModel { String? companyImageURL; String? companyMainCompany; List? countryList; - String? createVacationRuleList; + CreateVacationRuleList? createVacationRuleList; String? deleteAttachmentList; String? deleteVacationRuleList; String? disableSessionList; @@ -662,7 +663,8 @@ class GenericResponseModel { countryList!.add(new GetCountriesListModel.fromJson(v)); }); } - createVacationRuleList = json['CreateVacationRuleList']; + + createVacationRuleList = json['CreateVacationRuleList'] != null ? new CreateVacationRuleList.fromJson(json['CreateVacationRuleList']) : null; deleteAttachmentList = json['DeleteAttachmentList']; deleteVacationRuleList = json['DeleteVacationRuleList']; disableSessionList = json['DisableSessionList']; @@ -1299,7 +1301,10 @@ class GenericResponseModel { if (this.countryList != null) { data['CountryList'] = this.countryList!.map((v) => v.toJson()).toList(); } - data['CreateVacationRuleList'] = this.createVacationRuleList; + + if (this.createVacationRuleList != null) { + data['CreateVacationRuleList'] = this.createVacationRuleList!.toJson(); + } data['DeleteAttachmentList'] = this.deleteAttachmentList; data['DeleteVacationRuleList'] = this.deleteVacationRuleList; data['DisableSessionList'] = this.disableSessionList; diff --git a/lib/models/vacation_rule/create_vacation_rule_list_model.dart b/lib/models/vacation_rule/create_vacation_rule_list_model.dart new file mode 100644 index 0000000..5fd489a --- /dev/null +++ b/lib/models/vacation_rule/create_vacation_rule_list_model.dart @@ -0,0 +1,18 @@ +class CreateVacationRuleList { + String? pRETURNMSG; + String? pRETURNSTATUS; + + CreateVacationRuleList({this.pRETURNMSG, this.pRETURNSTATUS}); + + CreateVacationRuleList.fromJson(Map json) { + pRETURNMSG = json['P_RETURN_MSG']; + pRETURNSTATUS = json['P_RETURN_STATUS']; + } + + Map toJson() { + final Map data = new Map(); + data['P_RETURN_MSG'] = this.pRETURNMSG; + data['P_RETURN_STATUS'] = this.pRETURNSTATUS; + return data; + } +} \ No newline at end of file diff --git a/lib/ui/attendance/add_vacation_rule_screen.dart b/lib/ui/attendance/add_vacation_rule_screen.dart index a76e65a..51bf0d7 100644 --- a/lib/ui/attendance/add_vacation_rule_screen.dart +++ b/lib/ui/attendance/add_vacation_rule_screen.dart @@ -4,10 +4,15 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/vacation_rule_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/generic_response_model.dart'; +import 'package:mohem_flutter_app/models/vacation_rule/create_vacation_rule_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/get_item_type_notifications_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/get_notification_reassign_mode_list_model.dart'; import 'package:mohem_flutter_app/models/vacation_rule/respond_attributes_list_model.dart'; @@ -18,6 +23,7 @@ import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/bottom_sheets/search_employee_bottom_sheet.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; @@ -41,11 +47,18 @@ class _AddVacationRuleScreenState extends State { GetNotificationReassignModeList? notificationReassignMode; List? respondAttributesList; + List? roleList = []; List? wfLookupList; ReplacementList? selectedReplacementEmployee; + String varcharInput = ""; + String numInput = ""; + DateTime? dateInput; + WFLookUpList? wfLook; + int currentStage = 0; + String message = ""; DateTime startTime = DateTime.now(); DateTime? endTime; @@ -89,14 +102,23 @@ class _AddVacationRuleScreenState extends State { List results = await Future.wait([ VacationRuleApiClient().getNotificationReassignMode(), VacationRuleApiClient().getRespondAttributes(selectedItemType!.iTEMTYPE!, selectedItemTypeNotification!.nOTIFICATIONNAME!), - // VacationRuleApiClient().getWfLookup(P_LOOKUP_TYPE), ]); notificationReassignModeList = results[0]; + GenericResponseModel respondAttribute = results[1]; + respondAttributesList = respondAttribute.respondAttributesList; + if (respondAttributesList?.isNotEmpty ?? false) { + int index = respondAttributesList!.indexWhere((element) => element.aTTRIBUTETYPE == "LOOKUP"); + if (index > -1) { + wfLookupList = await VacationRuleApiClient().getWfLookup(respondAttributesList![index].aTTRIBUTEFORMAT!); + } + } + roleList = respondAttribute.respondRolesList; + if (selectedItemType!.iTEMTYPE != "*") { notificationReassignModeList!.add( GetNotificationReassignModeList( rADIOBUTTONLABEL: "Deliver notifications to me regardless of any general rules", - rADIOBUTTONACTION: "deliver_notification", + rADIOBUTTONACTION: "DELIVER", // ionic: DELIVER rADIOBUTTONSEQ: 1, ), ); @@ -105,13 +127,25 @@ class _AddVacationRuleScreenState extends State { notificationReassignModeList!.add( GetNotificationReassignModeList( rADIOBUTTONLABEL: "Close", - rADIOBUTTONACTION: "close", + rADIOBUTTONACTION: "CLOSE", // ionic: CLOSE + rADIOBUTTONSEQ: 1, + ), + ); + } + if (respondAttributesList!.isNotEmpty && !(selectedItemTypeNotification!.fYIFLAG == "Y")) { + notificationReassignModeList!.add( + GetNotificationReassignModeList( + rADIOBUTTONLABEL: "Respond", + rADIOBUTTONACTION: "RESPOND", // ionic: RESPOND rADIOBUTTONSEQ: 1, ), ); } - respondAttributesList = results[1]; - // wfLookupList = results[2]; + + if (notificationReassignModeList!.isNotEmpty) { + notificationReassignMode = notificationReassignModeList!.first; + } + Utils.hideLoading(context); currentStage = 3; setState(() {}); @@ -121,6 +155,111 @@ class _AddVacationRuleScreenState extends State { } } + List getDynamicWidgetList() { + List respondAttributesWidgetList = []; + for (int i = 0; i < respondAttributesList!.length; i++) { + if (respondAttributesList![i].aTTRIBUTETYPE == "VARCHAR2") { + respondAttributesWidgetList.add( + DynamicTextFieldWidget(respondAttributesList![i].aTTRIBUTEDISPLAYNAME!, respondAttributesList![i].aTTRIBUTENAME!, onChange: (message) { + varcharInput = message; + }).paddingOnly(bottom: 12), + ); + } else if (respondAttributesList![i].aTTRIBUTETYPE == "LOOKUP") { + respondAttributesWidgetList.add( + PopupMenuButton( + child: DynamicTextFieldWidget( + respondAttributesList![i].aTTRIBUTEDISPLAYNAME!, + wfLook?.lOOKUPMEANING ?? respondAttributesList![i].aTTRIBUTENAME!, + isEnable: false, + isPopup: true, + ).paddingOnly(bottom: 12), + itemBuilder: (_) => >[ + for (int i = 0; i < wfLookupList!.length; i++) PopupMenuItem(value: i, child: Text(wfLookupList![i].lOOKUPMEANING!)), + ], + onSelected: (int popupIndex) { + wfLook = wfLookupList![popupIndex]; + setState(() {}); + }, + ), + ); + } else if (respondAttributesList![i].aTTRIBUTETYPE == "DATE") { + respondAttributesWidgetList.add(DynamicTextFieldWidget( + respondAttributesList![i].aTTRIBUTEDISPLAYNAME!, + dateInput?.toString() ?? respondAttributesList![i].aTTRIBUTENAME!, + suffixIconData: Icons.calendar_today, + isEnable: false, + onTap: () async { + dateInput = await _selectDate(context); + setState(() {}); + }, + ).paddingOnly(bottom: 12)); + } else if (respondAttributesList![i].aTTRIBUTETYPE == "NUMBER") { + respondAttributesWidgetList.add( + DynamicTextFieldWidget( + respondAttributesList![i].aTTRIBUTEDISPLAYNAME!, + respondAttributesList![i].aTTRIBUTENAME!, + isInputTypeNum: true, + onChange: (input) { + numInput = input; + }, + ), + ); + } + } + return respondAttributesWidgetList; + } + + void createVacationRule(List> respondAttributeList) async { + try { + Utils.showLoading(context); + CreateVacationRuleList? createVacationRuleList = await VacationRuleApiClient().createVacationRule(DateUtil.convertDateToStringLocation(startTime), DateUtil.convertDateToStringLocation(endTime!), + selectedItemType!.iTEMTYPE!, selectedItemTypeNotification!.nOTIFICATIONNAME!, message, getPAction(), selectedReplacementEmployee!.userName!, respondAttributeList); + Utils.hideLoading(context); + Utils.showToast("Vacation rule added."); + Navigator.popUntil(context, ModalRoute.withName('AppRoutes.dashboard')); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + String getPAction() { + String pAction = ""; + switch (notificationReassignMode?.rADIOBUTTONACTION ?? "") { + case 'DELEGATE': + { + pAction = "FORWARD"; + break; + } + case 'RESPOND': + { + pAction = "RESPOND"; + break; + } + case 'CLOSE': + { + pAction = "RESPOND"; + break; + } + case 'DELIVER': + { + pAction = "NOOP"; + break; + } + case 'TRANSFER': + { + pAction = "TRANSFER"; + break; + } + default: + { + pAction = ""; + break; + } + } + return pAction; + } + @override void dispose() { super.dispose(); @@ -132,7 +271,7 @@ class _AddVacationRuleScreenState extends State { backgroundColor: Colors.white, appBar: AppBarWidget( context, - title: LocaleKeys.vacationRule.tr(), // todo @Sikander change title to 'Vacation Type' + title: LocaleKeys.vacationType.tr(), ), body: vrItemTypesList == null ? const SizedBox() @@ -233,46 +372,75 @@ class _AddVacationRuleScreenState extends State { "Message", "Write a message", lines: 2, - onChange: (message) {}, - // isEnable: false, - // isPopup: true, - ).paddingOnly(bottom: 12), - PopupMenuButton( - child: DynamicTextFieldWidget( - "Notification Reassign", - notificationReassignMode == null ? "Select Notification" : notificationReassignMode!.rADIOBUTTONLABEL ?? "", - isEnable: false, - isPopup: true, - ).paddingOnly(bottom: 12), - itemBuilder: (_) => >[ - for (int i = 0; i < notificationReassignModeList!.length; i++) PopupMenuItem(value: i, child: Text(notificationReassignModeList![i].rADIOBUTTONLABEL!)), - ], - onSelected: (int popupIndex) { - if (notificationReassignMode == notificationReassignModeList![popupIndex]) { - return; - } - notificationReassignMode = notificationReassignModeList![popupIndex]; - setState(() {}); - }), - DynamicTextFieldWidget( - "Select Employee", - selectedReplacementEmployee == null ? "Search employee for replacement" : selectedReplacementEmployee!.employeeDisplayName ?? "", - isEnable: false, - onTap: () { - showMyBottomSheet( - context, - child: SearchEmployeeBottomSheet( - title: "Search for Employee", - apiMode: "DELEGATE", - onSelectEmployee: (_selectedEmployee) { - // Navigator.pop(context); - selectedReplacementEmployee = _selectedEmployee; - setState(() {}); - }, - ), - ); + onChange: (message) { + this.message = message; }, ).paddingOnly(bottom: 12), + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + itemBuilder: (cxt, index) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 20, + height: 20, + 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: notificationReassignModeList![index] == notificationReassignMode ? MyColors.grey3AColor : Colors.transparent, + borderRadius: BorderRadius.all(const Radius.circular(100)), + ), + ), + ), + 9.width, + (notificationReassignModeList![index].rADIOBUTTONLABEL!).toText12(color: MyColors.grey57Color).expanded + ], + ).onPress(() { + if (notificationReassignMode == notificationReassignModeList![index]) { + return; + } + notificationReassignMode = notificationReassignModeList![index]; + setState(() {}); + }); + }, + separatorBuilder: (cxt, index) => 12.height, + itemCount: notificationReassignModeList!.length) + .objectContainerBorderView(title: "Notification Reassign"), + 12.height, + if (respondAttributesList?.isNotEmpty ?? false) ...getDynamicWidgetList(), + if (roleList!.isNotEmpty && notificationReassignMode?.rADIOBUTTONACTION == 'RESPOND' || + // if (notificationReassignMode?.rADIOBUTTONACTION == 'RESPOND' || + (notificationReassignMode?.rADIOBUTTONACTION == 'DELEGATE') || + (notificationReassignMode?.rADIOBUTTONACTION == 'TRANSFER')) + DynamicTextFieldWidget( + "Select Employee", + selectedReplacementEmployee == null ? "Search employee for replacement" : selectedReplacementEmployee!.employeeDisplayName ?? "", + isEnable: false, + onTap: () { + showMyBottomSheet( + context, + child: SearchEmployeeBottomSheet( + title: "Search for Employee", + apiMode: "DELEGATE", + onSelectEmployee: (_selectedEmployee) { + // Navigator.pop(context); + selectedReplacementEmployee = _selectedEmployee; + setState(() {}); + }, + ), + ); + }, + ).paddingOnly(bottom: 12), ], ).objectContainerView(title: "Step 3") ] @@ -283,11 +451,54 @@ class _AddVacationRuleScreenState extends State { currentStage != 3 ? null : () { - if (currentStage == 1) { - getItemTypeNotificationsList(); - } else if (currentStage == 2) { - callCombineApis(); + if (endTime == null) { + Utils.showToast("Please specify End Time"); + return; + } else if (notificationReassignMode == null) { + Utils.showToast("Please select notification reassign"); + return; + } else if (selectedReplacementEmployee == null) { + Utils.showToast("Please select employee for replacement"); + return; } + + List> list = []; + + if (respondAttributesList?.isNotEmpty ?? false) { + for (int i = 0; i < respondAttributesList!.length; i++) { + if (respondAttributesList![i].aTTRIBUTETYPE == "VARCHAR2") { + list.add({"ATTRIBUTE_NAME": respondAttributesList![i].aTTRIBUTENAME, "ATTRIBUTE_TEXT_VALUE": varcharInput}); + } + if (respondAttributesList![i].aTTRIBUTETYPE == "LOOKUP") { + if (wfLook == null) { + Utils.showToast('Please select action'); + break; + } + list.add({"ATTRIBUTE_NAME": respondAttributesList![i].aTTRIBUTENAME, "ATTRIBUTE_TEXT_VALUE": wfLook!.lOOKUPCODE}); + } + if (respondAttributesList![i].aTTRIBUTETYPE == "DATE") { + if (dateInput == null) { + Utils.showToast('Please select date'); + break; + } + list.add({"ATTRIBUTE_NAME": respondAttributesList![i].aTTRIBUTENAME, "ATTRIBUTE_TEXT_VALUE": DateUtil.convertDateToStringLocation(dateInput!)}); + } + if (respondAttributesList![i].aTTRIBUTETYPE == "NUMBER") { + list.add({"ATTRIBUTE_NAME": respondAttributesList![i].aTTRIBUTENAME, "ATTRIBUTE_TEXT_VALUE": numInput}); + } + } + } + + showDialog( + context: context, + builder: (cxt) => ConfirmDialog( + message: LocaleKeys.areYouSureYouWantToSubmit.tr(), + onTap: () { + Navigator.pop(context); + createVacationRule(list); + }, + ), + ); }, ).insideContainer, ], @@ -338,4 +549,35 @@ class _AddVacationRuleScreenState extends State { if (_time == null) return "Select date and time"; return DateFormat("MM/dd/yyyy hh:mm:ss a").format(_time); } + + Future _selectDate(BuildContext context) async { + DateTime time = dateInput ?? DateTime.now(); + if (Platform.isIOS) { + await showCupertinoModalPopup( + context: context, + builder: (cxt) => Container( + height: 250, + color: Colors.white, + child: CupertinoDatePicker( + backgroundColor: Colors.white, + mode: CupertinoDatePickerMode.date, + onDateTimeChanged: (value) { + if (value != null && value != dateInput) { + time = value; + } + }, + initialDateTime: dateInput, + ), + ), + ); + } else { + final DateTime? picked = + await showDatePicker(context: context, initialDate: dateInput ?? DateTime.now(), initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101)); + if (picked != null && picked != dateInput) { + time = picked; + } + } + time = DateTime(time.year, time.month, time.day); + return time; + } } diff --git a/lib/ui/attendance/vacation_rule_screen.dart b/lib/ui/attendance/vacation_rule_screen.dart index a2aa5df..5598e05 100644 --- a/lib/ui/attendance/vacation_rule_screen.dart +++ b/lib/ui/attendance/vacation_rule_screen.dart @@ -140,7 +140,7 @@ class _VacationRuleScreenState extends State { } String getParsedTime(String time) { - DateTime date = DateFormat("mm/dd/yyyy").parse(time); + DateTime date = DateFormat("MM/dd/yyyy").parse(time); return DateFormat("d MMM yyyy").format(date); } } diff --git a/lib/widgets/dialogs/confirm_dialog.dart b/lib/widgets/dialogs/confirm_dialog.dart index 7264a9b..4c94340 100644 --- a/lib/widgets/dialogs/confirm_dialog.dart +++ b/lib/widgets/dialogs/confirm_dialog.dart @@ -1,25 +1,28 @@ import 'package:easy_localization/src/public_ext.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/classes/colors.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/widgets/button/default_button.dart'; class ConfirmDialog extends StatelessWidget { final String? title; - final String? message; + final String message; final String? okTitle; final VoidCallback? onTap; - const ConfirmDialog({Key? key, this.title, @required this.message, this.okTitle, this.onTap}) : super(key: key); + const ConfirmDialog({Key? key, this.title, required this.message, this.okTitle, this.onTap}) : super(key: key); @override Widget build(BuildContext context) { return Dialog( backgroundColor: Colors.white, - shape: RoundedRectangleBorder(), - insetPadding: EdgeInsets.only(left: 21, right: 21), + shape: const RoundedRectangleBorder(), + insetPadding: const EdgeInsets.only(left: 21, right: 21), child: Padding( - padding: EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28), + padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, @@ -28,33 +31,27 @@ class ConfirmDialog extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: Padding( - padding: const EdgeInsets.only(top: 16.0), - child: Text( - title ?? LocaleKeys.confirm.tr(), - style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Color(0xff2B353E), height: 35 / 24, letterSpacing: -0.96), - ), - ), + child: Text( + title ?? LocaleKeys.confirm.tr(), + style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, height: 35 / 24, letterSpacing: -0.96), + ).paddingOnly(top: 16), ), IconButton( padding: EdgeInsets.zero, - icon: Icon(Icons.close), - color: Color(0xff2B353E), - constraints: BoxConstraints(), + icon: const Icon(Icons.close), + color: MyColors.darkTextColor, + constraints: const BoxConstraints(), onPressed: () { Navigator.pop(context); }, ) ], ), - Text( - message ?? "", - style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff808080), letterSpacing: -0.48), - ), - SizedBox(height: 28), + message.toText16(color: MyColors.lightGrayColor), + 28.height, DefaultButton( okTitle ?? LocaleKeys.ok.tr(), - onTap == null ? () => Navigator.pop(context) : onTap, + onTap ?? () => Navigator.pop(context), textColor: Colors.white, //color: Ap.green, ), From 14047154255ed3d128c05134f179099f2a967d00 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 23 Aug 2022 16:11:52 +0300 Subject: [PATCH 3/3] Vacation rule translation added. --- assets/langs/ar-SA.json | 31 +++++++++-- assets/langs/en-US.json | 31 +++++++++-- lib/generated/codegen_loader.g.dart | 54 +++++++++++++++++++ lib/generated/locale_keys.g.dart | 23 ++++++++ .../attendance/add_vacation_rule_screen.dart | 53 +++++++++--------- 5 files changed, 157 insertions(+), 35 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 6821686..0c6ce54 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -311,11 +311,34 @@ "requestType": "نوع الطلب", "employeeDigitalID": "هويةالموظف الرقمية", "businessCard": "بطاقة العمل", - "checkOut":"وقت الخروج", - "regular":"منتظم", - "mark" : "علامة", - "selectMethodOfAttendance":"اختر طريقة تسجيل الحضور", + "checkOut": "وقت الخروج", + "regular": "منتظم", + "mark": "علامة", + "selectMethodOfAttendance": "اختر طريقة تسجيل الحضور", "comeNearHMGWifi": "HMG wifi من فضلك اقترب من", + "deliverNotificationToMeRegardless": "تسليم الإخطارات إلي بغض النظر عن أي قواعد عامة", + "close": "أغلق", + "respond": "يرد", + "vacationRuleAdded": "تمت إضافة قاعدة الإجازة", + "selectTypeT": "اختر صنف", + "notification": "تنبيه", + "selectNotification": "حدد إعلام", + "ifAllSelectedYouWillSkip": "* إذا تم تحديد الكل ، فستنتقل إلى الخطوة 3", + "applyForVacationRule": "التقدم بطلب للحصول على قانون الإجازة", + "step1": "الخطوة 1", + "step2": "الخطوة 2", + "step3": "الخطوه 3", + "message": "رسالة", + "writeAMessage": "اكتب رسالة", + "notificationReassign": "إعادة تعيين الإخطار", + "selectEmployee": "حدد الموظف", + "searchEmployeeForReplacement": "ابحث عن موظف بديل", + "searchForEmployee": "ابحث عن موظف", + "pleaseSpecifyEndTime": "الرجاء تحديد وقت الانتهاء", + "pleaseSelectNotificationReassign": "يرجى تحديد إعادة تعيين الإخطار", + "pleaseSelectEmployeeForReplacement": "الرجاء تحديد موظف للاستبدال", + "pleaseSelectAction": "الرجاء تحديد الإجراء", + "pleaseSelectDate": "الرجاء تحديد التاريخ", "profile": { "reset_password": { "label": "Reset Password", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 03ac050..812fa49 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -311,11 +311,34 @@ "wantToReject": "Are you sure want to reject?", "employeeDigitalID": "Employee Digital ID", "businessCard": "Business Card", - "checkOut":"Check Out", - "regular":"Regular", - "mark" : "Mark", - "selectMethodOfAttendance":"Select the method to mark the attendance", + "checkOut": "Check Out", + "regular": "Regular", + "mark": "Mark", + "selectMethodOfAttendance": "Select the method to mark the attendance", "comeNearHMGWifi": "Please come near to HMG wifi", + "deliverNotificationToMeRegardless": "Deliver notifications to me regardless of any general rules", + "close": "Close", + "respond": "Respond", + "vacationRuleAdded": "Vacation rule added", + "selectTypeT": "Select Type", + "notification": "Notification", + "selectNotification": "Select Notification", + "ifAllSelectedYouWillSkip": "*If All is selected, you will skip to step 3", + "applyForVacationRule": "Apply for Vacation Rule", + "step1": "Step 1", + "step2": "Step 2", + "step3": "Step 3", + "message": "Message", + "writeAMessage": "Write a message", + "notificationReassign": "Notification Reassign", + "selectEmployee": "Select Employee", + "searchEmployeeForReplacement": "Search employee for replacement", + "searchForEmployee": "Search for Employee", + "pleaseSpecifyEndTime": "Please specify End Time", + "pleaseSelectNotificationReassign": "Please select notification reassign", + "pleaseSelectEmployeeForReplacement": "Please select employee for replacement", + "pleaseSelectAction": "Please select action", + "pleaseSelectDate": "Please select date", "profile": { "reset_password": { "label": "Reset Password", diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 2fa8d35..57323da 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -47,6 +47,9 @@ class CodegenLoader extends AssetLoader{ "viewAllServices": "عرض جميع الخدمات", "monthlyAttendance": "الحضور الشهري", "vacationRule": "حكم اجازة", + "vacationType": "نوع الاجازة", + "startDateT": "تاريخ البدء", + "endDateT": "تاريخ الانتهاء", "workFromHome": "العمل من المنزل", "ticketRequest": "طلب تذكرة", "viewAllOffers": "مشاهدة جميع العروض", @@ -248,6 +251,7 @@ class CodegenLoader extends AssetLoader{ "myAttendance": "حضوري", "workOnBreak": "التعويض عن العمل اثناءالاستراحه", "next": "التالي", + "apply": "يتقدم", "mobile": "التليفون المحمول", "completingYear": "نحن نقدر لك لاستكمال خدمة", "year": "سنة", @@ -328,6 +332,29 @@ class CodegenLoader extends AssetLoader{ "mark": "علامة", "selectMethodOfAttendance": "اختر طريقة تسجيل الحضور", "comeNearHMGWifi": "HMG wifi من فضلك اقترب من", + "deliverNotificationToMeRegardless": "تسليم الإخطارات إلي بغض النظر عن أي قواعد عامة", + "close": "أغلق", + "respond": "يرد", + "vacationRuleAdded": "تمت إضافة قاعدة الإجازة", + "selectTypeT": "اختر صنف", + "notification": "تنبيه", + "selectNotification": "حدد إعلام", + "ifAllSelectedYouWillSkip": "* إذا تم تحديد الكل ، فستنتقل إلى الخطوة 3", + "applyForVacationRule": "التقدم بطلب للحصول على قانون الإجازة", + "step1": "الخطوة 1", + "step2": "الخطوة 2", + "step3": "الخطوه 3", + "message": "رسالة", + "writeAMessage": "اكتب رسالة", + "notificationReassign": "إعادة تعيين الإخطار", + "selectEmployee": "حدد الموظف", + "searchEmployeeForReplacement": "ابحث عن موظف بديل", + "searchForEmployee": "ابحث عن موظف", + "pleaseSpecifyEndTime": "الرجاء تحديد وقت الانتهاء", + "pleaseSelectNotificationReassign": "يرجى تحديد إعادة تعيين الإخطار", + "pleaseSelectEmployeeForReplacement": "الرجاء تحديد موظف للاستبدال", + "pleaseSelectAction": "الرجاء تحديد الإجراء", + "pleaseSelectDate": "الرجاء تحديد التاريخ", "profile": { "reset_password": { "label": "Reset Password", @@ -395,6 +422,9 @@ static const Map en_US = { "viewAllServices": "View All Services", "monthlyAttendance": "Monthly Attendance", "vacationRule": "Vacation Rule", + "vacationType": "Vacation Type", + "startDateT": "Start Date", + "endDateT": "End Date", "workFromHome": "Work From Home", "ticketRequest": "Ticket Request", "viewAllOffers": "View All Offers", @@ -596,6 +626,7 @@ static const Map en_US = { "myAttendance": "My Attendance", "workOnBreak": "Work On Break", "next": "Next", + "apply": "Apply", "mobile": "Mobile", "year": "Year", "month": "Month", @@ -676,6 +707,29 @@ static const Map en_US = { "mark": "Mark", "selectMethodOfAttendance": "Select the method to mark the attendance", "comeNearHMGWifi": "Please come near to HMG wifi", + "deliverNotificationToMeRegardless": "Deliver notifications to me regardless of any general rules", + "close": "Close", + "respond": "Respond", + "vacationRuleAdded": "Vacation rule added", + "selectTypeT": "Select Type", + "notification": "Notification", + "selectNotification": "Select Notification", + "ifAllSelectedYouWillSkip": "*If All is selected, you will skip to step 3", + "applyForVacationRule": "Apply for Vacation Rule", + "step1": "Step 1", + "step2": "Step 2", + "step3": "Step 3", + "message": "Message", + "writeAMessage": "Write a message", + "notificationReassign": "Notification Reassign", + "selectEmployee": "Select Employee", + "searchEmployeeForReplacement": "Search employee for replacement", + "searchForEmployee": "Search for Employee", + "pleaseSpecifyEndTime": "Please specify End Time", + "pleaseSelectNotificationReassign": "Please select notification reassign", + "pleaseSelectEmployeeForReplacement": "Please select employee for replacement", + "pleaseSelectAction": "Please select action", + "pleaseSelectDate": "Please select date", "profile": { "reset_password": { "label": "Reset Password", diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index c37b5c8..d736c34 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -317,6 +317,29 @@ abstract class LocaleKeys { static const mark = 'mark'; static const selectMethodOfAttendance = 'selectMethodOfAttendance'; static const comeNearHMGWifi = 'comeNearHMGWifi'; + static const deliverNotificationToMeRegardless = 'deliverNotificationToMeRegardless'; + static const close = 'close'; + static const respond = 'respond'; + static const vacationRuleAdded = 'vacationRuleAdded'; + static const selectTypeT = 'selectTypeT'; + static const notification = 'notification'; + static const selectNotification = 'selectNotification'; + static const ifAllSelectedYouWillSkip = 'ifAllSelectedYouWillSkip'; + static const applyForVacationRule = 'applyForVacationRule'; + static const step1 = 'step1'; + static const step2 = 'step2'; + static const step3 = 'step3'; + static const message = 'message'; + static const writeAMessage = 'writeAMessage'; + static const notificationReassign = 'notificationReassign'; + static const selectEmployee = 'selectEmployee'; + static const searchEmployeeForReplacement = 'searchEmployeeForReplacement'; + static const searchForEmployee = 'searchForEmployee'; + static const pleaseSpecifyEndTime = 'pleaseSpecifyEndTime'; + static const pleaseSelectNotificationReassign = 'pleaseSelectNotificationReassign'; + static const pleaseSelectEmployeeForReplacement = 'pleaseSelectEmployeeForReplacement'; + static const pleaseSelectAction = 'pleaseSelectAction'; + static const pleaseSelectDate = 'pleaseSelectDate'; static const profile_reset_password_label = 'profile.reset_password.label'; static const profile_reset_password_username = 'profile.reset_password.username'; static const profile_reset_password_password = 'profile.reset_password.password'; diff --git a/lib/ui/attendance/add_vacation_rule_screen.dart b/lib/ui/attendance/add_vacation_rule_screen.dart index 51bf0d7..b7f7f5d 100644 --- a/lib/ui/attendance/add_vacation_rule_screen.dart +++ b/lib/ui/attendance/add_vacation_rule_screen.dart @@ -7,6 +7,7 @@ import 'package:mohem_flutter_app/api/vacation_rule_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/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'; @@ -117,7 +118,7 @@ class _AddVacationRuleScreenState extends State { if (selectedItemType!.iTEMTYPE != "*") { notificationReassignModeList!.add( GetNotificationReassignModeList( - rADIOBUTTONLABEL: "Deliver notifications to me regardless of any general rules", + rADIOBUTTONLABEL: LocaleKeys.deliverNotificationToMeRegardless.tr(), rADIOBUTTONACTION: "DELIVER", // ionic: DELIVER rADIOBUTTONSEQ: 1, ), @@ -126,7 +127,7 @@ class _AddVacationRuleScreenState extends State { if (selectedItemTypeNotification!.fYIFLAG == "Y") { notificationReassignModeList!.add( GetNotificationReassignModeList( - rADIOBUTTONLABEL: "Close", + rADIOBUTTONLABEL: LocaleKeys.close.tr(), rADIOBUTTONACTION: "CLOSE", // ionic: CLOSE rADIOBUTTONSEQ: 1, ), @@ -135,7 +136,7 @@ class _AddVacationRuleScreenState extends State { if (respondAttributesList!.isNotEmpty && !(selectedItemTypeNotification!.fYIFLAG == "Y")) { notificationReassignModeList!.add( GetNotificationReassignModeList( - rADIOBUTTONLABEL: "Respond", + rADIOBUTTONLABEL: LocaleKeys.respond.tr(), rADIOBUTTONACTION: "RESPOND", // ionic: RESPOND rADIOBUTTONSEQ: 1, ), @@ -215,8 +216,8 @@ class _AddVacationRuleScreenState extends State { CreateVacationRuleList? createVacationRuleList = await VacationRuleApiClient().createVacationRule(DateUtil.convertDateToStringLocation(startTime), DateUtil.convertDateToStringLocation(endTime!), selectedItemType!.iTEMTYPE!, selectedItemTypeNotification!.nOTIFICATIONNAME!, message, getPAction(), selectedReplacementEmployee!.userName!, respondAttributeList); Utils.hideLoading(context); - Utils.showToast("Vacation rule added."); - Navigator.popUntil(context, ModalRoute.withName('AppRoutes.dashboard')); + Utils.showToast("Vacation rule added"); + Navigator.popUntil(context, ModalRoute.withName(AppRoutes.dashboard)); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); @@ -287,7 +288,7 @@ class _AddVacationRuleScreenState extends State { PopupMenuButton( child: DynamicTextFieldWidget( LocaleKeys.itemType.tr(), - selectedItemType == null ? "Select Type" : selectedItemType!.iTEMTYPEDISPLAYNAME!, + selectedItemType == null ? LocaleKeys.selectType.tr() : selectedItemType!.iTEMTYPEDISPLAYNAME!, isEnable: false, isPopup: true, ).paddingOnly(bottom: 12), @@ -310,13 +311,13 @@ class _AddVacationRuleScreenState extends State { notificationReassignMode = null; getItemTypeNotificationsList(); } - }).objectContainerView(title: "Apply for Vacation Rule\nStep 1", note: "*If All is selected, you will skip to step 3"), + }).objectContainerView(title: "${LocaleKeys.applyForVacationRule.tr()}\n${LocaleKeys.step1.tr()}", note: LocaleKeys.ifAllSelectedYouWillSkip.tr()), if ((itemTypeNotificationsList ?? []).isNotEmpty) ...[ 12.height, PopupMenuButton( child: DynamicTextFieldWidget( "Notification", - selectedItemTypeNotification == null ? "Select Notification" : selectedItemTypeNotification!.nOTIFICATIONDISPLAYNAME!, + selectedItemTypeNotification == null ? LocaleKeys.selectNotification.tr() : selectedItemTypeNotification!.nOTIFICATIONDISPLAYNAME!, isEnable: false, isPopup: true, ).paddingOnly(bottom: 12), @@ -331,17 +332,17 @@ class _AddVacationRuleScreenState extends State { notificationReassignMode = null; setState(() {}); callCombineApis(); - }).objectContainerView(title: "Step 2") + }).objectContainerView(title: LocaleKeys.step2.tr()) ], if (selectedItemType != null && selectedItemTypeNotification != null && currentStage == 3) ...[ 12.height, Column( children: [ ItemDetailView(LocaleKeys.itemType.tr(), selectedItemType!.iTEMTYPEDISPLAYNAME!), - ItemDetailView("Notification", selectedItemTypeNotification!.nOTIFICATIONDISPLAYNAME!), + ItemDetailView(LocaleKeys.notification.tr(), selectedItemTypeNotification!.nOTIFICATIONDISPLAYNAME!), 12.height, DynamicTextFieldWidget( - "Start Date", + LocaleKeys.startDateT.tr(), formattedDate(startTime), suffixIconData: Icons.calendar_today, isEnable: false, @@ -355,7 +356,7 @@ class _AddVacationRuleScreenState extends State { ), 12.height, DynamicTextFieldWidget( - "End Date", + LocaleKeys.endDateT.tr(), formattedDate(endTime), suffixIconData: Icons.calendar_today, isEnable: false, @@ -369,8 +370,8 @@ class _AddVacationRuleScreenState extends State { ), 12.height, DynamicTextFieldWidget( - "Message", - "Write a message", + LocaleKeys.message.tr(), + LocaleKeys.writeAMessage.tr(), lines: 2, onChange: (message) { this.message = message; @@ -415,7 +416,7 @@ class _AddVacationRuleScreenState extends State { }, separatorBuilder: (cxt, index) => 12.height, itemCount: notificationReassignModeList!.length) - .objectContainerBorderView(title: "Notification Reassign"), + .objectContainerBorderView(title: LocaleKeys.notificationReassign.tr()), 12.height, if (respondAttributesList?.isNotEmpty ?? false) ...getDynamicWidgetList(), if (roleList!.isNotEmpty && notificationReassignMode?.rADIOBUTTONACTION == 'RESPOND' || @@ -423,15 +424,15 @@ class _AddVacationRuleScreenState extends State { (notificationReassignMode?.rADIOBUTTONACTION == 'DELEGATE') || (notificationReassignMode?.rADIOBUTTONACTION == 'TRANSFER')) DynamicTextFieldWidget( - "Select Employee", - selectedReplacementEmployee == null ? "Search employee for replacement" : selectedReplacementEmployee!.employeeDisplayName ?? "", + LocaleKeys.selectEmployee.tr(), + selectedReplacementEmployee == null ? LocaleKeys.searchEmployeeForReplacement.tr() : selectedReplacementEmployee!.employeeDisplayName ?? "", isEnable: false, onTap: () { showMyBottomSheet( context, child: SearchEmployeeBottomSheet( - title: "Search for Employee", - apiMode: "DELEGATE", + title: LocaleKeys.searchForEmployee.tr(), + apiMode: LocaleKeys.delegate.tr(), onSelectEmployee: (_selectedEmployee) { // Navigator.pop(context); selectedReplacementEmployee = _selectedEmployee; @@ -442,7 +443,7 @@ class _AddVacationRuleScreenState extends State { }, ).paddingOnly(bottom: 12), ], - ).objectContainerView(title: "Step 3") + ).objectContainerView(title: LocaleKeys.step3.tr()) ] ], ).expanded, @@ -452,18 +453,16 @@ class _AddVacationRuleScreenState extends State { ? null : () { if (endTime == null) { - Utils.showToast("Please specify End Time"); + Utils.showToast(LocaleKeys.pleaseSpecifyEndTime.tr()); return; } else if (notificationReassignMode == null) { - Utils.showToast("Please select notification reassign"); + Utils.showToast(LocaleKeys.pleaseSelectNotificationReassign.tr()); return; } else if (selectedReplacementEmployee == null) { - Utils.showToast("Please select employee for replacement"); + Utils.showToast(LocaleKeys.pleaseSelectEmployeeForReplacement.tr()); return; } - List> list = []; - if (respondAttributesList?.isNotEmpty ?? false) { for (int i = 0; i < respondAttributesList!.length; i++) { if (respondAttributesList![i].aTTRIBUTETYPE == "VARCHAR2") { @@ -471,14 +470,14 @@ class _AddVacationRuleScreenState extends State { } if (respondAttributesList![i].aTTRIBUTETYPE == "LOOKUP") { if (wfLook == null) { - Utils.showToast('Please select action'); + Utils.showToast(LocaleKeys.pleaseSelectAction.tr()); break; } list.add({"ATTRIBUTE_NAME": respondAttributesList![i].aTTRIBUTENAME, "ATTRIBUTE_TEXT_VALUE": wfLook!.lOOKUPCODE}); } if (respondAttributesList![i].aTTRIBUTETYPE == "DATE") { if (dateInput == null) { - Utils.showToast('Please select date'); + Utils.showToast(LocaleKeys.pleaseSelectDate.tr()); break; } list.add({"ATTRIBUTE_NAME": respondAttributesList![i].aTTRIBUTENAME, "ATTRIBUTE_TEXT_VALUE": DateUtil.convertDateToStringLocation(dateInput!)});