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.

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