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.

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