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.

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