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.

364 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. }
  110. }
  111. Widget _btnExecuteTimePicker() {
  112. return WidgetFieldDateTimePicker(
  113. initDateTime: executeTime,
  114. onUpdateDateTime: (selectedDate) {
  115. _other.executeDate =
  116. selectedDate.convertLocalDateTimeToStringUtcDateTime();
  117. });
  118. }
  119. List<DropdownMenuItem<ActionType>> _buildDropMenu(List<ActionType> actions) {
  120. return actions
  121. .map((action) => DropdownMenuItem<ActionType>(
  122. child: Text(action.description.toString()),
  123. value: action,
  124. ))
  125. .toList();
  126. }
  127. Widget _dropdownAcionTypes() {
  128. return StreamBuilder(
  129. stream: getActionTypeBloc.actions,
  130. builder: (context, AsyncSnapshot<dynamic> snapshot) {
  131. if (snapshot.hasData) {
  132. return DropdownButtonFormField<ActionType>(
  133. value: _actionType,
  134. hint: Text("Hoạt động *"),
  135. onChanged: (ActionType newValue) {
  136. setState(() {
  137. _actionType = newValue;
  138. _other.activityTypeName = newValue.name;
  139. });
  140. },
  141. validator: (value) => value == null ? "Hoạt động" : null,
  142. isExpanded: true,
  143. items: _buildDropMenu(_actionTypes));
  144. } else if (snapshot.hasError) {
  145. return Container();
  146. } else {
  147. return Center(
  148. child: CircularProgressIndicator(),
  149. );
  150. }
  151. },
  152. );
  153. }
  154. Widget _descriptionField() {
  155. return TextFieldDescriptionWidget(
  156. controller: _descriptionController,
  157. onSaved: (newValue) {
  158. _other.description = newValue;
  159. },
  160. );
  161. }
  162. Widget _executeByField() {
  163. return TextFormField(
  164. keyboardType: TextInputType.text,
  165. decoration: InputDecoration(labelText: "Người thực hiện"),
  166. enabled: false,
  167. controller: _executeByController,
  168. onSaved: (newValue) {},
  169. );
  170. }
  171. @override
  172. Widget build(BuildContext context) => KeyboardDismisser(
  173. gestures: [
  174. GestureType.onTap,
  175. GestureType.onPanUpdateDownDirection,
  176. ],
  177. child: Scaffold(
  178. backgroundColor: Colors.white,
  179. key: _scaffoldKey,
  180. appBar: AppBarWidget(
  181. isBack: true,
  182. action: InkWell(
  183. child: Text(
  184. 'Huỷ',
  185. style: TextStyle(
  186. color: Colors.red, fontWeight: FontWeight.normal),
  187. ),
  188. onTap: () {
  189. if (Get.isSnackbarOpen) Get.back();
  190. Get.back();
  191. },
  192. ),
  193. ),
  194. body: KeyboardDismisser(
  195. child: MultiBlocProvider(
  196. providers: [
  197. BlocProvider<ActionDetailBloc>(
  198. create: (context) =>
  199. ActionDetailBloc(repository: Repository())
  200. ..add(FetchData(
  201. isNeedFetchData: widget.isEdit,
  202. apiActivity: ConstCommon.apiDetailOther,
  203. activityId: widget.activityId))),
  204. BlocProvider<MediaHelperBloc>(
  205. create: (context) =>
  206. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  207. )
  208. ],
  209. child: Form(
  210. key: _formKey,
  211. autovalidate: _autoValidate,
  212. child: SafeArea(
  213. child: SingleChildScrollView(
  214. child:
  215. BlocConsumer<ActionDetailBloc, ActionDetailState>(
  216. listener: (context, state) async {
  217. if (state is ActionDetailFailure) {
  218. LoadingDialog.hideLoadingDialog(context);
  219. } else if (state is ActionDetailSuccess) {
  220. LoadingDialog.hideLoadingDialog(context);
  221. _other = Other.fromJson(state.item);
  222. _other.activityId = widget.activityId;
  223. _descriptionController.text =
  224. _other.description ?? "";
  225. _executeByController.text = _other.createdByName;
  226. //select harvest
  227. getActionTypeBloc.getActionTypes((data) {
  228. _actionTypes = data;
  229. for (var item in _actionTypes) {
  230. if (item.name == _other.activityTypeName) {
  231. _actionType = item;
  232. break;
  233. }
  234. }
  235. }, (err) {});
  236. Get.find<ChangeDateTimePicker>().change(_other
  237. .executeDate
  238. .convertStringServerDateTimeToLocalDateTime());
  239. //Show media
  240. if (Validators.stringNotNullOrEmpty(
  241. _other.media)) {
  242. BlocProvider.of<MediaHelperBloc>(context).add(
  243. ChangeListMedia(
  244. items:
  245. UtilAction.convertFilePathToMedia(
  246. _other.media)));
  247. }
  248. } else if (state is ActionDetailInitial) {
  249. } else if (state is ActionDetailLoading) {
  250. LoadingDialog.showLoadingDialog(context);
  251. }
  252. },
  253. builder: (context, state) {
  254. return Column(
  255. children: [
  256. Padding(
  257. padding: const EdgeInsets.all(8.0),
  258. child: Column(
  259. crossAxisAlignment:
  260. CrossAxisAlignment.start,
  261. children: <Widget>[
  262. Text(
  263. plot_action_other,
  264. style: TextStyle(
  265. fontWeight: FontWeight.w500,
  266. fontSize: 22),
  267. ),
  268. SizedBox(
  269. height: 8.0,
  270. ),
  271. Container(
  272. width: double.infinity,
  273. child: Text(
  274. "Ngày thực hiện *",
  275. style: TextStyle(
  276. color: Colors.black54,
  277. fontSize: 13.0),
  278. ),
  279. ),
  280. _btnExecuteTimePicker(),
  281. SizedBox(
  282. height: 8.0,
  283. ),
  284. _dropdownAcionTypes(),
  285. SizedBox(
  286. height: 8.0,
  287. ),
  288. _descriptionField(),
  289. SizedBox(
  290. height: 8.0,
  291. ),
  292. _executeByField(),
  293. SizedBox(
  294. height: 8.0,
  295. ),
  296. ],
  297. ),
  298. ),
  299. Container(
  300. width: double.infinity,
  301. height: 16,
  302. color: Colors.grey[200],
  303. ),
  304. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  305. builder: (context, state) {
  306. if (state is MediaHelperSuccess) {
  307. return WidgetMediaPicker(
  308. currentItems: state.items,
  309. onChangeFiles: (newPathFiles,
  310. deletePathFiles) async {
  311. Get.find<ChangeFileController>()
  312. .change(newPathFiles,
  313. deletePathFiles);
  314. });
  315. } else {
  316. return Center(
  317. child: CircularProgressIndicator());
  318. }
  319. }),
  320. Padding(
  321. padding: const EdgeInsets.all(8.0),
  322. child: ButtonWidget(
  323. title: 'CẬP NHẬT',
  324. onPressed: () {
  325. FocusScopeNode currentFocus =
  326. FocusScope.of(context);
  327. if (!currentFocus.hasPrimaryFocus) {
  328. currentFocus.unfocus();
  329. }
  330. _validateInputs();
  331. }),
  332. ),
  333. ],
  334. );
  335. },
  336. ),
  337. ),
  338. )),
  339. ))));
  340. @override
  341. void dispose() {
  342. _descriptionController.dispose();
  343. _executeByController.dispose();
  344. super.dispose();
  345. }
  346. }