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.

495 lines
21KB

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