import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/validator/validator.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/helper/utils.dart'; import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/generic_attachment_model.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/new_models/building.dart'; import 'package:test_sa/models/new_models/floor.dart'; import 'package:test_sa/models/new_models/site.dart'; import 'package:test_sa/modules/cm_module/cm_request_utils.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/modules/incident_module/incident_lookup_provider.dart'; import 'package:test_sa/modules/incident_module/incident_provider.dart'; import 'package:test_sa/modules/loan_module/models/medical_department_model.dart'; import 'package:test_sa/modules/loan_module/provider/medical_department_provider.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; import 'package:test_sa/providers/gas_request_providers/site_provider.dart'; import 'package:test_sa/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/lookups/yes_no_lookup_provider.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import '../../models/new_models/department.dart'; import 'incident_attachment_model.dart'; class CreateIncidentRequestPage extends StatefulWidget { static const String id = "/create-incident"; CreateIncidentRequestPage({Key? key}) : super(key: key); @override _CreateIncidentRequestPageState createState() { return _CreateIncidentRequestPageState(); } } class _CreateIncidentRequestPageState extends State { final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); List attachments = []; MedicalDepartmentModel? _medicalDepartmentModel; Site? _empSite; Site? _selectedSite; Building? _selectedBuilding; Floor? _selectedFloor; Department? _selectedDepartment; Asset? device; Lookup? incidentType; Lookup? ovrSystem; Lookup? rootCause; Lookup? involvedPerson; Lookup? gender; DateTime? occurrenceDate; Map payload = {}; @override void initState() { super.initState(); payload["id"] = 0; payload["isFromMobile"] = 0; payload["requestorUserId"] = context.userProvider.user!.userID; payload["requestorSiteId"] = context.userProvider.user!.clientId; } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, appBar: DefaultAppBar(title: 'Incident'.addTranslation), body: Form( key: _formKey, child: Column( children: [ SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ ...empSiteSection(), 16.height, ...incidentInfoSection(), if (incidentType?.value == 1) ...[ 16.height, "Asset Details".bodyText(context).custom(color: AppColor.black10), 8.height, AssetPicker( device: device, showLoading: false, borderColor: AppColor.black20, onPick: (asset) async { device = asset; payload["assetId"] = asset.modelDefinition?.id; payload["oracleCode"] = asset.modelDefinition?.oracleCodes?.first.codeValue; payload["model"] = asset.modelDefinition?.modelName; payload["manufacturer"] = asset.modelDefinition?.manufacturerId; payload["assetOrigin"] = asset.modelDefinition?.assetName; payload["siteId"] = asset.site?.id; payload["buildingId"] = asset.building?.id; payload["floorId"] = asset.floor?.id; payload["departmentId"] = asset.department?.id; setState(() {}); }, ) ], if (incidentType?.value != null && incidentType?.value != 1) ...[ 16.height, ...siteSection(), ], 16.height, ...detailsSection(), 16.height, ...optionQuestions(), 16.height, "Attachments".bodyText(context).custom(color: AppColor.black10), 8.height, AttachmentPicker( label: context.translation.attachments, attachment: attachments, buttonColor: AppColor.black10, onlyImages: false, showAsListView: true, buttonIcon: 'image-plus'.toSvgAsset(color: context.isDark ? AppColor.primary10 : AppColor.neutral120), onChange: (_attachments) { attachments = _attachments; setState(() {}); }, ), ], ).toShadowContainer(context, borderRadius: 20), ).expanded, FooterActionButton.footerContainer( context: context, child: AppFilledButton( buttonColor: AppColor.primary10, label: context.translation.submitRequest, onPressed: _submit, // buttonColor: AppColor.primary10, ), ), ], ), ), ); } List optionQuestions() { return [ 'Additional Information & Comments'.addTranslation.bodyText(context).custom(color: AppColor.black10), 8.height, AppTextFormField( initialValue: "", labelText: "Some Comments", style: TextStyle(fontWeight: FontWeight.w500, fontSize: context.isTablet() ? 16 : 12, color: context.isDark ? Colors.white : const Color(0xff3B3D4A)), labelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: context.isTablet() ? 16 : 12, color: context.isDark ? Colors.white : const Color(0xff767676)), floatingLabelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: context.isTablet() ? 16 : 12, color: context.isDark ? Colors.white : const Color(0xff3B3D4A)), backgroundColor: AppColor.fieldBgColor(context), showShadow: false, textInputType: TextInputType.multiline, makeMultiLinesNull: false, onChange: (value) { payload["comments"] = value; }, ), ]; } List siteSection() { return [ 'Site Details'.addTranslation.bodyText(context).custom(color: AppColor.black10), 8.height, SingleItemDropDownMenu( context: context, title: context.translation.site, initialValue: _selectedSite, showShadow: false, validator: (value) { if (value == null) return "Please select a site"; return null; }, backgroundColor: AppColor.fieldBgColor(context), showAsBottomSheet: true, onSelect: (value) { _selectedSite = value; payload["siteId"] = value?.id; setState(() {}); }, ), 8.height, SingleItemDropDownMenu( context: context, title: context.translation.building, initialValue: _selectedBuilding, showShadow: false, showAsBottomSheet: true, validator: (value) { if (value == null) return "Please select a building"; return null; }, backgroundColor: AppColor.fieldBgColor(context), enabled: _selectedSite?.buildings?.isNotEmpty ?? false, staticData: _selectedSite?.buildings ?? [], onSelect: (value) { _selectedBuilding = value; _selectedFloor = null; _selectedDepartment = null; payload["buildingId"] = value?.id; setState(() {}); }, ), 8.height, SingleItemDropDownMenu( context: context, title: context.translation.floor, showShadow: false, showAsBottomSheet: true, initialValue: _selectedFloor, backgroundColor: AppColor.fieldBgColor(context), enabled: _selectedBuilding?.floors?.isNotEmpty ?? false, staticData: _selectedBuilding?.floors ?? [], validator: (value) { if (value == null) return "Please select a floor"; return null; }, onSelect: (value) { _selectedFloor = value; _selectedDepartment = null; payload["floorId"] = value?.id; setState(() {}); }, ), 8.height, SingleItemDropDownMenu( context: context, title: context.translation.department, showShadow: false, showAsBottomSheet: true, initialValue: _selectedDepartment, backgroundColor: AppColor.fieldBgColor(context), enabled: _selectedFloor?.departments?.isNotEmpty ?? false, staticData: _selectedFloor?.departments ?? [], validator: (value) { if (value == null) return "Please select a department"; return null; }, onSelect: (value) { _selectedDepartment = value; payload["departmentId"] = value?.id; setState(() {}); }, ), ]; } List empSiteSection() { return [ SingleItemDropDownMenu( context: context, title: "Employee Site", initialValue: _empSite, showShadow: false, validator: (value) { if (value == null) return "Please select a site"; return null; }, backgroundColor: AppColor.fieldBgColor(context), showAsBottomSheet: true, onSelect: (value) { _empSite = value; payload["requestorSiteId"] = value?.id; setState(() {}); }, ), 8.height, SingleItemDropDownMenu( context: context, title: "Employee Department", showShadow: false, validator: (value) { if (value == null) return "Please select a department"; return null; }, showAsBottomSheet: true, initialValue: _medicalDepartmentModel, requestById: context.userProvider.user?.clientId, backgroundColor: AppColor.fieldBgColor(context), onSelect: (value) { _medicalDepartmentModel = value; payload["requestorFlowDepartmentId"] = value?.id; setState(() {}); }, ), ]; } List incidentInfoSection() { return [ "Incident Details".bodyText(context).custom(color: AppColor.black10), 8.height, SingleItemDropDownMenu( context: context, height: 56.toScreenHeight, title: "Incident Type", initialValue: incidentType, showShadow: false, validator: (value) { if (value == null) return "Mandatory"; return null; }, backgroundColor: AppColor.fieldBgColor(context), showAsBottomSheet: true, onSelect: (value) { incidentType = value; payload["incidentClassificationId"] = value?.id; setState(() {}); }, ), 8.height, SingleItemDropDownMenu( context: context, height: 56.toScreenHeight, title: "Is there any existing OVR System?", initialValue: ovrSystem, showShadow: false, validator: (value) { if (value == null) return "Mandatory"; return null; }, backgroundColor: AppColor.fieldBgColor(context), showAsBottomSheet: true, onSelect: (value) { ovrSystem = value; payload["existingOvrTicketId"] = value?.id; setState(() {}); }, ), if (ovrSystem?.value == 1) ...[ 8.height, AppTextFormField( initialValue: "", labelText: "OVR Ticket Number", validator: (value) { if ((value ?? "").isEmpty) return "Mandatory"; return null; }, style: Theme.of(context).textTheme.titleMedium, backgroundColor: AppColor.fieldBgColor(context), labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), showShadow: false, textInputType: TextInputType.name, textInputAction: TextInputAction.next, onChange: (value) { payload["ovrTicketNumber"] = value; }, ), ], 8.height, AppTextFormField( initialValue: "", labelText: "Incident Title", validator: (value) { if ((value ?? "").isEmpty) return "Mandatory"; return null; }, style: Theme.of(context).textTheme.titleMedium, backgroundColor: AppColor.fieldBgColor(context), labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), showShadow: false, textInputType: TextInputType.name, textInputAction: TextInputAction.next, onChange: (value) { payload["incidentTitle"] = value; }, ), 8.height, AppTextFormField( initialValue: "", labelText: "Incident Description", validator: (value) { if ((value ?? "").isEmpty) return "Mandatory"; return null; }, style: Theme.of(context).textTheme.titleMedium, backgroundColor: AppColor.fieldBgColor(context), labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), showShadow: false, textInputType: TextInputType.name, textInputAction: TextInputAction.next, onChange: (value) { payload["incidentDescription"] = value; }, ), ]; } List detailsSection() { return [ 'Details'.addTranslation.bodyText(context).custom(color: AppColor.black10), 8.height, SingleItemDropDownMenu( context: context, height: 56.toScreenHeight, title: "Root Cause", initialValue: rootCause, showShadow: false, validator: (value) { if (value == null) return "Mandatory"; return null; }, backgroundColor: AppColor.fieldBgColor(context), showAsBottomSheet: true, onSelect: (value) { rootCause = value; payload["rootCauseId"] = value?.id; setState(() {}); }, ), if (rootCause?.value == 5) ...[ 8.height, AppTextFormField( initialValue: "", labelText: "Root Cause (Other)", validator: (value) { if ((value ?? "").isEmpty) return "Mandatory"; return null; }, style: Theme.of(context).textTheme.titleMedium, backgroundColor: AppColor.fieldBgColor(context), labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), showShadow: false, textInputType: TextInputType.name, textInputAction: TextInputAction.next, onChange: (value) { payload["otherRootCause"] = value; }, ), ], 8.height, SingleItemDropDownMenu( context: context, height: 56.toScreenHeight, title: "Person Involved", initialValue: involvedPerson, showShadow: false, validator: (value) { if (value == null) return "Mandatory"; return null; }, backgroundColor: AppColor.fieldBgColor(context), showAsBottomSheet: true, onSelect: (value) { involvedPerson = value; payload["personInvolvedId"] = value?.id; }, ), 8.height, SingleItemDropDownMenu( context: context, height: 56.toScreenHeight, title: "Gender", initialValue: gender, showShadow: false, validator: (value) { if (value == null) return "Mandatory"; return null; }, backgroundColor: AppColor.fieldBgColor(context), showAsBottomSheet: true, onSelect: (value) { gender = value; payload["genderId"] = value?.id; }, ), 8.height, AppTextFormField( initialValue: "", labelText: "Person Involved ID", validator: (value) { if (involvedPerson?.value == 3 && (value ?? "").isEmpty) return "Mandatory"; return null; }, style: Theme.of(context).textTheme.titleMedium, backgroundColor: AppColor.fieldBgColor(context), labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), showShadow: false, textInputType: TextInputType.number, textInputAction: TextInputAction.next, onChange: (value) { payload["personInvolvedEmployeeId"] = value; }, ), 8.height, AppTextFormField( initialValue: "", labelText: "Person Involved Name", validator: (value) { if (involvedPerson?.value == 3 && (value ?? "").isEmpty) return "Mandatory"; return null; }, style: Theme.of(context).textTheme.titleMedium, backgroundColor: AppColor.fieldBgColor(context), labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), showShadow: false, textInputType: TextInputType.name, textInputAction: TextInputAction.next, onChange: (value) { payload["personInvolvedEmployeeName"] = value; }, ), 8.height, ADatePicker( label: "Occurrence Date & Time", hideShadow: true, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, date: occurrenceDate, from: DateTime.now().subtract(const Duration(days: 365)), // enable: widget.enabled ? _tempPickerTimer == null : false, formatDateWithTime: true, onDatePicker: (selectedDate) { showTimePicker( context: context, initialTime: TimeOfDay.now(), builder: (BuildContext context, Widget? child) { final ThemeData currentTheme = Theme.of(context); return Theme( data: currentTheme.copyWith( timePickerTheme: TimePickerThemeData( dialHandColor: AppColor.primary10, dialBackgroundColor: Colors.grey.withOpacity(0.1), hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)), dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent), dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10), dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)), entryModeIconColor: AppColor.primary10, ), textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)), ), child: child!, ); }, ).then((selectedTime) { if (selectedTime != null) { occurrenceDate = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); setState(() {}); } }); }, ), ]; } Future _submit() async { FocusScope.of(context).unfocus(); if (_formKey.currentState!.validate()) { if (occurrenceDate == null) { "Please select occurrence Data".showToast; return; } payload["occurrenceDate"] = occurrenceDate!.toIso8601String(); _formKey.currentState!.save(); List attachmentList = []; for (var item in attachments) { String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? ''; attachmentList.add(IncidentAttachments(id: 0, attachmentName: fileName, incidentId: 0)); } Utils.showLoading(context); IncidentProvider incidentProvider = Provider.of(context, listen: false); payload["incidentAttachments"] = attachmentList.map((v) => v.toJson()).toList(); bool isSuccess = await incidentProvider.addIncidentRequest(payload); Utils.hideLoading(context); if (isSuccess) { Navigator.pop(context); } } } }