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