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.

508 lines
19KB

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