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.

459 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_utils.dart';
  10. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  11. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  12. import 'package:farm_tpf/utils/const_common.dart';
  13. import 'package:farm_tpf/utils/const_string.dart';
  14. import 'package:farm_tpf/utils/const_style.dart';
  15. import 'package:farm_tpf/utils/pref.dart';
  16. import 'package:farm_tpf/utils/validators.dart';
  17. import 'package:flutter/material.dart';
  18. import 'package:flutter_bloc/flutter_bloc.dart';
  19. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  20. import 'package:get/get.dart';
  21. import 'package:intl/intl.dart';
  22. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  23. import 'package:pattern_formatter/pattern_formatter.dart';
  24. import 'package:farm_tpf/utils/formatter.dart';
  25. import '../util_action.dart';
  26. class EditActionDiseaseScreen extends StatefulWidget {
  27. final int cropId;
  28. final bool isEdit;
  29. final int activityId;
  30. EditActionDiseaseScreen(
  31. {@required this.cropId, this.isEdit = false, this.activityId});
  32. @override
  33. _EditActionDiseaseScreenState createState() =>
  34. _EditActionDiseaseScreenState();
  35. }
  36. class _EditActionDiseaseScreenState extends State<EditActionDiseaseScreen> {
  37. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  38. final _repository = Repository();
  39. GlobalKey<FormState> _formKey = GlobalKey();
  40. bool _autoValidate = false;
  41. Disease _disease = Disease();
  42. var pref = LocalPref();
  43. TextEditingController _typesOfPestController = TextEditingController();
  44. TextEditingController _numTreeController = TextEditingController();
  45. TextEditingController _harmLevelController = TextEditingController();
  46. TextEditingController _treePercentController = TextEditingController();
  47. TextEditingController _locationController = TextEditingController();
  48. TextEditingController _naturalEnemyController = TextEditingController();
  49. TextEditingController _treatmentMeasuresController = TextEditingController();
  50. TextEditingController _descriptionController = TextEditingController();
  51. final _executeByController = TextEditingController();
  52. String executeTimeView;
  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. var parsedExecuteDate =
  66. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  67. _disease.executeDate = "$parsedExecuteDate";
  68. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  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 FlatButton(
  144. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  145. onPressed: () {
  146. DatePicker.showDateTimePicker(context,
  147. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  148. setState(() {
  149. var parsedDate =
  150. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  151. _disease.executeDate = "$parsedDate";
  152. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  153. });
  154. }, currentTime: executeTime, locale: LocaleType.vi);
  155. },
  156. child: Container(
  157. padding:
  158. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  159. decoration: BoxDecoration(
  160. border: kBorderTextField,
  161. ),
  162. child: Row(
  163. children: [
  164. Expanded(
  165. child: Text(
  166. //TODO: check condition
  167. executeTimeView == null ? "$executeTime" : executeTimeView,
  168. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  169. )),
  170. Icon(
  171. Icons.date_range,
  172. color: Colors.blue,
  173. ),
  174. ],
  175. )));
  176. }
  177. Widget _typeOfPestField() {
  178. return TextFormField(
  179. keyboardType: TextInputType.text,
  180. decoration: InputDecoration(labelText: "Loại dịch hại *"),
  181. controller: _typesOfPestController,
  182. validator: (String value) {
  183. return Validators.validateNotNullOrEmpty(value, "Loại dịch hại");
  184. },
  185. onSaved: (newValue) {
  186. _disease.typesOfPest = newValue;
  187. },
  188. );
  189. }
  190. Widget _harmLevelField() {
  191. return TextFormField(
  192. keyboardType: TextInputType.text,
  193. decoration: InputDecoration(labelText: "Mức độ gây hại"),
  194. controller: _harmLevelController,
  195. onSaved: (newValue) {
  196. _disease.harmLevel = newValue;
  197. },
  198. );
  199. }
  200. Widget _treePercentField() {
  201. return TextFormField(
  202. keyboardType: TextInputType.numberWithOptions(decimal: true),
  203. inputFormatters: [
  204. ThousandsFormatter(
  205. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  206. ],
  207. decoration: InputDecoration(labelText: "% cây"),
  208. controller: _treePercentController,
  209. onSaved: (newValue) {
  210. _disease.treePercent = newValue;
  211. },
  212. );
  213. }
  214. Widget _locationField() {
  215. return TextFormField(
  216. keyboardType: TextInputType.text,
  217. decoration: InputDecoration(labelText: "Vị trí"),
  218. controller: _locationController,
  219. onSaved: (newValue) {
  220. _disease.location = newValue;
  221. },
  222. );
  223. }
  224. Widget _naturalEnemyField() {
  225. return TextFormField(
  226. keyboardType: TextInputType.text,
  227. decoration: InputDecoration(labelText: "Thiên địch"),
  228. controller: _naturalEnemyController,
  229. onSaved: (newValue) {
  230. _disease.naturalEnemy = newValue;
  231. },
  232. );
  233. }
  234. Widget _treatmentMeasuresField() {
  235. return TextFormField(
  236. keyboardType: TextInputType.text,
  237. decoration: InputDecoration(labelText: "Biện pháp xử lý"),
  238. controller: _treatmentMeasuresController,
  239. onSaved: (newValue) {
  240. _disease.treatmentMeasures = newValue;
  241. },
  242. );
  243. }
  244. Widget _descriptionField() {
  245. return TextFormField(
  246. keyboardType: TextInputType.text,
  247. decoration: InputDecoration(labelText: "Ghi chú"),
  248. controller: _descriptionController,
  249. onSaved: (newValue) {
  250. _disease.description = newValue;
  251. },
  252. );
  253. }
  254. Widget _executeByField() {
  255. return TextFormField(
  256. keyboardType: TextInputType.text,
  257. decoration: InputDecoration(labelText: "Người thực hiện"),
  258. enabled: false,
  259. controller: _executeByController,
  260. onSaved: (newValue) {},
  261. );
  262. }
  263. _actionAppBar() {
  264. IconButton iconButton;
  265. if (1 == 1) {
  266. iconButton = IconButton(
  267. icon: Icon(
  268. Icons.done,
  269. color: Colors.black,
  270. ),
  271. onPressed: () {
  272. FocusScopeNode currentFocus = FocusScope.of(context);
  273. if (!currentFocus.hasPrimaryFocus) {
  274. currentFocus.unfocus();
  275. }
  276. _validateInputs();
  277. },
  278. );
  279. return <Widget>[iconButton];
  280. }
  281. return <Widget>[Container()];
  282. }
  283. @override
  284. Widget build(BuildContext context) => KeyboardDismisser(
  285. gestures: [
  286. GestureType.onTap,
  287. GestureType.onPanUpdateDownDirection,
  288. ],
  289. child: Scaffold(
  290. key: _scaffoldKey,
  291. appBar: AppBar(
  292. centerTitle: true,
  293. title: Text(plot_action_disease),
  294. actions: _actionAppBar()),
  295. body: KeyboardDismisser(
  296. child: MultiBlocProvider(
  297. providers: [
  298. BlocProvider<ActionDetailBloc>(
  299. create: (context) =>
  300. ActionDetailBloc(repository: Repository())
  301. ..add(FetchData(
  302. isNeedFetchData: widget.isEdit,
  303. apiActivity: ConstCommon.apiDetailDisease,
  304. activityId: widget.activityId))),
  305. BlocProvider<MediaHelperBloc>(
  306. create: (context) =>
  307. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  308. )
  309. ],
  310. child: Form(
  311. key: _formKey,
  312. autovalidate: _autoValidate,
  313. child: SingleChildScrollView(
  314. padding: EdgeInsets.all(8.0),
  315. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  316. listener: (context, state) async {
  317. if (state is ActionDetailFailure) {
  318. LoadingDialog.hideLoadingDialog(context);
  319. } else if (state is ActionDetailSuccess) {
  320. LoadingDialog.hideLoadingDialog(context);
  321. print(state.item);
  322. _disease = Disease.fromJson(state.item);
  323. _disease.activityId = widget.activityId;
  324. _typesOfPestController.text =
  325. _disease.typesOfPest ?? "";
  326. _harmLevelController.text =
  327. _disease.harmLevel ?? "";
  328. _treePercentController.text = _disease.treePercent
  329. .formatStringToStringDecimal();
  330. _locationController.text =
  331. _disease.location.formatStringToStringDecimal();
  332. _naturalEnemyController.text =
  333. _disease.naturalEnemy ?? "";
  334. _treatmentMeasuresController.text =
  335. _disease.treatmentMeasures ?? "";
  336. _descriptionController.text =
  337. _disease.description ?? "";
  338. _executeByController.text = _disease.executeBy;
  339. try {
  340. executeTime =
  341. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  342. .parse(_disease.executeDate);
  343. } catch (_) {}
  344. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  345. .format(executeTime);
  346. //Show media
  347. if (_disease.media != null) {
  348. BlocProvider.of<MediaHelperBloc>(context).add(
  349. ChangeListMedia(
  350. items: UtilAction.convertFilePathToMedia(
  351. _disease.media)));
  352. }
  353. } else if (state is ActionDetailInitial) {
  354. } else if (state is ActionDetailLoading) {
  355. LoadingDialog.showLoadingDialog(context);
  356. }
  357. },
  358. builder: (context, state) {
  359. return Column(
  360. children: <Widget>[
  361. Container(
  362. width: double.infinity,
  363. child: Text(
  364. "Ngày thực hiện *",
  365. style: TextStyle(
  366. color: Colors.black54, fontSize: 13.0),
  367. ),
  368. ),
  369. _btnExecuteTimePicker(),
  370. SizedBox(
  371. height: 8.0,
  372. ),
  373. _typeOfPestField(),
  374. SizedBox(
  375. height: 8.0,
  376. ),
  377. _harmLevelField(),
  378. SizedBox(
  379. height: 8.0,
  380. ),
  381. _treePercentField(),
  382. SizedBox(
  383. height: 8.0,
  384. ),
  385. _locationField(),
  386. SizedBox(
  387. height: 8.0,
  388. ),
  389. _naturalEnemyField(),
  390. SizedBox(
  391. height: 8.0,
  392. ),
  393. _treatmentMeasuresField(),
  394. SizedBox(
  395. height: 8.0,
  396. ),
  397. _descriptionField(),
  398. SizedBox(
  399. height: 8.0,
  400. ),
  401. _executeByField(),
  402. SizedBox(
  403. height: 8.0,
  404. ),
  405. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  406. builder: (context, state) {
  407. if (state is MediaHelperSuccess) {
  408. return WidgetMediaPicker(
  409. currentItems: state.items,
  410. onChangeFiles: (newPathFiles,
  411. deletePathFiles) async {
  412. Get.find<ChangeFileController>().change(
  413. newPathFiles, deletePathFiles);
  414. });
  415. } else {
  416. return Center(
  417. child: CircularProgressIndicator());
  418. }
  419. }),
  420. ],
  421. );
  422. },
  423. ),
  424. )),
  425. ))));
  426. @override
  427. void dispose() {
  428. _typesOfPestController.dispose();
  429. _harmLevelController.dispose();
  430. _treePercentController.dispose();
  431. _locationController.dispose();
  432. _naturalEnemyController.dispose();
  433. _treatmentMeasuresController.dispose();
  434. _descriptionController.dispose();
  435. _executeByController.dispose();
  436. super.dispose();
  437. }
  438. }