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.

418 lines
19KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/Harvest.dart';
  3. import 'package:farm_tpf/data/api/app_exception.dart';
  4. import 'package:farm_tpf/data/repository/repository.dart';
  5. import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart';
  6. import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
  7. import 'package:farm_tpf/presentation/custom_widgets/button_icon_widget.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/harvest_process/sc_edit_action_harvest_process.dart';
  17. import 'package:farm_tpf/presentation/screens/actions/packing/sc_edit_action_packing.dart';
  18. import 'package:farm_tpf/presentation/screens/actions/sell/sc_edit_action_sell.dart';
  19. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  20. import 'package:farm_tpf/presentation/screens/actions/util_action.dart';
  21. import 'package:farm_tpf/utils/const_common.dart';
  22. import 'package:farm_tpf/utils/const_icons.dart';
  23. import 'package:farm_tpf/utils/const_string.dart';
  24. import 'package:farm_tpf/utils/const_style.dart';
  25. import 'package:farm_tpf/utils/pref.dart';
  26. import 'package:farm_tpf/utils/validators.dart';
  27. import 'package:flutter/material.dart';
  28. import 'package:flutter_bloc/flutter_bloc.dart';
  29. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  30. import 'package:get/get.dart';
  31. import 'package:intl/intl.dart';
  32. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  33. import 'package:pattern_formatter/pattern_formatter.dart';
  34. import 'package:farm_tpf/utils/formatter.dart';
  35. class EditActionHarvestScreen extends StatefulWidget {
  36. final int cropId;
  37. final bool isEdit;
  38. final int? activityId;
  39. EditActionHarvestScreen({required this.cropId, this.isEdit = false, this.activityId});
  40. @override
  41. _EditActionHarvestScreenState createState() => _EditActionHarvestScreenState();
  42. }
  43. class _EditActionHarvestScreenState extends State<EditActionHarvestScreen> {
  44. final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  45. final _repository = Repository();
  46. GlobalKey<FormState> _formKey = GlobalKey();
  47. bool _autoValidate = false;
  48. Harvest _harvest = Harvest();
  49. TextEditingController _l1Controller = TextEditingController();
  50. TextEditingController _l2Controller = TextEditingController();
  51. TextEditingController _l3Controller = TextEditingController();
  52. TextEditingController _removedQuantityController = TextEditingController();
  53. TextEditingController _descriptionController = TextEditingController();
  54. final _executeByController = TextEditingController();
  55. var pref = LocalPref();
  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. _harvest.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>().newFiles;
  75. try {
  76. _harvest.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  77. var activityHarvest = jsonEncode(_harvest.toJson()).toString();
  78. //ADD NEW
  79. if (_harvest.activityId == null) {
  80. _repository.createAction((value) {
  81. LoadingDialog.hideLoadingDialog(context);
  82. Get.back(result: value);
  83. Utils.showSnackBarSuccess(message: label_add_success);
  84. }, (error) {
  85. LoadingDialog.hideLoadingDialog(context);
  86. Utils.showSnackBarError(message: AppException.handleError(error));
  87. },
  88. apiAddAction: ConstCommon.apiAddHarvest,
  89. paramActivity: ConstCommon.paramsActionHarvest,
  90. activityAction: activityHarvest,
  91. filePaths: filePaths);
  92. } else {
  93. //UPDATE
  94. _repository.updateAction((value) {
  95. LoadingDialog.hideLoadingDialog(context);
  96. Get.back(result: value);
  97. Utils.showSnackBarSuccess(message: label_update_success);
  98. }, (error) {
  99. LoadingDialog.hideLoadingDialog(context);
  100. Utils.showSnackBarError(message: AppException.handleError(error));
  101. },
  102. apiUpdateAction: ConstCommon.apiUpdateHarvest,
  103. paramActivity: ConstCommon.paramsActionHarvest,
  104. activityAction: activityHarvest,
  105. filePaths: filePaths);
  106. }
  107. } catch (e) {
  108. LoadingDialog.hideLoadingDialog(context);
  109. print(e.toString());
  110. }
  111. } else {
  112. _autoValidate = true;
  113. }
  114. }
  115. Widget _btnExecuteTimePicker() {
  116. return WidgetFieldDateTimePicker(
  117. initDateTime: executeTime,
  118. onUpdateDateTime: (selectedDate) {
  119. _harvest.executeDate = selectedDate.convertLocalDateTimeToStringUtcDateTime();
  120. });
  121. }
  122. Widget _l1Field() {
  123. return WidgetTextFormFieldNumber(
  124. hintValue: "Số lượng/khối lượng loại 1",
  125. textController: _l1Controller,
  126. onSaved: (newValue) {
  127. _harvest.collectedQuantityLv1 = (newValue ?? '0').parseDoubleThousand();
  128. },
  129. onChanged: (_) {},
  130. validator: (_) {},
  131. );
  132. }
  133. Widget _l2Field() {
  134. return WidgetTextFormFieldNumber(
  135. hintValue: "Số lượng/khối lượng loại 2",
  136. textController: _l2Controller,
  137. onSaved: (newValue) {
  138. _harvest.collectedQuantityLv2 = (newValue ?? '0').parseDoubleThousand();
  139. },
  140. onChanged: (_) {},
  141. validator: (_) {},
  142. );
  143. }
  144. Widget _l3Field() {
  145. return WidgetTextFormFieldNumber(
  146. hintValue: "Số lượng/khối lượng loại 3",
  147. textController: _l3Controller,
  148. onSaved: (newValue) {
  149. _harvest.collectedQuantityLv3 = (newValue ?? '0').parseDoubleThousand();
  150. },
  151. onChanged: (_) {},
  152. validator: (_) {},
  153. );
  154. }
  155. Widget _removedQuantityField() {
  156. return WidgetTextFormFieldNumber(
  157. hintValue: "Số lượng/khối lượng loại bỏ",
  158. textController: _removedQuantityController,
  159. onSaved: (newValue) {
  160. _harvest.removedQuantity = (newValue ?? '0').parseDoubleThousand();
  161. },
  162. onChanged: (_) {},
  163. validator: (_) {},
  164. );
  165. }
  166. Widget _descriptionField() {
  167. return TextFieldDescriptionWidget(
  168. controller: _descriptionController,
  169. onSaved: (newValue) {
  170. _harvest.description = newValue;
  171. });
  172. }
  173. Widget _executeByField() {
  174. return TextFormField(
  175. keyboardType: TextInputType.text,
  176. decoration: const InputDecoration(labelText: "Người thực hiện"),
  177. enabled: false,
  178. controller: _executeByController,
  179. onSaved: (newValue) {},
  180. );
  181. }
  182. @override
  183. Widget build(BuildContext context) => KeyboardDismisser(
  184. gestures: [
  185. GestureType.onTap,
  186. GestureType.onPanUpdateDownDirection,
  187. ],
  188. child: Scaffold(
  189. backgroundColor: Colors.white,
  190. key: _scaffoldKey,
  191. appBar: AppBarWidget(
  192. isBack: true,
  193. action: InkWell(
  194. child: const Text(
  195. 'Huỷ',
  196. style: TextStyle(color: Colors.red, fontWeight: FontWeight.normal),
  197. ),
  198. onTap: () {
  199. if (Get.isSnackbarOpen) Get.back();
  200. Get.back();
  201. },
  202. ),
  203. ),
  204. body: KeyboardDismisser(
  205. child: MultiBlocProvider(
  206. providers: [
  207. BlocProvider<ActionDetailBloc>(
  208. create: (context) => ActionDetailBloc(repository: Repository())
  209. ..add(
  210. FetchData(
  211. isNeedFetchData: widget.isEdit,
  212. apiActivity: ConstCommon.apiDetailHarvest,
  213. activityId: widget.activityId ?? -1,
  214. ),
  215. ),
  216. ),
  217. BlocProvider<MediaHelperBloc>(
  218. create: (context) => MediaHelperBloc()..add(ChangeListMedia(items: [])),
  219. )
  220. ],
  221. child: Form(
  222. key: _formKey,
  223. // autovalidate: _autoValidate,
  224. child: SafeArea(
  225. child: SingleChildScrollView(
  226. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  227. listener: (context, state) async {
  228. if (state is ActionDetailFailure) {
  229. LoadingDialog.hideLoadingDialog(context);
  230. } else if (state is ActionDetailSuccess) {
  231. LoadingDialog.hideLoadingDialog(context);
  232. print(state.item);
  233. _harvest = Harvest.fromJson(state.item);
  234. _harvest.activityId = widget.activityId ?? -1;
  235. _l1Controller.text = _harvest.collectedQuantityLv1?.formatNumtoStringDecimal() ?? '';
  236. _l2Controller.text = _harvest.collectedQuantityLv2?.formatNumtoStringDecimal() ?? '';
  237. _l3Controller.text = _harvest.collectedQuantityLv3?.formatNumtoStringDecimal() ?? '';
  238. _removedQuantityController.text = _harvest.removedQuantity?.formatNumtoStringDecimal() ?? '';
  239. _descriptionController.text = _harvest.description ?? "";
  240. _executeByController.text = _harvest.executeBy ?? '';
  241. Get.find<ChangeDateTimePicker>()
  242. .change(_harvest.executeDate?.convertStringServerDateTimeToLocalDateTime() ?? DateTime.now());
  243. //Show media
  244. if (Validators.stringNotNullOrEmpty(_harvest.media ?? '')) {
  245. BlocProvider.of<MediaHelperBloc>(context)
  246. .add(ChangeListMedia(items: UtilAction.convertFilePathToMedia(_harvest.media ?? '')));
  247. }
  248. } else if (state is ActionDetailInitial) {
  249. } else if (state is ActionDetailLoading) {
  250. LoadingDialog.showLoadingDialog(context);
  251. }
  252. },
  253. builder: (context, state) {
  254. return Column(
  255. children: [
  256. Padding(
  257. padding: const EdgeInsets.all(8.0),
  258. child: Column(
  259. crossAxisAlignment: CrossAxisAlignment.start,
  260. children: <Widget>[
  261. const Text(
  262. plot_action_harvest,
  263. style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
  264. ),
  265. const SizedBox(
  266. height: 8.0,
  267. ),
  268. Container(
  269. width: double.infinity,
  270. child: const Text(
  271. "Ngày thực hiện *",
  272. style: TextStyle(color: Colors.black54, fontSize: 13.0),
  273. ),
  274. ),
  275. _btnExecuteTimePicker(),
  276. const SizedBox(
  277. height: 8.0,
  278. ),
  279. _l1Field(),
  280. const SizedBox(
  281. height: 8.0,
  282. ),
  283. _l2Field(),
  284. const SizedBox(
  285. height: 8.0,
  286. ),
  287. _l3Field(),
  288. const SizedBox(
  289. height: 8.0,
  290. ),
  291. _removedQuantityField(),
  292. const SizedBox(
  293. height: 8.0,
  294. ),
  295. _descriptionField(),
  296. const SizedBox(
  297. height: 8.0,
  298. ),
  299. _executeByField(),
  300. const SizedBox(
  301. height: 8.0,
  302. ),
  303. ],
  304. ),
  305. ),
  306. Container(
  307. width: double.infinity,
  308. height: 16,
  309. color: Colors.grey[200],
  310. ),
  311. BlocBuilder<MediaHelperBloc, MediaHelperState>(builder: (context, state) {
  312. if (state is MediaHelperSuccess) {
  313. return WidgetMediaPicker(
  314. currentItems: state.items,
  315. onChangeFiles: (newPathFiles, deletePathFiles) async {
  316. Get.find<ChangeFileController>().change(newPathFiles, deletePathFiles);
  317. });
  318. } else {
  319. return const Center(child: CircularProgressIndicator());
  320. }
  321. }),
  322. Container(
  323. width: double.infinity,
  324. height: 16,
  325. color: Colors.grey[200],
  326. ),
  327. ButtonIconWidget(
  328. leadingIcon: AppIcons.icHarvestProcess,
  329. trailingIcon: AppIcons.icArrowRight,
  330. title: plot_action_harvest_process,
  331. onTap: () {
  332. if (_harvest.id != null) {
  333. Get.to(EditActionHarvestProcessScreen(
  334. cropId: widget.cropId,
  335. harvestId: _harvest.id,
  336. ));
  337. } else {
  338. Get.to(EditActionHarvestProcessScreen(cropId: widget.cropId));
  339. }
  340. }),
  341. ButtonIconWidget(
  342. leadingIcon: AppIcons.icPacking,
  343. trailingIcon: AppIcons.icArrowRight,
  344. title: plot_action_packing,
  345. onTap: () {
  346. if (_harvest.id != null) {
  347. Get.to(EditActionPackingScreen(
  348. cropId: widget.cropId,
  349. harvestId: _harvest.id,
  350. ));
  351. } else {
  352. Get.to(EditActionPackingScreen(cropId: widget.cropId));
  353. }
  354. }),
  355. ButtonIconWidget(
  356. leadingIcon: AppIcons.icSell,
  357. trailingIcon: AppIcons.icArrowRight,
  358. title: plot_action_sell,
  359. onTap: () {
  360. if (_harvest.id != null) {
  361. Get.to(EditActionSellScreen(
  362. cropId: widget.cropId,
  363. harvestId: _harvest.id,
  364. ));
  365. } else {
  366. Get.to(EditActionSellScreen(cropId: widget.cropId));
  367. }
  368. }),
  369. const SizedBox(
  370. height: 16,
  371. ),
  372. Padding(
  373. padding: const EdgeInsets.all(8.0),
  374. child: ButtonWidget(
  375. title: 'CẬP NHẬT',
  376. onPressed: () {
  377. var currentFocus = FocusScope.of(context);
  378. if (!currentFocus.hasPrimaryFocus) {
  379. currentFocus.unfocus();
  380. }
  381. _validateInputs();
  382. }),
  383. ),
  384. ],
  385. );
  386. },
  387. ),
  388. ),
  389. )),
  390. ))));
  391. @override
  392. void dispose() {
  393. _l1Controller.dispose();
  394. _l2Controller.dispose();
  395. _l3Controller.dispose();
  396. _removedQuantityController.dispose();
  397. _descriptionController.dispose();
  398. _executeByController.dispose();
  399. super.dispose();
  400. }
  401. }