| @@ -2,22 +2,28 @@ import 'SuppliesUsing.dart'; | |||
| class HarvestProcess { | |||
| int id; | |||
| int cropId; | |||
| int activityId; | |||
| int harvestId; | |||
| String executeDate; | |||
| String description; | |||
| int quantityLv1; | |||
| int quantityLv2; | |||
| int quantityLv3; | |||
| int removedQuantity; | |||
| String executeBy; | |||
| String media; | |||
| num quantityLv1; | |||
| num quantityLv2; | |||
| num quantityLv3; | |||
| num removedQuantity; | |||
| List<SuppliesUsing> suppliesUsing; | |||
| HarvestProcess( | |||
| {this.id, | |||
| this.cropId, | |||
| this.activityId, | |||
| this.harvestId, | |||
| this.executeDate, | |||
| this.description, | |||
| this.executeBy, | |||
| this.media, | |||
| this.quantityLv1, | |||
| this.quantityLv2, | |||
| this.quantityLv3, | |||
| @@ -26,10 +32,13 @@ class HarvestProcess { | |||
| HarvestProcess.fromJson(Map<String, dynamic> json) { | |||
| id = json['id']; | |||
| cropId = json['cropId']; | |||
| activityId = json['activityId']; | |||
| harvestId = json['harvestId']; | |||
| executeDate = json['executeDate']; | |||
| description = json['description']; | |||
| executeBy = json['executeBy']; | |||
| media = json['media']; | |||
| quantityLv1 = json['quantityLv1']; | |||
| quantityLv2 = json['quantityLv2']; | |||
| quantityLv3 = json['quantityLv3']; | |||
| @@ -45,10 +54,13 @@ class HarvestProcess { | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['id'] = this.id; | |||
| data['cropId'] = this.cropId; | |||
| data['activityId'] = this.activityId; | |||
| data['harvestId'] = this.harvestId; | |||
| data['executeDate'] = this.executeDate; | |||
| data['description'] = this.description; | |||
| data['executeBy'] = this.executeBy; | |||
| data['media'] = this.media; | |||
| data['quantityLv1'] = this.quantityLv1; | |||
| data['quantityLv2'] = this.quantityLv2; | |||
| data['quantityLv3'] = this.quantityLv3; | |||
| @@ -7,6 +7,7 @@ import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.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/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'; | |||
| @@ -418,7 +419,17 @@ class _EditActionHarvestScreenState extends State<EditActionHarvestScreen> { | |||
| borderRadius: | |||
| new BorderRadius.circular(8.0)), | |||
| color: Colors.lightGreen, | |||
| onPressed: () {}, | |||
| onPressed: () { | |||
| if (_harvest.id != null) { | |||
| Get.to(EditActionHarvestProcessScreen( | |||
| cropId: widget.cropId, | |||
| harvestId: _harvest.id, | |||
| )); | |||
| } else { | |||
| Get.to(EditActionHarvestProcessScreen( | |||
| cropId: widget.cropId)); | |||
| } | |||
| }, | |||
| child: Text( | |||
| plot_action_harvest_process, | |||
| style: TextStyle( | |||
| @@ -1,7 +1,43 @@ | |||
| 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/bloc/media_helper_bloc.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/screens/actions/bloc/action_detail_bloc.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/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: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(); | |||
| @@ -9,12 +45,479 @@ class EditActionHarvestProcessScreen extends StatefulWidget { | |||
| 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 | |||
| Widget build(BuildContext context) { | |||
| return Scaffold( | |||
| appBar: AppBar( | |||
| title: Text(plot_action_harvest_process), | |||
| ), | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _harvestProcess.suppliesUsing = new List<SuppliesUsing>(); | |||
| var parsedExecuteDate = | |||
| DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime); | |||
| _harvestProcess.executeDate = "$parsedExecuteDate"; | |||
| executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime); | |||
| _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>().files; | |||
| List<SuppliesUsing> newSups = []; | |||
| suppliesUsing.forEach((sup) { | |||
| var newSup = sup; | |||
| newSup.suppliesInWarehouseId = sup.tbSuppliesInWarehouseId; | |||
| newSup.equipmentOfCustomerId = sup.tbEquipmentOfCustomerId; | |||
| newSups.add(newSup); | |||
| }); | |||
| _harvestProcess.suppliesUsing = newSups; | |||
| try { | |||
| var activityHarvestProcess = | |||
| jsonEncode(_harvestProcess.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_harvestProcess.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Get.snackbar(label_add_success, "Hoạt động xử lý sau thu hoạch", | |||
| snackPosition: SnackPosition.BOTTOM); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| _scaffoldKey.currentState.showSnackBar(SnackBar( | |||
| content: Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| children: <Widget>[ | |||
| Flexible(child: Text(AppException.handleError(error))), | |||
| Icon(Icons.error), | |||
| ], | |||
| ), | |||
| backgroundColor: Colors.red, | |||
| duration: Duration(seconds: 3), | |||
| )); | |||
| }, | |||
| apiAddAction: ConstCommon.apiAddHarvestProcess, | |||
| paramActivity: ConstCommon.paramsActionHarvestProcess, | |||
| activityAction: activityHarvestProcess, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Get.snackbar(label_update_success, "Hoạt động xử lý sau thu hoạch", | |||
| snackPosition: SnackPosition.BOTTOM); | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| _scaffoldKey.currentState.showSnackBar(SnackBar( | |||
| content: Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| children: <Widget>[ | |||
| Flexible(child: Text(AppException.handleError(error))), | |||
| Icon(Icons.error), | |||
| ], | |||
| ), | |||
| backgroundColor: Colors.red, | |||
| duration: Duration(seconds: 3), | |||
| )); | |||
| }, | |||
| 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; | |||
| }); | |||
| }, | |||
| validator: (value) => value == null ? "Mã thu hoạch" : null, | |||
| 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(() { | |||
| var parsedDate = | |||
| DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date); | |||
| _harvestProcess.executeDate = "$parsedDate"; | |||
| executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date); | |||
| }); | |||
| }, 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 TextFormField( | |||
| keyboardType: TextInputType.numberWithOptions(decimal: true), | |||
| inputFormatters: [ | |||
| ThousandsFormatter( | |||
| formatter: NumberFormat("#,###.##", "es"), allowFraction: true) | |||
| ], | |||
| decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 1"), | |||
| controller: _l1Controller, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.quantityLv1 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l2Field() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.numberWithOptions(decimal: true), | |||
| inputFormatters: [ | |||
| ThousandsFormatter( | |||
| formatter: NumberFormat("#,###.##", "es"), allowFraction: true) | |||
| ], | |||
| decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 2"), | |||
| controller: _l2Controller, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.quantityLv2 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _l3Field() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.numberWithOptions(decimal: true), | |||
| inputFormatters: [ | |||
| ThousandsFormatter( | |||
| formatter: NumberFormat("#,###.##", "es"), allowFraction: true) | |||
| ], | |||
| decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 3"), | |||
| controller: _l3Controller, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.quantityLv3 = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _removedQuantityField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.numberWithOptions(decimal: true), | |||
| inputFormatters: [ | |||
| ThousandsFormatter( | |||
| formatter: NumberFormat("#,###.##", "es"), allowFraction: true) | |||
| ], | |||
| decoration: InputDecoration(labelText: "Số lượng/khối lượng loại bỏ"), | |||
| controller: _removedQuantityController, | |||
| onSaved: (newValue) { | |||
| _harvestProcess.removedQuantity = newValue.parseDoubleThousand(); | |||
| }, | |||
| ); | |||
| } | |||
| Widget _descriptionField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Ghi chú"), | |||
| 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) {}, | |||
| ); | |||
| } | |||
| _actionAppBar() { | |||
| IconButton iconButton; | |||
| if (1 == 1) { | |||
| iconButton = IconButton( | |||
| icon: Icon( | |||
| Icons.done, | |||
| color: Colors.black, | |||
| ), | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| }, | |||
| ); | |||
| return <Widget>[iconButton]; | |||
| } | |||
| return <Widget>[Container()]; | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) => KeyboardDismisser( | |||
| gestures: [ | |||
| GestureType.onTap, | |||
| GestureType.onPanUpdateDownDirection, | |||
| ], | |||
| child: Scaffold( | |||
| key: _scaffoldKey, | |||
| appBar: AppBar( | |||
| centerTitle: true, | |||
| title: Text(plot_action_harvest_process), | |||
| actions: _actionAppBar()), | |||
| 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: SingleChildScrollView( | |||
| padding: EdgeInsets.all(8.0), | |||
| 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) {}); | |||
| try { | |||
| executeTime = | |||
| DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") | |||
| .parse(_harvestProcess.executeDate); | |||
| executeTimeView = DateFormat("dd/MM/yyyy HH:mm") | |||
| .format(executeTime); | |||
| } catch (_) {} | |||
| //Show media | |||
| if (_harvestProcess.media != null) { | |||
| await UtilAction.cacheFiles(_harvestProcess.media) | |||
| .then((value) { | |||
| BlocProvider.of<MediaHelperBloc>(context) | |||
| .add(ChangeListMedia(items: value)); | |||
| }).whenComplete(() { | |||
| print("completed"); | |||
| }); | |||
| } | |||
| //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: <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, | |||
| ), | |||
| _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, | |||
| ), | |||
| WidgetHarvestProcessSupply( | |||
| currentItems: [], | |||
| onChangeSupplies: (value) { | |||
| suppliesUsing = value; | |||
| }), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (filePaths) async { | |||
| Get.find<ChangeFileController>() | |||
| .addAllFile(filePaths); | |||
| }); | |||
| } else { | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| ], | |||
| ); | |||
| }, | |||
| ), | |||
| )), | |||
| )))); | |||
| @override | |||
| void dispose() { | |||
| _l1Controller.dispose(); | |||
| _l2Controller.dispose(); | |||
| _l3Controller.dispose(); | |||
| _removedQuantityController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,468 @@ | |||
| import 'package:farm_tpf/custom_model/Device.dart'; | |||
| import 'package:farm_tpf/custom_model/SuppliesUsing.dart'; | |||
| import 'package:farm_tpf/custom_model/Supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeDevice.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeFormButton.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeSupplyUsing.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeUnit.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/resource_device_activity/sc_device_activity.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/const_color.dart'; | |||
| import 'package:farm_tpf/utils/const_common.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import 'package:intl/intl.dart'; | |||
| import 'package:pattern_formatter/pattern_formatter.dart'; | |||
| import '../util_action.dart'; | |||
| class WidgetHarvestProcessSupply extends StatefulWidget { | |||
| final List<SuppliesUsing> currentItems; | |||
| final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; | |||
| WidgetHarvestProcessSupply( | |||
| {this.currentItems, @required this.onChangeSupplies}); | |||
| @override | |||
| _WidgetHarvestProcessSupplyState createState() => | |||
| _WidgetHarvestProcessSupplyState(); | |||
| } | |||
| class _WidgetHarvestProcessSupplyState | |||
| extends State<WidgetHarvestProcessSupply> { | |||
| final _dosageController = TextEditingController(); | |||
| final _quantityController = TextEditingController(); | |||
| final _howToUseController = TextEditingController(); | |||
| final changeSelectedSupply = Get.put(ChangeSupply()); | |||
| final changeSupplyUsing = Get.put(ChangeSupplyUsing()); | |||
| final changeUnit = Get.put(ChangeUnit()); | |||
| final changeButton = Get.put(ChangeButtonInForm()); | |||
| final changeSelectedDevice = Get.put(ChangeDevice()); | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| changeSelectedSupply.initValue(); | |||
| changeSelectedDevice.initValue(); | |||
| changeSupplyUsing.init(widget.currentItems); | |||
| changeUnit.initValue(); | |||
| changeButton.resetValue(); | |||
| } | |||
| Widget _buildListSupply() { | |||
| return GetBuilder<ChangeSupplyUsing>(builder: (value) { | |||
| widget.onChangeSupplies(value.currentItems); | |||
| if (value.currentItems.isEmpty) { | |||
| return Container(); | |||
| } else { | |||
| return Container( | |||
| height: 120, | |||
| child: ListView.builder( | |||
| physics: ClampingScrollPhysics(), | |||
| scrollDirection: Axis.horizontal, | |||
| shrinkWrap: true, | |||
| itemCount: value.currentItems.length, | |||
| itemBuilder: (context, index) { | |||
| return GestureDetector( | |||
| onTap: () { | |||
| print("edit"); | |||
| changeSupplyUsing.changeIndexEdit(index); | |||
| changeButton.updateToEdit(true); | |||
| var editedSupplyUsing = value.currentItems[index]; | |||
| var editedSupply = Supply() | |||
| ..id = editedSupplyUsing.tbSuppliesInWarehouseId | |||
| ..tbSuppliesName = editedSupplyUsing.supplyName | |||
| ..unit = editedSupplyUsing.supplyUnit; | |||
| changeSelectedSupply.change(editedSupply); | |||
| var editedDevice = Device() | |||
| ..id = editedSupplyUsing.tbEquipmentOfCustomerId | |||
| ..name = editedSupplyUsing.equipmentName; | |||
| changeSelectedDevice.change(editedDevice); | |||
| changeUnit | |||
| .updateListByUnitName(editedSupplyUsing.supplyUnit); | |||
| changeUnit.updateSelected(editedSupplyUsing.supplyUnit); | |||
| _dosageController.text = editedSupplyUsing.dosage; | |||
| _howToUseController.text = editedSupplyUsing.howToUse; | |||
| _quantityController.text = editedSupplyUsing.quantity | |||
| .formatNumtoStringDecimal(); | |||
| }, | |||
| 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: 150, | |||
| child: Column( | |||
| children: [ | |||
| SizedBox( | |||
| height: 12.0, | |||
| ), | |||
| Flexible( | |||
| child: Text( | |||
| value.currentItems[index].supplyName ?? | |||
| "", | |||
| overflow: TextOverflow.ellipsis, | |||
| maxLines: 1), | |||
| ), | |||
| Flexible( | |||
| child: Text( | |||
| "${value.currentItems[index].dosage ?? ""}")), | |||
| Flexible( | |||
| child: Text( | |||
| "${value.currentItems[index].quantity.formatNumtoStringDecimal() ?? ""} ${value.currentItems[index].supplyUnit ?? ""}")), | |||
| Flexible( | |||
| child: Text( | |||
| "${value.currentItems[index].equipmentName ?? ""}")), | |||
| Flexible( | |||
| child: Text( | |||
| "${value.currentItems[index].howToUse ?? ""}")), | |||
| ], | |||
| ), | |||
| ), | |||
| )), | |||
| Positioned( | |||
| top: -10, | |||
| right: -10, | |||
| child: IconButton( | |||
| icon: Icon( | |||
| Icons.cancel, | |||
| color: Colors.redAccent, | |||
| ), | |||
| onPressed: () { | |||
| changeSupplyUsing.deleteSupply(index); | |||
| }), | |||
| ) | |||
| ], | |||
| ))); | |||
| })); | |||
| } | |||
| }); | |||
| } | |||
| Widget _btnSelectSubstrates() { | |||
| return GetBuilder<ChangeSupply>(builder: (data) { | |||
| 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: "Hoá chất xử lý", | |||
| type: ConstCommon.supplyTypeAll, | |||
| selectedId: changeSelectedSupply.selectedSupplyId), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) { | |||
| var result = value as Supply; | |||
| changeSelectedSupply.change(result); | |||
| changeUnit.updateListByUnitName(result.unit); | |||
| } | |||
| }); | |||
| }, | |||
| 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( | |||
| changeSelectedSupply.selectedSupplyName ?? | |||
| "Hoá chất xử lý", | |||
| style: TextStyle( | |||
| fontSize: 14.0, color: Colors.black87)))), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| }); | |||
| } | |||
| Widget _btnSelectDevice() { | |||
| return GetBuilder<ChangeDevice>(builder: (data) { | |||
| return FlatButton( | |||
| padding: | |||
| EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||
| onPressed: () { | |||
| Navigator.of(context) | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => ListDeviceActivity( | |||
| selectedId: changeSelectedDevice.selectedDeviceId), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) { | |||
| var result = value as Device; | |||
| changeSelectedDevice.change(result); | |||
| } | |||
| }); | |||
| }, | |||
| 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( | |||
| changeSelectedDevice.selectedDeviceName ?? | |||
| "Thiết bị", | |||
| style: TextStyle( | |||
| fontSize: 14.0, color: Colors.black87)))), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ))); | |||
| }); | |||
| } | |||
| Widget _dropdownUnitTypes() { | |||
| return GetBuilder<ChangeUnit>(builder: (data) { | |||
| return DropdownButtonFormField<String>( | |||
| itemHeight: 100, | |||
| value: data.selectedUnit.isEmpty ? null : data.selectedUnit, | |||
| items: data.currentUnits | |||
| .map((label) => DropdownMenuItem( | |||
| child: Text(label), | |||
| value: label, | |||
| )) | |||
| .toList(), | |||
| onChanged: (value) { | |||
| var currentQuantity = _quantityController.text; | |||
| num assignValue = currentQuantity.parseDoubleThousand(); | |||
| if (assignValue != null) { | |||
| var oldSelected = data.selectedUnit; | |||
| if (oldSelected == value) { | |||
| } else { | |||
| assignValue = UtilAction.convertUnit( | |||
| inputValue: assignValue, | |||
| oldUnit: oldSelected, | |||
| newUnit: value); | |||
| } | |||
| _quantityController.text = assignValue.formatNumtoStringDecimal(); | |||
| } | |||
| changeUnit.updateSelected(value); | |||
| }, | |||
| ); | |||
| }); | |||
| } | |||
| _quantityField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.numberWithOptions(decimal: true), | |||
| inputFormatters: [ | |||
| ThousandsFormatter( | |||
| formatter: NumberFormat("#,###.##", "es"), allowFraction: true) | |||
| ], | |||
| decoration: InputDecoration(labelText: "Tổng lượng sử dụng *"), | |||
| controller: _quantityController); | |||
| } | |||
| _buttonInForm() { | |||
| return GetBuilder<ChangeButtonInForm>(builder: (_) { | |||
| return Align( | |||
| alignment: Alignment.centerRight, | |||
| child: Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| children: [ | |||
| _.isEdit | |||
| ? OutlineButton( | |||
| shape: RoundedRectangleBorder( | |||
| borderRadius: new BorderRadius.circular(8.0)), | |||
| child: Text("Huỷ"), | |||
| onPressed: () { | |||
| changeButton.resetValue(); | |||
| _resetForm(); | |||
| _hidenKeyboard(context); | |||
| }) | |||
| : SizedBox(), | |||
| _.isEdit | |||
| ? FlatButton( | |||
| color: COLOR_CONST.DEFAULT, | |||
| shape: RoundedRectangleBorder( | |||
| borderRadius: new BorderRadius.circular(8.0)), | |||
| onPressed: () { | |||
| var currentSupply = changeSelectedSupply.currentSupply; | |||
| var currentDevice = changeSelectedDevice.currentDevice; | |||
| var currentQuantity = | |||
| _quantityController.text.parseDoubleThousand(); | |||
| if (currentSupply.id != null && currentQuantity > 0) { | |||
| var quantityWithCurrentSupplyUnit = | |||
| UtilAction.convertUnit( | |||
| inputValue: currentQuantity, | |||
| oldUnit: changeUnit.selectedUnit, | |||
| newUnit: | |||
| changeSelectedSupply.currentSupply.unit); | |||
| SuppliesUsing newSup = SuppliesUsing() | |||
| ..dosage = _dosageController.text | |||
| ..howToUse = _howToUseController.text | |||
| ..quantity = quantityWithCurrentSupplyUnit | |||
| ..tbSuppliesInWarehouseId = currentSupply.id | |||
| ..suppliesInWarehouseId = currentSupply.id | |||
| ..supplyName = currentSupply.tbSuppliesName | |||
| ..tbEquipmentOfCustomerId = currentDevice.id | |||
| ..equipmentOfCustomerId = currentDevice.id | |||
| ..equipmentName = currentDevice.name | |||
| ..supplyUnit = currentSupply.unit | |||
| ..unit = currentSupply.unit; | |||
| changeSupplyUsing.editSupply( | |||
| changeSupplyUsing.currentIndex, newSup); | |||
| _resetForm(); | |||
| _hidenKeyboard(context); | |||
| } | |||
| }, | |||
| child: Text( | |||
| "Sửa", | |||
| style: TextStyle(color: Colors.white), | |||
| )) | |||
| : FlatButton( | |||
| color: COLOR_CONST.DEFAULT, | |||
| shape: RoundedRectangleBorder( | |||
| borderRadius: new BorderRadius.circular(8.0)), | |||
| onPressed: () { | |||
| var currentSupply = changeSelectedSupply.currentSupply; | |||
| var currentDevice = changeSelectedDevice.currentDevice; | |||
| var currentQuantity = | |||
| _quantityController.text.parseDoubleThousand(); | |||
| if (currentSupply.id != null && currentQuantity > 0) { | |||
| var quantityWithCurrentSupplyUnit = | |||
| UtilAction.convertUnit( | |||
| inputValue: currentQuantity, | |||
| oldUnit: changeUnit.selectedUnit, | |||
| newUnit: | |||
| changeSelectedSupply.currentSupply.unit); | |||
| SuppliesUsing newSup = SuppliesUsing() | |||
| ..dosage = _dosageController.text | |||
| ..howToUse = _howToUseController.text | |||
| ..quantity = quantityWithCurrentSupplyUnit | |||
| ..tbSuppliesInWarehouseId = currentSupply.id | |||
| ..suppliesInWarehouseId = currentSupply.id | |||
| ..supplyName = currentSupply.tbSuppliesName | |||
| ..supplyUnit = currentSupply.unit | |||
| ..tbEquipmentOfCustomerId = currentDevice.id | |||
| ..equipmentOfCustomerId = currentDevice.id | |||
| ..equipmentName = currentDevice.name | |||
| ..unit = currentSupply.unit; | |||
| changeSupplyUsing.addSupply(newSup); | |||
| _resetForm(); | |||
| _hidenKeyboard(context); | |||
| } | |||
| }, | |||
| child: Text( | |||
| "Thêm", | |||
| style: TextStyle(color: Colors.white), | |||
| )) | |||
| ], | |||
| ), | |||
| ); | |||
| }); | |||
| } | |||
| Widget _formEdit() { | |||
| return Container( | |||
| padding: EdgeInsets.all(8.0), | |||
| decoration: BoxDecoration( | |||
| shape: BoxShape.rectangle, | |||
| borderRadius: BorderRadius.circular(10), | |||
| color: Colors.white, | |||
| border: Border.all(color: COLOR_CONST.DEFAULT)), | |||
| child: Column( | |||
| children: [ | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Hoá chất xử lý *", | |||
| style: TextStyle(color: Colors.black54, fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnSelectSubstrates(), | |||
| TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| controller: _dosageController, | |||
| decoration: InputDecoration(labelText: "Liều lượng sử dụng"), | |||
| onSaved: (newValue) {}, | |||
| ), | |||
| Row( | |||
| mainAxisSize: MainAxisSize.min, | |||
| mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |||
| crossAxisAlignment: CrossAxisAlignment.center, | |||
| children: [ | |||
| Expanded( | |||
| flex: 2, | |||
| child: Container( | |||
| height: 70, | |||
| child: _quantityField(), | |||
| ), | |||
| ), | |||
| SizedBox( | |||
| width: 16.0, | |||
| ), | |||
| Expanded( | |||
| flex: 1, | |||
| child: Align( | |||
| alignment: Alignment.bottomCenter, | |||
| child: _dropdownUnitTypes(), | |||
| )), | |||
| ]), | |||
| Container( | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Thiết bị", | |||
| style: TextStyle(color: Colors.black54, fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnSelectDevice(), | |||
| TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| controller: _howToUseController, | |||
| decoration: InputDecoration(labelText: "Phương pháp sử dụng"), | |||
| onSaved: (newValue) {}, | |||
| ), | |||
| _buttonInForm() | |||
| ], | |||
| )); | |||
| } | |||
| _resetForm() { | |||
| changeSupplyUsing.changeIndexEdit(-1); | |||
| changeButton.resetValue(); | |||
| _dosageController.text = ""; | |||
| _howToUseController.text = ""; | |||
| _quantityController.text = ""; | |||
| changeUnit.initValue(); | |||
| changeSelectedSupply.initValue(); | |||
| changeSelectedDevice.initValue(); | |||
| } | |||
| _hidenKeyboard(BuildContext context) { | |||
| FocusScopeNode currentFocus = FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Column( | |||
| children: [_formEdit(), _buildListSupply()], | |||
| ); | |||
| } | |||
| } | |||
| @@ -14,7 +14,6 @@ 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'; | |||
| @@ -8,6 +8,7 @@ import 'package:farm_tpf/presentation/screens/actions/dung/sc_edit_action_dung.d | |||
| import 'package:farm_tpf/presentation/screens/actions/end/sc_edit_action_end.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/environment_update/sc_edit_action_environment_update.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/harvest/sc_edit_action_harvest.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/harvest_process/sc_edit_action_harvest_process.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/nursery/sc_edit_action_nursery.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/other/sc_edit_action_other.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/packing/sc_edit_action_packing.dart'; | |||
| @@ -476,6 +477,12 @@ class ItemInfinityWidget extends StatelessWidget { | |||
| activityId: item.id, | |||
| isEdit: true, | |||
| )); | |||
| } else if (item.activityTypeName == "ACTIVE_TYPE_PROCESS") { | |||
| Get.to(EditActionHarvestProcessScreen( | |||
| cropId: item.cropId, | |||
| activityId: item.id, | |||
| isEdit: true, | |||
| )); | |||
| } else { | |||
| //TODO: Check other types | |||
| Get.to(EditActionOtherScreen( | |||
| @@ -18,6 +18,7 @@ class ConstCommon { | |||
| 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"; | |||
| @@ -71,6 +72,10 @@ class ConstCommon { | |||
| 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"; | |||