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.

502 lines
19KB

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