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.

453 lines
19KB

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