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.

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