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.

656 lines
29KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/Nursery.dart';
  3. import 'package:farm_tpf/custom_model/NurseryDetail.dart';
  4. import 'package:farm_tpf/custom_model/Supply.dart';
  5. import 'package:farm_tpf/data/api/app_exception.dart';
  6. import 'package:farm_tpf/data/repository/repository.dart';
  7. import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
  8. import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  10. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  11. import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart';
  12. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  13. import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
  14. import 'package:farm_tpf/presentation/screens/actions/nursery/bloc/expansion_list_bloc.dart';
  15. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
  16. import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart';
  17. import 'package:farm_tpf/presentation/screens/resources/sc_resource_helper.dart';
  18. import 'package:farm_tpf/utils/bloc/bloc/status_add_form_bloc.dart';
  19. import 'package:farm_tpf/utils/const_color.dart';
  20. import 'package:farm_tpf/utils/const_common.dart';
  21. import 'package:farm_tpf/utils/const_string.dart';
  22. import 'package:farm_tpf/utils/const_style.dart';
  23. import 'package:farm_tpf/utils/pref.dart';
  24. import 'package:farm_tpf/utils/validators.dart';
  25. import 'package:flutter/material.dart';
  26. import 'package:flutter_bloc/flutter_bloc.dart';
  27. import 'package:get/get.dart';
  28. import 'package:get/state_manager.dart';
  29. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  30. import 'package:farm_tpf/utils/formatter.dart';
  31. import '../util_action.dart';
  32. class EditActionNurseryScreen extends StatefulWidget {
  33. final int cropId;
  34. final bool isEdit;
  35. final int activityId;
  36. EditActionNurseryScreen(
  37. {@required this.cropId, this.isEdit = false, this.activityId});
  38. @override
  39. _EditActionNurseryState createState() => _EditActionNurseryState();
  40. }
  41. class _EditActionNurseryState extends State<EditActionNurseryScreen> {
  42. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  43. final _repository = Repository();
  44. GlobalKey<FormState> _formKey = GlobalKey();
  45. bool _autoValidate = false;
  46. Nursery _nursery = Nursery();
  47. var pref = LocalPref();
  48. TextEditingController _substrateController = TextEditingController();
  49. TextEditingController _seedLengthController = TextEditingController();
  50. TextEditingController _quantityController = TextEditingController();
  51. TextEditingController _seedIncubationTimeController = TextEditingController();
  52. TextEditingController _descriptionController = TextEditingController();
  53. TextEditingController _workerNameController = TextEditingController();
  54. TextEditingController _trayNumberController = TextEditingController();
  55. final _executeByController = TextEditingController();
  56. DateTime executeTime = DateTime.now();
  57. List<NurseryDetail> currentNurseryDetail = List<NurseryDetail>();
  58. int currentIndexUpdate = -1;
  59. bool isResetForm = true;
  60. final changeSupply = Get.put(ChangeSupply());
  61. int selectedSupplyId = -1;
  62. List<String> filePaths = List<String>();
  63. var changeFileController = Get.put(ChangeFileController());
  64. Future<Null> getSharedPrefs() async {
  65. var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  66. _executeByController.text = currentFullName ?? "";
  67. }
  68. @override
  69. void initState() {
  70. super.initState();
  71. getSharedPrefs();
  72. changeSupply.initValue();
  73. changeFileController.initValue();
  74. _nursery.nurseryDetail = new List<NurseryDetail>();
  75. _nursery.cropId = widget.cropId;
  76. }
  77. _validateInputs() async {
  78. if (_formKey.currentState.validate()) {
  79. _formKey.currentState.save();
  80. LoadingDialog.showLoadingDialog(context);
  81. _nursery.nurseryDetail = currentNurseryDetail;
  82. filePaths = Get.find<ChangeFileController>().newFiles;
  83. _nursery.mediaDel = Get.find<ChangeFileController>().deleteFiles;
  84. var activityNursery = jsonEncode(_nursery.toJson()).toString();
  85. //ADD NEW
  86. if (_nursery.activityId == null) {
  87. _repository.createAction((value) {
  88. LoadingDialog.hideLoadingDialog(context);
  89. Get.back(result: value);
  90. Utils.showSnackBarSuccess(message: label_add_success);
  91. }, (error) {
  92. LoadingDialog.hideLoadingDialog(context);
  93. Utils.showSnackBarError(message: AppException.handleError(error));
  94. },
  95. apiAddAction: ConstCommon.apiAddNursery,
  96. paramActivity: ConstCommon.paramsActionNursery,
  97. activityAction: activityNursery,
  98. filePaths: filePaths);
  99. } else {
  100. //UPDATE
  101. _repository.updateAction((value) {
  102. LoadingDialog.hideLoadingDialog(context);
  103. Get.back(result: value);
  104. Utils.showSnackBarSuccess(message: label_update_success);
  105. }, (error) {
  106. LoadingDialog.hideLoadingDialog(context);
  107. Utils.showSnackBarError(message: AppException.handleError(error));
  108. },
  109. apiUpdateAction: ConstCommon.apiUpdateNursery,
  110. paramActivity: ConstCommon.paramsActionNursery,
  111. activityAction: activityNursery,
  112. filePaths: filePaths);
  113. }
  114. } else {
  115. _autoValidate = true;
  116. }
  117. }
  118. Widget _btnExecuteTimePicker() {
  119. return WidgetFieldDateTimePicker(
  120. initDateTime: executeTime,
  121. onUpdateDateTime: (selectedDate) {
  122. _nursery.executeDate =
  123. selectedDate.convertLocalDateTimeToStringUtcDateTime();
  124. });
  125. }
  126. Widget _btnSelectSubstrates() {
  127. return FlatButton(
  128. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  129. onPressed: () {
  130. Navigator.of(context)
  131. .push(MaterialPageRoute(
  132. builder: (_) => ResourceHelperScreen(
  133. titleName: "Giá thể",
  134. type: ConstCommon.supplyTypeSubStrate,
  135. selectedId: Get.find<ChangeSupply>().selectedSupplyId,
  136. currentItems: [],
  137. currentEditId: -1),
  138. fullscreenDialog: false))
  139. .then((value) {
  140. if (value != null) {
  141. var result = value as Supply;
  142. _nursery.substratesId = result.id;
  143. changeSupply.change(result);
  144. print("Home: $value");
  145. }
  146. });
  147. },
  148. child: Container(
  149. padding:
  150. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  151. decoration: BoxDecoration(
  152. border: kBorderTextField,
  153. ),
  154. child: Row(
  155. children: [
  156. GetBuilder<ChangeSupply>(
  157. builder: (_) => Expanded(
  158. child: Text(
  159. changeSupply.selectedSupplyName == null
  160. ? "Loại giá thể"
  161. : changeSupply.selectedSupplyName.toString(),
  162. style: TextStyle(
  163. fontSize: 14.0, color: Colors.black87)))),
  164. Icon(
  165. Icons.arrow_drop_down,
  166. color: Colors.grey,
  167. ),
  168. ],
  169. )));
  170. }
  171. Widget _seedLengthField() {
  172. return WidgetTextFormFieldNumber(
  173. hintValue: "Chiều dài mầm",
  174. textController: _seedLengthController,
  175. onSaved: (newValue) {
  176. _nursery.seedLength = newValue.parseDoubleThousand();
  177. },
  178. );
  179. }
  180. Widget _quantityField() {
  181. return WidgetTextFormFieldNumber(
  182. hintValue: "Số lượng hạt gieo",
  183. textController: _quantityController,
  184. onSaved: (newValue) {
  185. _nursery.quantity = newValue.parseDoubleThousand();
  186. },
  187. );
  188. }
  189. Widget _seedIncubationTimeField() {
  190. return WidgetTextFormFieldNumber(
  191. hintValue: "Thời gian ngâm hạt",
  192. textController: _seedIncubationTimeController,
  193. onSaved: (newValue) {
  194. _nursery.seedIncubationTime = newValue.parseDoubleThousand();
  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. _nursery.description = newValue;
  205. },
  206. );
  207. }
  208. Widget _executeByField() {
  209. return TextFormField(
  210. keyboardType: TextInputType.text,
  211. decoration: InputDecoration(labelText: "Người thực hiện"),
  212. enabled: false,
  213. controller: _executeByController,
  214. onSaved: (newValue) {},
  215. );
  216. }
  217. Widget _btnAddWorker() {
  218. //TODO :check flow error sua item -> xoa list -> bam nut them
  219. return Builder(builder: (context) {
  220. return BlocConsumer<StatusAddFormBloc, StatusAddFormState>(
  221. listener: (context, state) {
  222. if (state is Edit) {
  223. isResetForm = false;
  224. _workerNameController.text = state.nurseryDetail.workerName;
  225. _trayNumberController.text = state.nurseryDetail.trayNumber;
  226. } else if (state is Delete) {
  227. if (currentIndexUpdate == state.index) {
  228. isResetForm = true;
  229. _workerNameController.text = "";
  230. _trayNumberController.text = "";
  231. }
  232. } else {
  233. isResetForm = true;
  234. _workerNameController.text = "";
  235. _trayNumberController.text = "";
  236. }
  237. }, builder: (context, state) {
  238. return Container(
  239. padding: EdgeInsets.all(8.0),
  240. decoration: BoxDecoration(
  241. shape: BoxShape.rectangle,
  242. borderRadius: BorderRadius.circular(10),
  243. color: Colors.white,
  244. border: Border.all(color: COLOR_CONST.DEFAULT)),
  245. child: Form(
  246. child: Column(
  247. children: [
  248. TextFormField(
  249. keyboardType: TextInputType.text,
  250. controller: _workerNameController,
  251. decoration: InputDecoration(labelText: "Tên công nhân *"),
  252. validator: (value) {
  253. return Validators.validateNotNullOrEmpty(
  254. value, "Tên công nhân");
  255. },
  256. onSaved: (newValue) {},
  257. ),
  258. TextFormField(
  259. keyboardType: TextInputType.text,
  260. controller: _trayNumberController,
  261. decoration: InputDecoration(labelText: "Ươm khây số"),
  262. onSaved: (newValue) {},
  263. ),
  264. Align(
  265. alignment: Alignment.centerRight,
  266. child: Row(
  267. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  268. children: [
  269. isResetForm
  270. ? Container()
  271. : OutlineButton(
  272. shape: RoundedRectangleBorder(
  273. borderRadius:
  274. new BorderRadius.circular(8.0)),
  275. child: Text("Huỷ"),
  276. onPressed: () {
  277. context
  278. .bloc<StatusAddFormBloc>()
  279. .add(Reset());
  280. }),
  281. FlatButton(
  282. color: COLOR_CONST.DEFAULT,
  283. shape: RoundedRectangleBorder(
  284. borderRadius: new BorderRadius.circular(8.0)),
  285. onPressed: () {
  286. if (Validators.stringNotNullOrEmpty(
  287. _workerNameController.text)) {
  288. NurseryDetail _nurseryDetail = NurseryDetail()
  289. ..workerName = _workerNameController.text
  290. ..trayNumber = _trayNumberController.text;
  291. if (state is Edit) {
  292. context.bloc<ExpansionListBloc>().add(Update(
  293. index: state.index,
  294. item: _nurseryDetail,
  295. items: state.items));
  296. } else {
  297. currentNurseryDetail.insert(
  298. 0, _nurseryDetail);
  299. BlocProvider.of<ExpansionListBloc>(context)
  300. .add(AddNew(items: currentNurseryDetail));
  301. }
  302. context.bloc<StatusAddFormBloc>().add(Reset());
  303. } else {
  304. Utils.showSnackBarWarning(
  305. message: "Vui lòng nhập tên công nhân");
  306. }
  307. },
  308. child: Text(
  309. (state is Edit) ? "Sửa" : "Thêm",
  310. style: TextStyle(color: Colors.white),
  311. ))
  312. ],
  313. ),
  314. ),
  315. ],
  316. ),
  317. ));
  318. });
  319. });
  320. }
  321. Widget _buildListAddWorker() {
  322. return Builder(builder: (context) {
  323. return BlocBuilder<ExpansionListBloc, ExpansionListState>(
  324. builder: (context, state) {
  325. if (state is ExpansionListSuccess) {
  326. currentNurseryDetail = state.items;
  327. if (currentNurseryDetail.isEmpty) {
  328. return Container();
  329. }
  330. return Container(
  331. height: 70,
  332. child: ListView.builder(
  333. physics: ClampingScrollPhysics(),
  334. scrollDirection: Axis.horizontal,
  335. shrinkWrap: true,
  336. itemCount: currentNurseryDetail.length,
  337. itemBuilder: (context, index) {
  338. return GestureDetector(
  339. onTap: () {
  340. print("edit worker");
  341. currentIndexUpdate = index;
  342. context.bloc<StatusAddFormBloc>().add(Changed(
  343. status: CRUDStatus.edit,
  344. index: index,
  345. nurseryDetail: currentNurseryDetail[index],
  346. items: currentNurseryDetail));
  347. },
  348. child: Card(
  349. child: Stack(
  350. alignment: Alignment.bottomCenter,
  351. overflow: Overflow.visible,
  352. children: <Widget>[
  353. Positioned(
  354. child: ClipRRect(
  355. borderRadius: BorderRadius.circular(8),
  356. child: Container(
  357. padding: EdgeInsets.all(4),
  358. width: 120,
  359. child: Column(
  360. mainAxisAlignment: MainAxisAlignment.center,
  361. children: [
  362. SizedBox(
  363. height: 12.0,
  364. ),
  365. Flexible(
  366. child: Text(
  367. currentNurseryDetail[index]
  368. .workerName ??
  369. "",
  370. overflow: TextOverflow.ellipsis,
  371. maxLines: 1),
  372. ),
  373. Validators.stringNotNullOrEmpty(
  374. currentNurseryDetail[index]
  375. .trayNumber)
  376. ? Flexible(
  377. child: Text(
  378. currentNurseryDetail[index]
  379. .trayNumber ??
  380. ""))
  381. : SizedBox()
  382. ],
  383. ),
  384. ),
  385. )),
  386. Positioned(
  387. top: -10,
  388. right: -10,
  389. child: IconButton(
  390. icon: Icon(
  391. Icons.cancel,
  392. color: Colors.redAccent,
  393. ),
  394. onPressed: () {
  395. print("Delete worker");
  396. context.bloc<ExpansionListBloc>().add(
  397. DeleteItem(
  398. index: index,
  399. items: currentNurseryDetail));
  400. context.bloc<StatusAddFormBloc>().add(
  401. Changed(
  402. status: CRUDStatus.delete,
  403. index: index,
  404. nurseryDetail:
  405. currentNurseryDetail[index],
  406. items: currentNurseryDetail));
  407. }),
  408. )
  409. ],
  410. )));
  411. }));
  412. } else if (state is ExpansionListFailure) {
  413. return Container();
  414. } else {
  415. return Container();
  416. }
  417. });
  418. });
  419. }
  420. _actionAppBar() {
  421. IconButton iconButton;
  422. if (1 == 1) {
  423. iconButton = IconButton(
  424. icon: Icon(
  425. Icons.done,
  426. color: Colors.black,
  427. ),
  428. onPressed: () {
  429. FocusScopeNode currentFocus = FocusScope.of(context);
  430. if (!currentFocus.hasPrimaryFocus) {
  431. currentFocus.unfocus();
  432. }
  433. if (!Validators.stringNotNullOrEmpty(_workerNameController.text) &&
  434. !Validators.stringNotNullOrEmpty(_trayNumberController.text)) {
  435. _validateInputs();
  436. } else {
  437. Utils.showDialog(
  438. title: "Tên công nhân hoặc khây trồng đang cập nhật",
  439. message: "Bạn có muốn cập nhật?",
  440. textConfirm: "Tiếp tục",
  441. textCancel: "Xem lại",
  442. onConfirm: () {
  443. Get.back();
  444. _validateInputs();
  445. });
  446. }
  447. },
  448. );
  449. return <Widget>[iconButton];
  450. }
  451. return <Widget>[Container()];
  452. }
  453. @override
  454. Widget build(BuildContext context) => KeyboardDismisser(
  455. gestures: [
  456. GestureType.onTap,
  457. GestureType.onPanUpdateDownDirection,
  458. ],
  459. child: Scaffold(
  460. key: _scaffoldKey,
  461. appBar: AppBar(
  462. centerTitle: true,
  463. title: Text(plot_action_nursery),
  464. actions: _actionAppBar()),
  465. body: KeyboardDismisser(
  466. child: MultiBlocProvider(
  467. providers: [
  468. BlocProvider<ExpansionListBloc>(
  469. create: (context) => ExpansionListBloc(),
  470. ),
  471. BlocProvider<StatusAddFormBloc>(
  472. create: (context) => StatusAddFormBloc(),
  473. ),
  474. BlocProvider<ActionDetailBloc>(
  475. create: (context) =>
  476. ActionDetailBloc(repository: Repository())
  477. ..add(FetchData(
  478. isNeedFetchData: widget.isEdit,
  479. apiActivity: ConstCommon.apiDetailNursery,
  480. activityId: widget.activityId))),
  481. BlocProvider<MediaHelperBloc>(
  482. create: (context) =>
  483. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  484. )
  485. ],
  486. child: Form(
  487. key: _formKey,
  488. autovalidate: _autoValidate,
  489. child: SingleChildScrollView(
  490. padding: EdgeInsets.all(8.0),
  491. child: BlocConsumer<ActionDetailBloc,
  492. ActionDetailState>(
  493. listener: (context, state) async {
  494. if (state is ActionDetailFailure) {
  495. print("fail");
  496. LoadingDialog.hideLoadingDialog(context);
  497. } else if (state is ActionDetailSuccess) {
  498. LoadingDialog.hideLoadingDialog(context);
  499. print("success");
  500. print(state.item);
  501. _nursery = Nursery.fromJson(state.item);
  502. _seedLengthController.text = _nursery
  503. .seedLength
  504. .formatNumtoStringDecimal();
  505. _quantityController.text = _nursery.quantity
  506. .formatNumtoStringDecimal();
  507. _seedIncubationTimeController.text = _nursery
  508. .seedIncubationTime
  509. .formatNumtoStringDecimal();
  510. _descriptionController.text =
  511. _nursery.description;
  512. _executeByController.text =
  513. _nursery.executeBy;
  514. Get.find<ChangeDateTimePicker>().change(_nursery
  515. .executeDate
  516. .convertStringServerDateTimeToLocalDateTime());
  517. //Show media
  518. if (Validators.stringNotNullOrEmpty(
  519. _nursery.media)) {
  520. BlocProvider.of<MediaHelperBloc>(context)
  521. .add(ChangeListMedia(
  522. items: UtilAction
  523. .convertFilePathToMedia(
  524. _nursery.media)));
  525. }
  526. //Show worker
  527. if (_nursery.nurseryDetail.length > 0) {
  528. BlocProvider.of<ExpansionListBloc>(context)
  529. .add(AddNew(
  530. items: _nursery.nurseryDetail));
  531. }
  532. //change subStrates
  533. if (_nursery.substratesId != null) {
  534. Get.find<ChangeSupply>().changeByIdAndName(
  535. _nursery.substratesId,
  536. _nursery.substrateName);
  537. }
  538. } else if (state is ActionDetailInitial) {
  539. print("init");
  540. } else if (state is ActionDetailLoading) {
  541. print("loading");
  542. LoadingDialog.showLoadingDialog(context);
  543. }
  544. },
  545. builder: (context, state) {
  546. return Column(
  547. children: <Widget>[
  548. Container(
  549. width: double.infinity,
  550. child: Text(
  551. "Ngày thực hiện *",
  552. style: TextStyle(
  553. color: Colors.black54,
  554. fontSize: 13.0),
  555. ),
  556. ),
  557. _btnExecuteTimePicker(),
  558. SizedBox(
  559. height: 8.0,
  560. ),
  561. Container(
  562. width: double.infinity,
  563. child: Text(
  564. "Loại giá thể",
  565. style: TextStyle(
  566. color: Colors.black54,
  567. fontSize: 13.0),
  568. ),
  569. ),
  570. _btnSelectSubstrates(),
  571. SizedBox(
  572. height: 8.0,
  573. ),
  574. _seedLengthField(),
  575. SizedBox(
  576. height: 8.0,
  577. ),
  578. _quantityField(),
  579. SizedBox(
  580. height: 8.0,
  581. ),
  582. _seedIncubationTimeField(),
  583. SizedBox(
  584. height: 8.0,
  585. ),
  586. _desciptionField(),
  587. SizedBox(
  588. height: 8.0,
  589. ),
  590. _executeByField(),
  591. SizedBox(
  592. height: 8.0,
  593. ),
  594. _buildListAddWorker(),
  595. SizedBox(
  596. height: 8.0,
  597. ),
  598. _btnAddWorker(),
  599. SizedBox(
  600. height: 8.0,
  601. ),
  602. BlocBuilder<MediaHelperBloc,
  603. MediaHelperState>(
  604. builder: (context, state) {
  605. if (state is MediaHelperSuccess) {
  606. print("length: " +
  607. state.items.length.toString());
  608. return WidgetMediaPicker(
  609. currentItems: state.items,
  610. onChangeFiles: (newPathFiles,
  611. deletePathFiles) async {
  612. Get.find<ChangeFileController>()
  613. .change(newPathFiles,
  614. deletePathFiles);
  615. });
  616. } else {
  617. return Center(
  618. child: CircularProgressIndicator());
  619. }
  620. }),
  621. ],
  622. );
  623. },
  624. ),
  625. ))))));
  626. @override
  627. void dispose() {
  628. _substrateController.dispose();
  629. _seedLengthController.dispose();
  630. _quantityController.dispose();
  631. _seedIncubationTimeController.dispose();
  632. _descriptionController.dispose();
  633. _executeByController.dispose();
  634. super.dispose();
  635. }
  636. }