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.

380 lines
16KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/Plant.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/plant/widget_plant_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/services.dart';
  23. import 'package:flutter_bloc/flutter_bloc.dart';
  24. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  25. import 'package:get/get.dart';
  26. import 'package:intl/intl.dart';
  27. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  28. import 'package:pattern_formatter/pattern_formatter.dart';
  29. import 'package:farm_tpf/utils/formatter.dart';
  30. import '../util_action.dart';
  31. class EditActionPlantScreen extends StatefulWidget {
  32. final int cropId;
  33. final bool isEdit;
  34. final int activityId;
  35. EditActionPlantScreen(
  36. {@required this.cropId, this.isEdit = false, this.activityId});
  37. @override
  38. _EditActionPlantScreenState createState() => _EditActionPlantScreenState();
  39. }
  40. class _EditActionPlantScreenState extends State<EditActionPlantScreen> {
  41. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  42. final _repository = Repository();
  43. GlobalKey<FormState> _formKey = GlobalKey();
  44. bool _autoValidate = false;
  45. Plant _plant = Plant();
  46. var pref = LocalPref();
  47. final _descriptionController = TextEditingController();
  48. final _quantityController = TextEditingController();
  49. final _densityController = TextEditingController();
  50. final _executeByController = TextEditingController();
  51. List<SuppliesUsing> suppliesUsing = new List<SuppliesUsing>();
  52. String executeTimeView;
  53. DateTime executeTime = DateTime.now();
  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. _plant.suppliesUsing = new List<SuppliesUsing>();
  66. var parsedExecuteDate =
  67. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  68. _plant.executeDate = "$parsedExecuteDate";
  69. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  70. _plant.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. newSups.add(newSup);
  82. });
  83. _plant.suppliesUsing = newSups;
  84. _plant.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  85. var activityPlant = jsonEncode(_plant.toJson()).toString();
  86. //ADD NEW
  87. if (_plant.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.apiAddPlant,
  97. paramActivity: ConstCommon.paramsActionPlant,
  98. activityAction: activityPlant,
  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.apiUpdatePlant,
  111. paramActivity: ConstCommon.paramsActionPlant,
  112. activityAction: activityPlant,
  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. _plant.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 _quantityField() {
  155. return WidgetTextFormFieldNumber(
  156. hintValue: "Số lượng cây trồng",
  157. textController: _quantityController,
  158. onSaved: (newValue) {
  159. _plant.quantity = newValue.parseDoubleThousand();
  160. },
  161. );
  162. }
  163. Widget _densityField() {
  164. return TextFormField(
  165. keyboardType: TextInputType.text,
  166. decoration: InputDecoration(labelText: "Mật độ"),
  167. controller: _densityController,
  168. onSaved: (newValue) {
  169. _plant.density = newValue;
  170. },
  171. );
  172. }
  173. Widget _desciptionField() {
  174. return TextFormField(
  175. keyboardType: TextInputType.text,
  176. decoration: InputDecoration(labelText: "Ghi chú"),
  177. controller: _descriptionController,
  178. onSaved: (newValue) {
  179. _plant.description = newValue;
  180. },
  181. );
  182. }
  183. Widget _executeByField() {
  184. return TextFormField(
  185. keyboardType: TextInputType.text,
  186. decoration: InputDecoration(labelText: "Người thực hiện"),
  187. enabled: false,
  188. controller: _executeByController,
  189. onSaved: (newValue) {},
  190. );
  191. }
  192. _actionAppBar() {
  193. IconButton iconButton;
  194. if (1 == 1) {
  195. iconButton = IconButton(
  196. icon: Icon(
  197. Icons.done,
  198. color: Colors.black,
  199. ),
  200. onPressed: () {
  201. FocusScopeNode currentFocus = FocusScope.of(context);
  202. if (!currentFocus.hasPrimaryFocus) {
  203. currentFocus.unfocus();
  204. }
  205. if (Get.find<ChangeSupply>().selectedSupplyId > 0) {
  206. Utils.showDialogConfirmSupply(onConfirm: () {
  207. Get.back();
  208. _validateInputs();
  209. });
  210. } else {
  211. _validateInputs();
  212. }
  213. },
  214. );
  215. return <Widget>[iconButton];
  216. }
  217. return <Widget>[Container()];
  218. }
  219. @override
  220. Widget build(BuildContext context) => KeyboardDismisser(
  221. gestures: [
  222. GestureType.onTap,
  223. GestureType.onPanUpdateDownDirection,
  224. ],
  225. child: Scaffold(
  226. key: _scaffoldKey,
  227. appBar: AppBar(
  228. centerTitle: true,
  229. title: Text(plot_action_plant),
  230. actions: _actionAppBar()),
  231. body: KeyboardDismisser(
  232. child: MultiBlocProvider(
  233. providers: [
  234. BlocProvider<ActionDetailBloc>(
  235. create: (context) =>
  236. ActionDetailBloc(repository: Repository())
  237. ..add(FetchData(
  238. isNeedFetchData: widget.isEdit,
  239. apiActivity: ConstCommon.apiDetailPlant,
  240. activityId: widget.activityId))),
  241. BlocProvider<MediaHelperBloc>(
  242. create: (context) =>
  243. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  244. )
  245. ],
  246. child: Form(
  247. key: _formKey,
  248. autovalidate: _autoValidate,
  249. child: SingleChildScrollView(
  250. padding: EdgeInsets.all(8.0),
  251. child: BlocConsumer<ActionDetailBloc,
  252. ActionDetailState>(
  253. listener: (context, state) async {
  254. if (state is ActionDetailFailure) {
  255. LoadingDialog.hideLoadingDialog(context);
  256. } else if (state is ActionDetailSuccess) {
  257. LoadingDialog.hideLoadingDialog(context);
  258. _plant = Plant.fromJson(state.item);
  259. _plant.activityId = widget.activityId;
  260. _quantityController.text = _plant.quantity
  261. .formatNumtoStringDecimal();
  262. _densityController.text = _plant.density;
  263. _descriptionController.text =
  264. _plant.description;
  265. _executeByController.text = _plant.executeBy;
  266. try {
  267. executeTime =
  268. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  269. .parse(_plant.executeDate);
  270. } catch (_) {}
  271. executeTimeView =
  272. DateFormat("dd/MM/yyyy HH:mm")
  273. .format(executeTime);
  274. //Show media
  275. if (Validators.stringNotNullOrEmpty(
  276. _plant.media)) {
  277. BlocProvider.of<MediaHelperBloc>(context)
  278. .add(ChangeListMedia(
  279. items: UtilAction
  280. .convertFilePathToMedia(
  281. _plant.media)));
  282. }
  283. //list supply
  284. suppliesUsing = _plant.suppliesUsing;
  285. Get.find<ChangeSupplyUsing>()
  286. .changeInitList(suppliesUsing);
  287. } else if (state is ActionDetailInitial) {
  288. print("init");
  289. } else if (state is ActionDetailLoading) {
  290. print("loading");
  291. LoadingDialog.showLoadingDialog(context);
  292. }
  293. },
  294. builder: (context, state) {
  295. return Column(
  296. children: <Widget>[
  297. Container(
  298. width: double.infinity,
  299. child: Text(
  300. "Ngày thực hiện *",
  301. style: TextStyle(
  302. color: Colors.black54,
  303. fontSize: 13.0),
  304. ),
  305. ),
  306. _btnExecuteTimePicker(),
  307. SizedBox(
  308. height: 8.0,
  309. ),
  310. _quantityField(),
  311. SizedBox(
  312. height: 8.0,
  313. ),
  314. _densityField(),
  315. SizedBox(
  316. height: 8.0,
  317. ),
  318. _desciptionField(),
  319. SizedBox(
  320. height: 8.0,
  321. ),
  322. _executeByField(),
  323. SizedBox(
  324. height: 8.0,
  325. ),
  326. WidgetPlantSupply(
  327. currentItems: [],
  328. onChangeSupplies: (value) {
  329. suppliesUsing = value;
  330. }),
  331. SizedBox(
  332. height: 8.0,
  333. ),
  334. BlocBuilder<MediaHelperBloc,
  335. MediaHelperState>(
  336. builder: (context, state) {
  337. if (state is MediaHelperSuccess) {
  338. return WidgetMediaPicker(
  339. currentItems: state.items,
  340. onChangeFiles: (newPathFiles,
  341. deletePathFiles) async {
  342. Get.find<ChangeFileController>()
  343. .change(newPathFiles,
  344. deletePathFiles);
  345. });
  346. } else {
  347. return Center(
  348. child: CircularProgressIndicator());
  349. }
  350. }),
  351. ],
  352. );
  353. },
  354. ),
  355. ))))));
  356. @override
  357. void dispose() {
  358. _quantityController.dispose();
  359. _densityController.dispose();
  360. _descriptionController.dispose();
  361. _executeByController.dispose();
  362. super.dispose();
  363. }
  364. }