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.

366 lines
15KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/Other.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/models/index.dart';
  6. import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart';
  7. import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
  8. import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart';
  10. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  11. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  12. import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_description.dart';
  13. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  14. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  15. import 'package:farm_tpf/presentation/screens/actions/other/bloc_get_action_type.dart';
  16. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  17. import 'package:farm_tpf/utils/const_common.dart';
  18. import 'package:farm_tpf/utils/const_string.dart';
  19. import 'package:farm_tpf/utils/pref.dart';
  20. import 'package:farm_tpf/utils/validators.dart';
  21. import 'package:flutter/material.dart';
  22. import 'package:flutter_bloc/flutter_bloc.dart';
  23. import 'package:get/get.dart';
  24. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  25. import 'package:farm_tpf/utils/formatter.dart';
  26. import '../util_action.dart';
  27. class EditActionOtherScreen extends StatefulWidget {
  28. final int cropId;
  29. final bool isEdit;
  30. final int activityId;
  31. EditActionOtherScreen(
  32. {@required this.cropId, this.isEdit = false, this.activityId});
  33. @override
  34. _EditActionOtherScreenState createState() => _EditActionOtherScreenState();
  35. }
  36. class _EditActionOtherScreenState extends State<EditActionOtherScreen> {
  37. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  38. final _repository = Repository();
  39. GlobalKey<FormState> _formKey = GlobalKey();
  40. bool _autoValidate = false;
  41. var pref = LocalPref();
  42. Other _other = Other();
  43. final _descriptionController = TextEditingController();
  44. final _executeByController = TextEditingController();
  45. List<ActionType> _actionTypes = List<ActionType>();
  46. ActionType _actionType;
  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. _other.cropId = widget.cropId;
  60. if (!widget.isEdit) {
  61. getActionTypeBloc.getActionTypes((data) {
  62. _actionTypes = data;
  63. }, (err) {});
  64. }
  65. }
  66. _validateInputs() async {
  67. if (_formKey.currentState.validate()) {
  68. _formKey.currentState.save();
  69. LoadingDialog.showLoadingDialog(context);
  70. filePaths = Get.find<ChangeFileController>().newFiles;
  71. try {
  72. _other.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  73. var activityOther = jsonEncode(_other.toJson()).toString();
  74. //ADD NEW
  75. if (_other.activityId == null) {
  76. _repository.createAction((value) {
  77. LoadingDialog.hideLoadingDialog(context);
  78. Get.back(result: value);
  79. Utils.showSnackBarSuccess(message: label_add_success);
  80. }, (error) {
  81. LoadingDialog.hideLoadingDialog(context);
  82. Utils.showSnackBarError(message: AppException.handleError(error));
  83. },
  84. apiAddAction: ConstCommon.apiAddOther,
  85. paramActivity: ConstCommon.paramsActionOther,
  86. activityAction: activityOther,
  87. filePaths: filePaths);
  88. } else {
  89. //UPDATE
  90. _repository.updateAction((value) {
  91. LoadingDialog.hideLoadingDialog(context);
  92. Get.back(result: value);
  93. Utils.showSnackBarSuccess(message: label_update_success);
  94. }, (error) {
  95. LoadingDialog.hideLoadingDialog(context);
  96. Utils.showSnackBarError(message: AppException.handleError(error));
  97. },
  98. apiUpdateAction: ConstCommon.apiUpdateOther,
  99. paramActivity: ConstCommon.paramsActionOther,
  100. activityAction: activityOther,
  101. filePaths: filePaths);
  102. }
  103. } catch (e) {
  104. LoadingDialog.hideLoadingDialog(context);
  105. print(e.toString());
  106. }
  107. } else {
  108. _autoValidate = true;
  109. Utils.showSnackBarWarning(message: label_validate_input_required);
  110. }
  111. }
  112. Widget _btnExecuteTimePicker() {
  113. return WidgetFieldDateTimePicker(
  114. initDateTime: executeTime,
  115. onUpdateDateTime: (selectedDate) {
  116. _other.executeDate =
  117. selectedDate.convertLocalDateTimeToStringUtcDateTime();
  118. });
  119. }
  120. List<DropdownMenuItem<ActionType>> _buildDropMenu(List<ActionType> actions) {
  121. return actions
  122. .map((action) => DropdownMenuItem<ActionType>(
  123. child: Text(action.description.toString()),
  124. value: action,
  125. ))
  126. .toList();
  127. }
  128. Widget _dropdownAcionTypes() {
  129. return StreamBuilder(
  130. stream: getActionTypeBloc.actions,
  131. builder: (context, AsyncSnapshot<dynamic> snapshot) {
  132. if (snapshot.hasData) {
  133. return DropdownButtonFormField<ActionType>(
  134. value: _actionType,
  135. hint: Text("Hoạt động *"),
  136. onChanged: (ActionType newValue) {
  137. setState(() {
  138. _actionType = newValue;
  139. _other.activityTypeName = newValue.name;
  140. });
  141. },
  142. validator: (value) =>
  143. value == null ? label_validate_input_empty : null,
  144. isExpanded: true,
  145. items: _buildDropMenu(_actionTypes));
  146. } else if (snapshot.hasError) {
  147. return Container();
  148. } else {
  149. return Center(
  150. child: CircularProgressIndicator(),
  151. );
  152. }
  153. },
  154. );
  155. }
  156. Widget _descriptionField() {
  157. return TextFieldDescriptionWidget(
  158. controller: _descriptionController,
  159. onSaved: (newValue) {
  160. _other.description = newValue;
  161. },
  162. );
  163. }
  164. Widget _executeByField() {
  165. return TextFormField(
  166. keyboardType: TextInputType.text,
  167. decoration: InputDecoration(labelText: "Người thực hiện"),
  168. enabled: false,
  169. controller: _executeByController,
  170. onSaved: (newValue) {},
  171. );
  172. }
  173. @override
  174. Widget build(BuildContext context) => KeyboardDismisser(
  175. gestures: [
  176. GestureType.onTap,
  177. GestureType.onPanUpdateDownDirection,
  178. ],
  179. child: Scaffold(
  180. backgroundColor: Colors.white,
  181. key: _scaffoldKey,
  182. appBar: AppBarWidget(
  183. isBack: true,
  184. action: InkWell(
  185. child: Text(
  186. 'Huỷ',
  187. style: TextStyle(
  188. color: Colors.red, fontWeight: FontWeight.normal),
  189. ),
  190. onTap: () {
  191. if (Get.isSnackbarOpen) Get.back();
  192. Get.back();
  193. },
  194. ),
  195. ),
  196. body: KeyboardDismisser(
  197. child: MultiBlocProvider(
  198. providers: [
  199. BlocProvider<ActionDetailBloc>(
  200. create: (context) =>
  201. ActionDetailBloc(repository: Repository())
  202. ..add(FetchData(
  203. isNeedFetchData: widget.isEdit,
  204. apiActivity: ConstCommon.apiDetailOther,
  205. activityId: widget.activityId))),
  206. BlocProvider<MediaHelperBloc>(
  207. create: (context) =>
  208. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  209. )
  210. ],
  211. child: Form(
  212. key: _formKey,
  213. autovalidate: _autoValidate,
  214. child: SafeArea(
  215. child: SingleChildScrollView(
  216. child:
  217. BlocConsumer<ActionDetailBloc, ActionDetailState>(
  218. listener: (context, state) async {
  219. if (state is ActionDetailFailure) {
  220. LoadingDialog.hideLoadingDialog(context);
  221. } else if (state is ActionDetailSuccess) {
  222. LoadingDialog.hideLoadingDialog(context);
  223. _other = Other.fromJson(state.item);
  224. _other.activityId = widget.activityId;
  225. _descriptionController.text =
  226. _other.description ?? "";
  227. _executeByController.text = _other.createdByName;
  228. //select harvest
  229. getActionTypeBloc.getActionTypes((data) {
  230. _actionTypes = data;
  231. for (var item in _actionTypes) {
  232. if (item.name == _other.activityTypeName) {
  233. _actionType = item;
  234. break;
  235. }
  236. }
  237. }, (err) {});
  238. Get.find<ChangeDateTimePicker>().change(_other
  239. .executeDate
  240. .convertStringServerDateTimeToLocalDateTime());
  241. //Show media
  242. if (Validators.stringNotNullOrEmpty(
  243. _other.media)) {
  244. BlocProvider.of<MediaHelperBloc>(context).add(
  245. ChangeListMedia(
  246. items:
  247. UtilAction.convertFilePathToMedia(
  248. _other.media)));
  249. }
  250. } else if (state is ActionDetailInitial) {
  251. } else if (state is ActionDetailLoading) {
  252. LoadingDialog.showLoadingDialog(context);
  253. }
  254. },
  255. builder: (context, state) {
  256. return Column(
  257. children: [
  258. Padding(
  259. padding: const EdgeInsets.all(8.0),
  260. child: Column(
  261. crossAxisAlignment:
  262. CrossAxisAlignment.start,
  263. children: <Widget>[
  264. Text(
  265. plot_action_other,
  266. style: TextStyle(
  267. fontWeight: FontWeight.w500,
  268. fontSize: 22),
  269. ),
  270. SizedBox(
  271. height: 8.0,
  272. ),
  273. Container(
  274. width: double.infinity,
  275. child: Text(
  276. "Ngày thực hiện *",
  277. style: TextStyle(
  278. color: Colors.black54,
  279. fontSize: 13.0),
  280. ),
  281. ),
  282. _btnExecuteTimePicker(),
  283. SizedBox(
  284. height: 8.0,
  285. ),
  286. _dropdownAcionTypes(),
  287. SizedBox(
  288. height: 8.0,
  289. ),
  290. _descriptionField(),
  291. SizedBox(
  292. height: 8.0,
  293. ),
  294. _executeByField(),
  295. SizedBox(
  296. height: 8.0,
  297. ),
  298. ],
  299. ),
  300. ),
  301. Container(
  302. width: double.infinity,
  303. height: 16,
  304. color: Colors.grey[200],
  305. ),
  306. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  307. builder: (context, state) {
  308. if (state is MediaHelperSuccess) {
  309. return WidgetMediaPicker(
  310. currentItems: state.items,
  311. onChangeFiles: (newPathFiles,
  312. deletePathFiles) async {
  313. Get.find<ChangeFileController>()
  314. .change(newPathFiles,
  315. deletePathFiles);
  316. });
  317. } else {
  318. return Center(
  319. child: CircularProgressIndicator());
  320. }
  321. }),
  322. Padding(
  323. padding: const EdgeInsets.all(8.0),
  324. child: ButtonWidget(
  325. title: 'CẬP NHẬT',
  326. onPressed: () {
  327. FocusScopeNode currentFocus =
  328. FocusScope.of(context);
  329. if (!currentFocus.hasPrimaryFocus) {
  330. currentFocus.unfocus();
  331. }
  332. _validateInputs();
  333. }),
  334. ),
  335. ],
  336. );
  337. },
  338. ),
  339. ),
  340. )),
  341. ))));
  342. @override
  343. void dispose() {
  344. _descriptionController.dispose();
  345. _executeByController.dispose();
  346. super.dispose();
  347. }
  348. }