| @@ -2,35 +2,44 @@ import 'SuppliesUsing.dart'; | |||
| class Spraying { | |||
| int id; | |||
| int activityId; | |||
| int cropId; | |||
| String media; | |||
| String executeDate; | |||
| String description; | |||
| int quarantinePeriod; | |||
| String weatherConditions; | |||
| num quarantinePeriod; | |||
| String resultAt; | |||
| String weatherConditions; | |||
| String purpose; | |||
| String description; | |||
| String executeBy; | |||
| List<SuppliesUsing> suppliesUsing; | |||
| Spraying( | |||
| {this.id, | |||
| this.activityId, | |||
| this.cropId, | |||
| this.media, | |||
| this.executeDate, | |||
| this.description, | |||
| this.quarantinePeriod, | |||
| this.weatherConditions, | |||
| this.resultAt, | |||
| this.weatherConditions, | |||
| this.purpose, | |||
| this.description, | |||
| this.executeBy, | |||
| this.suppliesUsing}); | |||
| Spraying.fromJson(Map<String, dynamic> json) { | |||
| id = json['id']; | |||
| activityId = json['activityId']; | |||
| cropId = json['cropId']; | |||
| media = json['media']; | |||
| executeDate = json['executeDate']; | |||
| description = json['description']; | |||
| quarantinePeriod = json['quarantinePeriod']; | |||
| weatherConditions = json['weatherConditions']; | |||
| resultAt = json['resultAt']; | |||
| weatherConditions = json['weatherConditions']; | |||
| purpose = json['purpose']; | |||
| description = json['description']; | |||
| executeBy = json['executeBy']; | |||
| if (json['suppliesUsing'] != null) { | |||
| suppliesUsing = new List<SuppliesUsing>(); | |||
| json['suppliesUsing'].forEach((v) { | |||
| @@ -42,13 +51,16 @@ class Spraying { | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['id'] = this.id; | |||
| data['activityId'] = this.activityId; | |||
| data['cropId'] = this.cropId; | |||
| data['media'] = this.media; | |||
| data['executeDate'] = this.executeDate; | |||
| data['description'] = this.description; | |||
| data['quarantinePeriod'] = this.quarantinePeriod; | |||
| data['weatherConditions'] = this.weatherConditions; | |||
| data['resultAt'] = this.resultAt; | |||
| data['weatherConditions'] = this.weatherConditions; | |||
| data['purpose'] = this.purpose; | |||
| data['description'] = this.description; | |||
| data['executeBy'] = this.executeBy; | |||
| if (this.suppliesUsing != null) { | |||
| data['suppliesUsing'] = | |||
| this.suppliesUsing.map((v) => v.toJson()).toList(); | |||
| @@ -1,19 +1,416 @@ | |||
| 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/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/spraying/widget_spraying_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 '../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(); | |||
| 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_spraying), | |||
| ), | |||
| void initState() { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| _spraying.suppliesUsing = new List<SuppliesUsing>(); | |||
| var parsedExecuteDate = | |||
| DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime); | |||
| _spraying.executeDate = "$parsedExecuteDate"; | |||
| executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime); | |||
| _spraying.cropId = widget.cropId; | |||
| } | |||
| _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); | |||
| }); | |||
| _spraying.suppliesUsing = newSups; | |||
| var activitySpraying = jsonEncode(_spraying.toJson()).toString(); | |||
| //ADD NEW | |||
| if (_spraying.activityId == null) { | |||
| _repository.createAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Get.snackbar(label_add_success, "Hoạt động phun thuốc BVTV", | |||
| 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.apiAddSpraying, | |||
| paramActivity: ConstCommon.paramsActionSpraying, | |||
| activityAction: activitySpraying, | |||
| filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateAction((value) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Get.back(result: value); | |||
| Get.snackbar(label_update_success, "Hoạt động phun thuốc BVTV", | |||
| 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.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(() { | |||
| var parsedDate = | |||
| DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date); | |||
| _spraying.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 _purposeField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Lý do sử dụng"), | |||
| controller: _purposeController, | |||
| onSaved: (newValue) { | |||
| _spraying.purpose = newValue; | |||
| }, | |||
| ); | |||
| } | |||
| Widget _quarantinePeriodField() { | |||
| return TextFormField( | |||
| keyboardType: TextInputType.numberWithOptions(decimal: true), | |||
| inputFormatters: [ | |||
| ThousandsFormatter( | |||
| formatter: NumberFormat("#,###.##", "es"), allowFraction: true) | |||
| ], | |||
| decoration: InputDecoration(labelText: "Thời gian cách ly"), | |||
| controller: _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 TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration(labelText: "Ghi chú"), | |||
| 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) {}, | |||
| ); | |||
| } | |||
| _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_spraying), | |||
| actions: _actionAppBar()), | |||
| 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: 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); | |||
| _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; | |||
| try { | |||
| executeTime = | |||
| DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") | |||
| .parse(_spraying.executeDate); | |||
| } catch (_) {} | |||
| executeTimeView = | |||
| DateFormat("dd/MM/yyyy HH:mm") | |||
| .format(executeTime); | |||
| //Show media | |||
| if (_spraying.media != null) { | |||
| await UtilAction.cacheFiles(_spraying.media) | |||
| .then((value) { | |||
| BlocProvider.of<MediaHelperBloc>(context) | |||
| .add(ChangeListMedia(items: value)); | |||
| }).whenComplete(() { | |||
| print("completed"); | |||
| }); | |||
| } | |||
| //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: <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, | |||
| ), | |||
| _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, | |||
| ), | |||
| WidgetSprayingSupply( | |||
| 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() { | |||
| _quarantinePeriodController.dispose(); | |||
| _purposeController.dispose(); | |||
| _weatherController.dispose(); | |||
| _descriptionController.dispose(); | |||
| _executeByController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,466 @@ | |||
| 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 WidgetSprayingSupply extends StatefulWidget { | |||
| final List<SuppliesUsing> currentItems; | |||
| final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; | |||
| WidgetSprayingSupply({this.currentItems, @required this.onChangeSupplies}); | |||
| @override | |||
| _WidgetSprayingSupplyState createState() => _WidgetSprayingSupplyState(); | |||
| } | |||
| class _WidgetSprayingSupplyState extends State<WidgetSprayingSupply> { | |||
| 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: "Thuốc BVTV", | |||
| 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 ?? | |||
| "Tên thương mại", | |||
| 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( | |||
| "Tên thương mại *", | |||
| 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()], | |||
| ); | |||
| } | |||
| } | |||
| @@ -76,8 +76,12 @@ class _PlotActionScreenState extends State<PlotActionScreen> { | |||
| EditActionDungScreen( | |||
| cropId: widget.cropId, | |||
| ))); | |||
| actions.add( | |||
| ActionType(plot_action_spraying, null, EditActionSprayingScreen())); | |||
| actions.add(ActionType( | |||
| plot_action_spraying, | |||
| null, | |||
| EditActionSprayingScreen( | |||
| cropId: widget.cropId, | |||
| ))); | |||
| actions.add(ActionType( | |||
| plot_action_disease, | |||
| null, | |||
| @@ -466,6 +470,12 @@ class ItemInfinityWidget extends StatelessWidget { | |||
| activityId: item.id, | |||
| isEdit: true, | |||
| )); | |||
| } else if (item.activityTypeName == "ACTIVE_TYPE_SPRAY") { | |||
| Get.to(EditActionSprayingScreen( | |||
| cropId: item.cropId, | |||
| activityId: item.id, | |||
| isEdit: true, | |||
| )); | |||
| } else { | |||
| //TODO: Check other types | |||
| Get.to(EditActionOtherScreen( | |||
| @@ -17,6 +17,7 @@ class ConstCommon { | |||
| 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"; | |||
| //nursery | |||
| static const String paramsActionNursery = "activityNursery"; | |||
| @@ -66,6 +67,10 @@ class ConstCommon { | |||
| 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"; | |||
| static const String supplyTypeSeed = "GIONG"; | |||
| static const String supplyTypeDung = "PHANBON"; | |||