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.

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