You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

420 lines
16KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/Disease.dart';
  3. import 'package:farm_tpf/custom_model/RequestDisease.dart';
  4. import 'package:farm_tpf/data/api/app_exception.dart';
  5. import 'package:farm_tpf/data/repository/repository.dart';
  6. import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
  7. import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart';
  8. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  10. import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart';
  11. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  12. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  13. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  14. import 'package:farm_tpf/utils/const_common.dart';
  15. import 'package:farm_tpf/utils/const_string.dart';
  16. import 'package:farm_tpf/utils/const_style.dart';
  17. import 'package:farm_tpf/utils/pref.dart';
  18. import 'package:farm_tpf/utils/validators.dart';
  19. import 'package:flutter/material.dart';
  20. import 'package:flutter_bloc/flutter_bloc.dart';
  21. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  22. import 'package:get/get.dart';
  23. import 'package:intl/intl.dart';
  24. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  25. import 'package:pattern_formatter/pattern_formatter.dart';
  26. import 'package:farm_tpf/utils/formatter.dart';
  27. import '../util_action.dart';
  28. class EditActionDiseaseScreen extends StatefulWidget {
  29. final int cropId;
  30. final bool isEdit;
  31. final int activityId;
  32. EditActionDiseaseScreen(
  33. {@required this.cropId, this.isEdit = false, this.activityId});
  34. @override
  35. _EditActionDiseaseScreenState createState() =>
  36. _EditActionDiseaseScreenState();
  37. }
  38. class _EditActionDiseaseScreenState extends State<EditActionDiseaseScreen> {
  39. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  40. final _repository = Repository();
  41. GlobalKey<FormState> _formKey = GlobalKey();
  42. bool _autoValidate = false;
  43. Disease _disease = Disease();
  44. var pref = LocalPref();
  45. TextEditingController _typesOfPestController = TextEditingController();
  46. TextEditingController _numTreeController = TextEditingController();
  47. TextEditingController _harmLevelController = TextEditingController();
  48. TextEditingController _treePercentController = TextEditingController();
  49. TextEditingController _locationController = TextEditingController();
  50. TextEditingController _naturalEnemyController = TextEditingController();
  51. TextEditingController _treatmentMeasuresController = TextEditingController();
  52. TextEditingController _descriptionController = TextEditingController();
  53. final _executeByController = TextEditingController();
  54. DateTime executeTime = DateTime.now();
  55. List<String> filePaths = List<String>();
  56. var changeFileController = Get.put(ChangeFileController());
  57. Future<Null> getSharedPrefs() async {
  58. var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  59. _executeByController.text = currentFullName ?? "";
  60. }
  61. @override
  62. void initState() {
  63. super.initState();
  64. getSharedPrefs();
  65. changeFileController.initValue();
  66. _disease.cropId = widget.cropId;
  67. }
  68. _validateInputs() async {
  69. if (_formKey.currentState.validate()) {
  70. _formKey.currentState.save();
  71. LoadingDialog.showLoadingDialog(context);
  72. filePaths = Get.find<ChangeFileController>().newFiles;
  73. //Create request general model
  74. try {
  75. RequestDisease requestDisease = RequestDisease()
  76. ..cropId = _disease.cropId
  77. ..activityId = _disease.activityId
  78. ..description = _disease.description
  79. ..executeDate = _disease.executeDate;
  80. var generalDetail = List<ObjectUpdateDetail>();
  81. generalDetail.add(ObjectUpdateDetail()
  82. ..name = "LOAI_DICH_HAI"
  83. ..index = _disease.typesOfPest);
  84. generalDetail.add(ObjectUpdateDetail()
  85. ..name = "MUC_DO_GAY_HAI"
  86. ..index = _disease.harmLevel);
  87. generalDetail.add(ObjectUpdateDetail()
  88. ..name = "PHAN_TRAM_CAY"
  89. ..index = _disease.treePercent);
  90. generalDetail.add(ObjectUpdateDetail()
  91. ..name = "VI_TRI"
  92. ..index = _disease.location);
  93. generalDetail.add(ObjectUpdateDetail()
  94. ..name = "THIEN_DICH"
  95. ..index = _disease.naturalEnemy);
  96. generalDetail.add(ObjectUpdateDetail()
  97. ..name = "BIEN_PHAP_XU_LY"
  98. ..index = _disease.treatmentMeasures);
  99. requestDisease.objectUpdateDetail = generalDetail;
  100. requestDisease.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  101. var activityDisease = jsonEncode(requestDisease.toJson()).toString();
  102. //ADD NEW
  103. if (_disease.activityId == null) {
  104. _repository.createAction((value) {
  105. LoadingDialog.hideLoadingDialog(context);
  106. Get.back(result: value);
  107. Utils.showSnackBarSuccess(message: label_add_success);
  108. }, (error) {
  109. LoadingDialog.hideLoadingDialog(context);
  110. Utils.showSnackBarError(message: AppException.handleError(error));
  111. },
  112. apiAddAction: ConstCommon.apiAddDisease,
  113. paramActivity: ConstCommon.paramsActionDisease,
  114. activityAction: activityDisease,
  115. filePaths: filePaths);
  116. } else {
  117. //UPDATE
  118. _repository.updateAction((value) {
  119. LoadingDialog.hideLoadingDialog(context);
  120. Get.back(result: value);
  121. Utils.showSnackBarSuccess(message: label_update_success);
  122. }, (error) {
  123. LoadingDialog.hideLoadingDialog(context);
  124. Utils.showSnackBarError(message: AppException.handleError(error));
  125. },
  126. apiUpdateAction: ConstCommon.apiUpdateDisease,
  127. paramActivity: ConstCommon.paramsActionDisease,
  128. activityAction: activityDisease,
  129. filePaths: filePaths);
  130. }
  131. } catch (e) {
  132. LoadingDialog.hideLoadingDialog(context);
  133. print(e.toString());
  134. }
  135. } else {
  136. _autoValidate = true;
  137. }
  138. }
  139. Widget _btnExecuteTimePicker() {
  140. return WidgetFieldDateTimePicker(
  141. initDateTime: executeTime,
  142. onUpdateDateTime: (selectedDate) {
  143. _disease.executeDate =
  144. selectedDate.convertLocalDateTimeToStringUtcDateTime();
  145. });
  146. }
  147. Widget _typeOfPestField() {
  148. return TextFormField(
  149. keyboardType: TextInputType.text,
  150. decoration: InputDecoration(labelText: "Loại dịch hại *"),
  151. controller: _typesOfPestController,
  152. validator: (String value) {
  153. return Validators.validateNotNullOrEmpty(value, "Loại dịch hại");
  154. },
  155. onSaved: (newValue) {
  156. _disease.typesOfPest = newValue;
  157. },
  158. );
  159. }
  160. Widget _harmLevelField() {
  161. return TextFormField(
  162. keyboardType: TextInputType.text,
  163. decoration: InputDecoration(labelText: "Mức độ gây hại"),
  164. controller: _harmLevelController,
  165. onSaved: (newValue) {
  166. _disease.harmLevel = newValue;
  167. },
  168. );
  169. }
  170. Widget _treePercentField() {
  171. return WidgetTextFormFieldNumber(
  172. hintValue: "% cây",
  173. textController: _treePercentController,
  174. onSaved: (newValue) {
  175. _disease.treePercent = newValue;
  176. },
  177. );
  178. }
  179. Widget _locationField() {
  180. return TextFormField(
  181. keyboardType: TextInputType.text,
  182. decoration: InputDecoration(labelText: "Vị trí"),
  183. controller: _locationController,
  184. onSaved: (newValue) {
  185. _disease.location = newValue;
  186. },
  187. );
  188. }
  189. Widget _naturalEnemyField() {
  190. return TextFormField(
  191. keyboardType: TextInputType.text,
  192. decoration: InputDecoration(labelText: "Thiên địch"),
  193. controller: _naturalEnemyController,
  194. onSaved: (newValue) {
  195. _disease.naturalEnemy = newValue;
  196. },
  197. );
  198. }
  199. Widget _treatmentMeasuresField() {
  200. return TextFormField(
  201. keyboardType: TextInputType.text,
  202. decoration: InputDecoration(labelText: "Biện pháp xử lý"),
  203. controller: _treatmentMeasuresController,
  204. onSaved: (newValue) {
  205. _disease.treatmentMeasures = newValue;
  206. },
  207. );
  208. }
  209. Widget _descriptionField() {
  210. return TextFormField(
  211. keyboardType: TextInputType.text,
  212. decoration: InputDecoration(labelText: "Ghi chú"),
  213. controller: _descriptionController,
  214. onSaved: (newValue) {
  215. _disease.description = newValue;
  216. },
  217. );
  218. }
  219. Widget _executeByField() {
  220. return TextFormField(
  221. keyboardType: TextInputType.text,
  222. decoration: InputDecoration(labelText: "Người thực hiện"),
  223. enabled: false,
  224. controller: _executeByController,
  225. onSaved: (newValue) {},
  226. );
  227. }
  228. _actionAppBar() {
  229. IconButton iconButton;
  230. if (1 == 1) {
  231. iconButton = IconButton(
  232. icon: Icon(
  233. Icons.done,
  234. color: Colors.black,
  235. ),
  236. onPressed: () {
  237. FocusScopeNode currentFocus = FocusScope.of(context);
  238. if (!currentFocus.hasPrimaryFocus) {
  239. currentFocus.unfocus();
  240. }
  241. _validateInputs();
  242. },
  243. );
  244. return <Widget>[iconButton];
  245. }
  246. return <Widget>[Container()];
  247. }
  248. @override
  249. Widget build(BuildContext context) => KeyboardDismisser(
  250. gestures: [
  251. GestureType.onTap,
  252. GestureType.onPanUpdateDownDirection,
  253. ],
  254. child: Scaffold(
  255. key: _scaffoldKey,
  256. appBar: AppBar(
  257. centerTitle: true,
  258. title: Text(plot_action_disease),
  259. actions: _actionAppBar()),
  260. body: KeyboardDismisser(
  261. child: MultiBlocProvider(
  262. providers: [
  263. BlocProvider<ActionDetailBloc>(
  264. create: (context) =>
  265. ActionDetailBloc(repository: Repository())
  266. ..add(FetchData(
  267. isNeedFetchData: widget.isEdit,
  268. apiActivity: ConstCommon.apiDetailDisease,
  269. activityId: widget.activityId))),
  270. BlocProvider<MediaHelperBloc>(
  271. create: (context) =>
  272. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  273. )
  274. ],
  275. child: Form(
  276. key: _formKey,
  277. autovalidate: _autoValidate,
  278. child: SingleChildScrollView(
  279. padding: EdgeInsets.all(8.0),
  280. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  281. listener: (context, state) async {
  282. if (state is ActionDetailFailure) {
  283. LoadingDialog.hideLoadingDialog(context);
  284. } else if (state is ActionDetailSuccess) {
  285. LoadingDialog.hideLoadingDialog(context);
  286. print(state.item);
  287. _disease = Disease.fromJson(state.item);
  288. _disease.activityId = widget.activityId;
  289. _typesOfPestController.text =
  290. _disease.typesOfPest ?? "";
  291. _harmLevelController.text =
  292. _disease.harmLevel ?? "";
  293. _treePercentController.text = _disease.treePercent
  294. .formatStringToStringDecimal();
  295. _locationController.text = _disease.location ?? "";
  296. _naturalEnemyController.text =
  297. _disease.naturalEnemy ?? "";
  298. _treatmentMeasuresController.text =
  299. _disease.treatmentMeasures ?? "";
  300. _descriptionController.text =
  301. _disease.description ?? "";
  302. _executeByController.text = _disease.executeBy;
  303. Get.find<ChangeDateTimePicker>().change(_disease
  304. .executeDate
  305. .convertStringServerDateTimeToLocalDateTime());
  306. //Show media
  307. if (Validators.stringNotNullOrEmpty(
  308. _disease.media)) {
  309. BlocProvider.of<MediaHelperBloc>(context).add(
  310. ChangeListMedia(
  311. items: UtilAction.convertFilePathToMedia(
  312. _disease.media)));
  313. }
  314. } else if (state is ActionDetailInitial) {
  315. } else if (state is ActionDetailLoading) {
  316. LoadingDialog.showLoadingDialog(context);
  317. }
  318. },
  319. builder: (context, state) {
  320. return Column(
  321. children: <Widget>[
  322. Container(
  323. width: double.infinity,
  324. child: Text(
  325. "Ngày thực hiện *",
  326. style: TextStyle(
  327. color: Colors.black54, fontSize: 13.0),
  328. ),
  329. ),
  330. _btnExecuteTimePicker(),
  331. SizedBox(
  332. height: 8.0,
  333. ),
  334. _typeOfPestField(),
  335. SizedBox(
  336. height: 8.0,
  337. ),
  338. _harmLevelField(),
  339. SizedBox(
  340. height: 8.0,
  341. ),
  342. _treePercentField(),
  343. SizedBox(
  344. height: 8.0,
  345. ),
  346. _locationField(),
  347. SizedBox(
  348. height: 8.0,
  349. ),
  350. _naturalEnemyField(),
  351. SizedBox(
  352. height: 8.0,
  353. ),
  354. _treatmentMeasuresField(),
  355. SizedBox(
  356. height: 8.0,
  357. ),
  358. _descriptionField(),
  359. SizedBox(
  360. height: 8.0,
  361. ),
  362. _executeByField(),
  363. SizedBox(
  364. height: 8.0,
  365. ),
  366. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  367. builder: (context, state) {
  368. if (state is MediaHelperSuccess) {
  369. return WidgetMediaPicker(
  370. currentItems: state.items,
  371. onChangeFiles: (newPathFiles,
  372. deletePathFiles) async {
  373. Get.find<ChangeFileController>().change(
  374. newPathFiles, deletePathFiles);
  375. });
  376. } else {
  377. return Center(
  378. child: CircularProgressIndicator());
  379. }
  380. }),
  381. ],
  382. );
  383. },
  384. ),
  385. )),
  386. ))));
  387. @override
  388. void dispose() {
  389. _typesOfPestController.dispose();
  390. _harmLevelController.dispose();
  391. _treePercentController.dispose();
  392. _locationController.dispose();
  393. _naturalEnemyController.dispose();
  394. _treatmentMeasuresController.dispose();
  395. _descriptionController.dispose();
  396. _executeByController.dispose();
  397. super.dispose();
  398. }
  399. }