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.

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