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.

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