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