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.

391 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/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/screens/actions/bloc/action_detail_bloc.dart';
  10. import 'package:farm_tpf/presentation/screens/actions/other/bloc_get_action_type.dart';
  11. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  12. import 'package:farm_tpf/utils/const_common.dart';
  13. import 'package:farm_tpf/utils/const_string.dart';
  14. import 'package:farm_tpf/utils/const_style.dart';
  15. import 'package:farm_tpf/utils/pref.dart';
  16. import 'package:farm_tpf/utils/validators.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:fluttertoast/fluttertoast.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>().files;
  74. try {
  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. Get.snackbar(label_add_success, "Hoạt động khác",
  82. snackPosition: SnackPosition.BOTTOM);
  83. }, (error) {
  84. LoadingDialog.hideLoadingDialog(context);
  85. _scaffoldKey.currentState.showSnackBar(SnackBar(
  86. content: Row(
  87. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  88. children: <Widget>[
  89. Flexible(child: Text(AppException.handleError(error))),
  90. Icon(Icons.error),
  91. ],
  92. ),
  93. backgroundColor: Colors.red,
  94. duration: Duration(seconds: 3),
  95. ));
  96. },
  97. apiAddAction: ConstCommon.apiAddOther,
  98. paramActivity: ConstCommon.paramsActionOther,
  99. activityAction: activityOther,
  100. filePaths: filePaths);
  101. } else {
  102. //UPDATE
  103. _repository.updateAction((value) {
  104. LoadingDialog.hideLoadingDialog(context);
  105. Get.back(result: value);
  106. Get.snackbar(label_update_success, "Hoạt động khác",
  107. snackPosition: SnackPosition.BOTTOM);
  108. }, (error) {
  109. LoadingDialog.hideLoadingDialog(context);
  110. _scaffoldKey.currentState.showSnackBar(SnackBar(
  111. content: Row(
  112. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  113. children: <Widget>[
  114. Flexible(child: Text(AppException.handleError(error))),
  115. Icon(Icons.error),
  116. ],
  117. ),
  118. backgroundColor: Colors.red,
  119. duration: Duration(seconds: 3),
  120. ));
  121. },
  122. apiUpdateAction: ConstCommon.apiUpdateOther,
  123. paramActivity: ConstCommon.paramsActionOther,
  124. activityAction: activityOther,
  125. filePaths: filePaths);
  126. }
  127. } catch (e) {
  128. LoadingDialog.hideLoadingDialog(context);
  129. print(e.toString());
  130. }
  131. } else {
  132. _autoValidate = true;
  133. }
  134. }
  135. Widget _btnExecuteTimePicker() {
  136. return FlatButton(
  137. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  138. onPressed: () {
  139. DatePicker.showDateTimePicker(context,
  140. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  141. setState(() {
  142. var parsedDate =
  143. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  144. _other.executeDate = "$parsedDate";
  145. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  146. });
  147. }, currentTime: executeTime, locale: LocaleType.vi);
  148. },
  149. child: Container(
  150. padding:
  151. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  152. decoration: BoxDecoration(
  153. border: kBorderTextField,
  154. ),
  155. child: Row(
  156. children: [
  157. Expanded(
  158. child: Text(
  159. //TODO: check condition
  160. executeTimeView == null ? "$executeTime" : executeTimeView,
  161. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  162. )),
  163. Icon(
  164. Icons.date_range,
  165. color: Colors.blue,
  166. ),
  167. ],
  168. )));
  169. }
  170. List<DropdownMenuItem<ActionType>> _buildDropMenu(List<ActionType> actions) {
  171. return actions
  172. .map((action) => DropdownMenuItem<ActionType>(
  173. child: Text(action.description.toString()),
  174. value: action,
  175. ))
  176. .toList();
  177. }
  178. Widget _dropdownAcionTypes() {
  179. return StreamBuilder(
  180. stream: getActionTypeBloc.actions,
  181. builder: (context, AsyncSnapshot<dynamic> snapshot) {
  182. if (snapshot.hasData) {
  183. return DropdownButtonFormField<ActionType>(
  184. value: _actionType,
  185. hint: Text("Hoạt động"),
  186. onChanged: (ActionType newValue) {
  187. setState(() {
  188. _actionType = newValue;
  189. _other.activityTypeName = newValue.name;
  190. });
  191. },
  192. validator: (value) => value == null ? "Hoạt động" : null,
  193. isExpanded: true,
  194. items: _buildDropMenu(_actionTypes));
  195. } else if (snapshot.hasError) {
  196. return Container();
  197. } else {
  198. return Center(
  199. child: CircularProgressIndicator(),
  200. );
  201. }
  202. },
  203. );
  204. }
  205. Widget _desciptionField() {
  206. return TextFormField(
  207. keyboardType: TextInputType.text,
  208. decoration: InputDecoration(labelText: "Ghi chú"),
  209. controller: _descriptionController,
  210. onSaved: (newValue) {
  211. _other.description = newValue;
  212. },
  213. );
  214. }
  215. Widget _executeByField() {
  216. return TextFormField(
  217. keyboardType: TextInputType.text,
  218. decoration: InputDecoration(labelText: "Người thực hiện"),
  219. enabled: false,
  220. controller: _executeByController,
  221. onSaved: (newValue) {},
  222. );
  223. }
  224. _actionAppBar() {
  225. IconButton iconButton;
  226. if (1 == 1) {
  227. iconButton = IconButton(
  228. icon: Icon(
  229. Icons.done,
  230. color: Colors.black,
  231. ),
  232. onPressed: () {
  233. FocusScopeNode currentFocus = FocusScope.of(context);
  234. if (!currentFocus.hasPrimaryFocus) {
  235. currentFocus.unfocus();
  236. }
  237. _validateInputs();
  238. },
  239. );
  240. return <Widget>[iconButton];
  241. }
  242. return <Widget>[Container()];
  243. }
  244. @override
  245. Widget build(BuildContext context) => KeyboardDismisser(
  246. gestures: [
  247. GestureType.onTap,
  248. GestureType.onPanUpdateDownDirection,
  249. ],
  250. child: Scaffold(
  251. key: _scaffoldKey,
  252. appBar: AppBar(
  253. centerTitle: true,
  254. title: Text(plot_action_other),
  255. actions: _actionAppBar()),
  256. body: KeyboardDismisser(
  257. child: MultiBlocProvider(
  258. providers: [
  259. BlocProvider<ActionDetailBloc>(
  260. create: (context) =>
  261. ActionDetailBloc(repository: Repository())
  262. ..add(FetchData(
  263. isNeedFetchData: widget.isEdit,
  264. apiActivity: ConstCommon.apiDetailOther,
  265. activityId: widget.activityId))),
  266. BlocProvider<MediaHelperBloc>(
  267. create: (context) =>
  268. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  269. )
  270. ],
  271. child: Form(
  272. key: _formKey,
  273. autovalidate: _autoValidate,
  274. child: SingleChildScrollView(
  275. padding: EdgeInsets.all(8.0),
  276. child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
  277. listener: (context, state) async {
  278. if (state is ActionDetailFailure) {
  279. LoadingDialog.hideLoadingDialog(context);
  280. } else if (state is ActionDetailSuccess) {
  281. LoadingDialog.hideLoadingDialog(context);
  282. _other = Other.fromJson(state.item);
  283. _other.activityId = widget.activityId;
  284. _descriptionController.text =
  285. _other.description ?? "";
  286. _executeByController.text = _other.createdByName;
  287. //select harvest
  288. getActionTypeBloc.getActionTypes((data) {
  289. _actionTypes = data;
  290. for (var item in _actionTypes) {
  291. if (item.name == _other.activityTypeName) {
  292. _actionType = item;
  293. break;
  294. }
  295. }
  296. }, (err) {});
  297. try {
  298. executeTime =
  299. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
  300. .parse(_other.executeDate);
  301. executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
  302. .format(executeTime);
  303. } catch (_) {}
  304. //Show media
  305. if (_other.media != null) {
  306. await UtilAction.cacheFiles(_other.media)
  307. .then((value) {
  308. BlocProvider.of<MediaHelperBloc>(context)
  309. .add(ChangeListMedia(items: value));
  310. }).whenComplete(() {
  311. print("completed");
  312. });
  313. }
  314. } else if (state is ActionDetailInitial) {
  315. } else if (state is ActionDetailLoading) {
  316. LoadingDialog.showLoadingDialog(context);
  317. }
  318. },
  319. builder: (context, state) {
  320. return Column(
  321. children: <Widget>[
  322. Container(
  323. width: double.infinity,
  324. child: Text(
  325. "Ngày thực hiện",
  326. style: TextStyle(
  327. color: Colors.black54, fontSize: 13.0),
  328. ),
  329. ),
  330. _btnExecuteTimePicker(),
  331. SizedBox(
  332. height: 8.0,
  333. ),
  334. _dropdownAcionTypes(),
  335. SizedBox(
  336. height: 8.0,
  337. ),
  338. _desciptionField(),
  339. SizedBox(
  340. height: 8.0,
  341. ),
  342. _executeByField(),
  343. SizedBox(
  344. height: 8.0,
  345. ),
  346. BlocBuilder<MediaHelperBloc, MediaHelperState>(
  347. builder: (context, state) {
  348. if (state is MediaHelperSuccess) {
  349. return WidgetMediaPicker(
  350. currentItems: state.items,
  351. onChangeFiles: (filePaths) async {
  352. Get.find<ChangeFileController>()
  353. .addAllFile(filePaths);
  354. });
  355. } else {
  356. return Center(
  357. child: CircularProgressIndicator());
  358. }
  359. }),
  360. ],
  361. );
  362. },
  363. ),
  364. )),
  365. ))));
  366. @override
  367. void dispose() {
  368. _descriptionController.dispose();
  369. _executeByController.dispose();
  370. super.dispose();
  371. }
  372. }