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