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.

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