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.

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