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