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.

392 lines
16KB

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