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.

470 lines
18KB

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