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.

373 lines
15KB

  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_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/plant/widget_plant_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:farm_tpf/utils/validators.dart';
  19. import 'package:flutter/material.dart';
  20. import 'package:flutter_bloc/flutter_bloc.dart';
  21. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  22. import 'package:get/get.dart';
  23. import 'package:intl/intl.dart';
  24. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  25. import 'package:pattern_formatter/pattern_formatter.dart';
  26. import 'package:farm_tpf/utils/formatter.dart';
  27. import '../util_action.dart';
  28. class EditActionPlantScreen extends StatefulWidget {
  29. final int cropId;
  30. final bool isEdit;
  31. final int activityId;
  32. EditActionPlantScreen(
  33. {@required this.cropId, this.isEdit = false, this.activityId});
  34. @override
  35. _EditActionPlantScreenState createState() => _EditActionPlantScreenState();
  36. }
  37. class _EditActionPlantScreenState extends State<EditActionPlantScreen> {
  38. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  39. final _repository = Repository();
  40. GlobalKey<FormState> _formKey = GlobalKey();
  41. bool _autoValidate = false;
  42. Plant _plant = Plant();
  43. var pref = LocalPref();
  44. final _descriptionController = TextEditingController();
  45. final _quantityController = TextEditingController();
  46. final _densityController = TextEditingController();
  47. final _executeByController = TextEditingController();
  48. List<SuppliesUsing> suppliesUsing = new List<SuppliesUsing>();
  49. String executeTimeView;
  50. DateTime executeTime = DateTime.now();
  51. List<String> filePaths = List<String>();
  52. var changeFileController = Get.put(ChangeFileController());
  53. Future<Null> getSharedPrefs() async {
  54. var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  55. _executeByController.text = currentFullName ?? "";
  56. }
  57. @override
  58. void initState() {
  59. super.initState();
  60. getSharedPrefs();
  61. changeFileController.initValue();
  62. _plant.suppliesUsing = new List<SuppliesUsing>();
  63. var parsedExecuteDate =
  64. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  65. _plant.executeDate = "$parsedExecuteDate";
  66. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  67. _plant.cropId = widget.cropId;
  68. }
  69. _validateInputs() async {
  70. if (_formKey.currentState.validate()) {
  71. _formKey.currentState.save();
  72. LoadingDialog.showLoadingDialog(context);
  73. filePaths = Get.find<ChangeFileController>().files;
  74. List<SuppliesUsing> newSups = [];
  75. suppliesUsing.forEach((sup) {
  76. var newSup = sup;
  77. newSup.suppliesInWarehouseId = sup.tbSuppliesInWarehouseId;
  78. newSups.add(newSup);
  79. });
  80. _plant.suppliesUsing = newSups;
  81. var activityPlant = jsonEncode(_plant.toJson()).toString();
  82. //ADD NEW
  83. if (_plant.activityId == null) {
  84. _repository.createAction((value) {
  85. LoadingDialog.hideLoadingDialog(context);
  86. Get.back(result: value);
  87. Utils.showSnackBarSuccess(message: label_add_success);
  88. }, (error) {
  89. LoadingDialog.hideLoadingDialog(context);
  90. Utils.showSnackBarError(message: AppException.handleError(error));
  91. },
  92. apiAddAction: ConstCommon.apiAddPlant,
  93. paramActivity: ConstCommon.paramsActionPlant,
  94. activityAction: activityPlant,
  95. filePaths: filePaths);
  96. } else {
  97. //UPDATE
  98. _repository.updateAction((value) {
  99. LoadingDialog.hideLoadingDialog(context);
  100. Get.back(result: value);
  101. Utils.showSnackBarSuccess(message: label_update_success);
  102. }, (error) {
  103. LoadingDialog.hideLoadingDialog(context);
  104. Utils.showSnackBarError(message: AppException.handleError(error));
  105. },
  106. apiUpdateAction: ConstCommon.apiUpdatePlant,
  107. paramActivity: ConstCommon.paramsActionPlant,
  108. activityAction: activityPlant,
  109. filePaths: filePaths);
  110. }
  111. } else {
  112. _autoValidate = true;
  113. }
  114. }
  115. Widget _btnExecuteTimePicker() {
  116. return FlatButton(
  117. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  118. onPressed: () {
  119. DatePicker.showDateTimePicker(context,
  120. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  121. setState(() {
  122. var parsedDate =
  123. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  124. _plant.executeDate = "$parsedDate";
  125. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  126. });
  127. }, currentTime: executeTime, locale: LocaleType.vi);
  128. },
  129. child: Container(
  130. padding:
  131. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  132. decoration: BoxDecoration(
  133. border: kBorderTextField,
  134. ),
  135. child: Row(
  136. children: [
  137. Expanded(
  138. child: Text(
  139. //TODO: check condition
  140. executeTimeView == null ? "$executeTime" : executeTimeView,
  141. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  142. )),
  143. Icon(
  144. Icons.date_range,
  145. color: Colors.blue,
  146. ),
  147. ],
  148. )));
  149. }
  150. Widget _quantityField() {
  151. return TextFormField(
  152. keyboardType: TextInputType.numberWithOptions(decimal: true),
  153. inputFormatters: [
  154. ThousandsFormatter(
  155. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  156. ],
  157. decoration: InputDecoration(labelText: "Số lượng cây trồng"),
  158. controller: _quantityController,
  159. onSaved: (newValue) {
  160. _plant.quantity = newValue.parseDoubleThousand();
  161. },
  162. );
  163. }
  164. Widget _densityField() {
  165. return TextFormField(
  166. keyboardType: TextInputType.text,
  167. decoration: InputDecoration(labelText: "Mật độ"),
  168. controller: _densityController,
  169. onSaved: (newValue) {
  170. _plant.density = newValue;
  171. },
  172. );
  173. }
  174. Widget _desciptionField() {
  175. return TextFormField(
  176. keyboardType: TextInputType.text,
  177. decoration: InputDecoration(labelText: "Ghi chú"),
  178. controller: _descriptionController,
  179. onSaved: (newValue) {
  180. _plant.description = newValue;
  181. },
  182. );
  183. }
  184. Widget _executeByField() {
  185. return TextFormField(
  186. keyboardType: TextInputType.text,
  187. decoration: InputDecoration(labelText: "Người thực hiện"),
  188. enabled: false,
  189. controller: _executeByController,
  190. onSaved: (newValue) {},
  191. );
  192. }
  193. _actionAppBar() {
  194. IconButton iconButton;
  195. if (1 == 1) {
  196. iconButton = IconButton(
  197. icon: Icon(
  198. Icons.done,
  199. color: Colors.black,
  200. ),
  201. onPressed: () {
  202. FocusScopeNode currentFocus = FocusScope.of(context);
  203. if (!currentFocus.hasPrimaryFocus) {
  204. currentFocus.unfocus();
  205. }
  206. _validateInputs();
  207. },
  208. );
  209. return <Widget>[iconButton];
  210. }
  211. return <Widget>[Container()];
  212. }
  213. @override
  214. Widget build(BuildContext context) => KeyboardDismisser(
  215. gestures: [
  216. GestureType.onTap,
  217. GestureType.onPanUpdateDownDirection,
  218. ],
  219. child: Scaffold(
  220. key: _scaffoldKey,
  221. appBar: AppBar(
  222. centerTitle: true,
  223. title: Text(plot_action_plant),
  224. actions: _actionAppBar()),
  225. body: KeyboardDismisser(
  226. child: MultiBlocProvider(
  227. providers: [
  228. BlocProvider<ActionDetailBloc>(
  229. create: (context) =>
  230. ActionDetailBloc(repository: Repository())
  231. ..add(FetchData(
  232. isNeedFetchData: widget.isEdit,
  233. apiActivity: ConstCommon.apiDetailPlant,
  234. activityId: widget.activityId))),
  235. BlocProvider<MediaHelperBloc>(
  236. create: (context) =>
  237. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  238. )
  239. ],
  240. child: Form(
  241. key: _formKey,
  242. autovalidate: _autoValidate,
  243. child: SingleChildScrollView(
  244. padding: EdgeInsets.all(8.0),
  245. child: BlocConsumer<ActionDetailBloc,
  246. ActionDetailState>(
  247. listener: (context, state) async {
  248. if (state is ActionDetailFailure) {
  249. LoadingDialog.hideLoadingDialog(context);
  250. } else if (state is ActionDetailSuccess) {
  251. LoadingDialog.hideLoadingDialog(context);
  252. _plant = Plant.fromJson(state.item);
  253. _plant.activityId = widget.activityId;
  254. _quantityController.text = _plant.quantity
  255. .formatNumtoStringDecimal();
  256. _densityController.text = _plant.density;
  257. _descriptionController.text =
  258. _plant.description;
  259. _executeByController.text = _plant.executeBy;
  260. try {
  261. executeTime =
  262. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  263. .parse(_plant.executeDate);
  264. } catch (_) {}
  265. executeTimeView =
  266. DateFormat("dd/MM/yyyy HH:mm")
  267. .format(executeTime);
  268. //Show media
  269. if (_plant.media != null) {
  270. await UtilAction.cacheFiles(_plant.media)
  271. .then((value) {
  272. BlocProvider.of<MediaHelperBloc>(context)
  273. .add(ChangeListMedia(items: value));
  274. }).whenComplete(() {
  275. print("completed");
  276. });
  277. }
  278. //list supply
  279. suppliesUsing = _plant.suppliesUsing;
  280. Get.find<ChangeSupplyUsing>()
  281. .changeInitList(suppliesUsing);
  282. } else if (state is ActionDetailInitial) {
  283. print("init");
  284. } else if (state is ActionDetailLoading) {
  285. print("loading");
  286. LoadingDialog.showLoadingDialog(context);
  287. }
  288. },
  289. builder: (context, state) {
  290. return Column(
  291. children: <Widget>[
  292. Container(
  293. width: double.infinity,
  294. child: Text(
  295. "Ngày thực hiện *",
  296. style: TextStyle(
  297. color: Colors.black54,
  298. fontSize: 13.0),
  299. ),
  300. ),
  301. _btnExecuteTimePicker(),
  302. SizedBox(
  303. height: 8.0,
  304. ),
  305. _quantityField(),
  306. SizedBox(
  307. height: 8.0,
  308. ),
  309. _densityField(),
  310. SizedBox(
  311. height: 8.0,
  312. ),
  313. _desciptionField(),
  314. SizedBox(
  315. height: 8.0,
  316. ),
  317. _executeByField(),
  318. SizedBox(
  319. height: 8.0,
  320. ),
  321. WidgetPlantSupply(
  322. currentItems: [],
  323. onChangeSupplies: (value) {
  324. suppliesUsing = value;
  325. }),
  326. SizedBox(
  327. height: 8.0,
  328. ),
  329. BlocBuilder<MediaHelperBloc,
  330. MediaHelperState>(
  331. builder: (context, state) {
  332. if (state is MediaHelperSuccess) {
  333. return WidgetMediaPicker(
  334. currentItems: state.items,
  335. onChangeFiles: (filePaths) async {
  336. Get.find<ChangeFileController>()
  337. .addAllFile(filePaths);
  338. });
  339. } else {
  340. return Center(
  341. child: CircularProgressIndicator());
  342. }
  343. }),
  344. ],
  345. );
  346. },
  347. ),
  348. ))))));
  349. @override
  350. void dispose() {
  351. _quantityController.dispose();
  352. _densityController.dispose();
  353. _descriptionController.dispose();
  354. _executeByController.dispose();
  355. super.dispose();
  356. }
  357. }