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.

414 lines
17KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/Dung.dart';
  3. import 'package:farm_tpf/custom_model/SuppliesUsing.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/controller/ChangeSupplyUsing.dart';
  11. import 'package:farm_tpf/presentation/screens/actions/dung/widget_dung_supply.dart';
  12. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  13. import 'package:farm_tpf/utils/const_common.dart';
  14. import 'package:farm_tpf/utils/const_string.dart';
  15. import 'package:farm_tpf/utils/const_style.dart';
  16. import 'package:farm_tpf/utils/pref.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 '../util_action.dart';
  26. class EditActionDungScreen extends StatefulWidget {
  27. final int cropId;
  28. final bool isEdit;
  29. final int activityId;
  30. EditActionDungScreen(
  31. {@required this.cropId, this.isEdit = false, this.activityId});
  32. @override
  33. _EditActionDungScreenState createState() => _EditActionDungScreenState();
  34. }
  35. class _EditActionDungScreenState extends State<EditActionDungScreen> {
  36. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  37. final _repository = Repository();
  38. GlobalKey<FormState> _formKey = GlobalKey();
  39. bool _autoValidate = false;
  40. Dung _dung = Dung();
  41. var pref = LocalPref();
  42. final _descriptionController = TextEditingController();
  43. final _purposeController = TextEditingController();
  44. final _weatherController = TextEditingController();
  45. final _executeByController = TextEditingController();
  46. final _quarantinePeriodController = TextEditingController();
  47. List<SuppliesUsing> suppliesUsing = new List<SuppliesUsing>();
  48. String executeTimeView;
  49. DateTime executeTime = DateTime.now();
  50. List<String> filePaths = List<String>();
  51. var changeFileController = Get.put(ChangeFileController());
  52. Future<Null> getSharedPrefs() async {
  53. var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  54. _executeByController.text = currentFullName ?? "";
  55. }
  56. @override
  57. void initState() {
  58. super.initState();
  59. getSharedPrefs();
  60. changeFileController.initValue();
  61. _dung.suppliesUsing = new List<SuppliesUsing>();
  62. var parsedExecuteDate =
  63. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  64. _dung.executeDate = "$parsedExecuteDate";
  65. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  66. _dung.cropId = widget.cropId;
  67. }
  68. _validateInputs() async {
  69. if (_formKey.currentState.validate()) {
  70. _formKey.currentState.save();
  71. LoadingDialog.showLoadingDialog(context);
  72. filePaths = Get.find<ChangeFileController>().files;
  73. List<SuppliesUsing> newSups = [];
  74. suppliesUsing.forEach((sup) {
  75. var newSup = sup;
  76. newSup.suppliesInWarehouseId = sup.tbSuppliesInWarehouseId;
  77. newSup.equipmentOfCustomerId = sup.tbEquipmentOfCustomerId;
  78. newSups.add(newSup);
  79. });
  80. _dung.suppliesUsing = newSups;
  81. var activityDung = jsonEncode(_dung.toJson()).toString();
  82. //ADD NEW
  83. if (_dung.activityId == null) {
  84. _repository.createAction((value) {
  85. LoadingDialog.hideLoadingDialog(context);
  86. Get.back(result: value);
  87. Get.snackbar(label_add_success, "Hoạt động bón phân",
  88. snackPosition: SnackPosition.BOTTOM);
  89. }, (error) {
  90. LoadingDialog.hideLoadingDialog(context);
  91. _scaffoldKey.currentState.showSnackBar(SnackBar(
  92. content: Row(
  93. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  94. children: <Widget>[
  95. Flexible(child: Text(AppException.handleError(error))),
  96. Icon(Icons.error),
  97. ],
  98. ),
  99. backgroundColor: Colors.red,
  100. duration: Duration(seconds: 3),
  101. ));
  102. },
  103. apiAddAction: ConstCommon.apiAddDung,
  104. paramActivity: ConstCommon.paramsActionDung,
  105. activityAction: activityDung,
  106. filePaths: filePaths);
  107. } else {
  108. //UPDATE
  109. _repository.updateAction((value) {
  110. LoadingDialog.hideLoadingDialog(context);
  111. Get.back(result: value);
  112. Get.snackbar(label_update_success, "Hoạt động bón phân",
  113. snackPosition: SnackPosition.BOTTOM);
  114. }, (error) {
  115. LoadingDialog.hideLoadingDialog(context);
  116. _scaffoldKey.currentState.showSnackBar(SnackBar(
  117. content: Row(
  118. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  119. children: <Widget>[
  120. Flexible(child: Text(AppException.handleError(error))),
  121. Icon(Icons.error),
  122. ],
  123. ),
  124. backgroundColor: Colors.red,
  125. duration: Duration(seconds: 3),
  126. ));
  127. },
  128. apiUpdateAction: ConstCommon.apiUpdateDung,
  129. paramActivity: ConstCommon.paramsActionDung,
  130. activityAction: activityDung,
  131. filePaths: filePaths);
  132. }
  133. } else {
  134. _autoValidate = true;
  135. }
  136. }
  137. Widget _btnExecuteTimePicker() {
  138. return FlatButton(
  139. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  140. onPressed: () {
  141. DatePicker.showDateTimePicker(context,
  142. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  143. setState(() {
  144. var parsedDate =
  145. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  146. _dung.executeDate = "$parsedDate";
  147. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  148. });
  149. }, currentTime: executeTime, locale: LocaleType.vi);
  150. },
  151. child: Container(
  152. padding:
  153. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  154. decoration: BoxDecoration(
  155. border: kBorderTextField,
  156. ),
  157. child: Row(
  158. children: [
  159. Expanded(
  160. child: Text(
  161. //TODO: check condition
  162. executeTimeView == null ? "$executeTime" : executeTimeView,
  163. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  164. )),
  165. Icon(
  166. Icons.date_range,
  167. color: Colors.blue,
  168. ),
  169. ],
  170. )));
  171. }
  172. Widget _purposeField() {
  173. return TextFormField(
  174. keyboardType: TextInputType.text,
  175. decoration: InputDecoration(labelText: "Lý do sử dụng"),
  176. controller: _purposeController,
  177. onSaved: (newValue) {
  178. _dung.purpose = newValue;
  179. },
  180. );
  181. }
  182. Widget _quarantinePeriodField() {
  183. return TextFormField(
  184. keyboardType: TextInputType.numberWithOptions(decimal: true),
  185. inputFormatters: [
  186. ThousandsFormatter(
  187. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  188. ],
  189. decoration: InputDecoration(labelText: "Thời gian cách ly"),
  190. controller: _quarantinePeriodController,
  191. onSaved: (newValue) {
  192. _dung.quarantinePeriod = newValue.parseDoubleThousand();
  193. },
  194. );
  195. }
  196. Widget _weatherField() {
  197. return TextFormField(
  198. keyboardType: TextInputType.text,
  199. decoration: InputDecoration(labelText: "Thời tiết"),
  200. controller: _weatherController,
  201. onSaved: (newValue) {
  202. _dung.weatherConditions = newValue;
  203. },
  204. );
  205. }
  206. Widget _desciptionField() {
  207. return TextFormField(
  208. keyboardType: TextInputType.text,
  209. decoration: InputDecoration(labelText: "Ghi chú"),
  210. controller: _descriptionController,
  211. onSaved: (newValue) {
  212. _dung.description = newValue;
  213. },
  214. );
  215. }
  216. Widget _executeByField() {
  217. return TextFormField(
  218. keyboardType: TextInputType.text,
  219. decoration: InputDecoration(labelText: "Người thực hiện"),
  220. enabled: false,
  221. controller: _executeByController,
  222. onSaved: (newValue) {},
  223. );
  224. }
  225. _actionAppBar() {
  226. IconButton iconButton;
  227. if (1 == 1) {
  228. iconButton = IconButton(
  229. icon: Icon(
  230. Icons.done,
  231. color: Colors.black,
  232. ),
  233. onPressed: () {
  234. FocusScopeNode currentFocus = FocusScope.of(context);
  235. if (!currentFocus.hasPrimaryFocus) {
  236. currentFocus.unfocus();
  237. }
  238. _validateInputs();
  239. },
  240. );
  241. return <Widget>[iconButton];
  242. }
  243. return <Widget>[Container()];
  244. }
  245. @override
  246. Widget build(BuildContext context) => KeyboardDismisser(
  247. gestures: [
  248. GestureType.onTap,
  249. GestureType.onPanUpdateDownDirection,
  250. ],
  251. child: Scaffold(
  252. key: _scaffoldKey,
  253. appBar: AppBar(
  254. centerTitle: true,
  255. title: Text(plot_action_dung),
  256. actions: _actionAppBar()),
  257. body: KeyboardDismisser(
  258. child: MultiBlocProvider(
  259. providers: [
  260. BlocProvider<ActionDetailBloc>(
  261. create: (context) =>
  262. ActionDetailBloc(repository: Repository())
  263. ..add(FetchData(
  264. isNeedFetchData: widget.isEdit,
  265. apiActivity: ConstCommon.apiDetailDung,
  266. activityId: widget.activityId))),
  267. BlocProvider<MediaHelperBloc>(
  268. create: (context) =>
  269. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  270. )
  271. ],
  272. child: Form(
  273. key: _formKey,
  274. autovalidate: _autoValidate,
  275. child: SingleChildScrollView(
  276. padding: EdgeInsets.all(8.0),
  277. child: BlocConsumer<ActionDetailBloc,
  278. ActionDetailState>(
  279. listener: (context, state) async {
  280. if (state is ActionDetailFailure) {
  281. LoadingDialog.hideLoadingDialog(context);
  282. } else if (state is ActionDetailSuccess) {
  283. LoadingDialog.hideLoadingDialog(context);
  284. _dung = Dung.fromJson(state.item);
  285. _dung.activityId = widget.activityId;
  286. _purposeController.text = _dung.purpose ?? "";
  287. _quarantinePeriodController.text = _dung
  288. .quarantinePeriod
  289. .formatNumtoStringDecimal();
  290. _weatherController.text =
  291. _dung.weatherConditions ?? "";
  292. _descriptionController.text =
  293. _dung.description;
  294. _executeByController.text = _dung.executeBy;
  295. try {
  296. executeTime =
  297. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  298. .parse(_dung.executeDate);
  299. } catch (_) {}
  300. executeTimeView =
  301. DateFormat("dd/MM/yyyy HH:mm")
  302. .format(executeTime);
  303. //Show media
  304. if (_dung.media != null) {
  305. await UtilAction.cacheFiles(_dung.media)
  306. .then((value) {
  307. BlocProvider.of<MediaHelperBloc>(context)
  308. .add(ChangeListMedia(items: value));
  309. }).whenComplete(() {
  310. print("completed");
  311. });
  312. }
  313. //list supply
  314. suppliesUsing = _dung.suppliesUsing;
  315. Get.find<ChangeSupplyUsing>()
  316. .changeInitList(suppliesUsing);
  317. } else if (state is ActionDetailInitial) {
  318. print("init");
  319. } else if (state is ActionDetailLoading) {
  320. print("loading");
  321. LoadingDialog.showLoadingDialog(context);
  322. }
  323. },
  324. builder: (context, state) {
  325. return Column(
  326. children: <Widget>[
  327. Container(
  328. width: double.infinity,
  329. child: Text(
  330. "Ngày thực hiện *",
  331. style: TextStyle(
  332. color: Colors.black54,
  333. fontSize: 13.0),
  334. ),
  335. ),
  336. _btnExecuteTimePicker(),
  337. SizedBox(
  338. height: 8.0,
  339. ),
  340. _purposeField(),
  341. SizedBox(
  342. height: 8.0,
  343. ),
  344. _quarantinePeriodField(),
  345. SizedBox(
  346. height: 8.0,
  347. ),
  348. _weatherField(),
  349. SizedBox(
  350. height: 8.0,
  351. ),
  352. _desciptionField(),
  353. SizedBox(
  354. height: 8.0,
  355. ),
  356. _executeByField(),
  357. SizedBox(
  358. height: 8.0,
  359. ),
  360. WidgetDungSupply(
  361. currentItems: [],
  362. onChangeSupplies: (value) {
  363. suppliesUsing = value;
  364. }),
  365. SizedBox(
  366. height: 8.0,
  367. ),
  368. BlocBuilder<MediaHelperBloc,
  369. MediaHelperState>(
  370. builder: (context, state) {
  371. if (state is MediaHelperSuccess) {
  372. return WidgetMediaPicker(
  373. currentItems: state.items,
  374. onChangeFiles: (filePaths) async {
  375. Get.find<ChangeFileController>()
  376. .addAllFile(filePaths);
  377. });
  378. } else {
  379. return Center(
  380. child: CircularProgressIndicator());
  381. }
  382. }),
  383. ],
  384. );
  385. },
  386. ),
  387. ))))));
  388. @override
  389. void dispose() {
  390. _quarantinePeriodController.dispose();
  391. _purposeController.dispose();
  392. _weatherController.dispose();
  393. _descriptionController.dispose();
  394. _executeByController.dispose();
  395. super.dispose();
  396. }
  397. }