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.

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