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.

306 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/custom_widgets/widget_utils.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 '../util_action.dart';
  23. class EditActionEndScreen extends StatefulWidget {
  24. final int cropId;
  25. final bool isEdit;
  26. final int activityId;
  27. EditActionEndScreen(
  28. {@required this.cropId, this.isEdit = false, this.activityId});
  29. @override
  30. _EditActionEndScreenState createState() => _EditActionEndScreenState();
  31. }
  32. class _EditActionEndScreenState extends State<EditActionEndScreen> {
  33. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  34. final _repository = Repository();
  35. GlobalKey<FormState> _formKey = GlobalKey();
  36. bool _autoValidate = false;
  37. End _end = End();
  38. final _descriptionController = TextEditingController();
  39. final _executeByController = TextEditingController();
  40. var pref = LocalPref();
  41. String executeTimeView;
  42. DateTime executeTime = DateTime.now();
  43. List<String> filePaths = List<String>();
  44. var changeFileController = Get.put(ChangeFileController());
  45. Future<Null> getSharedPrefs() async {
  46. var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  47. _executeByController.text = currentFullName ?? "";
  48. }
  49. @override
  50. void initState() {
  51. super.initState();
  52. getSharedPrefs();
  53. changeFileController.initValue();
  54. var parsedExecuteDate =
  55. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  56. _end.executeDate = "$parsedExecuteDate";
  57. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  58. _end.cropId = widget.cropId;
  59. }
  60. _validateInputs() async {
  61. if (_formKey.currentState.validate()) {
  62. _formKey.currentState.save();
  63. LoadingDialog.showLoadingDialog(context);
  64. filePaths = Get.find<ChangeFileController>().newFiles;
  65. try {
  66. _end.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  67. var activityEnd = jsonEncode(_end.toJson()).toString();
  68. //ADD NEW
  69. if (_end.activityId == null) {
  70. _repository.createAction((value) {
  71. LoadingDialog.hideLoadingDialog(context);
  72. Get.back(result: value);
  73. Utils.showSnackBarSuccess(message: label_add_success);
  74. }, (error) {
  75. LoadingDialog.hideLoadingDialog(context);
  76. Utils.showSnackBarError(message: AppException.handleError(error));
  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. Utils.showSnackBarSuccess(message: label_update_success);
  88. }, (error) {
  89. LoadingDialog.hideLoadingDialog(context);
  90. Utils.showSnackBarError(message: AppException.handleError(error));
  91. },
  92. apiUpdateAction: ConstCommon.apiUpdateEnd,
  93. paramActivity: ConstCommon.paramsActionEnd,
  94. activityAction: activityEnd,
  95. filePaths: filePaths);
  96. }
  97. } catch (e) {
  98. LoadingDialog.hideLoadingDialog(context);
  99. print(e.toString());
  100. }
  101. } else {
  102. _autoValidate = true;
  103. }
  104. }
  105. Widget _btnExecuteTimePicker() {
  106. return FlatButton(
  107. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  108. onPressed: () {
  109. DatePicker.showDateTimePicker(context,
  110. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  111. setState(() {
  112. var parsedDate =
  113. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  114. _end.executeDate = "$parsedDate";
  115. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  116. });
  117. }, currentTime: executeTime, locale: LocaleType.vi);
  118. },
  119. child: Container(
  120. padding:
  121. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  122. decoration: BoxDecoration(
  123. border: kBorderTextField,
  124. ),
  125. child: Row(
  126. children: [
  127. Expanded(
  128. child: Text(
  129. //TODO: check condition
  130. executeTimeView == null ? "$executeTime" : executeTimeView,
  131. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  132. )),
  133. Icon(
  134. Icons.date_range,
  135. color: Colors.blue,
  136. ),
  137. ],
  138. )));
  139. }
  140. _actionAppBar() {
  141. IconButton iconButton;
  142. if (1 == 1) {
  143. iconButton = IconButton(
  144. icon: Icon(
  145. Icons.done,
  146. color: Colors.black,
  147. ),
  148. onPressed: () {
  149. FocusScopeNode currentFocus = FocusScope.of(context);
  150. if (!currentFocus.hasPrimaryFocus) {
  151. currentFocus.unfocus();
  152. }
  153. _validateInputs();
  154. },
  155. );
  156. return <Widget>[iconButton];
  157. }
  158. return <Widget>[Container()];
  159. }
  160. Widget _descriptionField() {
  161. return TextFormField(
  162. keyboardType: TextInputType.text,
  163. decoration: InputDecoration(labelText: "Ghi chú"),
  164. controller: _descriptionController,
  165. onSaved: (newValue) {
  166. _end.description = newValue;
  167. },
  168. );
  169. }
  170. Widget _executeByField() {
  171. return TextFormField(
  172. keyboardType: TextInputType.text,
  173. decoration: InputDecoration(labelText: "Người thực hiện"),
  174. enabled: false,
  175. controller: _executeByController,
  176. onSaved: (newValue) {},
  177. );
  178. }
  179. @override
  180. Widget build(BuildContext context) => KeyboardDismisser(
  181. gestures: [
  182. GestureType.onTap,
  183. GestureType.onPanUpdateDownDirection,
  184. ],
  185. child: Scaffold(
  186. key: _scaffoldKey,
  187. appBar: AppBar(
  188. centerTitle: true,
  189. title: Text(plot_action_finish),
  190. actions: _actionAppBar()),
  191. body: KeyboardDismisser(
  192. child: MultiBlocProvider(
  193. providers: [
  194. BlocProvider<ActionDetailBloc>(
  195. create: (context) =>
  196. ActionDetailBloc(repository: Repository())
  197. ..add(FetchData(
  198. isNeedFetchData: widget.isEdit,
  199. apiActivity: ConstCommon.apiDetailEnd,
  200. activityId: widget.activityId))),
  201. BlocProvider<MediaHelperBloc>(
  202. create: (context) =>
  203. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  204. )
  205. ],
  206. child: Form(
  207. key: _formKey,
  208. autovalidate: _autoValidate,
  209. child: SingleChildScrollView(
  210. padding: EdgeInsets.all(8.0),
  211. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  212. listener: (context, state) async {
  213. if (state is ActionDetailFailure) {
  214. LoadingDialog.hideLoadingDialog(context);
  215. } else if (state is ActionDetailSuccess) {
  216. LoadingDialog.hideLoadingDialog(context);
  217. _end = End.fromJson(state.item);
  218. _end.activityId = widget.activityId;
  219. _descriptionController.text =
  220. _end.description ?? "";
  221. _executeByController.text = _end.createdByName;
  222. try {
  223. executeTime =
  224. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  225. .parse(_end.executeDate);
  226. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  227. .format(executeTime);
  228. } catch (_) {}
  229. //Show media
  230. if (Validators.stringNotNullOrEmpty(_end.media)) {
  231. BlocProvider.of<MediaHelperBloc>(context).add(
  232. ChangeListMedia(
  233. items: UtilAction.convertFilePathToMedia(
  234. _end.media)));
  235. }
  236. } else if (state is ActionDetailInitial) {
  237. } else if (state is ActionDetailLoading) {
  238. LoadingDialog.showLoadingDialog(context);
  239. }
  240. },
  241. builder: (context, state) {
  242. return Column(
  243. children: <Widget>[
  244. Container(
  245. width: double.infinity,
  246. child: Text(
  247. "Ngày thực hiện *",
  248. style: TextStyle(
  249. color: Colors.black54, fontSize: 13.0),
  250. ),
  251. ),
  252. _btnExecuteTimePicker(),
  253. SizedBox(
  254. height: 8.0,
  255. ),
  256. _descriptionField(),
  257. SizedBox(
  258. height: 8.0,
  259. ),
  260. _executeByField(),
  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: (newPathFiles,
  270. deletePathFiles) async {
  271. Get.find<ChangeFileController>().change(
  272. newPathFiles, deletePathFiles);
  273. });
  274. } else {
  275. return Center(
  276. child: CircularProgressIndicator());
  277. }
  278. }),
  279. ],
  280. );
  281. },
  282. ),
  283. )),
  284. ))));
  285. @override
  286. void dispose() {
  287. _descriptionController.dispose();
  288. _executeByController.dispose();
  289. super.dispose();
  290. }
  291. }