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.

498 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>().files;
  75. try {
  76. var activityHarvest = jsonEncode(_harvest.toJson()).toString();
  77. //ADD NEW
  78. if (_harvest.activityId == null) {
  79. _repository.createAction((value) {
  80. LoadingDialog.hideLoadingDialog(context);
  81. Get.back(result: value);
  82. Utils.showSnackBarSuccess(message: label_add_success);
  83. }, (error) {
  84. LoadingDialog.hideLoadingDialog(context);
  85. Utils.showSnackBarError(message: AppException.handleError(error));
  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. Utils.showSnackBarSuccess(message: label_update_success);
  97. }, (error) {
  98. LoadingDialog.hideLoadingDialog(context);
  99. Utils.showSnackBarError(message: AppException.handleError(error));
  100. },
  101. apiUpdateAction: ConstCommon.apiUpdateHarvest,
  102. paramActivity: ConstCommon.paramsActionHarvest,
  103. activityAction: activityHarvest,
  104. filePaths: filePaths);
  105. }
  106. } catch (e) {
  107. LoadingDialog.hideLoadingDialog(context);
  108. print(e.toString());
  109. }
  110. } else {
  111. _autoValidate = true;
  112. }
  113. }
  114. Widget _btnExecuteTimePicker() {
  115. return FlatButton(
  116. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  117. onPressed: () {
  118. DatePicker.showDateTimePicker(context,
  119. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  120. setState(() {
  121. var parsedDate =
  122. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  123. _harvest.executeDate = "$parsedDate";
  124. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  125. });
  126. }, currentTime: executeTime, locale: LocaleType.vi);
  127. },
  128. child: Container(
  129. padding:
  130. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  131. decoration: BoxDecoration(
  132. border: kBorderTextField,
  133. ),
  134. child: Row(
  135. children: [
  136. Expanded(
  137. child: Text(
  138. //TODO: check condition
  139. executeTimeView == null ? "$executeTime" : executeTimeView,
  140. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  141. )),
  142. Icon(
  143. Icons.date_range,
  144. color: Colors.blue,
  145. ),
  146. ],
  147. )));
  148. }
  149. Widget _l1Field() {
  150. return TextFormField(
  151. keyboardType: TextInputType.numberWithOptions(decimal: true),
  152. inputFormatters: [
  153. ThousandsFormatter(
  154. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  155. ],
  156. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 1"),
  157. controller: _l1Controller,
  158. onSaved: (newValue) {
  159. _harvest.collectedQuantityLv1 = newValue.parseDoubleThousand();
  160. },
  161. );
  162. }
  163. Widget _l2Field() {
  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 2"),
  171. controller: _l2Controller,
  172. onSaved: (newValue) {
  173. _harvest.collectedQuantityLv2 = newValue.parseDoubleThousand();
  174. },
  175. );
  176. }
  177. Widget _l3Field() {
  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 3"),
  185. controller: _l3Controller,
  186. onSaved: (newValue) {
  187. _harvest.collectedQuantityLv3 = newValue.parseDoubleThousand();
  188. },
  189. );
  190. }
  191. Widget _removedQuantityField() {
  192. return TextFormField(
  193. keyboardType: TextInputType.numberWithOptions(decimal: true),
  194. inputFormatters: [
  195. ThousandsFormatter(
  196. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  197. ],
  198. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại bỏ"),
  199. controller: _removedQuantityController,
  200. onSaved: (newValue) {
  201. _harvest.removedQuantity = newValue.parseDoubleThousand();
  202. },
  203. );
  204. }
  205. Widget _descriptionField() {
  206. return TextFormField(
  207. keyboardType: TextInputType.text,
  208. decoration: InputDecoration(labelText: "Ghi chú"),
  209. controller: _descriptionController,
  210. onSaved: (newValue) {
  211. _harvest.description = newValue;
  212. },
  213. );
  214. }
  215. Widget _executeByField() {
  216. return TextFormField(
  217. keyboardType: TextInputType.text,
  218. decoration: InputDecoration(labelText: "Người thực hiện"),
  219. enabled: false,
  220. controller: _executeByController,
  221. onSaved: (newValue) {},
  222. );
  223. }
  224. _actionAppBar() {
  225. IconButton iconButton;
  226. if (1 == 1) {
  227. iconButton = IconButton(
  228. icon: Icon(
  229. Icons.done,
  230. color: Colors.black,
  231. ),
  232. onPressed: () {
  233. FocusScopeNode currentFocus = FocusScope.of(context);
  234. if (!currentFocus.hasPrimaryFocus) {
  235. currentFocus.unfocus();
  236. }
  237. _validateInputs();
  238. },
  239. );
  240. return <Widget>[iconButton];
  241. }
  242. return <Widget>[Container()];
  243. }
  244. @override
  245. Widget build(BuildContext context) => KeyboardDismisser(
  246. gestures: [
  247. GestureType.onTap,
  248. GestureType.onPanUpdateDownDirection,
  249. ],
  250. child: Scaffold(
  251. key: _scaffoldKey,
  252. appBar: AppBar(
  253. centerTitle: true,
  254. title: Text(plot_action_harvest),
  255. actions: _actionAppBar()),
  256. body: KeyboardDismisser(
  257. child: MultiBlocProvider(
  258. providers: [
  259. BlocProvider<ActionDetailBloc>(
  260. create: (context) =>
  261. ActionDetailBloc(repository: Repository())
  262. ..add(FetchData(
  263. isNeedFetchData: widget.isEdit,
  264. apiActivity: ConstCommon.apiDetailHarvest,
  265. activityId: widget.activityId))),
  266. BlocProvider<MediaHelperBloc>(
  267. create: (context) =>
  268. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  269. )
  270. ],
  271. child: Form(
  272. key: _formKey,
  273. autovalidate: _autoValidate,
  274. child: SingleChildScrollView(
  275. padding: EdgeInsets.all(8.0),
  276. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  277. listener: (context, state) async {
  278. if (state is ActionDetailFailure) {
  279. LoadingDialog.hideLoadingDialog(context);
  280. } else if (state is ActionDetailSuccess) {
  281. LoadingDialog.hideLoadingDialog(context);
  282. print(state.item);
  283. _harvest = Harvest.fromJson(state.item);
  284. _harvest.activityId = widget.activityId;
  285. _l1Controller.text = _harvest.collectedQuantityLv1
  286. .formatNumtoStringDecimal();
  287. _l2Controller.text = _harvest.collectedQuantityLv2
  288. .formatNumtoStringDecimal();
  289. _l3Controller.text = _harvest.collectedQuantityLv3
  290. .formatNumtoStringDecimal();
  291. _removedQuantityController.text = _harvest
  292. .removedQuantity
  293. .formatNumtoStringDecimal();
  294. _descriptionController.text =
  295. _harvest.description ?? "";
  296. _executeByController.text = _harvest.executeBy;
  297. try {
  298. executeTime =
  299. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  300. .parse(_harvest.executeDate);
  301. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  302. .format(executeTime);
  303. } catch (_) {}
  304. //Show media
  305. if (_harvest.media != null) {
  306. await UtilAction.cacheFiles(_harvest.media)
  307. .then((value) {
  308. BlocProvider.of<MediaHelperBloc>(context)
  309. .add(ChangeListMedia(items: value));
  310. }).whenComplete(() {
  311. print("completed");
  312. });
  313. }
  314. } else if (state is ActionDetailInitial) {
  315. } else if (state is ActionDetailLoading) {
  316. LoadingDialog.showLoadingDialog(context);
  317. }
  318. },
  319. builder: (context, state) {
  320. return Column(
  321. children: <Widget>[
  322. Container(
  323. width: double.infinity,
  324. child: Text(
  325. "Ngày thực hiện *",
  326. style: TextStyle(
  327. color: Colors.black54, fontSize: 13.0),
  328. ),
  329. ),
  330. _btnExecuteTimePicker(),
  331. SizedBox(
  332. height: 8.0,
  333. ),
  334. _l1Field(),
  335. SizedBox(
  336. height: 8.0,
  337. ),
  338. _l2Field(),
  339. SizedBox(
  340. height: 8.0,
  341. ),
  342. _l3Field(),
  343. SizedBox(
  344. height: 8.0,
  345. ),
  346. _removedQuantityField(),
  347. SizedBox(
  348. height: 8.0,
  349. ),
  350. _descriptionField(),
  351. SizedBox(
  352. height: 8.0,
  353. ),
  354. _executeByField(),
  355. SizedBox(
  356. height: 8.0,
  357. ),
  358. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  359. builder: (context, state) {
  360. if (state is MediaHelperSuccess) {
  361. return WidgetMediaPicker(
  362. currentItems: state.items,
  363. onChangeFiles: (filePaths) async {
  364. Get.find<ChangeFileController>()
  365. .addAllFile(filePaths);
  366. });
  367. } else {
  368. return Center(
  369. child: CircularProgressIndicator());
  370. }
  371. }),
  372. Row(
  373. mainAxisAlignment:
  374. MainAxisAlignment.spaceBetween,
  375. children: [
  376. SizedBox(
  377. width: Get.width / 2 - 16,
  378. child: FlatButton(
  379. padding: EdgeInsets.all(14),
  380. shape: RoundedRectangleBorder(
  381. borderRadius:
  382. new BorderRadius.circular(8.0)),
  383. color: Colors.lightGreen,
  384. onPressed: () {
  385. if (_harvest.id != null) {
  386. Get.to(EditActionHarvestProcessScreen(
  387. cropId: widget.cropId,
  388. harvestId: _harvest.id,
  389. ));
  390. } else {
  391. Get.to(EditActionHarvestProcessScreen(
  392. cropId: widget.cropId));
  393. }
  394. },
  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. _executeByController.dispose();
  478. super.dispose();
  479. }
  480. }