|
|
|
@@ -1,18 +1,36 @@ |
|
|
|
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/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/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:fluttertoast/fluttertoast.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(); |
|
|
|
@@ -26,24 +44,25 @@ class _EditActionCropStatusScreenState |
|
|
|
bool _autoValidate = false; |
|
|
|
CropStatus _cropStatus = CropStatus(); |
|
|
|
var pref = LocalPref(); |
|
|
|
FlutterToast flutterToast; |
|
|
|
TextEditingController _cropRateController = TextEditingController(); |
|
|
|
TextEditingController _numTreeController = TextEditingController(); |
|
|
|
TextEditingController _hightOfTreeController = TextEditingController(); |
|
|
|
TextEditingController _heightOfTreeController = TextEditingController(); |
|
|
|
TextEditingController _numberOfLeafController = TextEditingController(); |
|
|
|
TextEditingController _leafSizeController = TextEditingController(); |
|
|
|
TextEditingController _leafColorController = TextEditingController(); |
|
|
|
TextEditingController _abilityProduceBudsController = TextEditingController(); |
|
|
|
TextEditingController _bodySizeController = TextEditingController(); |
|
|
|
TextEditingController _internodeLengthController = TextEditingController(); |
|
|
|
TextEditingController _descriptionController = TextEditingController(); |
|
|
|
|
|
|
|
String executeTimeView; |
|
|
|
DateTime executeTime = DateTime.now(); |
|
|
|
List<String> filePaths = List<String>(); |
|
|
|
var changeFileController = Get.put(ChangeFileController()); |
|
|
|
|
|
|
|
@override |
|
|
|
void initState() { |
|
|
|
super.initState(); |
|
|
|
flutterToast = FlutterToast(context); |
|
|
|
changeFileController.initValue(); |
|
|
|
//UPDATE |
|
|
|
if (_cropStatus != null) { |
|
|
|
try { |
|
|
|
@@ -57,6 +76,107 @@ class _EditActionCropStatusScreenState |
|
|
|
_cropStatus.executeDate = "$parsedExecuteDate"; |
|
|
|
} |
|
|
|
executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime); |
|
|
|
_cropStatus.cropId = widget.cropId; |
|
|
|
} |
|
|
|
|
|
|
|
_validateInputs() async { |
|
|
|
if (_formKey.currentState.validate()) { |
|
|
|
_formKey.currentState.save(); |
|
|
|
LoadingDialog.showLoadingDialog(context); |
|
|
|
filePaths = Get.find<ChangeFileController>().files; |
|
|
|
//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; |
|
|
|
var activityCropStatus = jsonEncode(generalModel.toJson()).toString(); |
|
|
|
// var activityCropStatus = jsonEncode(_cropStatus.toJson()).toString(); |
|
|
|
//ADD NEW |
|
|
|
if (_cropStatus.activityId == null) { |
|
|
|
_repository.createAction((value) { |
|
|
|
LoadingDialog.hideLoadingDialog(context); |
|
|
|
Get.back(result: value); |
|
|
|
Get.snackbar(label_add_success, "Hoạt động thực trạng cây trồng", |
|
|
|
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.apiAddCropStatus, |
|
|
|
paramActivity: ConstCommon.paramsActionCropStatus, |
|
|
|
activityAction: activityCropStatus, |
|
|
|
filePaths: filePaths); |
|
|
|
} else { |
|
|
|
//UPDATE |
|
|
|
_repository.updateAction((value) { |
|
|
|
LoadingDialog.hideLoadingDialog(context); |
|
|
|
Get.back(result: value); |
|
|
|
Get.snackbar(label_update_success, "Hoạt động thực trạng cây trồng", |
|
|
|
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.apiUpdateCropStatus, |
|
|
|
paramActivity: ConstCommon.paramsActionCropStatus, |
|
|
|
activityAction: activityCropStatus, |
|
|
|
filePaths: filePaths); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
LoadingDialog.hideLoadingDialog(context); |
|
|
|
print(e.toString()); |
|
|
|
} |
|
|
|
} else { |
|
|
|
_autoValidate = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Widget _btnExecuteTimePicker() { |
|
|
|
@@ -108,7 +228,7 @@ class _EditActionCropStatusScreenState |
|
|
|
return Validators.validNumber(value, "Tỉ lệ lên cây"); |
|
|
|
}, |
|
|
|
onSaved: (newValue) { |
|
|
|
_cropStatus.cropRate = newValue.parseDoubleThousand(); |
|
|
|
_cropStatus.cropRate = newValue; |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
@@ -126,7 +246,7 @@ class _EditActionCropStatusScreenState |
|
|
|
return Validators.validNumber(value, "Số lượng lên cây"); |
|
|
|
}, |
|
|
|
onSaved: (newValue) { |
|
|
|
_cropStatus.numberOfTreeToGrow = newValue.parseDoubleThousand(); |
|
|
|
_cropStatus.numberOfTreeToGrow = newValue; |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
@@ -139,12 +259,12 @@ class _EditActionCropStatusScreenState |
|
|
|
formatter: NumberFormat("#,###.##", "es"), allowFraction: true) |
|
|
|
], |
|
|
|
decoration: InputDecoration(labelText: "Chiều cao cây"), |
|
|
|
controller: _hightOfTreeController, |
|
|
|
controller: _heightOfTreeController, |
|
|
|
validator: (String value) { |
|
|
|
return Validators.validNumber(value, "Chiều cao cây"); |
|
|
|
}, |
|
|
|
onSaved: (newValue) { |
|
|
|
_cropStatus.hightOfTree = newValue.parseDoubleThousand(); |
|
|
|
_cropStatus.heightOfTree = newValue; |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
@@ -162,7 +282,7 @@ class _EditActionCropStatusScreenState |
|
|
|
return Validators.validNumber(value, "Số lá"); |
|
|
|
}, |
|
|
|
onSaved: (newValue) { |
|
|
|
_cropStatus.numberOfLeaf = newValue.parseDoubleThousand(); |
|
|
|
_cropStatus.numberOfLeaf = newValue; |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
@@ -180,7 +300,7 @@ class _EditActionCropStatusScreenState |
|
|
|
return Validators.validNumber(value, "Kích thước lá"); |
|
|
|
}, |
|
|
|
onSaved: (newValue) { |
|
|
|
_cropStatus.leafSize = newValue.parseDoubleThousand(); |
|
|
|
_cropStatus.leafSize = newValue; |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
@@ -196,7 +316,7 @@ class _EditActionCropStatusScreenState |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget _bodySizeField() { |
|
|
|
Widget _internodeLengthField() { |
|
|
|
return TextFormField( |
|
|
|
keyboardType: TextInputType.numberWithOptions(decimal: true), |
|
|
|
inputFormatters: [ |
|
|
|
@@ -204,12 +324,12 @@ class _EditActionCropStatusScreenState |
|
|
|
formatter: NumberFormat("#,###.##", "es"), allowFraction: true) |
|
|
|
], |
|
|
|
decoration: InputDecoration(labelText: "Dài đốt thân"), |
|
|
|
controller: _bodySizeController, |
|
|
|
controller: _internodeLengthController, |
|
|
|
validator: (String value) { |
|
|
|
return Validators.validNumber(value, "Dài đốt thân"); |
|
|
|
}, |
|
|
|
onSaved: (newValue) { |
|
|
|
_cropStatus.bodySize = newValue.parseDoubleThousand(); |
|
|
|
_cropStatus.internodeLength = newValue; |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
@@ -231,7 +351,7 @@ class _EditActionCropStatusScreenState |
|
|
|
decoration: InputDecoration(labelText: "Ghi chú"), |
|
|
|
controller: _descriptionController, |
|
|
|
onSaved: (newValue) { |
|
|
|
_cropStatus.note = newValue; |
|
|
|
_cropStatus.description = newValue; |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
@@ -244,7 +364,13 @@ class _EditActionCropStatusScreenState |
|
|
|
Icons.done, |
|
|
|
color: Colors.black, |
|
|
|
), |
|
|
|
onPressed: () {}, |
|
|
|
onPressed: () { |
|
|
|
FocusScopeNode currentFocus = FocusScope.of(context); |
|
|
|
if (!currentFocus.hasPrimaryFocus) { |
|
|
|
currentFocus.unfocus(); |
|
|
|
} |
|
|
|
_validateInputs(); |
|
|
|
}, |
|
|
|
); |
|
|
|
return <Widget>[iconButton]; |
|
|
|
} |
|
|
|
@@ -264,71 +390,164 @@ class _EditActionCropStatusScreenState |
|
|
|
title: Text(plot_action_crop_status), |
|
|
|
actions: _actionAppBar()), |
|
|
|
body: KeyboardDismisser( |
|
|
|
child: Form( |
|
|
|
key: _formKey, |
|
|
|
autovalidate: _autoValidate, |
|
|
|
child: SingleChildScrollView( |
|
|
|
padding: 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), |
|
|
|
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: SingleChildScrollView( |
|
|
|
padding: EdgeInsets.all(8.0), |
|
|
|
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 ?? ""; |
|
|
|
|
|
|
|
try { |
|
|
|
executeTime = |
|
|
|
DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") |
|
|
|
.parse(_cropStatus.executeDate); |
|
|
|
} catch (_) {} |
|
|
|
executeTimeView = DateFormat("dd/MM/yyyy HH:mm") |
|
|
|
.format(executeTime); |
|
|
|
//Show media |
|
|
|
if (_cropStatus.media != null) { |
|
|
|
await UtilAction.cacheFiles(_cropStatus.media) |
|
|
|
.then((value) { |
|
|
|
print("then: ${value.length}"); |
|
|
|
BlocProvider.of<MediaHelperBloc>(context) |
|
|
|
.add(ChangeListMedia(items: value)); |
|
|
|
}).whenComplete(() { |
|
|
|
print("completed"); |
|
|
|
}); |
|
|
|
} |
|
|
|
} 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, |
|
|
|
), |
|
|
|
_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, |
|
|
|
), |
|
|
|
), |
|
|
|
_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, |
|
|
|
), |
|
|
|
_bodySizeField(), |
|
|
|
SizedBox( |
|
|
|
height: 8.0, |
|
|
|
), |
|
|
|
_abilityProduceBudsField(), |
|
|
|
SizedBox( |
|
|
|
height: 8.0, |
|
|
|
), |
|
|
|
_desciptionField() |
|
|
|
], |
|
|
|
), |
|
|
|
))))); |
|
|
|
_desciptionField(), |
|
|
|
BlocBuilder<MediaHelperBloc, MediaHelperState>( |
|
|
|
builder: (context, state) { |
|
|
|
if (state is MediaHelperSuccess) { |
|
|
|
print("length: " + |
|
|
|
state.items.length.toString()); |
|
|
|
return WidgetMediaPicker( |
|
|
|
currentItems: state.items, |
|
|
|
onChangeFiles: (filePaths) async { |
|
|
|
Get.find<ChangeFileController>() |
|
|
|
.addAllFile(filePaths); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
return Center( |
|
|
|
child: CircularProgressIndicator()); |
|
|
|
} |
|
|
|
}), |
|
|
|
], |
|
|
|
); |
|
|
|
}, |
|
|
|
), |
|
|
|
)), |
|
|
|
)))); |
|
|
|
@override |
|
|
|
void dispose() { |
|
|
|
_cropRateController.dispose(); |
|
|
|
_numTreeController.dispose(); |
|
|
|
_hightOfTreeController.dispose(); |
|
|
|
_heightOfTreeController.dispose(); |
|
|
|
_numberOfLeafController.dispose(); |
|
|
|
_leafSizeController.dispose(); |
|
|
|
_leafColorController.dispose(); |
|
|
|
_abilityProduceBudsController.dispose(); |
|
|
|
_bodySizeController.dispose(); |
|
|
|
_internodeLengthController.dispose(); |
|
|
|
_descriptionController.dispose(); |
|
|
|
super.dispose(); |
|
|
|
} |