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
17KB

  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/bloc/media_helper_bloc.dart';
  6. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  7. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  8. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  9. import 'package:farm_tpf/presentation/screens/actions/packing/sc_edit_action_packing.dart';
  10. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  11. import 'package:farm_tpf/presentation/screens/actions/util_action.dart';
  12. import 'package:farm_tpf/utils/const_common.dart';
  13. import 'package:farm_tpf/utils/const_string.dart';
  14. import 'package:farm_tpf/utils/const_style.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. class EditActionHarvestScreen extends StatefulWidget {
  25. final int cropId;
  26. final bool isEdit;
  27. final int activityId;
  28. EditActionHarvestScreen(
  29. {@required this.cropId, this.isEdit = false, this.activityId});
  30. @override
  31. _EditActionHarvestScreenState createState() =>
  32. _EditActionHarvestScreenState();
  33. }
  34. class _EditActionHarvestScreenState extends State<EditActionHarvestScreen> {
  35. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  36. final _repository = Repository();
  37. GlobalKey<FormState> _formKey = GlobalKey();
  38. bool _autoValidate = false;
  39. Harvest _harvest = Harvest();
  40. TextEditingController _l1Controller = TextEditingController();
  41. TextEditingController _l2Controller = TextEditingController();
  42. TextEditingController _l3Controller = TextEditingController();
  43. TextEditingController _removedQuantityController = TextEditingController();
  44. TextEditingController _descriptionController = TextEditingController();
  45. String executeTimeView;
  46. DateTime executeTime = DateTime.now();
  47. List<String> filePaths = List<String>();
  48. var changeFileController = Get.put(ChangeFileController());
  49. @override
  50. void initState() {
  51. super.initState();
  52. changeFileController.initValue();
  53. var parsedExecuteDate =
  54. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  55. _harvest.executeDate = "$parsedExecuteDate";
  56. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  57. _harvest.cropId = widget.cropId;
  58. }
  59. _validateInputs() async {
  60. if (_formKey.currentState.validate()) {
  61. _formKey.currentState.save();
  62. LoadingDialog.showLoadingDialog(context);
  63. filePaths = Get.find<ChangeFileController>().files;
  64. try {
  65. var activityHarvest = jsonEncode(_harvest.toJson()).toString();
  66. //ADD NEW
  67. if (_harvest.activityId == null) {
  68. _repository.createAction((value) {
  69. LoadingDialog.hideLoadingDialog(context);
  70. Get.back(result: value);
  71. Get.snackbar(label_add_success, "Hoạt động thu hoạch",
  72. snackPosition: SnackPosition.BOTTOM);
  73. }, (error) {
  74. LoadingDialog.hideLoadingDialog(context);
  75. _scaffoldKey.currentState.showSnackBar(SnackBar(
  76. content: Row(
  77. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  78. children: <Widget>[
  79. Flexible(child: Text(AppException.handleError(error))),
  80. Icon(Icons.error),
  81. ],
  82. ),
  83. backgroundColor: Colors.red,
  84. duration: Duration(seconds: 3),
  85. ));
  86. },
  87. apiAddAction: ConstCommon.apiAddHarvest,
  88. paramActivity: ConstCommon.paramsActionHarvest,
  89. activityAction: activityHarvest,
  90. filePaths: filePaths);
  91. } else {
  92. //UPDATE
  93. _repository.updateAction((value) {
  94. LoadingDialog.hideLoadingDialog(context);
  95. Get.back(result: value);
  96. Get.snackbar(label_update_success, "Hoạt động thu hoạch",
  97. snackPosition: SnackPosition.BOTTOM);
  98. }, (error) {
  99. LoadingDialog.hideLoadingDialog(context);
  100. _scaffoldKey.currentState.showSnackBar(SnackBar(
  101. content: Row(
  102. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  103. children: <Widget>[
  104. Flexible(child: Text(AppException.handleError(error))),
  105. Icon(Icons.error),
  106. ],
  107. ),
  108. backgroundColor: Colors.red,
  109. duration: Duration(seconds: 3),
  110. ));
  111. },
  112. apiUpdateAction: ConstCommon.apiUpdateHarvest,
  113. paramActivity: ConstCommon.paramsActionHarvest,
  114. activityAction: activityHarvest,
  115. filePaths: filePaths);
  116. }
  117. } catch (e) {
  118. LoadingDialog.hideLoadingDialog(context);
  119. print(e.toString());
  120. }
  121. } else {
  122. _autoValidate = true;
  123. }
  124. }
  125. Widget _btnExecuteTimePicker() {
  126. return FlatButton(
  127. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  128. onPressed: () {
  129. DatePicker.showDateTimePicker(context,
  130. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  131. setState(() {
  132. var parsedDate =
  133. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  134. _harvest.executeDate = "$parsedDate";
  135. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  136. });
  137. }, currentTime: executeTime, locale: LocaleType.vi);
  138. },
  139. child: Container(
  140. padding:
  141. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  142. decoration: BoxDecoration(
  143. border: kBorderTextField,
  144. ),
  145. child: Row(
  146. children: [
  147. Expanded(
  148. child: Text(
  149. //TODO: check condition
  150. executeTimeView == null ? "$executeTime" : executeTimeView,
  151. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  152. )),
  153. Icon(
  154. Icons.date_range,
  155. color: Colors.blue,
  156. ),
  157. ],
  158. )));
  159. }
  160. Widget _l1Field() {
  161. return TextFormField(
  162. keyboardType: TextInputType.numberWithOptions(decimal: true),
  163. inputFormatters: [
  164. ThousandsFormatter(
  165. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  166. ],
  167. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 1"),
  168. controller: _l1Controller,
  169. validator: (String value) {
  170. return Validators.validNumber(value, "Số lượng/khối lượng loại 1");
  171. },
  172. onSaved: (newValue) {
  173. _harvest.collectedQuantityLv1 = newValue.parseDoubleThousand();
  174. },
  175. );
  176. }
  177. Widget _l2Field() {
  178. return TextFormField(
  179. keyboardType: TextInputType.numberWithOptions(decimal: true),
  180. inputFormatters: [
  181. ThousandsFormatter(
  182. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  183. ],
  184. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 2"),
  185. controller: _l2Controller,
  186. validator: (String value) {
  187. return Validators.validNumber(value, "Số lượng/khối lượng loại 2");
  188. },
  189. onSaved: (newValue) {
  190. _harvest.collectedQuantityLv2 = newValue.parseDoubleThousand();
  191. },
  192. );
  193. }
  194. Widget _l3Field() {
  195. return TextFormField(
  196. keyboardType: TextInputType.numberWithOptions(decimal: true),
  197. inputFormatters: [
  198. ThousandsFormatter(
  199. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  200. ],
  201. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 3"),
  202. controller: _l3Controller,
  203. validator: (String value) {
  204. return Validators.validNumber(value, "Số lượng/khối lượng loại 3");
  205. },
  206. onSaved: (newValue) {
  207. _harvest.collectedQuantityLv3 = newValue.parseDoubleThousand();
  208. },
  209. );
  210. }
  211. Widget _removedQuantityField() {
  212. return TextFormField(
  213. keyboardType: TextInputType.numberWithOptions(decimal: true),
  214. inputFormatters: [
  215. ThousandsFormatter(
  216. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  217. ],
  218. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại bỏ"),
  219. controller: _removedQuantityController,
  220. validator: (String value) {
  221. return Validators.validNumber(value, "Số lượng/khối lượng loại bỏ");
  222. },
  223. onSaved: (newValue) {
  224. _harvest.removedQuantity = newValue.parseDoubleThousand();
  225. },
  226. );
  227. }
  228. Widget _descriptionField() {
  229. return TextFormField(
  230. keyboardType: TextInputType.text,
  231. decoration: InputDecoration(labelText: "Ghi chú"),
  232. controller: _descriptionController,
  233. onSaved: (newValue) {
  234. _harvest.description = newValue;
  235. },
  236. );
  237. }
  238. _actionAppBar() {
  239. IconButton iconButton;
  240. if (1 == 1) {
  241. iconButton = IconButton(
  242. icon: Icon(
  243. Icons.done,
  244. color: Colors.black,
  245. ),
  246. onPressed: () {
  247. FocusScopeNode currentFocus = FocusScope.of(context);
  248. if (!currentFocus.hasPrimaryFocus) {
  249. currentFocus.unfocus();
  250. }
  251. _validateInputs();
  252. },
  253. );
  254. return <Widget>[iconButton];
  255. }
  256. return <Widget>[Container()];
  257. }
  258. @override
  259. Widget build(BuildContext context) => KeyboardDismisser(
  260. gestures: [
  261. GestureType.onTap,
  262. GestureType.onPanUpdateDownDirection,
  263. ],
  264. child: Scaffold(
  265. key: _scaffoldKey,
  266. appBar: AppBar(
  267. centerTitle: true,
  268. title: Text(plot_action_harvest),
  269. actions: _actionAppBar()),
  270. body: KeyboardDismisser(
  271. child: MultiBlocProvider(
  272. providers: [
  273. BlocProvider<ActionDetailBloc>(
  274. create: (context) =>
  275. ActionDetailBloc(repository: Repository())
  276. ..add(FetchData(
  277. isNeedFetchData: widget.isEdit,
  278. apiActivity: ConstCommon.apiDetailHarvest,
  279. activityId: widget.activityId))),
  280. BlocProvider<MediaHelperBloc>(
  281. create: (context) =>
  282. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  283. )
  284. ],
  285. child: Form(
  286. key: _formKey,
  287. autovalidate: _autoValidate,
  288. child: SingleChildScrollView(
  289. padding: EdgeInsets.all(8.0),
  290. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  291. listener: (context, state) async {
  292. if (state is ActionDetailFailure) {
  293. LoadingDialog.hideLoadingDialog(context);
  294. } else if (state is ActionDetailSuccess) {
  295. LoadingDialog.hideLoadingDialog(context);
  296. print(state.item);
  297. _harvest = Harvest.fromJson(state.item);
  298. _harvest.activityId = widget.activityId;
  299. _l1Controller.text = _harvest.collectedQuantityLv1
  300. .formatNumtoStringDecimal();
  301. _l2Controller.text = _harvest.collectedQuantityLv2
  302. .formatNumtoStringDecimal();
  303. _l3Controller.text = _harvest.collectedQuantityLv3
  304. .formatNumtoStringDecimal();
  305. _removedQuantityController.text = _harvest
  306. .removedQuantity
  307. .formatNumtoStringDecimal();
  308. _descriptionController.text =
  309. _harvest.description ?? "";
  310. try {
  311. executeTime =
  312. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  313. .parse(_harvest.executeDate);
  314. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  315. .format(executeTime);
  316. } catch (_) {}
  317. //Show media
  318. if (_harvest.media != null) {
  319. await UtilAction.cacheFiles(_harvest.media)
  320. .then((value) {
  321. BlocProvider.of<MediaHelperBloc>(context)
  322. .add(ChangeListMedia(items: value));
  323. }).whenComplete(() {
  324. print("completed");
  325. });
  326. }
  327. } else if (state is ActionDetailInitial) {
  328. } else if (state is ActionDetailLoading) {
  329. LoadingDialog.showLoadingDialog(context);
  330. }
  331. },
  332. builder: (context, state) {
  333. return Column(
  334. children: <Widget>[
  335. Container(
  336. width: double.infinity,
  337. child: Text(
  338. "Ngày thực hiện",
  339. style: TextStyle(
  340. color: Colors.black54, fontSize: 13.0),
  341. ),
  342. ),
  343. _btnExecuteTimePicker(),
  344. SizedBox(
  345. height: 8.0,
  346. ),
  347. _l1Field(),
  348. SizedBox(
  349. height: 8.0,
  350. ),
  351. _l2Field(),
  352. SizedBox(
  353. height: 8.0,
  354. ),
  355. _l3Field(),
  356. SizedBox(
  357. height: 8.0,
  358. ),
  359. _removedQuantityField(),
  360. SizedBox(
  361. height: 8.0,
  362. ),
  363. _descriptionField(),
  364. SizedBox(
  365. height: 8.0,
  366. ),
  367. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  368. builder: (context, state) {
  369. if (state is MediaHelperSuccess) {
  370. return WidgetMediaPicker(
  371. currentItems: state.items,
  372. onChangeFiles: (filePaths) async {
  373. Get.find<ChangeFileController>()
  374. .addAllFile(filePaths);
  375. });
  376. } else {
  377. return Center(
  378. child: CircularProgressIndicator());
  379. }
  380. }),
  381. IconButton(
  382. icon: Icon(Icons.ac_unit),
  383. onPressed: () {
  384. Get.to(EditActionPackingScreen(
  385. cropId: widget.cropId));
  386. })
  387. ],
  388. );
  389. },
  390. ),
  391. )),
  392. ))));
  393. @override
  394. void dispose() {
  395. _l1Controller.dispose();
  396. _l2Controller.dispose();
  397. _l3Controller.dispose();
  398. _removedQuantityController.dispose();
  399. _descriptionController.dispose();
  400. super.dispose();
  401. }
  402. }