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.

368 lines
14KB

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