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.

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