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.

481 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. onSaved: (newValue) {
  230. _disease.treePercent = newValue;
  231. },
  232. );
  233. }
  234. Widget _locationField() {
  235. return TextFormField(
  236. keyboardType: TextInputType.text,
  237. decoration: InputDecoration(labelText: "Vị trí"),
  238. controller: _locationController,
  239. onSaved: (newValue) {
  240. _disease.location = newValue;
  241. },
  242. );
  243. }
  244. Widget _naturalEnemyField() {
  245. return TextFormField(
  246. keyboardType: TextInputType.text,
  247. decoration: InputDecoration(labelText: "Thiên địch"),
  248. controller: _naturalEnemyController,
  249. onSaved: (newValue) {
  250. _disease.naturalEnemy = newValue;
  251. },
  252. );
  253. }
  254. Widget _treatmentMeasuresField() {
  255. return TextFormField(
  256. keyboardType: TextInputType.text,
  257. decoration: InputDecoration(labelText: "Biện pháp xử lý"),
  258. controller: _treatmentMeasuresController,
  259. onSaved: (newValue) {
  260. _disease.treatmentMeasures = newValue;
  261. },
  262. );
  263. }
  264. Widget _descriptionField() {
  265. return TextFormField(
  266. keyboardType: TextInputType.text,
  267. decoration: InputDecoration(labelText: "Ghi chú"),
  268. controller: _descriptionController,
  269. onSaved: (newValue) {
  270. _disease.description = newValue;
  271. },
  272. );
  273. }
  274. Widget _executeByField() {
  275. return TextFormField(
  276. keyboardType: TextInputType.text,
  277. decoration: InputDecoration(labelText: "Người thực hiện"),
  278. enabled: false,
  279. controller: _executeByController,
  280. onSaved: (newValue) {},
  281. );
  282. }
  283. _actionAppBar() {
  284. IconButton iconButton;
  285. if (1 == 1) {
  286. iconButton = IconButton(
  287. icon: Icon(
  288. Icons.done,
  289. color: Colors.black,
  290. ),
  291. onPressed: () {
  292. FocusScopeNode currentFocus = FocusScope.of(context);
  293. if (!currentFocus.hasPrimaryFocus) {
  294. currentFocus.unfocus();
  295. }
  296. _validateInputs();
  297. },
  298. );
  299. return <Widget>[iconButton];
  300. }
  301. return <Widget>[Container()];
  302. }
  303. @override
  304. Widget build(BuildContext context) => KeyboardDismisser(
  305. gestures: [
  306. GestureType.onTap,
  307. GestureType.onPanUpdateDownDirection,
  308. ],
  309. child: Scaffold(
  310. key: _scaffoldKey,
  311. appBar: AppBar(
  312. centerTitle: true,
  313. title: Text(plot_action_disease),
  314. actions: _actionAppBar()),
  315. body: KeyboardDismisser(
  316. child: MultiBlocProvider(
  317. providers: [
  318. BlocProvider<ActionDetailBloc>(
  319. create: (context) =>
  320. ActionDetailBloc(repository: Repository())
  321. ..add(FetchData(
  322. isNeedFetchData: widget.isEdit,
  323. apiActivity: ConstCommon.apiDetailDisease,
  324. activityId: widget.activityId))),
  325. BlocProvider<MediaHelperBloc>(
  326. create: (context) =>
  327. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  328. )
  329. ],
  330. child: Form(
  331. key: _formKey,
  332. autovalidate: _autoValidate,
  333. child: SingleChildScrollView(
  334. padding: EdgeInsets.all(8.0),
  335. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  336. listener: (context, state) async {
  337. if (state is ActionDetailFailure) {
  338. LoadingDialog.hideLoadingDialog(context);
  339. } else if (state is ActionDetailSuccess) {
  340. LoadingDialog.hideLoadingDialog(context);
  341. print(state.item);
  342. _disease = Disease.fromJson(state.item);
  343. _disease.activityId = widget.activityId;
  344. _typesOfPestController.text =
  345. _disease.typesOfPest ?? "";
  346. _harmLevelController.text =
  347. _disease.harmLevel ?? "";
  348. _treePercentController.text = _disease.treePercent
  349. .formatStringToStringDecimal();
  350. _locationController.text =
  351. _disease.location.formatStringToStringDecimal();
  352. _naturalEnemyController.text =
  353. _disease.naturalEnemy ?? "";
  354. _treatmentMeasuresController.text =
  355. _disease.treatmentMeasures ?? "";
  356. _descriptionController.text =
  357. _disease.description ?? "";
  358. _executeByController.text = _disease.executeBy;
  359. try {
  360. executeTime =
  361. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  362. .parse(_disease.executeDate);
  363. } catch (_) {}
  364. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  365. .format(executeTime);
  366. //Show media
  367. if (_disease.media != null) {
  368. await UtilAction.cacheFiles(_disease.media)
  369. .then((value) {
  370. BlocProvider.of<MediaHelperBloc>(context)
  371. .add(ChangeListMedia(items: value));
  372. }).whenComplete(() {
  373. print("completed");
  374. });
  375. }
  376. } else if (state is ActionDetailInitial) {
  377. } else if (state is ActionDetailLoading) {
  378. LoadingDialog.showLoadingDialog(context);
  379. }
  380. },
  381. builder: (context, state) {
  382. return Column(
  383. children: <Widget>[
  384. Container(
  385. width: double.infinity,
  386. child: Text(
  387. "Ngày thực hiện *",
  388. style: TextStyle(
  389. color: Colors.black54, fontSize: 13.0),
  390. ),
  391. ),
  392. _btnExecuteTimePicker(),
  393. SizedBox(
  394. height: 8.0,
  395. ),
  396. _typeOfPestField(),
  397. SizedBox(
  398. height: 8.0,
  399. ),
  400. _harmLevelField(),
  401. SizedBox(
  402. height: 8.0,
  403. ),
  404. _treePercentField(),
  405. SizedBox(
  406. height: 8.0,
  407. ),
  408. _locationField(),
  409. SizedBox(
  410. height: 8.0,
  411. ),
  412. _naturalEnemyField(),
  413. SizedBox(
  414. height: 8.0,
  415. ),
  416. _treatmentMeasuresField(),
  417. SizedBox(
  418. height: 8.0,
  419. ),
  420. _descriptionField(),
  421. SizedBox(
  422. height: 8.0,
  423. ),
  424. _executeByField(),
  425. SizedBox(
  426. height: 8.0,
  427. ),
  428. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  429. builder: (context, state) {
  430. if (state is MediaHelperSuccess) {
  431. return WidgetMediaPicker(
  432. currentItems: state.items,
  433. onChangeFiles: (filePaths) async {
  434. Get.find<ChangeFileController>()
  435. .addAllFile(filePaths);
  436. });
  437. } else {
  438. return Center(
  439. child: CircularProgressIndicator());
  440. }
  441. }),
  442. ],
  443. );
  444. },
  445. ),
  446. )),
  447. ))));
  448. @override
  449. void dispose() {
  450. _typesOfPestController.dispose();
  451. _harmLevelController.dispose();
  452. _treePercentController.dispose();
  453. _locationController.dispose();
  454. _naturalEnemyController.dispose();
  455. _treatmentMeasuresController.dispose();
  456. _descriptionController.dispose();
  457. _executeByController.dispose();
  458. super.dispose();
  459. }
  460. }