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.

483 lines
18KB

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