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/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'; 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'; 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/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'; class AddVacationRuleScreen extends StatefulWidget { AddVacationRuleScreen({Key? key}) : super(key: key); @override _AddVacationRuleScreenState createState() { return _AddVacationRuleScreenState(); } } class _AddVacationRuleScreenState extends State { List? vrItemTypesList; VrItemTypesList? selectedItemType; List? itemTypeNotificationsList; GetItemTypeNotificationsList? selectedItemTypeNotification; List? notificationReassignModeList; 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; @override void initState() { super.initState(); getVacationRulesList(); } void getVacationRulesList() async { try { Utils.showLoading(context); vrItemTypesList = await VacationRuleApiClient().getVrItemTypes(); Utils.hideLoading(context); currentStage = 1; setState(() {}); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); } } void getItemTypeNotificationsList() async { try { Utils.showLoading(context); itemTypeNotificationsList = await VacationRuleApiClient().getItemTypeNotifications(selectedItemType!.iTEMTYPE!); itemTypeNotificationsList!.insert(0, GetItemTypeNotificationsList(nOTIFICATIONDISPLAYNAME: "All", nOTIFICATIONNAME: "*", fYIFLAG: "N")); Utils.hideLoading(context); currentStage = 2; setState(() {}); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); } } void callCombineApis() async { try { Utils.showLoading(context); List results = await Future.wait([ VacationRuleApiClient().getNotificationReassignMode(), VacationRuleApiClient().getRespondAttributes(selectedItemType!.iTEMTYPE!, selectedItemTypeNotification!.nOTIFICATIONNAME!), ]); 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: LocaleKeys.deliverNotificationToMeRegardless.tr(), rADIOBUTTONACTION: "DELIVER", // ionic: DELIVER rADIOBUTTONSEQ: 1, ), ); } if (selectedItemTypeNotification!.fYIFLAG == "Y") { notificationReassignModeList!.add( GetNotificationReassignModeList( rADIOBUTTONLABEL: LocaleKeys.close.tr(), rADIOBUTTONACTION: "CLOSE", // ionic: CLOSE rADIOBUTTONSEQ: 1, ), ); } if (respondAttributesList!.isNotEmpty && !(selectedItemTypeNotification!.fYIFLAG == "Y")) { notificationReassignModeList!.add( GetNotificationReassignModeList( rADIOBUTTONLABEL: LocaleKeys.respond.tr(), rADIOBUTTONACTION: "RESPOND", // ionic: RESPOND rADIOBUTTONSEQ: 1, ), ); } if (notificationReassignModeList!.isNotEmpty) { notificationReassignMode = notificationReassignModeList!.first; } Utils.hideLoading(context); currentStage = 3; setState(() {}); } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); } } 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(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBarWidget( context, title: LocaleKeys.vacationType.tr(), ), body: vrItemTypesList == null ? const SizedBox() : (vrItemTypesList!.isEmpty ? Utils.getNoDataWidget(context) : Column( children: [ ListView( padding: const EdgeInsets.all(21), physics: const BouncingScrollPhysics(), children: [ if (vrItemTypesList!.isNotEmpty) PopupMenuButton( child: DynamicTextFieldWidget( LocaleKeys.itemType.tr(), selectedItemType == null ? LocaleKeys.selectType.tr() : 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: "${LocaleKeys.applyForVacationRule.tr()}\n${LocaleKeys.step1.tr()}", note: LocaleKeys.ifAllSelectedYouWillSkip.tr()), if ((itemTypeNotificationsList ?? []).isNotEmpty) ...[ 12.height, PopupMenuButton( child: DynamicTextFieldWidget( "Notification", selectedItemTypeNotification == null ? LocaleKeys.selectNotification.tr() : 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: LocaleKeys.step2.tr()) ], if (selectedItemType != null && selectedItemTypeNotification != null && currentStage == 3) ...[ 12.height, Column( children: [ ItemDetailView(LocaleKeys.itemType.tr(), selectedItemType!.iTEMTYPEDISPLAYNAME!), ItemDetailView(LocaleKeys.notification.tr(), selectedItemTypeNotification!.nOTIFICATIONDISPLAYNAME!), 12.height, DynamicTextFieldWidget( LocaleKeys.startDateT.tr(), 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( LocaleKeys.endDateT.tr(), 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( LocaleKeys.message.tr(), LocaleKeys.writeAMessage.tr(), lines: 2, 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: LocaleKeys.notificationReassign.tr()), 12.height, if (respondAttributesList?.isNotEmpty ?? false) ...getDynamicWidgetList(), if (roleList!.isNotEmpty && notificationReassignMode?.rADIOBUTTONACTION == 'RESPOND' || // if (notificationReassignMode?.rADIOBUTTONACTION == 'RESPOND' || (notificationReassignMode?.rADIOBUTTONACTION == 'DELEGATE') || (notificationReassignMode?.rADIOBUTTONACTION == 'TRANSFER')) DynamicTextFieldWidget( LocaleKeys.selectEmployee.tr(), selectedReplacementEmployee == null ? LocaleKeys.searchEmployeeForReplacement.tr() : selectedReplacementEmployee!.employeeDisplayName ?? "", isEnable: false, onTap: () { showMyBottomSheet( context, child: SearchEmployeeBottomSheet( title: LocaleKeys.searchForEmployee.tr(), apiMode: LocaleKeys.delegate.tr(), fromChat: false, onSelectEmployee: (_selectedEmployee) { // Navigator.pop(context); selectedReplacementEmployee = _selectedEmployee; setState(() {}); }, ), ); }, ).paddingOnly(bottom: 12), ], ).objectContainerView(title: LocaleKeys.step3.tr()) ] ], ).expanded, DefaultButton( LocaleKeys.apply.tr(), currentStage != 3 ? null : () { if (endTime == null) { Utils.showToast(LocaleKeys.pleaseSpecifyEndTime.tr()); return; } else if (notificationReassignMode == null) { Utils.showToast(LocaleKeys.pleaseSelectNotificationReassign.tr()); return; } else if (selectedReplacementEmployee == null) { 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") { list.add({"ATTRIBUTE_NAME": respondAttributesList![i].aTTRIBUTENAME, "ATTRIBUTE_TEXT_VALUE": varcharInput}); } if (respondAttributesList![i].aTTRIBUTETYPE == "LOOKUP") { if (wfLook == null) { 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(LocaleKeys.pleaseSelectDate.tr()); 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, ], )), ); } 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 { DateTime? picked = await showDatePicker(context: context, initialDate: _time, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101)); 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); } 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 { 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; } }