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