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.

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