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.

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