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.

527 lines
20KB

  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/screens/actions/bloc/action_detail_bloc.dart';
  10. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  11. import 'package:farm_tpf/utils/const_common.dart';
  12. import 'package:farm_tpf/utils/const_string.dart';
  13. import 'package:farm_tpf/utils/const_style.dart';
  14. import 'package:farm_tpf/utils/pref.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 '../bloc_get_harvest.dart';
  25. import '../util_action.dart';
  26. class EditActionSellScreen extends StatefulWidget {
  27. final int cropId;
  28. final bool isEdit;
  29. final int activityId;
  30. final int harvestId;
  31. EditActionSellScreen(
  32. {@required this.cropId,
  33. this.isEdit = false,
  34. this.activityId,
  35. this.harvestId});
  36. @override
  37. _EditActionSellScreenState createState() => _EditActionSellScreenState();
  38. }
  39. class _EditActionSellScreenState extends State<EditActionSellScreen> {
  40. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  41. final _repository = Repository();
  42. GlobalKey<FormState> _formKey = GlobalKey();
  43. bool _autoValidate = false;
  44. Sell _sell = Sell();
  45. TextEditingController _l1Controller = TextEditingController();
  46. TextEditingController _l2Controller = TextEditingController();
  47. TextEditingController _l3Controller = TextEditingController();
  48. TextEditingController _removedQuantityController = TextEditingController();
  49. TextEditingController _descriptionController = TextEditingController();
  50. final _buyerController = 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. _sell.executeDate = "$parsedExecuteDate";
  71. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  72. _sell.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 activitySell = jsonEncode(_sell.toJson()).toString();
  92. //ADD NEW
  93. if (_sell.activityId == null) {
  94. _repository.createAction((value) {
  95. LoadingDialog.hideLoadingDialog(context);
  96. Get.back(result: value);
  97. Get.snackbar(label_add_success, "Hoạt động xuất bán",
  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.apiAddSell,
  114. paramActivity: ConstCommon.paramsActionSell,
  115. activityAction: activitySell,
  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 xuất bán",
  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.apiUpdateSell,
  139. paramActivity: ConstCommon.paramsActionSell,
  140. activityAction: activitySell,
  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. _sell.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. _sell.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. _sell.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. _sell.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. _sell.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. _sell.removedQuantity = newValue.parseDoubleThousand();
  284. },
  285. );
  286. }
  287. Widget _buyerField() {
  288. return TextFormField(
  289. keyboardType: TextInputType.text,
  290. decoration: InputDecoration(labelText: "Khách hàng"),
  291. controller: _buyerController,
  292. validator: (String value) {
  293. return Validators.validateNotNullOrEmpty(value, "Khách hàng");
  294. },
  295. onSaved: (newValue) {
  296. _sell.buyer = newValue;
  297. },
  298. );
  299. }
  300. Widget _descriptionField() {
  301. return TextFormField(
  302. keyboardType: TextInputType.text,
  303. decoration: InputDecoration(labelText: "Ghi chú"),
  304. controller: _descriptionController,
  305. onSaved: (newValue) {
  306. _sell.description = newValue;
  307. },
  308. );
  309. }
  310. Widget _executeByField() {
  311. return TextFormField(
  312. keyboardType: TextInputType.text,
  313. decoration: InputDecoration(labelText: "Người thực hiện"),
  314. enabled: false,
  315. controller: _executeByController,
  316. onSaved: (newValue) {},
  317. );
  318. }
  319. _actionAppBar() {
  320. IconButton iconButton;
  321. if (1 == 1) {
  322. iconButton = IconButton(
  323. icon: Icon(
  324. Icons.done,
  325. color: Colors.black,
  326. ),
  327. onPressed: () {
  328. FocusScopeNode currentFocus = FocusScope.of(context);
  329. if (!currentFocus.hasPrimaryFocus) {
  330. currentFocus.unfocus();
  331. }
  332. _validateInputs();
  333. },
  334. );
  335. return <Widget>[iconButton];
  336. }
  337. return <Widget>[Container()];
  338. }
  339. @override
  340. Widget build(BuildContext context) => KeyboardDismisser(
  341. gestures: [
  342. GestureType.onTap,
  343. GestureType.onPanUpdateDownDirection,
  344. ],
  345. child: Scaffold(
  346. key: _scaffoldKey,
  347. appBar: AppBar(
  348. centerTitle: true,
  349. title: Text(plot_action_sell),
  350. actions: _actionAppBar()),
  351. body: KeyboardDismisser(
  352. child: MultiBlocProvider(
  353. providers: [
  354. BlocProvider<ActionDetailBloc>(
  355. create: (context) =>
  356. ActionDetailBloc(repository: Repository())
  357. ..add(FetchData(
  358. isNeedFetchData: widget.isEdit,
  359. apiActivity: ConstCommon.apiDetailSell,
  360. activityId: widget.activityId))),
  361. BlocProvider<MediaHelperBloc>(
  362. create: (context) =>
  363. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  364. )
  365. ],
  366. child: Form(
  367. key: _formKey,
  368. autovalidate: _autoValidate,
  369. child: SingleChildScrollView(
  370. padding: EdgeInsets.all(8.0),
  371. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  372. listener: (context, state) async {
  373. if (state is ActionDetailFailure) {
  374. LoadingDialog.hideLoadingDialog(context);
  375. } else if (state is ActionDetailSuccess) {
  376. LoadingDialog.hideLoadingDialog(context);
  377. print(state.item);
  378. _sell = Sell.fromJson(state.item);
  379. _sell.activityId = widget.activityId;
  380. _l1Controller.text =
  381. _sell.quantityLv1.formatNumtoStringDecimal();
  382. _l2Controller.text =
  383. _sell.quantityLv2.formatNumtoStringDecimal();
  384. _l3Controller.text =
  385. _sell.quantityLv3.formatNumtoStringDecimal();
  386. _removedQuantityController.text = _sell
  387. .removedQuantity
  388. .formatNumtoStringDecimal();
  389. _buyerController.text = _sell.buyer ?? "";
  390. _descriptionController.text =
  391. _sell.description ?? "";
  392. _executeByController.text = _sell.executeBy;
  393. //select harvest
  394. getHarvestBloc.getHarvests((data) {
  395. _harvests = data;
  396. for (var item in _harvests) {
  397. if (item.id == _sell.harvestId) {
  398. harvestValue = item;
  399. break;
  400. }
  401. }
  402. }, (err) {});
  403. try {
  404. executeTime =
  405. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  406. .parse(_sell.executeDate);
  407. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  408. .format(executeTime);
  409. } catch (_) {}
  410. //Show media
  411. if (_sell.media != null) {
  412. await UtilAction.cacheFiles(_sell.media)
  413. .then((value) {
  414. BlocProvider.of<MediaHelperBloc>(context)
  415. .add(ChangeListMedia(items: value));
  416. }).whenComplete(() {
  417. print("completed");
  418. });
  419. }
  420. } else if (state is ActionDetailInitial) {
  421. } else if (state is ActionDetailLoading) {
  422. LoadingDialog.showLoadingDialog(context);
  423. }
  424. },
  425. builder: (context, state) {
  426. return Column(
  427. children: <Widget>[
  428. Container(
  429. width: double.infinity,
  430. child: Text(
  431. "Ngày thực hiện",
  432. style: TextStyle(
  433. color: Colors.black54, fontSize: 13.0),
  434. ),
  435. ),
  436. _btnExecuteTimePicker(),
  437. SizedBox(
  438. height: 8.0,
  439. ),
  440. _dropdownHarvest(),
  441. SizedBox(
  442. height: 8.0,
  443. ),
  444. _l1Field(),
  445. SizedBox(
  446. height: 8.0,
  447. ),
  448. _l2Field(),
  449. SizedBox(
  450. height: 8.0,
  451. ),
  452. _l3Field(),
  453. SizedBox(
  454. height: 8.0,
  455. ),
  456. _removedQuantityField(),
  457. SizedBox(
  458. height: 8.0,
  459. ),
  460. _buyerField(),
  461. SizedBox(
  462. height: 8.0,
  463. ),
  464. _descriptionField(),
  465. SizedBox(
  466. height: 8.0,
  467. ),
  468. _executeByField(),
  469. SizedBox(
  470. height: 8.0,
  471. ),
  472. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  473. builder: (context, state) {
  474. if (state is MediaHelperSuccess) {
  475. return WidgetMediaPicker(
  476. currentItems: state.items,
  477. onChangeFiles: (filePaths) async {
  478. Get.find<ChangeFileController>()
  479. .addAllFile(filePaths);
  480. });
  481. } else {
  482. return Center(
  483. child: CircularProgressIndicator());
  484. }
  485. }),
  486. ],
  487. );
  488. },
  489. ),
  490. )),
  491. ))));
  492. @override
  493. void dispose() {
  494. _l1Controller.dispose();
  495. _l2Controller.dispose();
  496. _l3Controller.dispose();
  497. _removedQuantityController.dispose();
  498. _descriptionController.dispose();
  499. _buyerController.dispose();
  500. _executeByController.dispose();
  501. super.dispose();
  502. }
  503. }