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.

411 lines
16KB

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