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.

455 lines
18KB

  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_loading.dart';
  8. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart';
  10. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  11. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  12. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  13. import 'package:farm_tpf/utils/const_common.dart';
  14. import 'package:farm_tpf/utils/const_string.dart';
  15. import 'package:farm_tpf/utils/const_style.dart';
  16. import 'package:farm_tpf/utils/pref.dart';
  17. import 'package:farm_tpf/utils/validators.dart';
  18. import 'package:flutter/material.dart';
  19. import 'package:flutter_bloc/flutter_bloc.dart';
  20. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  21. import 'package:get/get.dart';
  22. import 'package:intl/intl.dart';
  23. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  24. import 'package:pattern_formatter/pattern_formatter.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. String executeTimeView;
  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. var parsedExecuteDate =
  67. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  68. _disease.executeDate = "$parsedExecuteDate";
  69. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  70. _disease.cropId = widget.cropId;
  71. }
  72. _validateInputs() async {
  73. if (_formKey.currentState.validate()) {
  74. _formKey.currentState.save();
  75. LoadingDialog.showLoadingDialog(context);
  76. filePaths = Get.find<ChangeFileController>().newFiles;
  77. //Create request general model
  78. try {
  79. RequestDisease requestDisease = RequestDisease()
  80. ..cropId = _disease.cropId
  81. ..activityId = _disease.activityId
  82. ..description = _disease.description
  83. ..executeDate = _disease.executeDate;
  84. var generalDetail = List<ObjectUpdateDetail>();
  85. generalDetail.add(ObjectUpdateDetail()
  86. ..name = "LOAI_DICH_HAI"
  87. ..index = _disease.typesOfPest);
  88. generalDetail.add(ObjectUpdateDetail()
  89. ..name = "MUC_DO_GAY_HAI"
  90. ..index = _disease.harmLevel);
  91. generalDetail.add(ObjectUpdateDetail()
  92. ..name = "PHAN_TRAM_CAY"
  93. ..index = _disease.treePercent);
  94. generalDetail.add(ObjectUpdateDetail()
  95. ..name = "VI_TRI"
  96. ..index = _disease.location);
  97. generalDetail.add(ObjectUpdateDetail()
  98. ..name = "THIEN_DICH"
  99. ..index = _disease.naturalEnemy);
  100. generalDetail.add(ObjectUpdateDetail()
  101. ..name = "BIEN_PHAP_XU_LY"
  102. ..index = _disease.treatmentMeasures);
  103. requestDisease.objectUpdateDetail = generalDetail;
  104. requestDisease.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  105. var activityDisease = jsonEncode(requestDisease.toJson()).toString();
  106. //ADD NEW
  107. if (_disease.activityId == null) {
  108. _repository.createAction((value) {
  109. LoadingDialog.hideLoadingDialog(context);
  110. Get.back(result: value);
  111. Utils.showSnackBarSuccess(message: label_add_success);
  112. }, (error) {
  113. LoadingDialog.hideLoadingDialog(context);
  114. Utils.showSnackBarError(message: AppException.handleError(error));
  115. },
  116. apiAddAction: ConstCommon.apiAddDisease,
  117. paramActivity: ConstCommon.paramsActionDisease,
  118. activityAction: activityDisease,
  119. filePaths: filePaths);
  120. } else {
  121. //UPDATE
  122. _repository.updateAction((value) {
  123. LoadingDialog.hideLoadingDialog(context);
  124. Get.back(result: value);
  125. Utils.showSnackBarSuccess(message: label_update_success);
  126. }, (error) {
  127. LoadingDialog.hideLoadingDialog(context);
  128. Utils.showSnackBarError(message: AppException.handleError(error));
  129. },
  130. apiUpdateAction: ConstCommon.apiUpdateDisease,
  131. paramActivity: ConstCommon.paramsActionDisease,
  132. activityAction: activityDisease,
  133. filePaths: filePaths);
  134. }
  135. } catch (e) {
  136. LoadingDialog.hideLoadingDialog(context);
  137. print(e.toString());
  138. }
  139. } else {
  140. _autoValidate = true;
  141. }
  142. }
  143. Widget _btnExecuteTimePicker() {
  144. return FlatButton(
  145. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  146. onPressed: () {
  147. DatePicker.showDateTimePicker(context,
  148. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  149. setState(() {
  150. var parsedDate =
  151. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  152. _disease.executeDate = "$parsedDate";
  153. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  154. });
  155. }, currentTime: executeTime, locale: LocaleType.vi);
  156. },
  157. child: Container(
  158. padding:
  159. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  160. decoration: BoxDecoration(
  161. border: kBorderTextField,
  162. ),
  163. child: Row(
  164. children: [
  165. Expanded(
  166. child: Text(
  167. //TODO: check condition
  168. executeTimeView == null ? "$executeTime" : executeTimeView,
  169. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  170. )),
  171. Icon(
  172. Icons.date_range,
  173. color: Colors.blue,
  174. ),
  175. ],
  176. )));
  177. }
  178. Widget _typeOfPestField() {
  179. return TextFormField(
  180. keyboardType: TextInputType.text,
  181. decoration: InputDecoration(labelText: "Loại dịch hại *"),
  182. controller: _typesOfPestController,
  183. validator: (String value) {
  184. return Validators.validateNotNullOrEmpty(value, "Loại dịch hại");
  185. },
  186. onSaved: (newValue) {
  187. _disease.typesOfPest = newValue;
  188. },
  189. );
  190. }
  191. Widget _harmLevelField() {
  192. return TextFormField(
  193. keyboardType: TextInputType.text,
  194. decoration: InputDecoration(labelText: "Mức độ gây hại"),
  195. controller: _harmLevelController,
  196. onSaved: (newValue) {
  197. _disease.harmLevel = newValue;
  198. },
  199. );
  200. }
  201. Widget _treePercentField() {
  202. return WidgetTextFormFieldNumber(
  203. hintValue: "% cây",
  204. textController: _treePercentController,
  205. onSaved: (newValue) {
  206. _disease.treePercent = newValue;
  207. },
  208. );
  209. }
  210. Widget _locationField() {
  211. return TextFormField(
  212. keyboardType: TextInputType.text,
  213. decoration: InputDecoration(labelText: "Vị trí"),
  214. controller: _locationController,
  215. onSaved: (newValue) {
  216. _disease.location = newValue;
  217. },
  218. );
  219. }
  220. Widget _naturalEnemyField() {
  221. return TextFormField(
  222. keyboardType: TextInputType.text,
  223. decoration: InputDecoration(labelText: "Thiên địch"),
  224. controller: _naturalEnemyController,
  225. onSaved: (newValue) {
  226. _disease.naturalEnemy = newValue;
  227. },
  228. );
  229. }
  230. Widget _treatmentMeasuresField() {
  231. return TextFormField(
  232. keyboardType: TextInputType.text,
  233. decoration: InputDecoration(labelText: "Biện pháp xử lý"),
  234. controller: _treatmentMeasuresController,
  235. onSaved: (newValue) {
  236. _disease.treatmentMeasures = newValue;
  237. },
  238. );
  239. }
  240. Widget _descriptionField() {
  241. return TextFormField(
  242. keyboardType: TextInputType.text,
  243. decoration: InputDecoration(labelText: "Ghi chú"),
  244. controller: _descriptionController,
  245. onSaved: (newValue) {
  246. _disease.description = newValue;
  247. },
  248. );
  249. }
  250. Widget _executeByField() {
  251. return TextFormField(
  252. keyboardType: TextInputType.text,
  253. decoration: InputDecoration(labelText: "Người thực hiện"),
  254. enabled: false,
  255. controller: _executeByController,
  256. onSaved: (newValue) {},
  257. );
  258. }
  259. _actionAppBar() {
  260. IconButton iconButton;
  261. if (1 == 1) {
  262. iconButton = IconButton(
  263. icon: Icon(
  264. Icons.done,
  265. color: Colors.black,
  266. ),
  267. onPressed: () {
  268. FocusScopeNode currentFocus = FocusScope.of(context);
  269. if (!currentFocus.hasPrimaryFocus) {
  270. currentFocus.unfocus();
  271. }
  272. _validateInputs();
  273. },
  274. );
  275. return <Widget>[iconButton];
  276. }
  277. return <Widget>[Container()];
  278. }
  279. @override
  280. Widget build(BuildContext context) => KeyboardDismisser(
  281. gestures: [
  282. GestureType.onTap,
  283. GestureType.onPanUpdateDownDirection,
  284. ],
  285. child: Scaffold(
  286. key: _scaffoldKey,
  287. appBar: AppBar(
  288. centerTitle: true,
  289. title: Text(plot_action_disease),
  290. actions: _actionAppBar()),
  291. body: KeyboardDismisser(
  292. child: MultiBlocProvider(
  293. providers: [
  294. BlocProvider<ActionDetailBloc>(
  295. create: (context) =>
  296. ActionDetailBloc(repository: Repository())
  297. ..add(FetchData(
  298. isNeedFetchData: widget.isEdit,
  299. apiActivity: ConstCommon.apiDetailDisease,
  300. activityId: widget.activityId))),
  301. BlocProvider<MediaHelperBloc>(
  302. create: (context) =>
  303. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  304. )
  305. ],
  306. child: Form(
  307. key: _formKey,
  308. autovalidate: _autoValidate,
  309. child: SingleChildScrollView(
  310. padding: EdgeInsets.all(8.0),
  311. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  312. listener: (context, state) async {
  313. if (state is ActionDetailFailure) {
  314. LoadingDialog.hideLoadingDialog(context);
  315. } else if (state is ActionDetailSuccess) {
  316. LoadingDialog.hideLoadingDialog(context);
  317. print(state.item);
  318. _disease = Disease.fromJson(state.item);
  319. _disease.activityId = widget.activityId;
  320. _typesOfPestController.text =
  321. _disease.typesOfPest ?? "";
  322. _harmLevelController.text =
  323. _disease.harmLevel ?? "";
  324. _treePercentController.text = _disease.treePercent
  325. .formatStringToStringDecimal();
  326. _locationController.text =
  327. _disease.location.formatStringToStringDecimal();
  328. _naturalEnemyController.text =
  329. _disease.naturalEnemy ?? "";
  330. _treatmentMeasuresController.text =
  331. _disease.treatmentMeasures ?? "";
  332. _descriptionController.text =
  333. _disease.description ?? "";
  334. _executeByController.text = _disease.executeBy;
  335. try {
  336. executeTime =
  337. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  338. .parse(_disease.executeDate);
  339. } catch (_) {}
  340. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  341. .format(executeTime);
  342. //Show media
  343. if (_disease.media != null) {
  344. BlocProvider.of<MediaHelperBloc>(context).add(
  345. ChangeListMedia(
  346. items: UtilAction.convertFilePathToMedia(
  347. _disease.media)));
  348. }
  349. } else if (state is ActionDetailInitial) {
  350. } else if (state is ActionDetailLoading) {
  351. LoadingDialog.showLoadingDialog(context);
  352. }
  353. },
  354. builder: (context, state) {
  355. return Column(
  356. children: <Widget>[
  357. Container(
  358. width: double.infinity,
  359. child: Text(
  360. "Ngày thực hiện *",
  361. style: TextStyle(
  362. color: Colors.black54, fontSize: 13.0),
  363. ),
  364. ),
  365. _btnExecuteTimePicker(),
  366. SizedBox(
  367. height: 8.0,
  368. ),
  369. _typeOfPestField(),
  370. SizedBox(
  371. height: 8.0,
  372. ),
  373. _harmLevelField(),
  374. SizedBox(
  375. height: 8.0,
  376. ),
  377. _treePercentField(),
  378. SizedBox(
  379. height: 8.0,
  380. ),
  381. _locationField(),
  382. SizedBox(
  383. height: 8.0,
  384. ),
  385. _naturalEnemyField(),
  386. SizedBox(
  387. height: 8.0,
  388. ),
  389. _treatmentMeasuresField(),
  390. SizedBox(
  391. height: 8.0,
  392. ),
  393. _descriptionField(),
  394. SizedBox(
  395. height: 8.0,
  396. ),
  397. _executeByField(),
  398. SizedBox(
  399. height: 8.0,
  400. ),
  401. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  402. builder: (context, state) {
  403. if (state is MediaHelperSuccess) {
  404. return WidgetMediaPicker(
  405. currentItems: state.items,
  406. onChangeFiles: (newPathFiles,
  407. deletePathFiles) async {
  408. Get.find<ChangeFileController>().change(
  409. newPathFiles, deletePathFiles);
  410. });
  411. } else {
  412. return Center(
  413. child: CircularProgressIndicator());
  414. }
  415. }),
  416. ],
  417. );
  418. },
  419. ),
  420. )),
  421. ))));
  422. @override
  423. void dispose() {
  424. _typesOfPestController.dispose();
  425. _harmLevelController.dispose();
  426. _treePercentController.dispose();
  427. _locationController.dispose();
  428. _naturalEnemyController.dispose();
  429. _treatmentMeasuresController.dispose();
  430. _descriptionController.dispose();
  431. _executeByController.dispose();
  432. super.dispose();
  433. }
  434. }