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.

302 lines
12KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/End.dart';
  3. import 'package:farm_tpf/data/api/app_exception.dart';
  4. import 'package:farm_tpf/data/repository/repository.dart';
  5. import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
  6. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  7. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  8. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  9. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  10. import 'package:farm_tpf/utils/const_common.dart';
  11. import 'package:farm_tpf/utils/const_string.dart';
  12. import 'package:farm_tpf/utils/const_style.dart';
  13. import 'package:flutter/material.dart';
  14. import 'package:flutter_bloc/flutter_bloc.dart';
  15. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  16. import 'package:get/get.dart';
  17. import 'package:intl/intl.dart';
  18. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  19. import '../util_action.dart';
  20. class EditActionEndScreen extends StatefulWidget {
  21. final int cropId;
  22. final bool isEdit;
  23. final int activityId;
  24. EditActionEndScreen(
  25. {@required this.cropId, this.isEdit = false, this.activityId});
  26. @override
  27. _EditActionEndScreenState createState() => _EditActionEndScreenState();
  28. }
  29. class _EditActionEndScreenState extends State<EditActionEndScreen> {
  30. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  31. final _repository = Repository();
  32. GlobalKey<FormState> _formKey = GlobalKey();
  33. bool _autoValidate = false;
  34. End _end = End();
  35. final _descriptionController = TextEditingController();
  36. String executeTimeView;
  37. DateTime executeTime = DateTime.now();
  38. List<String> filePaths = List<String>();
  39. var changeFileController = Get.put(ChangeFileController());
  40. @override
  41. void initState() {
  42. super.initState();
  43. changeFileController.initValue();
  44. var parsedExecuteDate =
  45. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  46. _end.executeDate = "$parsedExecuteDate";
  47. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  48. _end.cropId = widget.cropId;
  49. }
  50. _validateInputs() async {
  51. if (_formKey.currentState.validate()) {
  52. _formKey.currentState.save();
  53. LoadingDialog.showLoadingDialog(context);
  54. filePaths = Get.find<ChangeFileController>().files;
  55. try {
  56. var activityEnd = jsonEncode(_end.toJson()).toString();
  57. //ADD NEW
  58. if (_end.activityId == null) {
  59. _repository.createAction((value) {
  60. LoadingDialog.hideLoadingDialog(context);
  61. Get.back(result: value);
  62. Get.snackbar(label_add_success, "Hoạt động kết thúc canh tác",
  63. snackPosition: SnackPosition.BOTTOM);
  64. }, (error) {
  65. LoadingDialog.hideLoadingDialog(context);
  66. _scaffoldKey.currentState.showSnackBar(SnackBar(
  67. content: Row(
  68. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  69. children: <Widget>[
  70. Flexible(child: Text(AppException.handleError(error))),
  71. Icon(Icons.error),
  72. ],
  73. ),
  74. backgroundColor: Colors.red,
  75. duration: Duration(seconds: 3),
  76. ));
  77. },
  78. apiAddAction: ConstCommon.apiAddEnd,
  79. paramActivity: ConstCommon.paramsActionEnd,
  80. activityAction: activityEnd,
  81. filePaths: filePaths);
  82. } else {
  83. //UPDATE
  84. _repository.updateAction((value) {
  85. LoadingDialog.hideLoadingDialog(context);
  86. Get.back(result: value);
  87. Get.snackbar(label_update_success, "Hoạt động kết thúc canh tác",
  88. snackPosition: SnackPosition.BOTTOM);
  89. }, (error) {
  90. LoadingDialog.hideLoadingDialog(context);
  91. _scaffoldKey.currentState.showSnackBar(SnackBar(
  92. content: Row(
  93. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  94. children: <Widget>[
  95. Flexible(child: Text(AppException.handleError(error))),
  96. Icon(Icons.error),
  97. ],
  98. ),
  99. backgroundColor: Colors.red,
  100. duration: Duration(seconds: 3),
  101. ));
  102. },
  103. apiUpdateAction: ConstCommon.apiUpdateEnd,
  104. paramActivity: ConstCommon.paramsActionEnd,
  105. activityAction: activityEnd,
  106. filePaths: filePaths);
  107. }
  108. } catch (e) {
  109. LoadingDialog.hideLoadingDialog(context);
  110. print(e.toString());
  111. }
  112. } else {
  113. _autoValidate = true;
  114. }
  115. }
  116. Widget _btnExecuteTimePicker() {
  117. return FlatButton(
  118. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  119. onPressed: () {
  120. DatePicker.showDateTimePicker(context,
  121. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  122. setState(() {
  123. var parsedDate =
  124. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  125. _end.executeDate = "$parsedDate";
  126. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  127. });
  128. }, currentTime: executeTime, locale: LocaleType.vi);
  129. },
  130. child: Container(
  131. padding:
  132. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  133. decoration: BoxDecoration(
  134. border: kBorderTextField,
  135. ),
  136. child: Row(
  137. children: [
  138. Expanded(
  139. child: Text(
  140. //TODO: check condition
  141. executeTimeView == null ? "$executeTime" : executeTimeView,
  142. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  143. )),
  144. Icon(
  145. Icons.date_range,
  146. color: Colors.blue,
  147. ),
  148. ],
  149. )));
  150. }
  151. _actionAppBar() {
  152. IconButton iconButton;
  153. if (1 == 1) {
  154. iconButton = IconButton(
  155. icon: Icon(
  156. Icons.done,
  157. color: Colors.black,
  158. ),
  159. onPressed: () {
  160. FocusScopeNode currentFocus = FocusScope.of(context);
  161. if (!currentFocus.hasPrimaryFocus) {
  162. currentFocus.unfocus();
  163. }
  164. _validateInputs();
  165. },
  166. );
  167. return <Widget>[iconButton];
  168. }
  169. return <Widget>[Container()];
  170. }
  171. Widget _descriptionField() {
  172. return TextFormField(
  173. keyboardType: TextInputType.text,
  174. decoration: InputDecoration(labelText: "Ghi chú"),
  175. controller: _descriptionController,
  176. onSaved: (newValue) {
  177. _end.description = newValue;
  178. },
  179. );
  180. }
  181. @override
  182. Widget build(BuildContext context) => KeyboardDismisser(
  183. gestures: [
  184. GestureType.onTap,
  185. GestureType.onPanUpdateDownDirection,
  186. ],
  187. child: Scaffold(
  188. key: _scaffoldKey,
  189. appBar: AppBar(
  190. centerTitle: true,
  191. title: Text(plot_action_finish),
  192. actions: _actionAppBar()),
  193. body: KeyboardDismisser(
  194. child: MultiBlocProvider(
  195. providers: [
  196. BlocProvider<ActionDetailBloc>(
  197. create: (context) =>
  198. ActionDetailBloc(repository: Repository())
  199. ..add(FetchData(
  200. isNeedFetchData: widget.isEdit,
  201. apiActivity: ConstCommon.apiDetailEnd,
  202. activityId: widget.activityId))),
  203. BlocProvider<MediaHelperBloc>(
  204. create: (context) =>
  205. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  206. )
  207. ],
  208. child: Form(
  209. key: _formKey,
  210. autovalidate: _autoValidate,
  211. child: SingleChildScrollView(
  212. padding: EdgeInsets.all(8.0),
  213. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  214. listener: (context, state) async {
  215. if (state is ActionDetailFailure) {
  216. LoadingDialog.hideLoadingDialog(context);
  217. } else if (state is ActionDetailSuccess) {
  218. LoadingDialog.hideLoadingDialog(context);
  219. _end = End.fromJson(state.item);
  220. _end.activityId = widget.activityId;
  221. _descriptionController.text =
  222. _end.description ?? "";
  223. try {
  224. executeTime =
  225. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  226. .parse(_end.executeDate);
  227. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  228. .format(executeTime);
  229. } catch (_) {}
  230. //Show media
  231. if (_end.media != null) {
  232. await UtilAction.cacheFiles(_end.media)
  233. .then((value) {
  234. BlocProvider.of<MediaHelperBloc>(context)
  235. .add(ChangeListMedia(items: value));
  236. }).whenComplete(() {
  237. print("completed");
  238. });
  239. }
  240. } else if (state is ActionDetailInitial) {
  241. } else if (state is ActionDetailLoading) {
  242. LoadingDialog.showLoadingDialog(context);
  243. }
  244. },
  245. builder: (context, state) {
  246. return Column(
  247. children: <Widget>[
  248. Container(
  249. width: double.infinity,
  250. child: Text(
  251. "Ngày thực hiện",
  252. style: TextStyle(
  253. color: Colors.black54, fontSize: 13.0),
  254. ),
  255. ),
  256. _btnExecuteTimePicker(),
  257. SizedBox(
  258. height: 8.0,
  259. ),
  260. _descriptionField(),
  261. SizedBox(
  262. height: 8.0,
  263. ),
  264. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  265. builder: (context, state) {
  266. if (state is MediaHelperSuccess) {
  267. return WidgetMediaPicker(
  268. currentItems: state.items,
  269. onChangeFiles: (filePaths) async {
  270. Get.find<ChangeFileController>()
  271. .addAllFile(filePaths);
  272. });
  273. } else {
  274. return Center(
  275. child: CircularProgressIndicator());
  276. }
  277. }),
  278. ],
  279. );
  280. },
  281. ),
  282. )),
  283. ))));
  284. @override
  285. void dispose() {
  286. _descriptionController.dispose();
  287. super.dispose();
  288. }
  289. }