You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mohemm-flutter-app/lib/ui/attendance/add_vacation_rule_screen.dart

583 lines
27 KiB
Dart

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<AddVacationRuleScreen> {
List<VrItemTypesList>? vrItemTypesList;
VrItemTypesList? selectedItemType;
List<GetItemTypeNotificationsList>? itemTypeNotificationsList;
GetItemTypeNotificationsList? selectedItemTypeNotification;
List<GetNotificationReassignModeList>? notificationReassignModeList;
GetNotificationReassignModeList? notificationReassignMode;
List<RespondAttributesList>? respondAttributesList;
List<String>? roleList = [];
List<WFLookUpList>? 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<Widget> getDynamicWidgetList() {
List<Widget> 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: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < wfLookupList!.length; i++) PopupMenuItem<int>(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<Map<String, dynamic>> 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: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < vrItemTypesList!.length; i++) PopupMenuItem<int>(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: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < itemTypeNotificationsList!.length; i++) PopupMenuItem<int>(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(),
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<Map<String, dynamic>> 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<DateTime> _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);
}
Future<DateTime> _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;
}
}