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.

473 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/custom_widgets/widget_utils.dart';
  10. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  11. import 'package:farm_tpf/presentation/screens/actions/bloc_get_harvest.dart';
  12. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.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: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. Utils.showSnackBarSuccess(message: label_add_success);
  98. }, (error) {
  99. LoadingDialog.hideLoadingDialog(context);
  100. Utils.showSnackBarError(message: AppException.handleError(error));
  101. },
  102. apiAddAction: ConstCommon.apiAddPacking,
  103. paramActivity: ConstCommon.paramsActionPacking,
  104. activityAction: activityPacking,
  105. filePaths: filePaths);
  106. } else {
  107. //UPDATE
  108. _repository.updateAction((value) {
  109. LoadingDialog.hideLoadingDialog(context);
  110. Get.back(result: value);
  111. Utils.showSnackBarSuccess(message: label_update_success);
  112. }, (error) {
  113. LoadingDialog.hideLoadingDialog(context);
  114. Utils.showSnackBarError(message: AppException.handleError(error));
  115. },
  116. apiUpdateAction: ConstCommon.apiUpdatePacking,
  117. paramActivity: ConstCommon.paramsActionPacking,
  118. activityAction: activityPacking,
  119. filePaths: filePaths);
  120. }
  121. } catch (e) {
  122. LoadingDialog.hideLoadingDialog(context);
  123. print(e.toString());
  124. }
  125. } else {
  126. _autoValidate = true;
  127. }
  128. }
  129. List<DropdownMenuItem<Harvest>> _buildDropMenu(List<Harvest> actions) {
  130. return actions
  131. .map((action) => DropdownMenuItem<Harvest>(
  132. child: Text("Mã thu hoạch " + action.id.toString()),
  133. value: action,
  134. ))
  135. .toList();
  136. }
  137. Widget _dropdownHarvest() {
  138. return StreamBuilder(
  139. stream: getHarvestBloc.actions,
  140. builder: (context, AsyncSnapshot<dynamic> snapshot) {
  141. if (snapshot.hasData) {
  142. return DropdownButtonFormField<Harvest>(
  143. value: harvestValue,
  144. hint: Text("Mã thu hoạch *"),
  145. onChanged: (Harvest newValue) {
  146. setState(() {
  147. harvestValue = newValue;
  148. _packing.harvestId = newValue.id;
  149. });
  150. },
  151. isExpanded: true,
  152. items: _buildDropMenu(_harvests));
  153. } else {
  154. return Center(
  155. child: CircularProgressIndicator(),
  156. );
  157. }
  158. },
  159. );
  160. }
  161. Widget _btnExecuteTimePicker() {
  162. return FlatButton(
  163. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  164. onPressed: () {
  165. DatePicker.showDateTimePicker(context,
  166. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  167. setState(() {
  168. var parsedDate =
  169. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  170. _packing.executeDate = "$parsedDate";
  171. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  172. });
  173. }, currentTime: executeTime, locale: LocaleType.vi);
  174. },
  175. child: Container(
  176. padding:
  177. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  178. decoration: BoxDecoration(
  179. border: kBorderTextField,
  180. ),
  181. child: Row(
  182. children: [
  183. Expanded(
  184. child: Text(
  185. //TODO: check condition
  186. executeTimeView == null ? "$executeTime" : executeTimeView,
  187. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  188. )),
  189. Icon(
  190. Icons.date_range,
  191. color: Colors.blue,
  192. ),
  193. ],
  194. )));
  195. }
  196. Widget _l1Field() {
  197. return TextFormField(
  198. keyboardType: TextInputType.numberWithOptions(decimal: true),
  199. inputFormatters: [
  200. ThousandsFormatter(
  201. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  202. ],
  203. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 1"),
  204. controller: _l1Controller,
  205. onSaved: (newValue) {
  206. _packing.quantityLv1 = newValue.parseDoubleThousand();
  207. },
  208. );
  209. }
  210. Widget _l2Field() {
  211. return TextFormField(
  212. keyboardType: TextInputType.numberWithOptions(decimal: true),
  213. inputFormatters: [
  214. ThousandsFormatter(
  215. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  216. ],
  217. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 2"),
  218. controller: _l2Controller,
  219. onSaved: (newValue) {
  220. _packing.quantityLv2 = newValue.parseDoubleThousand();
  221. },
  222. );
  223. }
  224. Widget _l3Field() {
  225. return TextFormField(
  226. keyboardType: TextInputType.numberWithOptions(decimal: true),
  227. inputFormatters: [
  228. ThousandsFormatter(
  229. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  230. ],
  231. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại 3"),
  232. controller: _l3Controller,
  233. onSaved: (newValue) {
  234. _packing.quantityLv3 = newValue.parseDoubleThousand();
  235. },
  236. );
  237. }
  238. Widget _removedQuantityField() {
  239. return TextFormField(
  240. keyboardType: TextInputType.numberWithOptions(decimal: true),
  241. inputFormatters: [
  242. ThousandsFormatter(
  243. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  244. ],
  245. decoration: InputDecoration(labelText: "Số lượng/khối lượng loại bỏ"),
  246. controller: _removedQuantityController,
  247. onSaved: (newValue) {
  248. _packing.removedQuantity = newValue.parseDoubleThousand();
  249. },
  250. );
  251. }
  252. Widget _descriptionField() {
  253. return TextFormField(
  254. keyboardType: TextInputType.text,
  255. decoration: InputDecoration(labelText: "Ghi chú"),
  256. controller: _descriptionController,
  257. onSaved: (newValue) {
  258. _packing.description = newValue;
  259. },
  260. );
  261. }
  262. Widget _executeByField() {
  263. return TextFormField(
  264. keyboardType: TextInputType.text,
  265. decoration: InputDecoration(labelText: "Người thực hiện"),
  266. enabled: false,
  267. controller: _executeByController,
  268. onSaved: (newValue) {},
  269. );
  270. }
  271. _actionAppBar() {
  272. IconButton iconButton;
  273. if (1 == 1) {
  274. iconButton = IconButton(
  275. icon: Icon(
  276. Icons.done,
  277. color: Colors.black,
  278. ),
  279. onPressed: () {
  280. FocusScopeNode currentFocus = FocusScope.of(context);
  281. if (!currentFocus.hasPrimaryFocus) {
  282. currentFocus.unfocus();
  283. }
  284. _validateInputs();
  285. },
  286. );
  287. return <Widget>[iconButton];
  288. }
  289. return <Widget>[Container()];
  290. }
  291. @override
  292. Widget build(BuildContext context) => KeyboardDismisser(
  293. gestures: [
  294. GestureType.onTap,
  295. GestureType.onPanUpdateDownDirection,
  296. ],
  297. child: Scaffold(
  298. key: _scaffoldKey,
  299. appBar: AppBar(
  300. centerTitle: true,
  301. title: Text(plot_action_packing),
  302. actions: _actionAppBar()),
  303. body: KeyboardDismisser(
  304. child: MultiBlocProvider(
  305. providers: [
  306. BlocProvider<ActionDetailBloc>(
  307. create: (context) =>
  308. ActionDetailBloc(repository: Repository())
  309. ..add(FetchData(
  310. isNeedFetchData: widget.isEdit,
  311. apiActivity: ConstCommon.apiDetailPacking,
  312. activityId: widget.activityId))),
  313. BlocProvider<MediaHelperBloc>(
  314. create: (context) =>
  315. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  316. )
  317. ],
  318. child: Form(
  319. key: _formKey,
  320. autovalidate: _autoValidate,
  321. child: SingleChildScrollView(
  322. padding: EdgeInsets.all(8.0),
  323. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  324. listener: (context, state) async {
  325. if (state is ActionDetailFailure) {
  326. LoadingDialog.hideLoadingDialog(context);
  327. } else if (state is ActionDetailSuccess) {
  328. LoadingDialog.hideLoadingDialog(context);
  329. print(state.item);
  330. _packing = Packing.fromJson(state.item);
  331. _packing.activityId = widget.activityId;
  332. _l1Controller.text =
  333. _packing.quantityLv1.formatNumtoStringDecimal();
  334. _l2Controller.text =
  335. _packing.quantityLv2.formatNumtoStringDecimal();
  336. _l3Controller.text =
  337. _packing.quantityLv3.formatNumtoStringDecimal();
  338. _removedQuantityController.text = _packing
  339. .removedQuantity
  340. .formatNumtoStringDecimal();
  341. _descriptionController.text =
  342. _packing.description ?? "";
  343. _executeByController.text = _packing.executeBy;
  344. //select harvest
  345. getHarvestBloc.getHarvests((data) {
  346. _harvests = data;
  347. for (var item in _harvests) {
  348. if (item.id == _packing.harvestId) {
  349. harvestValue = item;
  350. break;
  351. }
  352. }
  353. }, (err) {});
  354. try {
  355. executeTime =
  356. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  357. .parse(_packing.executeDate);
  358. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  359. .format(executeTime);
  360. } catch (_) {}
  361. //Show media
  362. if (_packing.media != null) {
  363. await UtilAction.cacheFiles(_packing.media)
  364. .then((value) {
  365. BlocProvider.of<MediaHelperBloc>(context)
  366. .add(ChangeListMedia(items: value));
  367. }).whenComplete(() {
  368. print("completed");
  369. });
  370. }
  371. } else if (state is ActionDetailInitial) {
  372. } else if (state is ActionDetailLoading) {
  373. LoadingDialog.showLoadingDialog(context);
  374. }
  375. },
  376. builder: (context, state) {
  377. return Column(
  378. children: <Widget>[
  379. Container(
  380. width: double.infinity,
  381. child: Text(
  382. "Ngày thực hiện *",
  383. style: TextStyle(
  384. color: Colors.black54, fontSize: 13.0),
  385. ),
  386. ),
  387. _btnExecuteTimePicker(),
  388. SizedBox(
  389. height: 8.0,
  390. ),
  391. _dropdownHarvest(),
  392. SizedBox(
  393. height: 8.0,
  394. ),
  395. _l1Field(),
  396. SizedBox(
  397. height: 8.0,
  398. ),
  399. _l2Field(),
  400. SizedBox(
  401. height: 8.0,
  402. ),
  403. _l3Field(),
  404. SizedBox(
  405. height: 8.0,
  406. ),
  407. _removedQuantityField(),
  408. SizedBox(
  409. height: 8.0,
  410. ),
  411. _descriptionField(),
  412. SizedBox(
  413. height: 8.0,
  414. ),
  415. _executeByField(),
  416. SizedBox(
  417. height: 8.0,
  418. ),
  419. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  420. builder: (context, state) {
  421. if (state is MediaHelperSuccess) {
  422. return WidgetMediaPicker(
  423. currentItems: state.items,
  424. onChangeFiles: (filePaths) async {
  425. Get.find<ChangeFileController>()
  426. .addAllFile(filePaths);
  427. });
  428. } else {
  429. return Center(
  430. child: CircularProgressIndicator());
  431. }
  432. }),
  433. ],
  434. );
  435. },
  436. ),
  437. )),
  438. ))));
  439. @override
  440. void dispose() {
  441. _l1Controller.dispose();
  442. _l2Controller.dispose();
  443. _l3Controller.dispose();
  444. _removedQuantityController.dispose();
  445. _descriptionController.dispose();
  446. _executeByController.dispose();
  447. super.dispose();
  448. }
  449. }