import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/models/new_models/department.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart'; import 'package:test_sa/models/timer_model.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/loading_list_notifier.dart'; import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; class TaskRequestForm extends StatefulWidget { final AssetTransfer model; const TaskRequestForm({Key? key, required this.model}) : super(key: key); @override State createState() => _TaskRequestFormState(); } class _TaskRequestFormState extends State { final bool _isLoading = false; final TextEditingController _requestedQuantityController = TextEditingController(); final AssetTransfer _formModel = AssetTransfer(); final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); List _files = []; bool installationTye = false; List completedActions = [ Lookup(value: 0, name: 'Physical Check'), Lookup(value: 1, name: 'Software Update'), Lookup(value: 0, name: 'Hardware Update'), ]; List impactStatus = [ Lookup(value: 0, name: 'Impacted'), Lookup(value: 1, name: 'Not Impacted'), ]; Lookup selectedValue = Lookup(value: 0, name: 'Impacted'); @override void initState() { _formModel.fromDetails(widget.model); _files = widget.model.receiverAttachments?.map((e) => File(e.attachmentName!)).toList() ?? []; super.initState(); } @override void dispose() { _requestedQuantityController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: DefaultAppBar(title: context.translation.taskRequest), key: _scaffoldKey, body: SafeArea( child: LoadingManager( isLoading: _isLoading, isFailedLoading: false, stateCode: 200, onRefresh: () async {}, child: Form( key: _formKey, child: Column( children: [ SingleChildScrollView( padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)), child: Column( children: [ Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _timerWidget(context, 0, true), 12.height, installationTye ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ADatePicker( label: context.translation.installationDate, hideShadow: true, backgroundColor: AppColor.neutral90, date: DateTime.now(), formatDateWithTime: false, onDatePicker: (selectedDate) { // Handle the selected date and time here. DateTime selectedDateTime = DateTime( selectedDate.year, selectedDate.month, selectedDate.day, ); }, ), 12.height, //TODO replace with provided lookup.. SingleItemDropDownMenu( context: context, height: 56.toScreenHeight, title: context.translation.serialNo, showShadow: false, backgroundColor: AppColor.neutral90, showAsBottomSheet: true, initialValue: null, onSelect: (status) { if (status != null) { setState(() {}); } }, ), 12.height, //TODO replace with provided lookup.. SingleItemDropDownMenu( context: context, title: context.translation.department, initialValue: Department(), enabled: true, backgroundColor: AppColor.neutral90, showShadow: false, staticData: [], showAsBottomSheet: true, onSelect: (value) {}, ), ], ) : Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ context.translation.completedActions.bodyText(context).custom(color: AppColor.white936), completedActionWidget(), 16.height, context.translation.impactStatus.bodyText(context).custom(color: AppColor.white936), impactStatusWidget(), ]), 12.height, AppTextFormField( initialValue: _formModel.receiverComment ?? "", labelText: context.translation.technicalComment, textInputType: TextInputType.multiline, backgroundColor: AppColor.neutral90, showShadow: false, alignLabelWithHint: true, onSaved: (value) { _formModel.receiverComment = value; }, ), 20.height, MultiFilesPicker( label: context.translation.attachFiles, files: _files, buttonColor: AppColor.black10, onlyImages: false, buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), ), ], ).toShadowContainer(context), 16.height, const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)), ], ), ).expanded, FooterActionButton.footerContainer( child: AppFilledButton( buttonColor: AppColor.green70, label: context.translation.markAsCompleted, onPressed: () {}, // buttonColor: AppColor.primary10, ), ), ], ), ), ), ), ); } void updateTimer({TimerModel? timer}) { _formModel.tbsTimer = timer; // if (timer?.startAt != null && timer?.endAt != null) { // _formModel.timerModelList = _formModel.timerModelList ?? []; // _formModel.timerModelList!.add(timer!); // } // notifyListeners(); } Widget completedActionWidget() { return Column( children: completedActions.asMap().entries.map((entry) { int index = entry.key; Lookup action = entry.value; return Row( children: [ Checkbox( value: action.value == 1, activeColor: AppColor.blueStatus(context), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onChanged: (value) { setState(() { completedActions[index] = Lookup(value: value! ? 1 : 0, name: action.name); }); }, ), action.name! .bodyText(context) .custom( color: context.isDark ? AppColor.primary50 : AppColor.neutral50, ) .expanded, ], ); }).toList(), ); } Widget impactStatusWidget() { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, // Aligns to the start children: impactStatus.map((item) { return Row( mainAxisSize: MainAxisSize.min, children: [ Radio( value: item, groupValue: selectedValue, activeColor: AppColor.blueStatus(context), visualDensity: VisualDensity.compact, // Removes extra spacing onChanged: (value) { selectedValue = value!; setState(() {}); }, ), Text( item.name!, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: context.isDark ? AppColor.primary50 : AppColor.neutral50, ), ), 16.width, // Adds spacing between items ], ); }).toList(), ); } Widget _timerWidget(BuildContext context, double totalWorkingHours, bool isTimerEnable) { return Column( mainAxisSize: MainAxisSize.min, children: [ AppTimer( label: context.translation.workingHours, timer: _formModel.tbsTimer, width: double.infinity, enabled: isTimerEnable, decoration: BoxDecoration( color: AppColor.neutral90, borderRadius: BorderRadius.circular(10), ), timerProgress: (isRunning) {}, onChange: (timer) async { updateTimer(timer: timer); return true; }, ), if (totalWorkingHours > 0.0) ...[ 12.height, Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start, children: [ 'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral90), 8.width, Text( ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()), style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600), ), ], ), ], ], ); } } class AssistantEmployeeCard extends StatefulWidget { const AssistantEmployeeCard({super.key}); @override State createState() => _AssistantEmployeeCardState(); } class _AssistantEmployeeCardState extends State { bool status = false; final TextEditingController _workingHoursController = TextEditingController(text: ''); bool isCurrentUserIsAssistantEmp = false; bool isExpanded = false; @override void initState() { // TODO: implement initState WidgetsBinding.instance.addPostFrameCallback((_) { getInitialData(); }); super.initState(); } Future getInitialData() async { final user = Provider.of(context, listen: false).user!; ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId); // if (isCurrentUserIsAssistantEmp) { // // _subWorkOrders.assistantEmployees = [widget.workOrder.assistantEmployees?.first?.copyWith(id: 0)]; // } } @override void dispose() { // TODO: implement dispose _workingHoursController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Consumer(builder: (context, requestDetailProvider, child) { return Column( children: [ SizedBox( height: 56.toScreenHeight, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ context.translation.assistantEmployee.heading6(context).custom(color: AppColor.black10), Icon(isExpanded ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded), ], ), ).onPress(() { setState(() { isExpanded = !isExpanded; }); }), isExpanded ? Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ ServiceReportAssistantEmployeeMenu( title: context.translation.select, backgroundColor: AppColor.neutral100, initialValue: null, assetId: 23, //TODO add check... // enable: !isCurrentUserIsAssistantEmp, onSelect: (employee) { if (employee == null) { requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = []; } else { requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = [employee.copyWith(id: 0)]; requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.user = AssignedEmployee(userId: employee.user?.id, userName: employee.user?.name); } }, ), 12.height, Row( mainAxisSize: MainAxisSize.min, children: [ ADatePicker( label: context.translation.startTime, hideShadow: true, backgroundColor: AppColor.neutral100, date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, formatDateWithTime: true, onDatePicker: (selectedDate) { showTimePicker( context: context, initialTime: TimeOfDay.now(), ).then((selectedTime) { // Handle the selected date and time here. if (selectedTime != null) { DateTime selectedDateTime = DateTime( selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute, ); requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate = selectedDateTime; requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); ServiceRequestUtils.calculateAndAssignWorkingHours( startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, workingHoursController: _workingHoursController, updateModel: (hours) { requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours = hours; }); } }); }, ).expanded, 8.width, ADatePicker( label: context.translation.endTime, hideShadow: true, backgroundColor: AppColor.neutral100, date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, formatDateWithTime: true, onDatePicker: (selectedDate) { showTimePicker( context: context, initialTime: TimeOfDay.now(), ).then((selectedTime) { // Handle the selected date and time here. if (selectedTime != null) { DateTime selectedDateTime = DateTime( selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute, ); //TODO need to replace with model attributes.. // if (requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate != null && // selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.startDate!)) { // "End Date time must be greater then start date".showToast; // return; // } // requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate = selectedDateTime; // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); // ServiceRequestUtils.calculateAndAssignWorkingHours( // startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, // endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, // workingHoursController: _workingHoursController, // updateModel: (hours) { // requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours = hours; // }); } }); }, ).expanded, ], ), 12.height, AppTextFormField( labelText: context.translation.workingHours, backgroundColor: AppColor.neutral80, controller: _workingHoursController, suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours != null ? requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours.toString() : '', textAlign: TextAlign.center, labelStyle: AppTextStyles.textFieldLabelStyle, enable: false, showShadow: false, style: Theme.of(context).textTheme.titleMedium, ), 12.height, AppTextFormField( initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment, labelText: context.translation.technicalComment, backgroundColor: AppColor.neutral100, showShadow: false, labelStyle: AppTextStyles.textFieldLabelStyle, alignLabelWithHint: true, textInputType: TextInputType.multiline, onChange: (value) { requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; }, onSaved: (value) { requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; }, ), 16.height, ], ) : const SizedBox(), ], ); }); } }