| @@ -1 +1 @@ | |||
| 471e09183e20ec9c20cca9b580fecc10 | |||
| d91c957b2422e26116533c8dae89710a | |||
| @@ -119,18 +119,21 @@ class TbObjectUpdateDTO { | |||
| } | |||
| class TbNurseryDetailsDTO { | |||
| int id; | |||
| String workerName; | |||
| String trayNumber; | |||
| TbNurseryDetailsDTO({this.workerName, this.trayNumber}); | |||
| TbNurseryDetailsDTO.fromJson(Map<String, dynamic> json) { | |||
| id = json['id']; | |||
| workerName = json['workerName']; | |||
| trayNumber = json['trayNumber']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['id'] = this.id; | |||
| data['workerName'] = this.workerName; | |||
| data['trayNumber'] = this.trayNumber; | |||
| return data; | |||
| @@ -14,34 +14,37 @@ class AppBarWidget extends StatelessWidget implements PreferredSizeWidget { | |||
| elevation: 0, | |||
| centerTitle: false, | |||
| title: isBack | |||
| ? InkWell( | |||
| child: Row( | |||
| mainAxisSize: MainAxisSize.min, | |||
| children: [ | |||
| Icon( | |||
| Icons.keyboard_arrow_left, | |||
| color: AppColors.YELLOW, | |||
| size: 35, | |||
| ), | |||
| Text( | |||
| 'Quay lại', | |||
| maxLines: 1, | |||
| style: TextStyle( | |||
| ? Row( | |||
| mainAxisSize: MainAxisSize.min, | |||
| children: [ | |||
| InkWell( | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| child: Row( | |||
| children: [ | |||
| Icon( | |||
| Icons.keyboard_arrow_left, | |||
| color: AppColors.YELLOW, | |||
| fontWeight: FontWeight.normal), | |||
| size: 35, | |||
| ), | |||
| Text( | |||
| 'Quay lại', | |||
| maxLines: 1, | |||
| style: TextStyle( | |||
| color: AppColors.YELLOW, | |||
| fontWeight: FontWeight.normal), | |||
| ), | |||
| ], | |||
| ), | |||
| SizedBox(width: 4), | |||
| Expanded( | |||
| child: Align( | |||
| alignment: Alignment.centerRight, | |||
| child: action ?? SizedBox(), | |||
| )) | |||
| ], | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| Expanded(child: Container()), | |||
| Align( | |||
| alignment: Alignment.centerRight, | |||
| child: action ?? SizedBox(), | |||
| ) | |||
| ], | |||
| ) | |||
| : SizedBox(), | |||
| automaticallyImplyLeading: false, | |||
| @@ -1,497 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/CropStatus.dart'; | |||
| import 'package:farm_tpf/custom_model/RequestGeneralModel.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/util_action.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| class EditActionCropStatusScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionCropStatusScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionCropStatusScreenState createState() => | |||
| _EditActionCropStatusScreenState(); | |||
| } | |||
| class _EditActionCropStatusScreenState | |||
| extends State<EditActionCropStatusScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| CropStatus _cropStatus = CropStatus(); | |||
| var pref = LocalPref(); | |||
| TextEditingController _cropRateController = TextEditingController(); | |||
| TextEditingController _numTreeController = TextEditingController(); | |||
| TextEditingController _heightOfTreeController = TextEditingController(); | |||
| TextEditingController _numberOfLeafController = TextEditingController(); | |||
| TextEditingController _leafSizeController = TextEditingController(); | |||
| TextEditingController _leafColorController = TextEditingController(); | |||
| TextEditingController _abilityProduceBudsController = TextEditingController(); | |||
| TextEditingController _internodeLengthController = TextEditingController(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _cropStatus.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| //Create request general model | |||
| try { | |||
| RequestGeneralModel generalModel = RequestGeneralModel() | |||
| ..cropId = _cropStatus.cropId | |||
| ..activityId = _cropStatus.activityId | |||
| ..description = _cropStatus.description | |||
| ..executeDate = _cropStatus.executeDate; | |||
| var generalDetail = List<ObjectUpdateDetail>(); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "TY_LE_CAY_TRONG" | |||
| ..index = _cropStatus.cropRate); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "SO_LUONG_LEN_CAY" | |||
| ..index = _cropStatus.numberOfTreeToGrow); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "CHIEU_CAO_CAY" | |||
| ..index = _cropStatus.heightOfTree); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "SO_LA" | |||
| ..index = _cropStatus.numberOfLeaf); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "KICH_THUOC_LA" | |||
| ..index = _cropStatus.leafSize); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "MAU_LA" | |||
| ..index = _cropStatus.leafColor); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "DAI_DOT_THAN" | |||
| ..index = _cropStatus.internodeLength); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "KHA_NANG_SINH_CHOI" | |||
| ..index = _cropStatus.abilityProduceBuds); | |||
| generalModel.objectUpdateDetail = generalDetail; | |||
| generalModel.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityCropStatus = jsonEncode(generalModel.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_cropStatus.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddCropStatus, | |||
| paramActivity: ConstCommon.paramsActionCropStatus, | |||
| activityAction: activityCropStatus, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateCropStatus, | |||
| paramActivity: ConstCommon.paramsActionCropStatus, | |||
| activityAction: activityCropStatus, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: exception_common); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _cropStatus.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _cropRateField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Tỉ lệ lên cây", | |||
| textController: _cropRateController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.cropRate = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _numTreeField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng lên cây", | |||
| textController: _numTreeController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.numberOfTreeToGrow = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _hightOfTreeField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Chiều cao cây", | |||
| textController: _heightOfTreeController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.heightOfTree = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _numberOfLeafField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lá", | |||
| textController: _numberOfLeafController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.numberOfLeaf = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _leafSizeField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Kích thước lá", | |||
| textController: _leafSizeController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.leafSize = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _leafColorField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Màu lá"), | |||
| controller: _leafColorController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.leafColor = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _internodeLengthField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Dài đốt thân", | |||
| textController: _internodeLengthController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.internodeLength = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _abilityProduceBudsField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Khả năng sinh chồi"), | |||
| controller: _abilityProduceBudsController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.abilityProduceBuds = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _desciptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _cropStatus.description = newValue; | |||
| }); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailCropStatus, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| print("fail"); | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print("success"); | |||
| print(state.item); | |||
| _cropStatus = CropStatus.fromJson(state.item); | |||
| _cropStatus.activityId = widget.activityId; | |||
| _cropRateController.text = _cropStatus.cropRate | |||
| .formatStringToStringDecimal(); | |||
| _numTreeController.text = _cropStatus | |||
| .numberOfTreeToGrow | |||
| .formatStringToStringDecimal(); | |||
| _heightOfTreeController.text = _cropStatus | |||
| .heightOfTree | |||
| .formatStringToStringDecimal(); | |||
| _numberOfLeafController.text = _cropStatus | |||
| .numberOfLeaf | |||
| .formatStringToStringDecimal(); | |||
| _leafSizeController.text = _cropStatus.leafSize | |||
| .formatStringToStringDecimal(); | |||
| _leafColorController.text = | |||
| _cropStatus.leafColor ?? ""; | |||
| _abilityProduceBudsController.text = | |||
| _cropStatus.abilityProduceBuds ?? ""; | |||
| _internodeLengthController.text = _cropStatus | |||
| .internodeLength | |||
| .formatStringToStringDecimal(); | |||
| _descriptionController.text = | |||
| _cropStatus.description ?? ""; | |||
| _executeByController.text = | |||
| _cropStatus.executeBy ?? ""; | |||
| Get.find<ChangeDateTimePicker>().change(_cropStatus | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _cropStatus.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _cropStatus.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| print("init"); | |||
| } else if (state is ActionDetailLoading) { | |||
| print("loading"); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_crop_status, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _cropRateField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _numTreeField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _hightOfTreeField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _numberOfLeafField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _leafSizeField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _leafColorField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _internodeLengthField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _abilityProduceBudsField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _desciptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| print("length: " + | |||
| state.items.length.toString()); | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _cropRateController.dispose(); | |||
| _numTreeController.dispose(); | |||
| _heightOfTreeController.dispose(); | |||
| _numberOfLeafController.dispose(); | |||
| _leafSizeController.dispose(); | |||
| _leafColorController.dispose(); | |||
| _abilityProduceBudsController.dispose(); | |||
| _internodeLengthController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,450 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Disease.dart'; | |||
| import 'package:farm_tpf/custom_model/RequestDisease.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionDiseaseScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionDiseaseScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionDiseaseScreenState createState() => | |||
| _EditActionDiseaseScreenState(); | |||
| } | |||
| class _EditActionDiseaseScreenState extends State<EditActionDiseaseScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Disease _disease = Disease(); | |||
| var pref = LocalPref(); | |||
| TextEditingController _typesOfPestController = TextEditingController(); | |||
| TextEditingController _numTreeController = TextEditingController(); | |||
| TextEditingController _harmLevelController = TextEditingController(); | |||
| TextEditingController _treePercentController = TextEditingController(); | |||
| TextEditingController _locationController = TextEditingController(); | |||
| TextEditingController _naturalEnemyController = TextEditingController(); | |||
| TextEditingController _treatmentMeasuresController = TextEditingController(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _disease.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| //Create request general model | |||
| try { | |||
| RequestDisease requestDisease = RequestDisease() | |||
| ..cropId = _disease.cropId | |||
| ..activityId = _disease.activityId | |||
| ..description = _disease.description | |||
| ..executeDate = _disease.executeDate; | |||
| var generalDetail = List<ObjectUpdateDetail>(); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "LOAI_DICH_HAI" | |||
| ..index = _disease.typesOfPest); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "MUC_DO_GAY_HAI" | |||
| ..index = _disease.harmLevel); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "PHAN_TRAM_CAY" | |||
| ..index = _disease.treePercent); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "VI_TRI" | |||
| ..index = _disease.location); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "THIEN_DICH" | |||
| ..index = _disease.naturalEnemy); | |||
| generalDetail.add(ObjectUpdateDetail() | |||
| ..name = "BIEN_PHAP_XU_LY" | |||
| ..index = _disease.treatmentMeasures); | |||
| requestDisease.objectUpdateDetail = generalDetail; | |||
| requestDisease.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityDisease = jsonEncode(requestDisease.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_disease.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddDisease, | |||
| paramActivity: ConstCommon.paramsActionDisease, | |||
| activityAction: activityDisease, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateDisease, | |||
| paramActivity: ConstCommon.paramsActionDisease, | |||
| activityAction: activityDisease, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| Utils.showSnackBarWarning(message: label_validate_input_required); | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _disease.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _typeOfPestField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Loại dịch hại *"), | |||
| controller: _typesOfPestController, | |||
| validator: (String value) { | |||
| return Validators.validateNotNullOrEmpty( | |||
| value, label_validate_input_empty); | |||
| }, | |||
| onSaved: (newValue) { | |||
| _disease.typesOfPest = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _harmLevelField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Mức độ gây hại"), | |||
| controller: _harmLevelController, | |||
| onSaved: (newValue) { | |||
| _disease.harmLevel = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _treePercentField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "% cây", | |||
| textController: _treePercentController, | |||
| onSaved: (newValue) { | |||
| _disease.treePercent = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _locationField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Vị trí"), | |||
| controller: _locationController, | |||
| onSaved: (newValue) { | |||
| _disease.location = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _naturalEnemyField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Thiên địch"), | |||
| controller: _naturalEnemyController, | |||
| onSaved: (newValue) { | |||
| _disease.naturalEnemy = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _treatmentMeasuresField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Biện pháp xử lý"), | |||
| controller: _treatmentMeasuresController, | |||
| onSaved: (newValue) { | |||
| _disease.treatmentMeasures = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _disease.description = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailDisease, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(state.item); | |||
| _disease = Disease.fromJson(state.item); | |||
| _disease.activityId = widget.activityId; | |||
| _typesOfPestController.text = | |||
| _disease.typesOfPest ?? ""; | |||
| _harmLevelController.text = | |||
| _disease.harmLevel ?? ""; | |||
| _treePercentController.text = _disease.treePercent | |||
| .formatStringToStringDecimal(); | |||
| _locationController.text = | |||
| _disease.location ?? ""; | |||
| _naturalEnemyController.text = | |||
| _disease.naturalEnemy ?? ""; | |||
| _treatmentMeasuresController.text = | |||
| _disease.treatmentMeasures ?? ""; | |||
| _descriptionController.text = | |||
| _disease.description ?? ""; | |||
| _executeByController.text = _disease.executeBy; | |||
| Get.find<ChangeDateTimePicker>().change(_disease | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _disease.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _disease.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| } else if (state is ActionDetailLoading) { | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_disease, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _typeOfPestField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _harmLevelField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _treePercentField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _locationField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _naturalEnemyField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _treatmentMeasuresField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _descriptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _typesOfPestController.dispose(); | |||
| _harmLevelController.dispose(); | |||
| _treePercentController.dispose(); | |||
| _locationController.dispose(); | |||
| _naturalEnemyController.dispose(); | |||
| _treatmentMeasuresController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,399 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Dung.dart'; | |||
| import 'package:farm_tpf/custom_model/SuppliesUsing.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeFieldInForm.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeSupplyUsing.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/dung/widget_dung_supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionDungScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionDungScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionDungScreenState createState() => _EditActionDungScreenState(); | |||
| } | |||
| class _EditActionDungScreenState extends State<EditActionDungScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Dung _dung = Dung(); | |||
| var pref = LocalPref(); | |||
| final _descriptionController = TextEditingController(); | |||
| final _purposeController = TextEditingController(); | |||
| final _weatherController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| final _quarantinePeriodController = TextEditingController(); | |||
| List<SuppliesUsing> suppliesUsing = new List<SuppliesUsing>(); | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _dung.suppliesUsing = new List<SuppliesUsing>(); | |||
| _dung.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| List<SuppliesUsing> newSups = []; | |||
| suppliesUsing.forEach((sup) { | |||
| var newSup = sup; | |||
| newSup.suppliesInWarehouseId = sup.tbSuppliesInWarehouseId; | |||
| newSup.equipmentOfCustomerId = sup.tbEquipmentOfCustomerId; | |||
| newSups.add(newSup); | |||
| }); | |||
| _dung.suppliesUsing = newSups; | |||
| _dung.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityDung = jsonEncode(_dung.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_dung.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddDung, | |||
| paramActivity: ConstCommon.paramsActionDung, | |||
| activityAction: activityDung, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateDung, | |||
| paramActivity: ConstCommon.paramsActionDung, | |||
| activityAction: activityDung, | |||
| filePaths: filePaths); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _dung.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _purposeField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Lý do sử dụng"), | |||
| controller: _purposeController, | |||
| onSaved: (newValue) { | |||
| _dung.purpose = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _quarantinePeriodField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Thời gian cách ly", | |||
| textController: _quarantinePeriodController, | |||
| onSaved: (newValue) { | |||
| _dung.quarantinePeriod = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _weatherField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Thời tiết"), | |||
| controller: _weatherController, | |||
| onSaved: (newValue) { | |||
| _dung.weatherConditions = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _desciptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _dung.description = newValue; | |||
| }); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailDung, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: BlocConsumer<ActionDetailBloc, | |||
| ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| _dung = Dung.fromJson(state.item); | |||
| _dung.activityId = widget.activityId; | |||
| _purposeController.text = | |||
| _dung.purpose ?? ""; | |||
| _quarantinePeriodController.text = _dung | |||
| .quarantinePeriod | |||
| .formatNumtoStringDecimal(); | |||
| _weatherController.text = | |||
| _dung.weatherConditions ?? ""; | |||
| _descriptionController.text = | |||
| _dung.description; | |||
| _executeByController.text = _dung.executeBy; | |||
| Get.find<ChangeDateTimePicker>().change(_dung | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _dung.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context) | |||
| .add(ChangeListMedia( | |||
| items: UtilAction | |||
| .convertFilePathToMedia( | |||
| _dung.media))); | |||
| } | |||
| //list supply | |||
| suppliesUsing = _dung.suppliesUsing; | |||
| Get.find<ChangeSupplyUsing>() | |||
| .changeInitList(suppliesUsing); | |||
| } else if (state is ActionDetailInitial) { | |||
| print("init"); | |||
| } else if (state is ActionDetailLoading) { | |||
| print("loading"); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_dung, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _purposeField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _quarantinePeriodField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _weatherField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _desciptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| WidgetDungSupply( | |||
| currentItems: [], | |||
| onChangeSupplies: (value) { | |||
| suppliesUsing = value; | |||
| }), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, | |||
| MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: | |||
| CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus | |||
| .hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| if (Get.find< | |||
| ChangeFieldFormSupply>() | |||
| .isChanged) { | |||
| Utils.showDialogConfirmSupply( | |||
| onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| }); | |||
| } else { | |||
| _validateInputs(); | |||
| } | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )))))); | |||
| @override | |||
| void dispose() { | |||
| _quarantinePeriodController.dispose(); | |||
| _purposeController.dispose(); | |||
| _weatherController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,299 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/End.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionEndScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionEndScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionEndScreenState createState() => _EditActionEndScreenState(); | |||
| } | |||
| class _EditActionEndScreenState extends State<EditActionEndScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| End _end = End(); | |||
| final _descriptionController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| var pref = LocalPref(); | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _end.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| try { | |||
| _end.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityEnd = jsonEncode(_end.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_end.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddEnd, | |||
| paramActivity: ConstCommon.paramsActionEnd, | |||
| activityAction: activityEnd, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateEnd, | |||
| paramActivity: ConstCommon.paramsActionEnd, | |||
| activityAction: activityEnd, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _end.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _end.description = newValue; | |||
| }); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailEnd, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| _end = End.fromJson(state.item); | |||
| _end.activityId = widget.activityId; | |||
| _descriptionController.text = | |||
| _end.description ?? ""; | |||
| _executeByController.text = _end.createdByName; | |||
| Get.find<ChangeDateTimePicker>().change(_end | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty(_end.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _end.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| } else if (state is ActionDetailLoading) { | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_finish, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _descriptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,464 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Environment.dart'; | |||
| import 'package:farm_tpf/custom_model/RequestEnvironment.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/util_action.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| class EditActionEnvironmentUpdate extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionEnvironmentUpdate( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionEnvironmentUpdateState createState() => | |||
| _EditActionEnvironmentUpdateState(); | |||
| } | |||
| class _EditActionEnvironmentUpdateState | |||
| extends State<EditActionEnvironmentUpdate> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Environment _environment = Environment(); | |||
| var pref = LocalPref(); | |||
| TextEditingController _ecController = TextEditingController(); | |||
| TextEditingController _phController = TextEditingController(); | |||
| TextEditingController _ocddController = TextEditingController(); | |||
| TextEditingController _temperatureController = TextEditingController(); | |||
| TextEditingController _doController = TextEditingController(); | |||
| TextEditingController _llnController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _environment.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| //Create request general model | |||
| try { | |||
| RequestEnvironment requestEnvironment = RequestEnvironment() | |||
| ..cropId = _environment.cropId | |||
| ..activityId = _environment.activityId | |||
| ..executeDate = _environment.executeDate; | |||
| var envDetail = List<EnvDetail>(); | |||
| envDetail.add(EnvDetail() | |||
| ..name = "EC" | |||
| ..index = _environment.ec); | |||
| envDetail.add(EnvDetail() | |||
| ..name = "pH" | |||
| ..index = _environment.pH); | |||
| envDetail.add(EnvDetail() | |||
| ..name = "OCDD" | |||
| ..index = _environment.ocdd); | |||
| envDetail.add(EnvDetail() | |||
| ..name = "TEMPERATURE" | |||
| ..index = _environment.temperature); | |||
| envDetail.add(EnvDetail() | |||
| ..name = "DO" | |||
| ..index = _environment.dodo); | |||
| envDetail.add(EnvDetail() | |||
| ..name = "LLN" | |||
| ..index = _environment.lln); | |||
| requestEnvironment.envDetail = envDetail; | |||
| requestEnvironment.mediaDel = | |||
| Get.find<ChangeFileController>().deleteFiles; | |||
| var activityEnvironmentUpdate = | |||
| jsonEncode(requestEnvironment.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_environment.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddEnvUpdate, | |||
| paramActivity: ConstCommon.paramsActionEnvUpdate, | |||
| activityAction: activityEnvironmentUpdate, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateEnvUpdate, | |||
| paramActivity: ConstCommon.paramsActionEnvUpdate, | |||
| activityAction: activityEnvironmentUpdate, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _environment.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _ecField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "EC", | |||
| textController: _ecController, | |||
| onSaved: (newValue) { | |||
| _environment.ec = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _phField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "pH", | |||
| textController: _phController, | |||
| onSaved: (newValue) { | |||
| _environment.pH = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _ocddField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Nhiệt độ dung dịch", | |||
| textController: _ocddController, | |||
| onSaved: (newValue) { | |||
| _environment.ocdd = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _temperatureField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Nhiệt độ môi trường", | |||
| textController: _temperatureController, | |||
| onSaved: (newValue) { | |||
| _environment.temperature = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _doField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Độ ẩm", | |||
| textController: _doController, | |||
| onSaved: (newValue) { | |||
| _environment.dodo = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _llnField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Lưu lượng nước", | |||
| textController: _llnController, | |||
| onSaved: (newValue) { | |||
| _environment.lln = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailEnvUpdate, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| print("fail"); | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print("success"); | |||
| print(state.item); | |||
| _environment = Environment.fromJson(state.item); | |||
| //Parse theo API :') | |||
| _environment.environmentUpdates | |||
| .forEach((envDetail) { | |||
| switch (envDetail.tbEnvironmentalName) { | |||
| case "EC": | |||
| _environment.ec = | |||
| envDetail.index.toString(); | |||
| break; | |||
| case "pH": | |||
| _environment.pH = | |||
| envDetail.index.toString(); | |||
| break; | |||
| case "OCDD": | |||
| _environment.ocdd = | |||
| envDetail.index.toString(); | |||
| break; | |||
| case "TEMPERATURE": | |||
| _environment.temperature = | |||
| envDetail.index.toString(); | |||
| break; | |||
| case "DO": | |||
| _environment.dodo = | |||
| envDetail.index.toString(); | |||
| break; | |||
| case "LLN": | |||
| _environment.lln = | |||
| envDetail.index.toString(); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| }); | |||
| _environment.activityId = widget.activityId; | |||
| _ecController.text = | |||
| _environment.ec.formatStringToStringDecimal(); | |||
| _phController.text = | |||
| _environment.pH.formatStringToStringDecimal(); | |||
| _ocddController.text = _environment.ocdd | |||
| .formatStringToStringDecimal(); | |||
| _temperatureController.text = _environment | |||
| .temperature | |||
| .formatStringToStringDecimal(); | |||
| _doController.text = _environment.dodo | |||
| .formatStringToStringDecimal(); | |||
| _llnController.text = _environment.lln | |||
| .formatStringToStringDecimal(); | |||
| _executeByController.text = | |||
| _environment.executeBy; | |||
| Get.find<ChangeDateTimePicker>().change(_environment | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _environment.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _environment.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| print("init"); | |||
| } else if (state is ActionDetailLoading) { | |||
| print("loading"); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_environment_update, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _ecField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _phField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _ocddField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _temperatureField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _doField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _llnField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _ecController.dispose(); | |||
| _phController.dispose(); | |||
| _ocddController.dispose(); | |||
| _temperatureController.dispose(); | |||
| _doController.dispose(); | |||
| _llnController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,437 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Harvest.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_icon_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/harvest_process/sc_edit_action_harvest_process.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/packing/sc_edit_action_packing.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/sell/sc_edit_action_sell.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/util_action.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_icons.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| class EditActionHarvestScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionHarvestScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionHarvestScreenState createState() => | |||
| _EditActionHarvestScreenState(); | |||
| } | |||
| class _EditActionHarvestScreenState extends State<EditActionHarvestScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Harvest _harvest = Harvest(); | |||
| TextEditingController _l1Controller = TextEditingController(); | |||
| TextEditingController _l2Controller = TextEditingController(); | |||
| TextEditingController _l3Controller = TextEditingController(); | |||
| TextEditingController _removedQuantityController = TextEditingController(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| var pref = LocalPref(); | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _harvest.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| try { | |||
| _harvest.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityHarvest = jsonEncode(_harvest.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_harvest.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddHarvest, | |||
| paramActivity: ConstCommon.paramsActionHarvest, | |||
| activityAction: activityHarvest, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateHarvest, | |||
| paramActivity: ConstCommon.paramsActionHarvest, | |||
| activityAction: activityHarvest, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _harvest.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _l1Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 1", | |||
| textController: _l1Controller, | |||
| onSaved: (newValue) { | |||
| _harvest.collectedQuantityLv1 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l2Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 2", | |||
| textController: _l2Controller, | |||
| onSaved: (newValue) { | |||
| _harvest.collectedQuantityLv2 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l3Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 3", | |||
| textController: _l3Controller, | |||
| onSaved: (newValue) { | |||
| _harvest.collectedQuantityLv3 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _removedQuantityField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại bỏ", | |||
| textController: _removedQuantityController, | |||
| onSaved: (newValue) { | |||
| _harvest.removedQuantity = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _harvest.description = newValue; | |||
| }); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailHarvest, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(state.item); | |||
| _harvest = Harvest.fromJson(state.item); | |||
| _harvest.activityId = widget.activityId; | |||
| _l1Controller.text = _harvest.collectedQuantityLv1 | |||
| .formatNumtoStringDecimal(); | |||
| _l2Controller.text = _harvest.collectedQuantityLv2 | |||
| .formatNumtoStringDecimal(); | |||
| _l3Controller.text = _harvest.collectedQuantityLv3 | |||
| .formatNumtoStringDecimal(); | |||
| _removedQuantityController.text = _harvest | |||
| .removedQuantity | |||
| .formatNumtoStringDecimal(); | |||
| _descriptionController.text = | |||
| _harvest.description ?? ""; | |||
| _executeByController.text = _harvest.executeBy; | |||
| Get.find<ChangeDateTimePicker>().change(_harvest | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _harvest.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _harvest.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| } else if (state is ActionDetailLoading) { | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_harvest, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l1Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l2Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l3Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _removedQuantityField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _descriptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| ButtonIconWidget( | |||
| leadingIcon: AppIcons.icHarvestProcess, | |||
| trailingIcon: AppIcons.icArrowRight, | |||
| title: plot_action_harvest_process, | |||
| onTap: () { | |||
| if (_harvest.id != null) { | |||
| Get.to(EditActionHarvestProcessScreen( | |||
| cropId: widget.cropId, | |||
| harvestId: _harvest.id, | |||
| )); | |||
| } else { | |||
| Get.to(EditActionHarvestProcessScreen( | |||
| cropId: widget.cropId)); | |||
| } | |||
| }), | |||
| ButtonIconWidget( | |||
| leadingIcon: AppIcons.icPacking, | |||
| trailingIcon: AppIcons.icArrowRight, | |||
| title: plot_action_packing, | |||
| onTap: () { | |||
| if (_harvest.id != null) { | |||
| Get.to(EditActionPackingScreen( | |||
| cropId: widget.cropId, | |||
| harvestId: _harvest.id, | |||
| )); | |||
| } else { | |||
| Get.to(EditActionPackingScreen( | |||
| cropId: widget.cropId)); | |||
| } | |||
| }), | |||
| ButtonIconWidget( | |||
| leadingIcon: AppIcons.icSell, | |||
| trailingIcon: AppIcons.icArrowRight, | |||
| title: plot_action_sell, | |||
| onTap: () { | |||
| if (_harvest.id != null) { | |||
| Get.to(EditActionSellScreen( | |||
| cropId: widget.cropId, | |||
| harvestId: _harvest.id, | |||
| )); | |||
| } else { | |||
| Get.to(EditActionSellScreen( | |||
| cropId: widget.cropId)); | |||
| } | |||
| }), | |||
| SizedBox( | |||
| height: 16, | |||
| ), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _l1Controller.dispose(); | |||
| _l2Controller.dispose(); | |||
| _l3Controller.dispose(); | |||
| _removedQuantityController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,526 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Harvest.dart'; | |||
| import 'package:farm_tpf/custom_model/HarvestProcess.dart'; | |||
| import 'package:farm_tpf/custom_model/SuppliesUsing.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeFieldInForm.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeSupplyUsing.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/harvest_process/widget_harvest_process_supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../bloc_get_harvest.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionHarvestProcessScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| final int harvestId; | |||
| EditActionHarvestProcessScreen( | |||
| {@required this.cropId, | |||
| this.isEdit = false, | |||
| this.activityId, | |||
| this.harvestId}); | |||
| @override | |||
| _EditActionHarvestProcessScreenState createState() => | |||
| _EditActionHarvestProcessScreenState(); | |||
| } | |||
| class _EditActionHarvestProcessScreenState | |||
| extends State<EditActionHarvestProcessScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| HarvestProcess _harvestProcess = HarvestProcess(); | |||
| TextEditingController _l1Controller = TextEditingController(); | |||
| TextEditingController _l2Controller = TextEditingController(); | |||
| TextEditingController _l3Controller = TextEditingController(); | |||
| TextEditingController _removedQuantityController = TextEditingController(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| List<SuppliesUsing> suppliesUsing = new List<SuppliesUsing>(); | |||
| var pref = LocalPref(); | |||
| List<Harvest> _harvests = List<Harvest>(); | |||
| Harvest harvestValue; | |||
| String executeTimeView; | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _harvestProcess.suppliesUsing = new List<SuppliesUsing>(); | |||
| _harvestProcess.executeDate = | |||
| executeTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| executeTimeView = executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| _harvestProcess.cropId = widget.cropId; | |||
| if (!widget.isEdit) { | |||
| getHarvestBloc.getHarvests((data) { | |||
| _harvests = data; | |||
| for (var item in _harvests) { | |||
| if (item.id == widget.harvestId) { | |||
| harvestValue = item; | |||
| break; | |||
| } | |||
| } | |||
| }, (err) {}); | |||
| } | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| List<SuppliesUsing> newSups = []; | |||
| suppliesUsing.forEach((sup) { | |||
| var newSup = sup; | |||
| newSup.suppliesInWarehouseId = sup.tbSuppliesInWarehouseId; | |||
| newSup.equipmentOfCustomerId = sup.tbEquipmentOfCustomerId; | |||
| newSups.add(newSup); | |||
| }); | |||
| _harvestProcess.suppliesUsing = newSups; | |||
| _harvestProcess.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| try { | |||
| var activityHarvestProcess = | |||
| jsonEncode(_harvestProcess.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_harvestProcess.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddHarvestProcess, | |||
| paramActivity: ConstCommon.paramsActionHarvestProcess, | |||
| activityAction: activityHarvestProcess, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateHarvestProcess, | |||
| paramActivity: ConstCommon.paramsActionHarvestProcess, | |||
| activityAction: activityHarvestProcess, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| List<DropdownMenuItem<Harvest>> _buildDropMenu(List<Harvest> actions) { | |||
| return actions | |||
| .map((action) => DropdownMenuItem<Harvest>( | |||
| child: Text("Mã thu hoạch " + action.id.toString()), | |||
| value: action, | |||
| )) | |||
| .toList(); | |||
| } | |||
| Widget _dropdownHarvest() { | |||
| return StreamBuilder( | |||
| stream: getHarvestBloc.actions, | |||
| builder: (context, AsyncSnapshot<dynamic> snapshot) { | |||
| if (snapshot.hasData) { | |||
| return DropdownButtonFormField<Harvest>( | |||
| value: harvestValue, | |||
| hint: Text("Mã thu hoạch"), | |||
| onChanged: (Harvest newValue) { | |||
| setState(() { | |||
| harvestValue = newValue; | |||
| _harvestProcess.harvestId = newValue.id; | |||
| }); | |||
| }, | |||
| isExpanded: true, | |||
| items: _buildDropMenu(_harvests)); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator(), | |||
| ); | |||
| } | |||
| }, | |||
| ); | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return FlatButton( | |||
| padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| DatePicker.showDateTimePicker(context, | |||
| showTitleActions: true, onChanged: (date) {}, onConfirm: (date) { | |||
| setState(() { | |||
| executeTime = date; | |||
| _harvestProcess.executeDate = | |||
| executeTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| executeTimeView = executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| }); | |||
| }, currentTime: executeTime, locale: LocaleType.vi); | |||
| }, | |||
| child: Container( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| Expanded( | |||
| child: Text( | |||
| //TODO: check condition | |||
| executeTimeView == null ? "$executeTime" : executeTimeView, | |||
| style: TextStyle(fontSize: 14.0, color: Colors.black87), | |||
| )), | |||
| Icon( | |||
| Icons.date_range, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| } | |||
| Widget _l1Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 1", | |||
| textController: _l1Controller, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.quantityLv1 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l2Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 2", | |||
| textController: _l2Controller, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.quantityLv2 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l3Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 3", | |||
| textController: _l3Controller, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.quantityLv3 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _removedQuantityField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại bỏ", | |||
| textController: _removedQuantityController, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.removedQuantity = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.description = newValue; | |||
| }); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: | |||
| ConstCommon.apiDetailHarvestProcess, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(state.item); | |||
| _harvestProcess = | |||
| HarvestProcess.fromJson(state.item); | |||
| _harvestProcess.activityId = widget.activityId; | |||
| _l1Controller.text = _harvestProcess.quantityLv1 | |||
| .formatNumtoStringDecimal(); | |||
| _l2Controller.text = _harvestProcess.quantityLv2 | |||
| .formatNumtoStringDecimal(); | |||
| _l3Controller.text = _harvestProcess.quantityLv3 | |||
| .formatNumtoStringDecimal(); | |||
| _removedQuantityController.text = _harvestProcess | |||
| .removedQuantity | |||
| .formatNumtoStringDecimal(); | |||
| _descriptionController.text = | |||
| _harvestProcess.description ?? ""; | |||
| _executeByController.text = | |||
| _harvestProcess.executeBy; | |||
| //select harvest | |||
| getHarvestBloc.getHarvests((data) { | |||
| _harvests = data; | |||
| for (var item in _harvests) { | |||
| if (item.id == _harvestProcess.harvestId) { | |||
| harvestValue = item; | |||
| break; | |||
| } | |||
| } | |||
| }, (err) {}); | |||
| executeTime = _harvestProcess.executeDate | |||
| .convertStringServerDateTimeToLocalDateTime(); | |||
| executeTimeView = | |||
| executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _harvestProcess.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _harvestProcess.media))); | |||
| } | |||
| //list supply | |||
| suppliesUsing = _harvestProcess.suppliesUsing; | |||
| Get.find<ChangeSupplyUsing>() | |||
| .changeInitList(suppliesUsing); | |||
| } else if (state is ActionDetailInitial) { | |||
| } else if (state is ActionDetailLoading) { | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_harvest_process, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _dropdownHarvest(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l1Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l2Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l3Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _removedQuantityField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _descriptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| WidgetHarvestProcessSupply( | |||
| currentItems: [], | |||
| onChangeSupplies: (value) { | |||
| suppliesUsing = value; | |||
| }), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| if (Get.find<ChangeFieldFormSupply>() | |||
| .isChanged) { | |||
| Utils.showDialogConfirmSupply( | |||
| onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| }); | |||
| } else { | |||
| _validateInputs(); | |||
| } | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _l1Controller.dispose(); | |||
| _l2Controller.dispose(); | |||
| _l3Controller.dispose(); | |||
| _removedQuantityController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,725 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Nursery.dart'; | |||
| import 'package:farm_tpf/custom_model/NurseryDetail.dart'; | |||
| import 'package:farm_tpf/custom_model/Supply.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/nursery/bloc/expansion_list_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/resources/sc_resource_helper.dart'; | |||
| import 'package:farm_tpf/utils/bloc/bloc/status_add_form_bloc.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:get/state_manager.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionNurseryScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionNurseryScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionNurseryState createState() => _EditActionNurseryState(); | |||
| } | |||
| class _EditActionNurseryState extends State<EditActionNurseryScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| GlobalKey<FormState> _formWorkerKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Nursery _nursery = Nursery(); | |||
| var pref = LocalPref(); | |||
| TextEditingController _substrateController = TextEditingController(); | |||
| TextEditingController _seedLengthController = TextEditingController(); | |||
| TextEditingController _quantityController = TextEditingController(); | |||
| TextEditingController _seedIncubationTimeController = TextEditingController(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| TextEditingController _workerNameController = TextEditingController(); | |||
| TextEditingController _trayNumberController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| DateTime executeTime = DateTime.now(); | |||
| List<NurseryDetail> currentNurseryDetail = List<NurseryDetail>(); | |||
| int currentIndexUpdate = -1; | |||
| bool isResetForm = true; | |||
| final changeSupply = Get.put(ChangeSupply()); | |||
| int selectedSupplyId = -1; | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeSupply.initValue(); | |||
| changeFileController.initValue(); | |||
| _nursery.nurseryDetail = new List<NurseryDetail>(); | |||
| _nursery.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| _nursery.nurseryDetail = currentNurseryDetail; | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| _nursery.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityNursery = jsonEncode(_nursery.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_nursery.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddNursery, | |||
| paramActivity: ConstCommon.paramsActionNursery, | |||
| activityAction: activityNursery, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateNursery, | |||
| paramActivity: ConstCommon.paramsActionNursery, | |||
| activityAction: activityNursery, | |||
| filePaths: filePaths); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _nursery.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _btnSelectSubstrates() { | |||
| return FlatButton( | |||
| padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| Navigator.of(context) | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => ResourceHelperScreen( | |||
| titleName: "Giá thể", | |||
| type: ConstCommon.supplyTypeSubStrate, | |||
| selectedId: Get.find<ChangeSupply>().selectedSupplyId, | |||
| currentItems: [], | |||
| currentEditId: -1), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) { | |||
| var result = value as Supply; | |||
| _nursery.substratesId = result.id; | |||
| changeSupply.change(result); | |||
| print("Home: $value"); | |||
| } | |||
| }); | |||
| }, | |||
| child: Container( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| GetBuilder<ChangeSupply>( | |||
| builder: (_) => Expanded( | |||
| child: Text( | |||
| changeSupply.selectedSupplyName == null | |||
| ? "Loại giá thể" | |||
| : changeSupply.selectedSupplyName.toString(), | |||
| style: TextStyle( | |||
| fontSize: 14.0, color: Colors.black87)))), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| } | |||
| Widget _seedLengthField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Chiều dài mầm", | |||
| textController: _seedLengthController, | |||
| onSaved: (newValue) { | |||
| _nursery.seedLength = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _quantityField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng hạt gieo", | |||
| textController: _quantityController, | |||
| onSaved: (newValue) { | |||
| _nursery.quantity = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _seedIncubationTimeField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Thời gian ngâm hạt", | |||
| textController: _seedIncubationTimeController, | |||
| onSaved: (newValue) { | |||
| _nursery.seedIncubationTime = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _desciptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _nursery.description = newValue; | |||
| }); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| Widget _btnAddWorker() { | |||
| //TODO :check flow error sua item -> xoa list -> bam nut them | |||
| return Builder(builder: (context) { | |||
| return BlocConsumer<StatusAddFormBloc, StatusAddFormState>( | |||
| listener: (context, state) { | |||
| if (state is Edit) { | |||
| isResetForm = false; | |||
| _workerNameController.text = state.nurseryDetail.workerName; | |||
| _trayNumberController.text = state.nurseryDetail.trayNumber; | |||
| } else if (state is Delete) { | |||
| if (currentIndexUpdate == state.index) { | |||
| isResetForm = true; | |||
| _workerNameController.text = ""; | |||
| _trayNumberController.text = ""; | |||
| } | |||
| } else { | |||
| isResetForm = true; | |||
| _workerNameController.text = ""; | |||
| _trayNumberController.text = ""; | |||
| } | |||
| }, builder: (context, state) { | |||
| return Container( | |||
| child: Form( | |||
| key: _formWorkerKey, | |||
| child: Column( | |||
| children: [ | |||
| Container( | |||
| padding: EdgeInsets.all(8.0), | |||
| margin: EdgeInsets.all(8), | |||
| decoration: BoxDecoration( | |||
| shape: BoxShape.rectangle, | |||
| borderRadius: BorderRadius.circular(10), | |||
| color: Colors.white, | |||
| border: Border.all(color: Colors.grey[300])), | |||
| child: Column( | |||
| children: [ | |||
| TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| controller: _workerNameController, | |||
| decoration: InputDecoration(labelText: "Tên công nhân *"), | |||
| validator: (value) { | |||
| return Validators.validateNotNullOrEmpty( | |||
| value, label_validate_input_empty); | |||
| }, | |||
| onSaved: (newValue) {}, | |||
| ), | |||
| TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| controller: _trayNumberController, | |||
| decoration: InputDecoration(labelText: "Ươm khây số"), | |||
| onSaved: (newValue) {}, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| margin: EdgeInsets.all(8), | |||
| child: Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| mainAxisSize: MainAxisSize.max, | |||
| children: [ | |||
| isResetForm | |||
| ? Container() | |||
| : OutlineButton( | |||
| shape: RoundedRectangleBorder( | |||
| borderRadius: new BorderRadius.circular(8.0)), | |||
| child: Text("Huỷ"), | |||
| onPressed: () { | |||
| context.bloc<StatusAddFormBloc>().add(Reset()); | |||
| }), | |||
| Expanded( | |||
| child: FlatButton( | |||
| onPressed: () { | |||
| if (_formWorkerKey.currentState.validate()) { | |||
| _formWorkerKey.currentState.save(); | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _workerNameController.text)) { | |||
| NurseryDetail _nurseryDetail = NurseryDetail() | |||
| ..workerName = _workerNameController.text | |||
| ..trayNumber = _trayNumberController.text; | |||
| if (state is Edit) { | |||
| context.bloc<ExpansionListBloc>().add(Update( | |||
| index: state.index, | |||
| item: _nurseryDetail, | |||
| items: state.items)); | |||
| } else { | |||
| currentNurseryDetail.insert( | |||
| 0, _nurseryDetail); | |||
| BlocProvider.of<ExpansionListBloc>(context) | |||
| .add(AddNew(items: currentNurseryDetail)); | |||
| } | |||
| context.bloc<StatusAddFormBloc>().add(Reset()); | |||
| } else { | |||
| Utils.showSnackBarWarning( | |||
| message: "Vui lòng nhập tên công nhân"); | |||
| } | |||
| } else { | |||
| // | |||
| if (!Validators.stringNotNullOrEmpty( | |||
| _workerNameController.text)) { | |||
| Utils.showSnackBarWarning( | |||
| message: "Vui lòng nhập tên công nhân"); | |||
| } | |||
| } | |||
| }, | |||
| child: Text( | |||
| (state is Edit) | |||
| ? "Sửa người thực hiện" | |||
| : "+ Thêm người thực hiện", | |||
| style: TextStyle(color: Colors.blue), | |||
| )), | |||
| ) | |||
| ], | |||
| ), | |||
| ), | |||
| ], | |||
| ), | |||
| )); | |||
| }); | |||
| }); | |||
| } | |||
| Widget _buildListAddWorker() { | |||
| return Builder(builder: (context) { | |||
| return BlocBuilder<ExpansionListBloc, ExpansionListState>( | |||
| builder: (context, state) { | |||
| if (state is ExpansionListSuccess) { | |||
| currentNurseryDetail = state.items; | |||
| if (currentNurseryDetail.isEmpty) { | |||
| return Container(); | |||
| } | |||
| return Container( | |||
| height: 70, | |||
| child: ListView.builder( | |||
| physics: ClampingScrollPhysics(), | |||
| scrollDirection: Axis.horizontal, | |||
| shrinkWrap: true, | |||
| itemCount: currentNurseryDetail.length, | |||
| itemBuilder: (context, index) { | |||
| return GestureDetector( | |||
| onTap: () { | |||
| print("edit worker"); | |||
| currentIndexUpdate = index; | |||
| context.bloc<StatusAddFormBloc>().add(Changed( | |||
| status: CRUDStatus.edit, | |||
| index: index, | |||
| nurseryDetail: currentNurseryDetail[index], | |||
| items: currentNurseryDetail)); | |||
| }, | |||
| child: Card( | |||
| child: Stack( | |||
| alignment: Alignment.bottomCenter, | |||
| overflow: Overflow.visible, | |||
| children: <Widget>[ | |||
| Positioned( | |||
| child: ClipRRect( | |||
| borderRadius: BorderRadius.circular(8), | |||
| child: Container( | |||
| padding: EdgeInsets.all(4), | |||
| width: 120, | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| children: [ | |||
| SizedBox( | |||
| height: 12.0, | |||
| ), | |||
| Flexible( | |||
| child: Text( | |||
| currentNurseryDetail[index] | |||
| .workerName ?? | |||
| "", | |||
| overflow: TextOverflow.ellipsis, | |||
| maxLines: 1), | |||
| ), | |||
| Validators.stringNotNullOrEmpty( | |||
| currentNurseryDetail[index] | |||
| .trayNumber) | |||
| ? Flexible( | |||
| child: Text( | |||
| currentNurseryDetail[index] | |||
| .trayNumber ?? | |||
| "")) | |||
| : SizedBox() | |||
| ], | |||
| ), | |||
| ), | |||
| )), | |||
| Positioned( | |||
| top: -10, | |||
| right: -10, | |||
| child: IconButton( | |||
| icon: Icon( | |||
| Icons.cancel, | |||
| color: Colors.redAccent, | |||
| ), | |||
| onPressed: () { | |||
| print("Delete worker"); | |||
| context.bloc<ExpansionListBloc>().add( | |||
| DeleteItem( | |||
| index: index, | |||
| items: currentNurseryDetail)); | |||
| context.bloc<StatusAddFormBloc>().add( | |||
| Changed( | |||
| status: CRUDStatus.delete, | |||
| index: index, | |||
| nurseryDetail: | |||
| currentNurseryDetail[index], | |||
| items: currentNurseryDetail)); | |||
| }), | |||
| ) | |||
| ], | |||
| ))); | |||
| })); | |||
| } else if (state is ExpansionListFailure) { | |||
| return Container(); | |||
| } else { | |||
| return Container(); | |||
| } | |||
| }); | |||
| }); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ExpansionListBloc>( | |||
| create: (context) => ExpansionListBloc(), | |||
| ), | |||
| BlocProvider<StatusAddFormBloc>( | |||
| create: (context) => StatusAddFormBloc(), | |||
| ), | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailNursery, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: BlocConsumer<ActionDetailBloc, | |||
| ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| print("fail"); | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print("success"); | |||
| print(state.item); | |||
| _nursery = Nursery.fromJson(state.item); | |||
| _seedLengthController.text = _nursery | |||
| .seedLength | |||
| .formatNumtoStringDecimal(); | |||
| _quantityController.text = _nursery.quantity | |||
| .formatNumtoStringDecimal(); | |||
| _seedIncubationTimeController.text = | |||
| _nursery.seedIncubationTime | |||
| .formatNumtoStringDecimal(); | |||
| _descriptionController.text = | |||
| _nursery.description; | |||
| _executeByController.text = | |||
| _nursery.executeBy; | |||
| Get.find<ChangeDateTimePicker>().change(_nursery | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _nursery.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context) | |||
| .add(ChangeListMedia( | |||
| items: UtilAction | |||
| .convertFilePathToMedia( | |||
| _nursery.media))); | |||
| } | |||
| //Show worker | |||
| if (_nursery.nurseryDetail.length > 0) { | |||
| BlocProvider.of<ExpansionListBloc>( | |||
| context) | |||
| .add(AddNew( | |||
| items: _nursery.nurseryDetail)); | |||
| } | |||
| //change subStrates | |||
| if (_nursery.substratesId != null) { | |||
| Get.find<ChangeSupply>() | |||
| .changeByIdAndName( | |||
| _nursery.substratesId, | |||
| _nursery.substrateName); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| print("init"); | |||
| } else if (state is ActionDetailLoading) { | |||
| print("loading"); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: EdgeInsets.all(8), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| 'Ươm', | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Loại giá thể", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnSelectSubstrates(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _seedLengthField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _quantityField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _seedIncubationTimeField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _desciptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _buildListAddWorker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _btnAddWorker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, | |||
| MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| print("length: " + | |||
| state.items.length.toString()); | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: | |||
| CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| SizedBox( | |||
| height: 16, | |||
| ), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus | |||
| .hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| if (!Validators | |||
| .stringNotNullOrEmpty( | |||
| _workerNameController | |||
| .text) && | |||
| !Validators | |||
| .stringNotNullOrEmpty( | |||
| _trayNumberController | |||
| .text)) { | |||
| _validateInputs(); | |||
| } else { | |||
| Utils.showDialog( | |||
| title: | |||
| "Tên công nhân hoặc khây trồng đang cập nhật", | |||
| message: | |||
| "Bạn có muốn cập nhật?", | |||
| textConfirm: "Tiếp tục", | |||
| textCancel: "Xem lại", | |||
| onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| }); | |||
| } | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )))))); | |||
| @override | |||
| void dispose() { | |||
| _substrateController.dispose(); | |||
| _seedLengthController.dispose(); | |||
| _quantityController.dispose(); | |||
| _seedIncubationTimeController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,32 +0,0 @@ | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:rxdart/rxdart.dart'; | |||
| class GetActionTypeBloc { | |||
| final _repository = Repository(); | |||
| final _getActionTypesFetcher = PublishSubject<dynamic>(); | |||
| Stream<dynamic> get actions => _getActionTypesFetcher.stream; | |||
| void getActionTypes( | |||
| Function(dynamic) onSuccess, Function(String) onError) async { | |||
| try { | |||
| _repository.getActionTypes().then((value) { | |||
| onSuccess(value); | |||
| _getActionTypesFetcher.sink.add(value); | |||
| }).catchError((onError) { | |||
| _getActionTypesFetcher.addError(onError); | |||
| onError(onError); | |||
| }); | |||
| } catch (e) { | |||
| _getActionTypesFetcher.addError(e); | |||
| onError(e); | |||
| } | |||
| } | |||
| void dispose() async { | |||
| await _getActionTypesFetcher.drain(); | |||
| _getActionTypesFetcher.close(); | |||
| } | |||
| } | |||
| final getActionTypeBloc = GetActionTypeBloc(); | |||
| @@ -1,366 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/ActionType.dart'; | |||
| import 'package:farm_tpf/custom_model/Other.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/models/index.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/other/bloc_get_action_type.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionOtherScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionOtherScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionOtherScreenState createState() => _EditActionOtherScreenState(); | |||
| } | |||
| class _EditActionOtherScreenState extends State<EditActionOtherScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| var pref = LocalPref(); | |||
| Other _other = Other(); | |||
| final _descriptionController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| List<ActionType> _actionTypes = List<ActionType>(); | |||
| ActionType _actionType; | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _other.cropId = widget.cropId; | |||
| if (!widget.isEdit) { | |||
| getActionTypeBloc.getActionTypes((data) { | |||
| _actionTypes = data; | |||
| }, (err) {}); | |||
| } | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| try { | |||
| _other.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityOther = jsonEncode(_other.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_other.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddOther, | |||
| paramActivity: ConstCommon.paramsActionOther, | |||
| activityAction: activityOther, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateOther, | |||
| paramActivity: ConstCommon.paramsActionOther, | |||
| activityAction: activityOther, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| Utils.showSnackBarWarning(message: label_validate_input_required); | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _other.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| List<DropdownMenuItem<ActionType>> _buildDropMenu(List<ActionType> actions) { | |||
| return actions | |||
| .map((action) => DropdownMenuItem<ActionType>( | |||
| child: Text(action.description.toString()), | |||
| value: action, | |||
| )) | |||
| .toList(); | |||
| } | |||
| Widget _dropdownAcionTypes() { | |||
| return StreamBuilder( | |||
| stream: getActionTypeBloc.actions, | |||
| builder: (context, AsyncSnapshot<dynamic> snapshot) { | |||
| if (snapshot.hasData) { | |||
| return DropdownButtonFormField<ActionType>( | |||
| value: _actionType, | |||
| hint: Text("Hoạt động *"), | |||
| onChanged: (ActionType newValue) { | |||
| setState(() { | |||
| _actionType = newValue; | |||
| _other.activityTypeName = newValue.name; | |||
| }); | |||
| }, | |||
| validator: (value) => | |||
| value == null ? label_validate_input_empty : null, | |||
| isExpanded: true, | |||
| items: _buildDropMenu(_actionTypes)); | |||
| } else if (snapshot.hasError) { | |||
| return Container(); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator(), | |||
| ); | |||
| } | |||
| }, | |||
| ); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _other.description = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailOther, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| _other = Other.fromJson(state.item); | |||
| _other.activityId = widget.activityId; | |||
| _descriptionController.text = | |||
| _other.description ?? ""; | |||
| _executeByController.text = _other.createdByName; | |||
| //select harvest | |||
| getActionTypeBloc.getActionTypes((data) { | |||
| _actionTypes = data; | |||
| for (var item in _actionTypes) { | |||
| if (item.name == _other.activityTypeName) { | |||
| _actionType = item; | |||
| break; | |||
| } | |||
| } | |||
| }, (err) {}); | |||
| Get.find<ChangeDateTimePicker>().change(_other | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _other.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _other.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| } else if (state is ActionDetailLoading) { | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_other, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _dropdownAcionTypes(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _descriptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,482 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Harvest.dart'; | |||
| import 'package:farm_tpf/custom_model/Packing.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc_get_harvest.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionPackingScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| final int harvestId; | |||
| EditActionPackingScreen( | |||
| {@required this.cropId, | |||
| this.isEdit = false, | |||
| this.activityId, | |||
| this.harvestId}); | |||
| @override | |||
| _EditActionPackingScreenState createState() => | |||
| _EditActionPackingScreenState(); | |||
| } | |||
| class _EditActionPackingScreenState extends State<EditActionPackingScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Packing _packing = Packing(); | |||
| TextEditingController _l1Controller = TextEditingController(); | |||
| TextEditingController _l2Controller = TextEditingController(); | |||
| TextEditingController _l3Controller = TextEditingController(); | |||
| TextEditingController _removedQuantityController = TextEditingController(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| var pref = LocalPref(); | |||
| List<Harvest> _harvests = List<Harvest>(); | |||
| Harvest harvestValue; | |||
| String executeTimeView; | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _packing.executeDate = | |||
| executeTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| executeTimeView = executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| _packing.cropId = widget.cropId; | |||
| if (!widget.isEdit) { | |||
| getHarvestBloc.getHarvests((data) { | |||
| _harvests = data; | |||
| for (var item in _harvests) { | |||
| if (item.id == widget.harvestId) { | |||
| harvestValue = item; | |||
| break; | |||
| } | |||
| } | |||
| }, (err) {}); | |||
| } | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| try { | |||
| _packing.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityPacking = jsonEncode(_packing.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_packing.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddPacking, | |||
| paramActivity: ConstCommon.paramsActionPacking, | |||
| activityAction: activityPacking, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdatePacking, | |||
| paramActivity: ConstCommon.paramsActionPacking, | |||
| activityAction: activityPacking, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| List<DropdownMenuItem<Harvest>> _buildDropMenu(List<Harvest> actions) { | |||
| return actions | |||
| .map((action) => DropdownMenuItem<Harvest>( | |||
| child: Text("Mã thu hoạch " + action.id.toString()), | |||
| value: action, | |||
| )) | |||
| .toList(); | |||
| } | |||
| Widget _dropdownHarvest() { | |||
| return StreamBuilder( | |||
| stream: getHarvestBloc.actions, | |||
| builder: (context, AsyncSnapshot<dynamic> snapshot) { | |||
| if (snapshot.hasData) { | |||
| return DropdownButtonFormField<Harvest>( | |||
| value: harvestValue, | |||
| hint: Text("Mã thu hoạch"), | |||
| onChanged: (Harvest newValue) { | |||
| setState(() { | |||
| harvestValue = newValue; | |||
| _packing.harvestId = newValue.id; | |||
| }); | |||
| }, | |||
| isExpanded: true, | |||
| items: _buildDropMenu(_harvests)); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator(), | |||
| ); | |||
| } | |||
| }, | |||
| ); | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return FlatButton( | |||
| padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| DatePicker.showDateTimePicker(context, | |||
| showTitleActions: true, onChanged: (date) {}, onConfirm: (date) { | |||
| setState(() { | |||
| executeTime = date; | |||
| _packing.executeDate = | |||
| executeTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| executeTimeView = executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| }); | |||
| }, currentTime: executeTime, locale: LocaleType.vi); | |||
| }, | |||
| child: Container( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| Expanded( | |||
| child: Text( | |||
| //TODO: check condition | |||
| executeTimeView == null ? "$executeTime" : executeTimeView, | |||
| style: TextStyle(fontSize: 14.0, color: Colors.black87), | |||
| )), | |||
| Icon( | |||
| Icons.date_range, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| } | |||
| Widget _l1Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 1", | |||
| textController: _l1Controller, | |||
| onSaved: (newValue) { | |||
| _packing.quantityLv1 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l2Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 2", | |||
| textController: _l2Controller, | |||
| onSaved: (newValue) { | |||
| _packing.quantityLv2 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l3Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 3", | |||
| textController: _l3Controller, | |||
| onSaved: (newValue) { | |||
| _packing.quantityLv3 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _removedQuantityField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại bỏ", | |||
| textController: _removedQuantityController, | |||
| onSaved: (newValue) { | |||
| _packing.removedQuantity = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _packing.description = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailPacking, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(state.item); | |||
| _packing = Packing.fromJson(state.item); | |||
| _packing.activityId = widget.activityId; | |||
| _l1Controller.text = _packing.quantityLv1 | |||
| .formatNumtoStringDecimal(); | |||
| _l2Controller.text = _packing.quantityLv2 | |||
| .formatNumtoStringDecimal(); | |||
| _l3Controller.text = _packing.quantityLv3 | |||
| .formatNumtoStringDecimal(); | |||
| _removedQuantityController.text = _packing | |||
| .removedQuantity | |||
| .formatNumtoStringDecimal(); | |||
| _descriptionController.text = | |||
| _packing.description ?? ""; | |||
| _executeByController.text = _packing.executeBy; | |||
| //select harvest | |||
| getHarvestBloc.getHarvests((data) { | |||
| _harvests = data; | |||
| for (var item in _harvests) { | |||
| if (item.id == _packing.harvestId) { | |||
| harvestValue = item; | |||
| break; | |||
| } | |||
| } | |||
| }, (err) {}); | |||
| executeTime = _packing.executeDate | |||
| .convertStringServerDateTimeToLocalDateTime(); | |||
| executeTimeView = | |||
| executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _packing.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _packing.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| } else if (state is ActionDetailLoading) { | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_packing, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _dropdownHarvest(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l1Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l2Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l3Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _removedQuantityField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _descriptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ) | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _l1Controller.dispose(); | |||
| _l2Controller.dispose(); | |||
| _l3Controller.dispose(); | |||
| _removedQuantityController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,389 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Plant.dart'; | |||
| import 'package:farm_tpf/custom_model/SuppliesUsing.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeFieldInForm.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeSupplyUsing.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/plant/widget_plant_supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter/services.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionPlantScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionPlantScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionPlantScreenState createState() => _EditActionPlantScreenState(); | |||
| } | |||
| class _EditActionPlantScreenState extends State<EditActionPlantScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Plant _plant = Plant(); | |||
| var pref = LocalPref(); | |||
| final _descriptionController = TextEditingController(); | |||
| final _quantityController = TextEditingController(); | |||
| final _densityController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| List<SuppliesUsing> suppliesUsing = new List<SuppliesUsing>(); | |||
| String executeTimeView; | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _plant.suppliesUsing = new List<SuppliesUsing>(); | |||
| _plant.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| List<SuppliesUsing> newSups = []; | |||
| suppliesUsing.forEach((sup) { | |||
| var newSup = sup; | |||
| newSup.suppliesInWarehouseId = sup.tbSuppliesInWarehouseId; | |||
| newSups.add(newSup); | |||
| }); | |||
| _plant.suppliesUsing = newSups; | |||
| _plant.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityPlant = jsonEncode(_plant.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_plant.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddPlant, | |||
| paramActivity: ConstCommon.paramsActionPlant, | |||
| activityAction: activityPlant, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdatePlant, | |||
| paramActivity: ConstCommon.paramsActionPlant, | |||
| activityAction: activityPlant, | |||
| filePaths: filePaths); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _plant.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _quantityField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng cây trồng", | |||
| textController: _quantityController, | |||
| onSaved: (newValue) { | |||
| _plant.quantity = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _densityField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Mật độ"), | |||
| controller: _densityController, | |||
| onSaved: (newValue) { | |||
| _plant.density = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _desciptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _plant.description = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailPlant, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: BlocConsumer<ActionDetailBloc, | |||
| ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| _plant = Plant.fromJson(state.item); | |||
| _plant.activityId = widget.activityId; | |||
| _quantityController.text = _plant.quantity | |||
| .formatNumtoStringDecimal(); | |||
| _densityController.text = _plant.density; | |||
| _descriptionController.text = | |||
| _plant.description; | |||
| _executeByController.text = | |||
| _plant.executeBy; | |||
| Get.find<ChangeDateTimePicker>().change(_plant | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _plant.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context) | |||
| .add(ChangeListMedia( | |||
| items: UtilAction | |||
| .convertFilePathToMedia( | |||
| _plant.media))); | |||
| } | |||
| //list supply | |||
| suppliesUsing = _plant.suppliesUsing; | |||
| Get.find<ChangeSupplyUsing>() | |||
| .changeInitList(suppliesUsing); | |||
| } else if (state is ActionDetailInitial) { | |||
| print("init"); | |||
| } else if (state is ActionDetailLoading) { | |||
| print("loading"); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| 'Trồng', | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _quantityField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _densityField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _desciptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| WidgetPlantSupply( | |||
| currentItems: [], | |||
| onChangeSupplies: (value) { | |||
| suppliesUsing = value; | |||
| }), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, | |||
| MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: | |||
| CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| SizedBox( | |||
| height: 8, | |||
| ), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus | |||
| .hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| if (Get.find< | |||
| ChangeFieldFormSupply>() | |||
| .isChanged) { | |||
| Utils.showDialogConfirmSupply( | |||
| onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| }); | |||
| } else { | |||
| _validateInputs(); | |||
| } | |||
| }), | |||
| ) | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )))))); | |||
| @override | |||
| void dispose() { | |||
| _quantityController.dispose(); | |||
| _densityController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -11,6 +11,7 @@ import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/dropdown_supply_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_action_field_date.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| @@ -149,13 +150,33 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| }); | |||
| //tbObjectUpdateDTOList | |||
| var _objectPrameters = <TbObjectUpdateDTO>[]; | |||
| valueObjects.forEach((key, value) { | |||
| var objectUpdate = TbObjectUpdateDTO() | |||
| ..tbObjectParameterId = int.tryParse(key) | |||
| ..index = value; | |||
| _objectPrameters.add(objectUpdate); | |||
| }); | |||
| _requestActivity.tbObjectUpdateDTOList = _objectPrameters; | |||
| if (widget.isEdit) { | |||
| // Edit | |||
| if (_requestActivity.tbObjectUpdateDTOList != null) { | |||
| _requestActivity.tbObjectUpdateDTOList.forEach((element) { | |||
| if (valueObjects.keys.contains(element.tbObjectParameterId)) { | |||
| var objectUpdate = TbObjectUpdateDTO() | |||
| ..id = element.id | |||
| ..tbObjectParameterId = element.tbObjectParameterId | |||
| ..index = | |||
| valueObjects[element.tbObjectParameterId.toString()]; | |||
| _objectPrameters.add(objectUpdate); | |||
| } | |||
| }); | |||
| _requestActivity.tbObjectUpdateDTOList = _objectPrameters; | |||
| } | |||
| } else { | |||
| //Add new | |||
| valueObjects.forEach((key, value) { | |||
| var objectUpdate = TbObjectUpdateDTO() | |||
| ..tbObjectParameterId = int.tryParse(key) | |||
| ..index = value; | |||
| _objectPrameters.add(objectUpdate); | |||
| }); | |||
| _requestActivity.tbObjectUpdateDTOList = _objectPrameters; | |||
| } | |||
| //CHECK NURSERY | |||
| if (widget.activityType == 'ACTIVE_TYPE_NURSERY') { | |||
| _requestActivity.tbNurseryDetailsDTOList = _nurseryDetails; | |||
| @@ -447,12 +468,17 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| } | |||
| } | |||
| void showDataWhenEdit() { | |||
| void showDataWhenEdit(BuildContext context) { | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty(_requestActivity.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add(ChangeListMedia( | |||
| items: UtilAction.convertFilePathToMedia(_requestActivity.media))); | |||
| try { | |||
| if (Validators.stringNotNullOrEmpty(_requestActivity.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add(ChangeListMedia( | |||
| items: UtilAction.convertFilePathToMedia(_requestActivity.media))); | |||
| } | |||
| } catch (e) { | |||
| print(e); | |||
| } | |||
| SchedulerBinding.instance.addPostFrameCallback((_) { | |||
| if (widget.activityType == 'ACTIVE_TYPE_PLANTING' || | |||
| widget.activityType == 'ACTIVE_TYPE_FERTILIZE' || | |||
| @@ -565,39 +591,41 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| child: Form( | |||
| key: _formKey, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: BlocBuilder<ActionUiCubit, ActionUiState>( | |||
| builder: (context, state) { | |||
| if (state is ActionUiLoading) { | |||
| print('loading...'); | |||
| return Center(child: CircularProgressIndicator()); | |||
| } else if (state is ActionUiSuccess) { | |||
| _actionUIForm = state.actionUIForm; | |||
| _requestActivity = state.activityDetail; | |||
| child: BlocBuilder<ActionUiCubit, ActionUiState>( | |||
| builder: (context, state) { | |||
| if (state is ActionUiLoading) { | |||
| print('loading...'); | |||
| return Center( | |||
| child: LoadingListPage(), | |||
| ); | |||
| } else if (state is ActionUiSuccess) { | |||
| _actionUIForm = state.actionUIForm; | |||
| _requestActivity = state.activityDetail; | |||
| //CREATE UI | |||
| _actionUIForm.objectParameterDTOList | |||
| .forEach((element) { | |||
| //generate controller | |||
| if (element.tbControlTypeName == 'text' || | |||
| element.tbControlTypeName == 'number' || | |||
| element.tbControlTypeName == 'textarea') { | |||
| var textEditingController = | |||
| new TextEditingController(); | |||
| textFieldControllers.putIfAbsent( | |||
| element.id.toString(), | |||
| () => textEditingController); | |||
| } | |||
| // generate value each parameter | |||
| valueObjects.putIfAbsent( | |||
| element.id.toString(), () => ''); | |||
| }); | |||
| //SHOW EDIT DATA | |||
| if (widget.isEdit) { | |||
| showDataWhenEdit(); | |||
| //CREATE UI | |||
| _actionUIForm.objectParameterDTOList | |||
| .forEach((element) { | |||
| //generate controller | |||
| if (element.tbControlTypeName == 'text' || | |||
| element.tbControlTypeName == 'number' || | |||
| element.tbControlTypeName == 'textarea') { | |||
| var textEditingController = | |||
| new TextEditingController(); | |||
| textFieldControllers.putIfAbsent( | |||
| element.id.toString(), | |||
| () => textEditingController); | |||
| } | |||
| // generate value each parameter | |||
| valueObjects.putIfAbsent( | |||
| element.id.toString(), () => ''); | |||
| }); | |||
| //SHOW EDIT DATA | |||
| if (widget.isEdit) { | |||
| showDataWhenEdit(context); | |||
| } | |||
| return Column( | |||
| return SingleChildScrollView( | |||
| child: Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| @@ -662,13 +690,13 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| } else if (state is ActionUiFailure) { | |||
| return Text(state.errorString); | |||
| } | |||
| return Container(); | |||
| }, | |||
| ), | |||
| ), | |||
| ); | |||
| } else if (state is ActionUiFailure) { | |||
| return Center(child: Text(state.errorString)); | |||
| } | |||
| return Container(); | |||
| }, | |||
| ), | |||
| )), | |||
| ))); | |||
| @@ -1,497 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Harvest.dart'; | |||
| import 'package:farm_tpf/custom_model/Sell.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../bloc_get_harvest.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionSellScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| final int harvestId; | |||
| EditActionSellScreen( | |||
| {@required this.cropId, | |||
| this.isEdit = false, | |||
| this.activityId, | |||
| this.harvestId}); | |||
| @override | |||
| _EditActionSellScreenState createState() => _EditActionSellScreenState(); | |||
| } | |||
| class _EditActionSellScreenState extends State<EditActionSellScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Sell _sell = Sell(); | |||
| TextEditingController _l1Controller = TextEditingController(); | |||
| TextEditingController _l2Controller = TextEditingController(); | |||
| TextEditingController _l3Controller = TextEditingController(); | |||
| TextEditingController _removedQuantityController = TextEditingController(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| final _buyerController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| var pref = LocalPref(); | |||
| List<Harvest> _harvests = List<Harvest>(); | |||
| Harvest harvestValue; | |||
| String executeTimeView; | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _sell.executeDate = executeTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| executeTimeView = executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| _sell.cropId = widget.cropId; | |||
| if (!widget.isEdit) { | |||
| getHarvestBloc.getHarvests((data) { | |||
| _harvests = data; | |||
| for (var item in _harvests) { | |||
| if (item.id == widget.harvestId) { | |||
| harvestValue = item; | |||
| break; | |||
| } | |||
| } | |||
| }, (err) {}); | |||
| } | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| try { | |||
| _sell.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activitySell = jsonEncode(_sell.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_sell.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddSell, | |||
| paramActivity: ConstCommon.paramsActionSell, | |||
| activityAction: activitySell, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateSell, | |||
| paramActivity: ConstCommon.paramsActionSell, | |||
| activityAction: activitySell, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| List<DropdownMenuItem<Harvest>> _buildDropMenu(List<Harvest> actions) { | |||
| return actions | |||
| .map((action) => DropdownMenuItem<Harvest>( | |||
| child: Text("Mã thu hoạch " + action.id.toString()), | |||
| value: action, | |||
| )) | |||
| .toList(); | |||
| } | |||
| Widget _dropdownHarvest() { | |||
| return StreamBuilder( | |||
| stream: getHarvestBloc.actions, | |||
| builder: (context, AsyncSnapshot<dynamic> snapshot) { | |||
| if (snapshot.hasData) { | |||
| return DropdownButtonFormField<Harvest>( | |||
| value: harvestValue, | |||
| hint: Text("Mã thu hoạch"), | |||
| onChanged: (Harvest newValue) { | |||
| setState(() { | |||
| harvestValue = newValue; | |||
| _sell.harvestId = newValue.id; | |||
| }); | |||
| }, | |||
| isExpanded: true, | |||
| items: _buildDropMenu(_harvests)); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator(), | |||
| ); | |||
| } | |||
| }, | |||
| ); | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return FlatButton( | |||
| padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| DatePicker.showDateTimePicker(context, | |||
| showTitleActions: true, onChanged: (date) {}, onConfirm: (date) { | |||
| setState(() { | |||
| executeTime = date; | |||
| _sell.executeDate = | |||
| executeTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| executeTimeView = executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| }); | |||
| }, currentTime: executeTime, locale: LocaleType.vi); | |||
| }, | |||
| child: Container( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| Expanded( | |||
| child: Text( | |||
| //TODO: check condition | |||
| executeTimeView == null ? "$executeTime" : executeTimeView, | |||
| style: TextStyle(fontSize: 14.0, color: Colors.black87), | |||
| )), | |||
| Icon( | |||
| Icons.date_range, | |||
| color: Colors.blue, | |||
| ), | |||
| ], | |||
| ))); | |||
| } | |||
| Widget _l1Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 1", | |||
| textController: _l1Controller, | |||
| onSaved: (newValue) { | |||
| _sell.quantityLv1 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l2Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 2", | |||
| textController: _l2Controller, | |||
| onSaved: (newValue) { | |||
| _sell.quantityLv2 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l3Field() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại 3", | |||
| textController: _l3Controller, | |||
| onSaved: (newValue) { | |||
| _sell.quantityLv3 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _removedQuantityField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Số lượng/khối lượng loại bỏ", | |||
| textController: _removedQuantityController, | |||
| onSaved: (newValue) { | |||
| _sell.removedQuantity = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _buyerField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Khách hàng"), | |||
| controller: _buyerController, | |||
| onSaved: (newValue) { | |||
| _sell.buyer = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _sell.description = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailSell, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(state.item); | |||
| _sell = Sell.fromJson(state.item); | |||
| _sell.activityId = widget.activityId; | |||
| _l1Controller.text = | |||
| _sell.quantityLv1.formatNumtoStringDecimal(); | |||
| _l2Controller.text = | |||
| _sell.quantityLv2.formatNumtoStringDecimal(); | |||
| _l3Controller.text = | |||
| _sell.quantityLv3.formatNumtoStringDecimal(); | |||
| _removedQuantityController.text = _sell | |||
| .removedQuantity | |||
| .formatNumtoStringDecimal(); | |||
| _buyerController.text = _sell.buyer ?? ""; | |||
| _descriptionController.text = | |||
| _sell.description ?? ""; | |||
| _executeByController.text = _sell.executeBy; | |||
| //select harvest | |||
| getHarvestBloc.getHarvests((data) { | |||
| _harvests = data; | |||
| for (var item in _harvests) { | |||
| if (item.id == _sell.harvestId) { | |||
| harvestValue = item; | |||
| break; | |||
| } | |||
| } | |||
| }, (err) {}); | |||
| executeTime = _sell.executeDate | |||
| .convertStringServerDateTimeToLocalDateTime(); | |||
| executeTimeView = | |||
| executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _sell.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _sell.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| } else if (state is ActionDetailLoading) { | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_sell, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _dropdownHarvest(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l1Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l2Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _l3Field(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _removedQuantityField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _buyerField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _descriptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _l1Controller.dispose(); | |||
| _l2Controller.dispose(); | |||
| _l3Controller.dispose(); | |||
| _removedQuantityController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _buyerController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,503 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/Spraying.dart'; | |||
| import 'package:farm_tpf/custom_model/SuppliesUsing.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeFieldInForm.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeSupplyUsing.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/spraying/widget_spraying_supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionSprayingScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionSprayingScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionSprayingScreenState createState() => | |||
| _EditActionSprayingScreenState(); | |||
| } | |||
| class _EditActionSprayingScreenState extends State<EditActionSprayingScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| Spraying _spraying = Spraying(); | |||
| var pref = LocalPref(); | |||
| final _descriptionController = TextEditingController(); | |||
| final _purposeController = TextEditingController(); | |||
| final _weatherController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| final _quarantinePeriodController = TextEditingController(); | |||
| List<SuppliesUsing> suppliesUsing = new List<SuppliesUsing>(); | |||
| String executeTimeView; | |||
| DateTime executeTime = DateTime.now(); | |||
| String resultAtView; | |||
| DateTime resultAtTime; | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _spraying.suppliesUsing = new List<SuppliesUsing>(); | |||
| _spraying.executeDate = | |||
| executeTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| executeTimeView = executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| _spraying.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| List<SuppliesUsing> newSups = []; | |||
| suppliesUsing.forEach((sup) { | |||
| var newSup = sup; | |||
| newSup.suppliesInWarehouseId = sup.tbSuppliesInWarehouseId; | |||
| newSup.equipmentOfCustomerId = sup.tbEquipmentOfCustomerId; | |||
| newSups.add(newSup); | |||
| }); | |||
| _spraying.suppliesUsing = newSups; | |||
| _spraying.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activitySpraying = jsonEncode(_spraying.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_spraying.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddSpraying, | |||
| paramActivity: ConstCommon.paramsActionSpraying, | |||
| activityAction: activitySpraying, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateSpraying, | |||
| paramActivity: ConstCommon.paramsActionSpraying, | |||
| activityAction: activitySpraying, | |||
| filePaths: filePaths); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return FlatButton( | |||
| padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| DatePicker.showDateTimePicker(context, | |||
| showTitleActions: true, onChanged: (date) {}, onConfirm: (date) { | |||
| setState(() { | |||
| if (resultAtTime != null && date.isAfter(resultAtTime)) { | |||
| Utils.showSnackBarWarning( | |||
| message: label_execute_date_must_after_result_time); | |||
| } else { | |||
| executeTime = date; | |||
| _spraying.executeDate = | |||
| executeTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| executeTimeView = executeTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| } | |||
| }); | |||
| }, currentTime: executeTime, locale: LocaleType.vi); | |||
| }, | |||
| child: Container( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| Expanded( | |||
| child: Text( | |||
| //TODO: check condition | |||
| executeTimeView == null ? "$executeTime" : executeTimeView, | |||
| style: TextStyle(fontSize: 14.0, color: Colors.black87), | |||
| )), | |||
| Icon( | |||
| Icons.date_range, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| } | |||
| Widget _btnResultAtTimePicker() { | |||
| return FlatButton( | |||
| padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| DatePicker.showDateTimePicker(context, | |||
| showTitleActions: true, onChanged: (date) {}, onConfirm: (date) { | |||
| setState(() { | |||
| if (executeTime.isAfter(date)) { | |||
| Utils.showSnackBarWarning( | |||
| message: label_execute_date_must_after_result_time); | |||
| } else { | |||
| resultAtTime = date; | |||
| _spraying.resultAt = | |||
| resultAtTime.convertLocalDateTimeToStringUtcDateTime(); | |||
| resultAtView = resultAtTime.displayDateTime_DDMMYYYY_HHmm(); | |||
| } | |||
| }); | |||
| }, currentTime: resultAtTime, locale: LocaleType.vi); | |||
| }, | |||
| child: Container( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Row( | |||
| children: [ | |||
| Expanded( | |||
| child: Text( | |||
| resultAtView == null ? "" : resultAtView, | |||
| style: TextStyle(fontSize: 14.0, color: Colors.black87), | |||
| )), | |||
| Icon( | |||
| Icons.date_range, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| } | |||
| Widget _purposeField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Lý do sử dụng"), | |||
| controller: _purposeController, | |||
| onSaved: (newValue) { | |||
| _spraying.purpose = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _quarantinePeriodField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Thời gian cách ly", | |||
| textController: _quarantinePeriodController, | |||
| onSaved: (newValue) { | |||
| _spraying.quarantinePeriod = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _weatherField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Thời tiết"), | |||
| controller: _weatherController, | |||
| onSaved: (newValue) { | |||
| _spraying.weatherConditions = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _desciptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _spraying.description = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailSpraying, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: BlocConsumer<ActionDetailBloc, | |||
| ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| _spraying = Spraying.fromJson(state.item); | |||
| _spraying.activityId = widget.activityId; | |||
| _purposeController.text = | |||
| _spraying.purpose ?? ""; | |||
| _quarantinePeriodController.text = _spraying | |||
| .quarantinePeriod | |||
| .formatNumtoStringDecimal(); | |||
| _weatherController.text = | |||
| _spraying.weatherConditions ?? ""; | |||
| _descriptionController.text = | |||
| _spraying.description; | |||
| _executeByController.text = | |||
| _spraying.executeBy; | |||
| executeTime = _spraying.executeDate | |||
| .convertStringServerDateTimeToLocalDateTime(); | |||
| executeTimeView = executeTime | |||
| .displayDateTime_DDMMYYYY_HHmm(); | |||
| resultAtTime = _spraying.resultAt | |||
| .convertStringServerDateTimeToLocalDateTime(); | |||
| resultAtView = resultAtTime | |||
| .displayDateTime_DDMMYYYY_HHmm(); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _spraying.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context) | |||
| .add(ChangeListMedia( | |||
| items: UtilAction | |||
| .convertFilePathToMedia( | |||
| _spraying.media))); | |||
| } | |||
| //list supply | |||
| suppliesUsing = _spraying.suppliesUsing; | |||
| Get.find<ChangeSupplyUsing>() | |||
| .changeInitList(suppliesUsing); | |||
| } else if (state is ActionDetailInitial) { | |||
| print("init"); | |||
| } else if (state is ActionDetailLoading) { | |||
| print("loading"); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| plot_action_spraying, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.w500, | |||
| fontSize: 22), | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _purposeField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _quarantinePeriodField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Thời gian ghi nhận kết quả", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnResultAtTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _weatherField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _desciptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| WidgetSprayingSupply( | |||
| currentItems: [], | |||
| onChangeSupplies: (value) { | |||
| suppliesUsing = value; | |||
| }), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, | |||
| MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: | |||
| CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus | |||
| .hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| if (Get.find< | |||
| ChangeFieldFormSupply>() | |||
| .isChanged) { | |||
| Utils.showDialogConfirmSupply( | |||
| onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| }); | |||
| } else { | |||
| _validateInputs(); | |||
| } | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )))))); | |||
| @override | |||
| void dispose() { | |||
| _quarantinePeriodController.dispose(); | |||
| _purposeController.dispose(); | |||
| _weatherController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -1,408 +0,0 @@ | |||
| import 'dart:convert'; | |||
| import 'package:farm_tpf/custom_model/UseWater.dart'; | |||
| import 'package:farm_tpf/custom_model/WaterType.dart'; | |||
| import 'package:farm_tpf/data/api/app_exception.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class EditActionUseWaterScreen extends StatefulWidget { | |||
| final int cropId; | |||
| final bool isEdit; | |||
| final int activityId; | |||
| EditActionUseWaterScreen( | |||
| {@required this.cropId, this.isEdit = false, this.activityId}); | |||
| @override | |||
| _EditActionUseWaterScreenState createState() => | |||
| _EditActionUseWaterScreenState(); | |||
| } | |||
| class _EditActionUseWaterScreenState extends State<EditActionUseWaterScreen> { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| final _repository = Repository(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| bool _autoValidate = false; | |||
| UseWater _useWater = UseWater(); | |||
| var pref = LocalPref(); | |||
| TextEditingController _amountController = TextEditingController(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| final _executeByController = TextEditingController(); | |||
| DateTime executeTime = DateTime.now(); | |||
| List<String> filePaths = List<String>(); | |||
| var changeFileController = Get.put(ChangeFileController()); | |||
| var changeRadio = Get.put(ChangeRadioButton()); | |||
| Future<Null> getSharedPrefs() async { | |||
| var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); | |||
| _executeByController.text = currentFullName ?? ""; | |||
| } | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| changeRadio.init(widget.isEdit); | |||
| _useWater.cropId = widget.cropId; | |||
| } | |||
| _validateInputs() async { | |||
| if (_formKey.currentState.validate()) { | |||
| _formKey.currentState.save(); | |||
| LoadingDialog.showLoadingDialog(context); | |||
| filePaths = Get.find<ChangeFileController>().newFiles; | |||
| //Create request general model | |||
| try { | |||
| _useWater.waterType = changeRadio.selectedWaterType.waterTypeName; | |||
| _useWater.mediaDel = Get.find<ChangeFileController>().deleteFiles; | |||
| var activityUseWater = jsonEncode(_useWater.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_useWater.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_add_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddUserWater, | |||
| paramActivity: ConstCommon.paramsActionUseWater, | |||
| activityAction: activityUseWater, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Utils.showSnackBarSuccess(message: label_update_success); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, | |||
| apiUpdateAction: ConstCommon.apiUpdateUseWater, | |||
| paramActivity: ConstCommon.paramsActionUseWater, | |||
| activityAction: activityUseWater, | |||
| filePaths: filePaths); | |||
| } | |||
| } catch (e) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(e.toString()); | |||
| } | |||
| } else { | |||
| _autoValidate = true; | |||
| } | |||
| } | |||
| Widget _btnExecuteTimePicker() { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _useWater.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| Widget _amountField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Thể tích nước sử dụng", | |||
| textController: _amountController, | |||
| onSaved: (newValue) { | |||
| _useWater.amount = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFieldDescriptionWidget( | |||
| controller: _descriptionController, | |||
| onSaved: (newValue) { | |||
| _useWater.description = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _executeByField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Người thực hiện"), | |||
| enabled: false, | |||
| controller: _executeByController, | |||
| onSaved: (newValue) {}, | |||
| ); | |||
| } | |||
| Widget _typeWater() { | |||
| return GetBuilder<ChangeRadioButton>( | |||
| builder: (value) { | |||
| if (value._waterTypes != null) { | |||
| return Container( | |||
| child: ListView.builder( | |||
| shrinkWrap: true, | |||
| physics: NeverScrollableScrollPhysics(), | |||
| itemBuilder: (context, index) { | |||
| return GestureDetector( | |||
| child: RadioListTile( | |||
| title: Text( | |||
| value._waterTypes[index].waterTypeDescription ?? | |||
| ""), | |||
| value: value._waterTypes[index], | |||
| groupValue: value.selectedWaterType == null | |||
| ? null | |||
| : value.selectedWaterType, | |||
| onChanged: (WaterType value) { | |||
| changeRadio.changeSelected(value); | |||
| }), | |||
| onTap: () {}); | |||
| }, | |||
| itemCount: value._waterTypes.length, | |||
| ), | |||
| ); | |||
| } else { | |||
| return Container(); | |||
| } | |||
| }, | |||
| ); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| backgroundColor: Colors.white, | |||
| key: _scaffoldKey, | |||
| appBar: AppBarWidget( | |||
| isBack: true, | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Huỷ', | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| if (Get.isSnackbarOpen) Get.back(); | |||
| Get.back(); | |||
| }, | |||
| ), | |||
| ), | |||
| body: KeyboardDismisser( | |||
| child: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionDetailBloc>( | |||
| create: (context) => | |||
| ActionDetailBloc(repository: Repository()) | |||
| ..add(FetchData( | |||
| isNeedFetchData: widget.isEdit, | |||
| apiActivity: ConstCommon.apiDetailUseWater, | |||
| activityId: widget.activityId))), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| key: _formKey, | |||
| autovalidate: _autoValidate, | |||
| child: SafeArea( | |||
| child: SingleChildScrollView( | |||
| child: | |||
| BlocConsumer<ActionDetailBloc, ActionDetailState>( | |||
| listener: (context, state) async { | |||
| if (state is ActionDetailFailure) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| } else if (state is ActionDetailSuccess) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| print(state.item); | |||
| _useWater = UseWater.fromJson(state.item); | |||
| _amountController.text = | |||
| _useWater.amount.formatNumtoStringDecimal(); | |||
| _descriptionController.text = | |||
| _useWater.description ?? ""; | |||
| _executeByController.text = _useWater.executeBy; | |||
| Get.find<ChangeDateTimePicker>().change(_useWater | |||
| .executeDate | |||
| .convertStringServerDateTimeToLocalDateTime()); | |||
| changeRadio | |||
| .initWithSelectedByName(_useWater.waterType); | |||
| //Show media | |||
| if (Validators.stringNotNullOrEmpty( | |||
| _useWater.media)) { | |||
| BlocProvider.of<MediaHelperBloc>(context).add( | |||
| ChangeListMedia( | |||
| items: | |||
| UtilAction.convertFilePathToMedia( | |||
| _useWater.media))); | |||
| } | |||
| } else if (state is ActionDetailInitial) { | |||
| } else if (state is ActionDetailLoading) { | |||
| LoadingDialog.showLoadingDialog(context); | |||
| } | |||
| }, | |||
| builder: (context, state) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| children: <Widget>[ | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _typeWater(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _amountField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _descriptionField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }), | |||
| ), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _amountController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| class ChangeRadioButton extends GetxController { | |||
| List<WaterType> _waterTypes; | |||
| WaterType selectedWaterType; | |||
| Future<void> init(bool isEditScreen) async { | |||
| //init if is NOT edit screen | |||
| if (!isEditScreen) { | |||
| selectedWaterType = WaterType(); | |||
| _waterTypes = List<WaterType>(); | |||
| //Get action types | |||
| Repository _repo = Repository(); | |||
| try { | |||
| var response = await _repo.getWaterTypes(); | |||
| if (response.length != null) { | |||
| _waterTypes = response; | |||
| _waterTypes.forEach((element) { | |||
| if (element.waterTypeName == "TYPE_WATERING_PLANTS") { | |||
| selectedWaterType = element; | |||
| } | |||
| }); | |||
| update(); | |||
| } | |||
| } catch (error) { | |||
| print(error.toString()); | |||
| } | |||
| } | |||
| } | |||
| void changeSelected(WaterType selected) { | |||
| selectedWaterType = selected; | |||
| update(); | |||
| } | |||
| //init and selected item | |||
| Future<void> initWithSelectedByName(String waterTypeName) async { | |||
| Repository _repo = Repository(); | |||
| try { | |||
| var response = await _repo.getWaterTypes(); | |||
| if (response.length != null) { | |||
| _waterTypes = response; | |||
| _waterTypes.forEach((element) { | |||
| if (element.waterTypeName == waterTypeName) { | |||
| selectedWaterType = element; | |||
| } | |||
| }); | |||
| update(); | |||
| } | |||
| } catch (error) { | |||
| print(error.toString()); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,10 +1,7 @@ | |||
| import 'package:farm_tpf/data/repository/authentication_repository.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/camera_helper.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/nursery/sc_edit_action_nursery.dart'; | |||
| import 'package:farm_tpf/presentation/screens/login/bloc/login_bloc.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||
| import 'login_form.dart'; | |||
| @@ -107,13 +107,9 @@ class PlotDetailBloc extends Bloc<PlotDetailEvent, PlotDetailState> { | |||
| response = await repository.getPlotDetailByCode(event.cropCode, | |||
| page: 0, size: pageSize); | |||
| } | |||
| var listActivities = List<Activities>(); | |||
| CropPlot cropPlot = response as CropPlot; | |||
| cropPlot.activities.forEach((element) { | |||
| listActivities.add(Activities.clone(element)); | |||
| }); | |||
| yield PlotDetailSuccess( | |||
| items: listActivities, | |||
| items: response.activities, | |||
| page: 0, | |||
| hasReachedMax: | |||
| response.activities.length < pageSize ? true : false); | |||
| @@ -1,3 +1,4 @@ | |||
| import 'package:auto_size_text/auto_size_text.dart'; | |||
| import 'package:cached_network_image/cached_network_image.dart'; | |||
| import 'package:farm_tpf/custom_model/ActionType.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| @@ -6,6 +7,7 @@ import 'package:farm_tpf/presentation/screens/actions/sc_action.dart'; | |||
| import 'package:farm_tpf/presentation/screens/plot_detail/bloc/cubit/plot_action_type_cubit.dart'; | |||
| import 'package:farm_tpf/utils/const_assets.dart'; | |||
| import 'package:farm_tpf/utils/const_color.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| import 'package:get/get.dart'; | |||
| @@ -26,7 +28,6 @@ class _PlotActionScreenState extends State<PlotActionScreen> | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| // _initActionButtons(); | |||
| } | |||
| @override | |||
| @@ -34,80 +35,6 @@ class _PlotActionScreenState extends State<PlotActionScreen> | |||
| super.dispose(); | |||
| } | |||
| // _initActionButtons() { | |||
| // //type: 0- Trồng, 1- ướm | |||
| // if (widget.cropType == 1) { | |||
| // actions.add(ActionType( | |||
| // plot_action_nursery, | |||
| // EditActionNurseryScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionNursery)); | |||
| // } else if (widget.cropType == 0) { | |||
| // actions.add(ActionType( | |||
| // plot_action_plant, | |||
| // EditActionPlantScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionPlant)); | |||
| // } | |||
| // actions.add(ActionType( | |||
| // plot_action_crop_status, | |||
| // EditActionCropStatusScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionCropStatus)); | |||
| // actions.add(ActionType( | |||
| // plot_action_environment_update, | |||
| // EditActionEnvironmentUpdate( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionEnvironment)); | |||
| // actions.add(ActionType( | |||
| // plot_action_dung, | |||
| // EditActionDungScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionDung)); | |||
| // actions.add(ActionType( | |||
| // plot_action_spraying, | |||
| // EditActionSprayingScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionSpraying)); | |||
| // actions.add(ActionType( | |||
| // plot_action_disease, | |||
| // EditActionDiseaseScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionDisease)); | |||
| // actions.add(ActionType( | |||
| // plot_action_use_water, | |||
| // EditActionUseWaterScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionUseWater)); | |||
| // actions.add(ActionType( | |||
| // plot_action_other, | |||
| // EditActionOtherScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionOther)); | |||
| // actions.add(ActionType( | |||
| // plot_action_harvest, | |||
| // EditActionHarvestScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionHarvest)); | |||
| // actions.add(ActionType( | |||
| // plot_action_finish, | |||
| // EditActionEndScreen( | |||
| // cropId: widget.cropId, | |||
| // ), | |||
| // AppAssets.icActionEnd)); | |||
| // } | |||
| Widget _createActionButtons(ActionType actionType, BuildContext _context) { | |||
| return GestureDetector( | |||
| onTap: () { | |||
| @@ -122,6 +49,7 @@ class _PlotActionScreenState extends State<PlotActionScreen> | |||
| }, | |||
| child: Container( | |||
| margin: EdgeInsets.all(8), | |||
| padding: EdgeInsets.all(4), | |||
| decoration: BoxDecoration( | |||
| border: Border.all(color: Colors.grey, width: 0.1), | |||
| color: Colors.white, | |||
| @@ -137,25 +65,37 @@ class _PlotActionScreenState extends State<PlotActionScreen> | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| crossAxisAlignment: CrossAxisAlignment.center, | |||
| children: [ | |||
| 1 == 1 | |||
| ? Image.asset( | |||
| Expanded( | |||
| flex: 1, | |||
| child: SizedBox( | |||
| width: Get.width / 10, | |||
| height: Get.height / 10, | |||
| child: CachedNetworkImage( | |||
| imageUrl: | |||
| '${ConstCommon.baseImageUrl}${actionType.urlLogo}', | |||
| placeholder: (context, url) => Icon( | |||
| Icons.broken_image, | |||
| ), | |||
| errorWidget: (context, url, error) => Image.asset( | |||
| AppAssets.logo, | |||
| width: Get.width / 9, | |||
| height: Get.width / 9, | |||
| ) | |||
| : CachedNetworkImage( | |||
| imageUrl: "http://via.placeholder.com/350x150", | |||
| placeholder: (context, url) => | |||
| CircularProgressIndicator(), | |||
| errorWidget: (context, url, error) => Icon(Icons.error), | |||
| ), | |||
| Text( | |||
| actionType.description, | |||
| textAlign: TextAlign.center, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.bold, | |||
| fontSize: 13, | |||
| color: AppColors.BLACK2, | |||
| ), | |||
| ), | |||
| ), | |||
| Expanded( | |||
| flex: 1, | |||
| child: Align( | |||
| alignment: Alignment.center, | |||
| child: AutoSizeText( | |||
| actionType.description, | |||
| textAlign: TextAlign.center, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.bold, | |||
| fontSize: 13, | |||
| color: AppColors.BLACK2, | |||
| ), | |||
| maxLines: 2, | |||
| ), | |||
| ), | |||
| ), | |||
| ], | |||
| @@ -4,16 +4,5 @@ class AppAssets { | |||
| static const splash = baseAssets + 'splash.png'; | |||
| static const logoWithSlogan = baseAssets + 'logoWithSlogan.png'; | |||
| static const tempImage = baseAssets + 'tempImage.png'; | |||
| static const icActionNursery = baseAssets + 'icActionNursery.png'; | |||
| static const icActionCropStatus = baseAssets + 'icActionCropStatus.png'; | |||
| static const icActionDisease = baseAssets + 'icActionDisease.png'; | |||
| static const icActionDung = baseAssets + 'icActionDung.png'; | |||
| static const icActionEnd = baseAssets + 'icActionEnd.png'; | |||
| static const icActionEnvironment = baseAssets + 'icActionEnvironment.png'; | |||
| static const icActionHarvest = baseAssets + 'icActionHarvest.png'; | |||
| static const icActionOther = baseAssets + 'icActionOther.png'; | |||
| static const icActionPlant = baseAssets + 'icActionPlant.png'; | |||
| static const icActionSpraying = baseAssets + 'icActionSpraying.png'; | |||
| static const icActionUseWater = baseAssets + 'icActionUseWater.png'; | |||
| static const icAddMedia = baseAssets + 'icAddMedia.png'; | |||
| } | |||
| @@ -6,78 +6,6 @@ class ConstCommon { | |||
| static const String baseImageUrl = "https://smf.aztrace.vn/upload/"; | |||
| static RegExp regExpDecimal = RegExp("[0-9.]"); | |||
| static const String apiDetailNursery = "api/activity-nursery"; | |||
| static const String apiDetailCropStatus = "api/activity-crop-status"; | |||
| static const String apiDetailEnvUpdate = "api/activity-environment-update"; | |||
| static const String apiDetailDisease = "api/activity-pests-investigation"; | |||
| static const String apiDetailUseWater = "api/activity-water-usage"; | |||
| static const String apiDetailHarvest = "api/activity-harvest"; | |||
| static const String apiDetailPacking = "api/activity-packing"; | |||
| static const String apiDetailSell = "api/activity-sell"; | |||
| static const String apiDetailEnd = "api/activity-end"; | |||
| static const String apiDetailOther = "api/activity-other"; | |||
| static const String apiDetailPlant = "api/activity-planting"; | |||
| static const String apiDetailDung = "api/activity-manuring"; | |||
| static const String apiDetailSpraying = "api/activity-spraying"; | |||
| static const String apiDetailHarvestProcess = "api/activity-process"; | |||
| //nursery | |||
| static const String paramsActionNursery = "activityNursery"; | |||
| static const String apiUpdateNursery = "api/updateNursery"; | |||
| static const String apiAddNursery = "api/createNursery"; | |||
| //crop_status | |||
| static const String paramsActionCropStatus = "activityCrop"; | |||
| static const String apiUpdateCropStatus = "api/updateStatusCrop"; | |||
| static const String apiAddCropStatus = "api/createStatusCrop"; | |||
| //Environment Update | |||
| static const String paramsActionEnvUpdate = "activityEnv"; | |||
| static const String apiUpdateEnvUpdate = "api/updateEnv"; | |||
| static const String apiAddEnvUpdate = "api/createEnv"; | |||
| //Disease | |||
| static const String paramsActionDisease = "activityPestsInvestigation"; | |||
| static const String apiUpdateDisease = "api/updatePestsInvestigation"; | |||
| static const String apiAddDisease = "api/createPestsInvestigation"; | |||
| //Use water | |||
| static const String paramsActionUseWater = "activityWaters"; | |||
| static const String apiUpdateUseWater = "api/updateWaters"; | |||
| static const String apiAddUserWater = "api/createWaters"; | |||
| //Harvest | |||
| static const String paramsActionHarvest = "activityHarvest"; | |||
| static const String apiUpdateHarvest = "api/updateActivityHarvest"; | |||
| static const String apiAddHarvest = "api/createActivityHarvest"; | |||
| //Packing | |||
| static const String paramsActionPacking = "activityPacking"; | |||
| static const String apiUpdatePacking = "api/updateActivityPacking"; | |||
| static const String apiAddPacking = "api/createActivityPacking"; | |||
| //Sell | |||
| static const String paramsActionSell = "activitySell"; | |||
| static const String apiUpdateSell = "api/updateActivitySell"; | |||
| static const String apiAddSell = "api/createActivitySell"; | |||
| //End | |||
| static const String paramsActionEnd = "activityEnd"; | |||
| static const String apiUpdateEnd = "api/updateActivityEnd"; | |||
| static const String apiAddEnd = "api/createActivityEnd"; | |||
| //Other | |||
| static const String paramsActionOther = "activityOther"; | |||
| static const String apiUpdateOther = "api/updateActivityOther"; | |||
| static const String apiAddOther = "api/createActivityOther"; | |||
| //Plant | |||
| static const String paramsActionPlant = "activityPlanting"; | |||
| static const String apiUpdatePlant = "api/updatePlanting"; | |||
| static const String apiAddPlant = "api/createPlanting"; | |||
| //Dung | |||
| static const String paramsActionDung = "activityManuring"; | |||
| static const String apiUpdateDung = "api/updateManuring"; | |||
| static const String apiAddDung = "api/createManuring"; | |||
| //Spraying | |||
| static const String paramsActionSpraying = "activitySpraying"; | |||
| static const String apiUpdateSpraying = "api/updateSpraying"; | |||
| static const String apiAddSpraying = "api/createSpraying"; | |||
| //Harvest Process | |||
| static const String paramsActionHarvestProcess = "activityProcess"; | |||
| static const String apiUpdateHarvestProcess = "api/updateActivityProcess"; | |||
| static const String apiAddHarvestProcess = "api/createActivityProcess"; | |||
| static const String supplyTypeSeed = "GIONG"; | |||
| static const String supplyTypeDung = "PHANBON"; | |||
| static const String supplyTypeSubStrate = "GIATHE"; | |||
| @@ -58,7 +58,8 @@ extension ddMM_HHmm on String { | |||
| String formatStringToStringDecimal() { | |||
| try { | |||
| var numOfString = double.tryParse(this.toString()); | |||
| var newValue = this.replaceAll(",", ""); | |||
| var numOfString = double.tryParse(newValue); | |||
| var numWithLocalSeparator = new NumberFormat.decimalPattern("en_US"); | |||
| final str = numWithLocalSeparator.format(numOfString); | |||
| return str; | |||
| @@ -29,6 +29,13 @@ packages: | |||
| url: "https://pub.dartlang.org" | |||
| source: hosted | |||
| version: "2.5.0-nullsafety.3" | |||
| auto_size_text: | |||
| dependency: "direct main" | |||
| description: | |||
| name: auto_size_text | |||
| url: "https://pub.dartlang.org" | |||
| source: hosted | |||
| version: "2.1.0" | |||
| badges: | |||
| dependency: "direct main" | |||
| description: | |||
| @@ -41,6 +41,7 @@ dependencies: | |||
| rflutter_alert: ^1.1.0 | |||
| badges: ^1.1.1 | |||
| cached_network_image: ^2.3.2+1 | |||
| auto_size_text: ^2.1.0 | |||
| camera: ^0.5.8+5 | |||
| path_provider: ^1.6.14 | |||