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.

520 lines
22KB

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