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.

495 lines
19KB

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