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.

451 lines
19KB

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