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.

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