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.

417 lines
16KB

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