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.

367 lines
15KB

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