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.

278 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/app_bar_widget.dart';
  6. import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
  7. import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart';
  8. import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  10. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  11. import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart';
  12. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  13. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  14. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  15. import 'package:farm_tpf/utils/const_common.dart';
  16. import 'package:farm_tpf/utils/const_string.dart';
  17. import 'package:farm_tpf/utils/pref.dart';
  18. import 'package:farm_tpf/utils/validators.dart';
  19. import 'package:flutter/material.dart';
  20. import 'package:flutter_bloc/flutter_bloc.dart';
  21. import 'package:get/get.dart';
  22. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  23. import 'package:farm_tpf/utils/formatter.dart';
  24. import '../util_action.dart';
  25. class EditActionEndScreen extends StatefulWidget {
  26. final int cropId;
  27. final bool isEdit;
  28. final int? activityId;
  29. EditActionEndScreen({required this.cropId, this.isEdit = false, this.activityId});
  30. @override
  31. _EditActionEndScreenState createState() => _EditActionEndScreenState();
  32. }
  33. class _EditActionEndScreenState extends State<EditActionEndScreen> {
  34. final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  35. final _repository = Repository();
  36. GlobalKey<FormState> _formKey = GlobalKey();
  37. bool _autoValidate = false;
  38. End _end = End();
  39. final _descriptionController = TextEditingController();
  40. final _executeByController = TextEditingController();
  41. var pref = LocalPref();
  42. DateTime executeTime = DateTime.now();
  43. List<String> filePaths = <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. _end.cropId = widget.cropId;
  55. }
  56. _validateInputs() async {
  57. if (_formKey.currentState!.validate()) {
  58. _formKey.currentState!.save();
  59. LoadingDialog.showLoadingDialog(context);
  60. filePaths = Get.find<ChangeFileController>().newFiles;
  61. try {
  62. _end.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  63. var activityEnd = jsonEncode(_end.toJson()).toString();
  64. //ADD NEW
  65. if (_end.activityId == null) {
  66. _repository.createAction((value) {
  67. LoadingDialog.hideLoadingDialog(context);
  68. Get.back(result: value);
  69. Utils.showSnackBarSuccess(message: label_add_success);
  70. }, (error) {
  71. LoadingDialog.hideLoadingDialog(context);
  72. Utils.showSnackBarError(message: AppException.handleError(error));
  73. }, apiAddAction: ConstCommon.apiAddEnd, paramActivity: ConstCommon.paramsActionEnd, activityAction: activityEnd, filePaths: filePaths);
  74. } else {
  75. //UPDATE
  76. _repository.updateAction((value) {
  77. LoadingDialog.hideLoadingDialog(context);
  78. Get.back(result: value);
  79. Utils.showSnackBarSuccess(message: label_update_success);
  80. }, (error) {
  81. LoadingDialog.hideLoadingDialog(context);
  82. Utils.showSnackBarError(message: AppException.handleError(error));
  83. },
  84. apiUpdateAction: ConstCommon.apiUpdateEnd,
  85. paramActivity: ConstCommon.paramsActionEnd,
  86. activityAction: activityEnd,
  87. filePaths: filePaths);
  88. }
  89. } catch (e) {
  90. LoadingDialog.hideLoadingDialog(context);
  91. print(e.toString());
  92. }
  93. } else {
  94. _autoValidate = true;
  95. }
  96. }
  97. Widget _btnExecuteTimePicker() {
  98. return WidgetFieldDateTimePicker(
  99. initDateTime: executeTime,
  100. onUpdateDateTime: (selectedDate) {
  101. _end.executeDate = selectedDate.convertLocalDateTimeToStringUtcDateTime();
  102. });
  103. }
  104. Widget _descriptionField() {
  105. return TextFieldDescriptionWidget(
  106. controller: _descriptionController,
  107. onSaved: (newValue) {
  108. _end.description = newValue;
  109. });
  110. }
  111. Widget _executeByField() {
  112. return TextFormField(
  113. keyboardType: TextInputType.text,
  114. decoration: const InputDecoration(labelText: "Người thực hiện"),
  115. enabled: false,
  116. controller: _executeByController,
  117. onSaved: (newValue) {},
  118. );
  119. }
  120. @override
  121. Widget build(BuildContext context) => KeyboardDismisser(
  122. gestures: [
  123. GestureType.onTap,
  124. GestureType.onPanUpdateDownDirection,
  125. ],
  126. child: Scaffold(
  127. backgroundColor: Colors.white,
  128. key: _scaffoldKey,
  129. appBar: AppBarWidget(
  130. isBack: true,
  131. action: InkWell(
  132. child: const Text(
  133. 'Huỷ',
  134. style: TextStyle(color: Colors.red, fontWeight: FontWeight.normal),
  135. ),
  136. onTap: () {
  137. if (Get.isSnackbarOpen) Get.back();
  138. Get.back();
  139. },
  140. ),
  141. ),
  142. body: KeyboardDismisser(
  143. child: MultiBlocProvider(
  144. providers: [
  145. BlocProvider<ActionDetailBloc>(
  146. create: (context) => ActionDetailBloc(repository: Repository())
  147. ..add(
  148. FetchData(isNeedFetchData: widget.isEdit, apiActivity: ConstCommon.apiDetailEnd, activityId: widget.activityId ?? -1),
  149. ),
  150. ),
  151. BlocProvider<MediaHelperBloc>(
  152. create: (context) => MediaHelperBloc()..add(ChangeListMedia(items: [])),
  153. )
  154. ],
  155. child: Form(
  156. key: _formKey,
  157. // autovalidate: _autoValidate,
  158. child: SafeArea(
  159. child: SingleChildScrollView(
  160. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  161. listener: (context, state) async {
  162. if (state is ActionDetailFailure) {
  163. LoadingDialog.hideLoadingDialog(context);
  164. } else if (state is ActionDetailSuccess) {
  165. LoadingDialog.hideLoadingDialog(context);
  166. _end = End.fromJson(state.item);
  167. _end.activityId = widget.activityId ?? -1;
  168. _descriptionController.text = _end.description ?? "";
  169. _executeByController.text = _end.createdByName ?? '';
  170. Get.find<ChangeDateTimePicker>().change(
  171. _end.executeDate?.convertStringServerDateTimeToLocalDateTime() ?? DateTime.now(),
  172. );
  173. //Show media
  174. if (Validators.stringNotNullOrEmpty(_end.media ?? '')) {
  175. BlocProvider.of<MediaHelperBloc>(context).add(
  176. ChangeListMedia(
  177. items: UtilAction.convertFilePathToMedia(_end.media ?? ''),
  178. ),
  179. );
  180. }
  181. } else if (state is ActionDetailInitial) {
  182. } else if (state is ActionDetailLoading) {
  183. LoadingDialog.showLoadingDialog(context);
  184. }
  185. },
  186. builder: (context, state) {
  187. return Column(
  188. children: [
  189. Padding(
  190. padding: const EdgeInsets.all(8.0),
  191. child: Column(
  192. crossAxisAlignment: CrossAxisAlignment.start,
  193. children: <Widget>[
  194. const Text(
  195. plot_action_finish,
  196. style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
  197. ),
  198. const SizedBox(
  199. height: 8.0,
  200. ),
  201. Container(
  202. width: double.infinity,
  203. child: const Text(
  204. "Ngày thực hiện *",
  205. style: TextStyle(color: Colors.black54, fontSize: 13.0),
  206. ),
  207. ),
  208. _btnExecuteTimePicker(),
  209. const SizedBox(
  210. height: 8.0,
  211. ),
  212. _descriptionField(),
  213. const SizedBox(
  214. height: 8.0,
  215. ),
  216. _executeByField(),
  217. const SizedBox(
  218. height: 8.0,
  219. ),
  220. ],
  221. ),
  222. ),
  223. Container(
  224. width: double.infinity,
  225. height: 16,
  226. color: Colors.grey[200],
  227. ),
  228. BlocBuilder<MediaHelperBloc, MediaHelperState>(builder: (context, state) {
  229. if (state is MediaHelperSuccess) {
  230. return WidgetMediaPicker(
  231. currentItems: state.items,
  232. onChangeFiles: (newPathFiles, deletePathFiles) async {
  233. Get.find<ChangeFileController>().change(newPathFiles, deletePathFiles);
  234. });
  235. } else {
  236. return const Center(child: CircularProgressIndicator());
  237. }
  238. }),
  239. Padding(
  240. padding: const EdgeInsets.all(8.0),
  241. child: ButtonWidget(
  242. title: 'CẬP NHẬT',
  243. onPressed: () {
  244. var currentFocus = FocusScope.of(context);
  245. if (!currentFocus.hasPrimaryFocus) {
  246. currentFocus.unfocus();
  247. }
  248. _validateInputs();
  249. }),
  250. ),
  251. ],
  252. );
  253. },
  254. ),
  255. ),
  256. )),
  257. ))));
  258. @override
  259. void dispose() {
  260. _descriptionController.dispose();
  261. _executeByController.dispose();
  262. super.dispose();
  263. }
  264. }