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.

365 lines
17KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/Dung.dart';
  3. import 'package:farm_tpf/custom_model/SuppliesUsing.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/controller/ChangeFieldInForm.dart';
  17. import 'package:farm_tpf/presentation/screens/actions/controller/ChangeSupplyUsing.dart';
  18. import 'package:farm_tpf/presentation/screens/actions/dung/widget_dung_supply.dart';
  19. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  20. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart';
  21. import 'package:farm_tpf/utils/const_common.dart';
  22. import 'package:farm_tpf/utils/const_string.dart';
  23. import 'package:farm_tpf/utils/const_style.dart';
  24. import 'package:farm_tpf/utils/pref.dart';
  25. import 'package:farm_tpf/utils/validators.dart';
  26. import 'package:flutter/material.dart';
  27. import 'package:flutter_bloc/flutter_bloc.dart';
  28. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  29. import 'package:get/get.dart';
  30. import 'package:intl/intl.dart';
  31. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  32. import 'package:pattern_formatter/pattern_formatter.dart';
  33. import 'package:farm_tpf/utils/formatter.dart';
  34. import '../util_action.dart';
  35. class EditActionDungScreen extends StatefulWidget {
  36. final int cropId;
  37. final bool isEdit;
  38. final int? activityId;
  39. EditActionDungScreen({required this.cropId, this.isEdit = false, this.activityId});
  40. @override
  41. _EditActionDungScreenState createState() => _EditActionDungScreenState();
  42. }
  43. class _EditActionDungScreenState extends State<EditActionDungScreen> {
  44. final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  45. final _repository = Repository();
  46. GlobalKey<FormState> _formKey = GlobalKey();
  47. bool _autoValidate = false;
  48. Dung _dung = Dung();
  49. var pref = LocalPref();
  50. final _descriptionController = TextEditingController();
  51. final _purposeController = TextEditingController();
  52. final _weatherController = TextEditingController();
  53. final _executeByController = TextEditingController();
  54. final _quarantinePeriodController = TextEditingController();
  55. List<SuppliesUsing> suppliesUsing = <SuppliesUsing>[];
  56. DateTime executeTime = DateTime.now();
  57. List<String> filePaths = <String>[];
  58. var changeFileController = Get.put(ChangeFileController());
  59. Future<Null> getSharedPrefs() async {
  60. var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  61. _executeByController.text = currentFullName ?? "";
  62. }
  63. @override
  64. void initState() {
  65. super.initState();
  66. getSharedPrefs();
  67. changeFileController.initValue();
  68. _dung.suppliesUsing = <SuppliesUsing>[];
  69. _dung.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. var newSups = <SuppliesUsing>[];
  77. suppliesUsing.forEach((sup) {
  78. var newSup = sup;
  79. newSup.suppliesInWarehouseId = sup.tbSuppliesInWarehouseId;
  80. newSup.equipmentOfCustomerId = sup.tbEquipmentOfCustomerId;
  81. newSups.add(newSup);
  82. });
  83. _dung.suppliesUsing = newSups;
  84. _dung.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  85. var activityDung = jsonEncode(_dung.toJson()).toString();
  86. //ADD NEW
  87. if (_dung.activityId == null) {
  88. _repository.createAction((value) {
  89. LoadingDialog.hideLoadingDialog(context);
  90. Get.back(result: value);
  91. Utils.showSnackBarSuccess(message: label_add_success);
  92. }, (error) {
  93. LoadingDialog.hideLoadingDialog(context);
  94. Utils.showSnackBarError(message: AppException.handleError(error));
  95. }, apiAddAction: ConstCommon.apiAddDung, paramActivity: ConstCommon.paramsActionDung, activityAction: activityDung, filePaths: filePaths);
  96. } else {
  97. //UPDATE
  98. _repository.updateAction((value) {
  99. LoadingDialog.hideLoadingDialog(context);
  100. Get.back(result: value);
  101. Utils.showSnackBarSuccess(message: label_update_success);
  102. }, (error) {
  103. LoadingDialog.hideLoadingDialog(context);
  104. Utils.showSnackBarError(message: AppException.handleError(error));
  105. },
  106. apiUpdateAction: ConstCommon.apiUpdateDung,
  107. paramActivity: ConstCommon.paramsActionDung,
  108. activityAction: activityDung,
  109. filePaths: filePaths);
  110. }
  111. } else {
  112. _autoValidate = true;
  113. }
  114. }
  115. Widget _btnExecuteTimePicker() {
  116. return WidgetFieldDateTimePicker(
  117. initDateTime: executeTime,
  118. onUpdateDateTime: (selectedDate) {
  119. _dung.executeDate = selectedDate.convertLocalDateTimeToStringUtcDateTime();
  120. });
  121. }
  122. Widget _purposeField() {
  123. return TextFormField(
  124. keyboardType: TextInputType.text,
  125. decoration: const InputDecoration(labelText: "Lý do sử dụng"),
  126. controller: _purposeController,
  127. onSaved: (newValue) {
  128. _dung.purpose = newValue ?? '';
  129. },
  130. );
  131. }
  132. Widget _quarantinePeriodField() {
  133. return WidgetTextFormFieldNumber(
  134. hintValue: "Thời gian cách ly",
  135. textController: _quarantinePeriodController,
  136. onSaved: (newValue) {
  137. _dung.quarantinePeriod = (newValue ?? '0').parseDoubleThousand();
  138. },
  139. onChanged: (_) {},
  140. validator: (_) {},
  141. );
  142. }
  143. Widget _weatherField() {
  144. return TextFormField(
  145. keyboardType: TextInputType.text,
  146. decoration: const InputDecoration(labelText: "Thời tiết"),
  147. controller: _weatherController,
  148. onSaved: (newValue) {
  149. _dung.weatherConditions = newValue ?? '';
  150. },
  151. );
  152. }
  153. Widget _desciptionField() {
  154. return TextFieldDescriptionWidget(
  155. controller: _descriptionController,
  156. onSaved: (newValue) {
  157. _dung.description = newValue;
  158. });
  159. }
  160. Widget _executeByField() {
  161. return TextFormField(
  162. keyboardType: TextInputType.text,
  163. decoration: const InputDecoration(labelText: "Người thực hiện"),
  164. enabled: false,
  165. controller: _executeByController,
  166. onSaved: (newValue) {},
  167. );
  168. }
  169. @override
  170. Widget build(BuildContext context) => KeyboardDismisser(
  171. gestures: [
  172. GestureType.onTap,
  173. GestureType.onPanUpdateDownDirection,
  174. ],
  175. child: Scaffold(
  176. backgroundColor: Colors.white,
  177. key: _scaffoldKey,
  178. appBar: AppBarWidget(
  179. isBack: true,
  180. action: InkWell(
  181. child: const Text(
  182. 'Huỷ',
  183. style: TextStyle(color: Colors.red, fontWeight: FontWeight.normal),
  184. ),
  185. onTap: () {
  186. if (Get.isSnackbarOpen) Get.back();
  187. Get.back();
  188. },
  189. ),
  190. ),
  191. body: KeyboardDismisser(
  192. child: MultiBlocProvider(
  193. providers: [
  194. BlocProvider<ActionDetailBloc>(
  195. create: (context) => ActionDetailBloc(repository: Repository())
  196. ..add(
  197. FetchData(isNeedFetchData: widget.isEdit, apiActivity: ConstCommon.apiDetailDung, activityId: widget.activityId ?? -1),
  198. ),
  199. ),
  200. BlocProvider<MediaHelperBloc>(
  201. create: (context) => MediaHelperBloc()..add(ChangeListMedia(items: [])),
  202. )
  203. ],
  204. child: Form(
  205. key: _formKey,
  206. // autovalidate: _autoValidate,
  207. child: SafeArea(
  208. child: SingleChildScrollView(
  209. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  210. listener: (context, state) async {
  211. if (state is ActionDetailFailure) {
  212. LoadingDialog.hideLoadingDialog(context);
  213. } else if (state is ActionDetailSuccess) {
  214. LoadingDialog.hideLoadingDialog(context);
  215. _dung = Dung.fromJson(state.item);
  216. _dung.activityId = widget.activityId ?? -1;
  217. _purposeController.text = _dung.purpose ?? "";
  218. _quarantinePeriodController.text = _dung.quarantinePeriod?.formatNumtoStringDecimal() ?? '';
  219. _weatherController.text = _dung.weatherConditions ?? "";
  220. _descriptionController.text = _dung.description ?? '';
  221. _executeByController.text = _dung.executeBy ?? '';
  222. Get.find<ChangeDateTimePicker>().change(
  223. _dung.executeDate?.convertStringServerDateTimeToLocalDateTime() ?? DateTime.now(),
  224. );
  225. //Show media
  226. if (Validators.stringNotNullOrEmpty(_dung.media ?? '')) {
  227. BlocProvider.of<MediaHelperBloc>(context)
  228. .add(ChangeListMedia(items: UtilAction.convertFilePathToMedia(_dung.media ?? '')));
  229. }
  230. //list supply
  231. suppliesUsing = _dung.suppliesUsing ?? <SuppliesUsing>[];
  232. Get.find<ChangeSupplyUsing>().changeInitList(suppliesUsing);
  233. } else if (state is ActionDetailInitial) {
  234. print("init");
  235. } else if (state is ActionDetailLoading) {
  236. print("loading");
  237. LoadingDialog.showLoadingDialog(context);
  238. }
  239. },
  240. builder: (context, state) {
  241. return Column(
  242. children: [
  243. Padding(
  244. padding: const EdgeInsets.all(8.0),
  245. child: Column(
  246. crossAxisAlignment: CrossAxisAlignment.start,
  247. children: <Widget>[
  248. const Text(
  249. plot_action_dung,
  250. style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
  251. ),
  252. const SizedBox(
  253. height: 8.0,
  254. ),
  255. Container(
  256. width: double.infinity,
  257. child: const Text(
  258. "Ngày thực hiện *",
  259. style: TextStyle(color: Colors.black54, fontSize: 13.0),
  260. ),
  261. ),
  262. _btnExecuteTimePicker(),
  263. const SizedBox(
  264. height: 8.0,
  265. ),
  266. _purposeField(),
  267. const SizedBox(
  268. height: 8.0,
  269. ),
  270. _quarantinePeriodField(),
  271. const SizedBox(
  272. height: 8.0,
  273. ),
  274. _weatherField(),
  275. const SizedBox(
  276. height: 8.0,
  277. ),
  278. _desciptionField(),
  279. const SizedBox(
  280. height: 8.0,
  281. ),
  282. _executeByField(),
  283. const SizedBox(
  284. height: 8.0,
  285. ),
  286. ],
  287. ),
  288. ),
  289. Container(
  290. width: double.infinity,
  291. height: 16,
  292. color: Colors.grey[200],
  293. ),
  294. WidgetDungSupply(
  295. currentItems: [],
  296. onChangeSupplies: (value) {
  297. suppliesUsing = value;
  298. }),
  299. Container(
  300. width: double.infinity,
  301. height: 16,
  302. color: Colors.grey[200],
  303. ),
  304. BlocBuilder<MediaHelperBloc, MediaHelperState>(builder: (context, state) {
  305. if (state is MediaHelperSuccess) {
  306. return WidgetMediaPicker(
  307. currentItems: state.items,
  308. onChangeFiles: (newPathFiles, deletePathFiles) async {
  309. Get.find<ChangeFileController>().change(newPathFiles, deletePathFiles);
  310. });
  311. } else {
  312. return const Center(child: CircularProgressIndicator());
  313. }
  314. }),
  315. Padding(
  316. padding: const EdgeInsets.all(8.0),
  317. child: ButtonWidget(
  318. title: 'CẬP NHẬT',
  319. onPressed: () {
  320. var currentFocus = FocusScope.of(context);
  321. if (!currentFocus.hasPrimaryFocus) {
  322. currentFocus.unfocus();
  323. }
  324. if (Get.find<ChangeFieldFormSupply>().isChanged) {
  325. Utils.showDialogConfirmSupply(onConfirm: () {
  326. Get.back();
  327. _validateInputs();
  328. });
  329. } else {
  330. _validateInputs();
  331. }
  332. }),
  333. ),
  334. ],
  335. );
  336. },
  337. ),
  338. ),
  339. ))))));
  340. @override
  341. void dispose() {
  342. _quarantinePeriodController.dispose();
  343. _purposeController.dispose();
  344. _weatherController.dispose();
  345. _descriptionController.dispose();
  346. _executeByController.dispose();
  347. super.dispose();
  348. }
  349. }