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.

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