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.

598 lines
23KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/Nursery.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/widget_media_helper.dart';
  7. import 'package:farm_tpf/presentation/screens/actions/nursery/bloc/expansion_list_bloc.dart';
  8. import 'package:farm_tpf/presentation/screens/resources/sc_resource_helper.dart';
  9. import 'package:farm_tpf/utils/bloc/bloc/status_add_form_bloc.dart';
  10. import 'package:farm_tpf/utils/const_color.dart';
  11. import 'package:farm_tpf/utils/const_common.dart';
  12. import 'package:farm_tpf/utils/const_string.dart';
  13. import 'package:farm_tpf/utils/const_style.dart';
  14. import 'package:farm_tpf/utils/pref.dart';
  15. import 'package:farm_tpf/utils/validators.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:fluttertoast/fluttertoast.dart';
  20. import 'package:get/get.dart';
  21. import 'package:get/state_manager.dart';
  22. import 'package:intl/intl.dart';
  23. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  24. import 'package:pattern_formatter/pattern_formatter.dart';
  25. import 'package:farm_tpf/utils/formatter.dart';
  26. class EditActionNurseryScreen extends StatefulWidget {
  27. @override
  28. _EditActionNurseryState createState() => _EditActionNurseryState();
  29. }
  30. class _EditActionNurseryState extends State<EditActionNurseryScreen> {
  31. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  32. final _repository = Repository();
  33. GlobalKey<FormState> _formKey = GlobalKey();
  34. bool _autoValidate = false;
  35. Nursery _nursery = Nursery();
  36. var pref = LocalPref();
  37. FlutterToast flutterToast;
  38. TextEditingController _substrateController = TextEditingController();
  39. TextEditingController _seedLengthController = TextEditingController();
  40. TextEditingController _quantityController = TextEditingController();
  41. TextEditingController _seedIncubationTimeController = TextEditingController();
  42. TextEditingController _descriptionController = TextEditingController();
  43. TextEditingController _workerNameController = TextEditingController();
  44. TextEditingController _trayNumberController = TextEditingController();
  45. String executeTimeView;
  46. DateTime executeTime = DateTime.now();
  47. List<NurseryDetail> currentNurseryDetail = List<NurseryDetail>();
  48. ExpansionListBloc _bloc;
  49. int currentIndexUpdate = -1;
  50. bool isResetForm = true;
  51. final changeSupply = Get.put(ChangeSupply());
  52. int selectedSupplyId = -1;
  53. List<String> filePaths = List<String>();
  54. var changeFileController = Get.put(ChangeFileController());
  55. @override
  56. void initState() {
  57. super.initState();
  58. changeSupply.initValue();
  59. changeFileController.initValue();
  60. filePaths.add(
  61. "/Users/macbook/Library/Developer/CoreSimulator/Devices/CC52586C-39AA-489B-A74D-83107AA9F7C1/data/Containers/Data/Application/F377B9A4-939D-42B2-9628-350C4A0BFD50/tmp/image_picker_801FCF0F-577F-4AFA-AC58-1C716A1C561C-30707-000015F0E14256F8.jpg");
  62. _nursery.nurseryDetail = new List<NurseryDetail>();
  63. flutterToast = FlutterToast(context);
  64. //UPDATE
  65. if (_nursery.cropId != null) {
  66. try {
  67. executeTime =
  68. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(_nursery.executeDate);
  69. } catch (_) {}
  70. } else {
  71. //ADD NEW
  72. var parsedExecuteDate =
  73. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
  74. _nursery.executeDate = "$parsedExecuteDate";
  75. //TODO: update cropid
  76. _nursery.cropId = 1;
  77. }
  78. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
  79. }
  80. _validateInputs() async {
  81. if (_formKey.currentState.validate()) {
  82. _formKey.currentState.save();
  83. _nursery.nurseryDetail = currentNurseryDetail;
  84. filePaths = Get.find<ChangeFileController>().files;
  85. var activityNursery = jsonEncode(_nursery.toJson()).toString();
  86. _repository.createNursery((value) {
  87. print("post ok");
  88. }, (error) {
  89. print("--------------------------------");
  90. print(error);
  91. }, activityNursery, filePaths: filePaths);
  92. } else {
  93. _autoValidate = true;
  94. }
  95. }
  96. Widget _btnExecuteTimePicker() {
  97. return FlatButton(
  98. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  99. onPressed: () {
  100. DatePicker.showDateTimePicker(context,
  101. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  102. setState(() {
  103. var parsedDate =
  104. DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
  105. _nursery.executeDate = "$parsedDate";
  106. executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(date);
  107. });
  108. }, currentTime: executeTime, locale: LocaleType.vi);
  109. },
  110. child: Container(
  111. padding:
  112. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  113. decoration: BoxDecoration(
  114. border: kBorderTextField,
  115. ),
  116. child: Row(
  117. children: [
  118. Expanded(
  119. child: Text(
  120. //TODO: check condition
  121. executeTimeView == null ? "$executeTime" : executeTimeView,
  122. style: TextStyle(fontSize: 14.0, color: Colors.black87),
  123. )),
  124. Icon(
  125. Icons.date_range,
  126. color: Colors.blue,
  127. ),
  128. ],
  129. )));
  130. }
  131. Widget _btnSelectSeed() {
  132. return FlatButton(
  133. padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0),
  134. onPressed: () {
  135. Navigator.of(context)
  136. .push(MaterialPageRoute(
  137. builder: (_) => ResourceHelperScreen(
  138. titleName: "Gía thể",
  139. type: ConstCommon.supplyTypeSubStrate,
  140. selectedId: Get.find<ChangeSupply>().selectedSupplyId),
  141. fullscreenDialog: false))
  142. .then((value) {
  143. if (value != null) {
  144. var result = value as Supply;
  145. _nursery.substrates = result.name;
  146. changeSupply.change(result);
  147. print("Home: $value");
  148. }
  149. });
  150. },
  151. child: Container(
  152. padding:
  153. EdgeInsets.only(top: 0.0, right: 0.0, bottom: 10.5, left: 0.0),
  154. decoration: BoxDecoration(
  155. border: kBorderTextField,
  156. ),
  157. child: Row(
  158. children: [
  159. GetBuilder<ChangeSupply>(
  160. builder: (_) => Expanded(
  161. child: Text(
  162. changeSupply.currentSupply.name == null
  163. ? "Loại giá thể"
  164. : changeSupply.currentSupply.name.toString(),
  165. style: TextStyle(
  166. fontSize: 14.0, color: Colors.black87)))),
  167. Icon(
  168. Icons.arrow_drop_down,
  169. color: Colors.grey,
  170. ),
  171. ],
  172. )));
  173. }
  174. Widget _seedLengthField() {
  175. return TextFormField(
  176. keyboardType: TextInputType.numberWithOptions(decimal: true),
  177. inputFormatters: [
  178. ThousandsFormatter(
  179. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  180. ],
  181. decoration: InputDecoration(labelText: "Chiều dài mần"),
  182. controller: _seedLengthController,
  183. validator: (String value) {
  184. return Validators.validNumber(value, "Chiều dài mần");
  185. },
  186. onSaved: (newValue) {
  187. _nursery.seedLength = newValue.parseDoubleThousand();
  188. },
  189. );
  190. }
  191. Widget _quantityField() {
  192. return TextFormField(
  193. keyboardType: TextInputType.numberWithOptions(decimal: true),
  194. inputFormatters: [
  195. ThousandsFormatter(
  196. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  197. ],
  198. decoration: InputDecoration(labelText: "Số lượng hạt gieo"),
  199. controller: _quantityController,
  200. validator: (String value) {
  201. return Validators.validNumber(value, "Số lượng hạt gieo");
  202. },
  203. onSaved: (newValue) {
  204. _nursery.quantity = newValue.parseDoubleThousand();
  205. },
  206. );
  207. }
  208. Widget _seedIncubationTimeField() {
  209. return TextFormField(
  210. keyboardType: TextInputType.numberWithOptions(decimal: true),
  211. inputFormatters: [
  212. ThousandsFormatter(
  213. formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
  214. ],
  215. decoration: InputDecoration(labelText: "Thời gian ngâm hạt"),
  216. controller: _seedIncubationTimeController,
  217. validator: (String value) {
  218. return Validators.validNumber(value, "Thời gian ngâm hạt");
  219. },
  220. onSaved: (newValue) {
  221. _nursery.seedIncubationTime = newValue.parseDoubleThousand();
  222. },
  223. );
  224. }
  225. Widget _desciptionField() {
  226. return TextFormField(
  227. keyboardType: TextInputType.text,
  228. decoration: InputDecoration(labelText: "Ghi chú"),
  229. controller: _descriptionController,
  230. onSaved: (newValue) {
  231. _nursery.description = newValue;
  232. },
  233. );
  234. }
  235. Widget _btnAddWorker() {
  236. //TODO :check flow error sua item -> xoa list -> bam nut them
  237. return Builder(builder: (context) {
  238. return BlocConsumer<StatusAddFormBloc, StatusAddFormState>(
  239. listener: (context, state) {
  240. if (state is Edit) {
  241. isResetForm = false;
  242. _workerNameController.text = state.nurseryDetail.workerName;
  243. _trayNumberController.text = state.nurseryDetail.trayNumber;
  244. } else if (state is Delete) {
  245. if (currentIndexUpdate == state.index) {
  246. isResetForm = true;
  247. _workerNameController.text = "";
  248. _trayNumberController.text = "";
  249. }
  250. } else {
  251. isResetForm = true;
  252. _workerNameController.text = "";
  253. _trayNumberController.text = "";
  254. }
  255. }, builder: (context, state) {
  256. return Container(
  257. padding: EdgeInsets.all(8.0),
  258. decoration: BoxDecoration(
  259. shape: BoxShape.rectangle,
  260. borderRadius: BorderRadius.circular(10),
  261. color: Colors.white,
  262. border: Border.all(color: COLOR_CONST.DEFAULT)),
  263. child: Column(
  264. children: [
  265. TextFormField(
  266. keyboardType: TextInputType.text,
  267. controller: _workerNameController,
  268. decoration: InputDecoration(labelText: "Tên công nhân"),
  269. onSaved: (newValue) {
  270. _nursery.description = newValue;
  271. },
  272. ),
  273. TextFormField(
  274. keyboardType: TextInputType.text,
  275. controller: _trayNumberController,
  276. decoration: InputDecoration(labelText: "Ươm khây số"),
  277. onSaved: (newValue) {
  278. _nursery.description = newValue;
  279. },
  280. ),
  281. Align(
  282. alignment: Alignment.centerRight,
  283. child: Row(
  284. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  285. children: [
  286. isResetForm
  287. ? Container()
  288. : OutlineButton(
  289. shape: RoundedRectangleBorder(
  290. borderRadius: new BorderRadius.circular(8.0)),
  291. child: Text("Huỷ"),
  292. onPressed: () {
  293. context.bloc<StatusAddFormBloc>().add(Reset());
  294. }),
  295. FlatButton(
  296. color: COLOR_CONST.DEFAULT,
  297. shape: RoundedRectangleBorder(
  298. borderRadius: new BorderRadius.circular(8.0)),
  299. onPressed: () {
  300. if (_workerNameController.text.isEmpty ||
  301. _trayNumberController.text.isEmpty) {
  302. return;
  303. }
  304. NurseryDetail _nurseryDetail = NurseryDetail()
  305. ..workerName = _workerNameController.text
  306. ..trayNumber = _trayNumberController.text;
  307. if (state is Edit) {
  308. context.bloc<ExpansionListBloc>().add(Update(
  309. index: state.index,
  310. item: _nurseryDetail,
  311. items: state.items));
  312. } else {
  313. currentNurseryDetail.insert(0, _nurseryDetail);
  314. BlocProvider.of<ExpansionListBloc>(context)
  315. .add(AddNew(items: currentNurseryDetail));
  316. }
  317. context.bloc<StatusAddFormBloc>().add(Reset());
  318. },
  319. child: Text(
  320. (state is Edit) ? "Sửa" : "Thêm",
  321. style: TextStyle(color: Colors.white),
  322. ))
  323. ],
  324. ),
  325. ),
  326. ],
  327. ));
  328. });
  329. });
  330. }
  331. Widget _buildListAddWorker() {
  332. return Builder(builder: (context) {
  333. return BlocBuilder<ExpansionListBloc, ExpansionListState>(
  334. builder: (context, state) {
  335. if (state is ExpansionListSuccess) {
  336. currentNurseryDetail = state.items;
  337. if (currentNurseryDetail.isEmpty) {
  338. return Container();
  339. }
  340. return Container(
  341. height: 70,
  342. child: ListView.builder(
  343. physics: ClampingScrollPhysics(),
  344. scrollDirection: Axis.horizontal,
  345. shrinkWrap: true,
  346. itemCount: currentNurseryDetail.length,
  347. itemBuilder: (context, index) {
  348. return GestureDetector(
  349. onTap: () {
  350. print("Show preview image or video");
  351. currentIndexUpdate = index;
  352. context.bloc<StatusAddFormBloc>().add(Changed(
  353. status: CRUDStatus.edit,
  354. index: index,
  355. nurseryDetail: currentNurseryDetail[index],
  356. items: currentNurseryDetail));
  357. },
  358. child: Card(
  359. child: Stack(
  360. alignment: Alignment.bottomCenter,
  361. overflow: Overflow.visible,
  362. children: <Widget>[
  363. Positioned(
  364. child: ClipRRect(
  365. borderRadius: BorderRadius.circular(8),
  366. child: Container(
  367. padding: EdgeInsets.all(4),
  368. width: 120,
  369. child: Column(
  370. children: [
  371. SizedBox(
  372. height: 12.0,
  373. ),
  374. Flexible(
  375. child: Text(
  376. currentNurseryDetail[index]
  377. .workerName ??
  378. "",
  379. overflow: TextOverflow.ellipsis,
  380. maxLines: 1),
  381. ),
  382. Flexible(
  383. child: Text(currentNurseryDetail[index]
  384. .trayNumber ??
  385. ""))
  386. ],
  387. ),
  388. ),
  389. )),
  390. Positioned(
  391. top: -10,
  392. right: -10,
  393. child: IconButton(
  394. icon: Icon(
  395. Icons.cancel,
  396. color: Colors.redAccent,
  397. ),
  398. onPressed: () {
  399. print("On tap delete media");
  400. context.bloc<ExpansionListBloc>().add(
  401. DeleteItem(
  402. index: index,
  403. items: currentNurseryDetail));
  404. context.bloc<StatusAddFormBloc>().add(
  405. Changed(
  406. status: CRUDStatus.delete,
  407. index: index,
  408. nurseryDetail:
  409. currentNurseryDetail[index],
  410. items: currentNurseryDetail));
  411. }),
  412. )
  413. ],
  414. )));
  415. }));
  416. } else if (state is ExpansionListFailure) {
  417. return Container();
  418. } else {
  419. return Container();
  420. }
  421. });
  422. });
  423. }
  424. _actionAppBar() {
  425. IconButton iconButton;
  426. if (1 == 1) {
  427. iconButton = IconButton(
  428. icon: Icon(
  429. Icons.done,
  430. color: Colors.black,
  431. ),
  432. onPressed: () {
  433. FocusScopeNode currentFocus = FocusScope.of(context);
  434. if (!currentFocus.hasPrimaryFocus) {
  435. currentFocus.unfocus();
  436. }
  437. _validateInputs();
  438. },
  439. );
  440. return <Widget>[iconButton];
  441. }
  442. return <Widget>[Container()];
  443. }
  444. @override
  445. Widget build(BuildContext context) => KeyboardDismisser(
  446. gestures: [
  447. GestureType.onTap,
  448. GestureType.onPanUpdateDownDirection,
  449. ],
  450. child: Scaffold(
  451. key: _scaffoldKey,
  452. appBar: AppBar(
  453. centerTitle: true,
  454. title: Text(plot_action_nursery),
  455. actions: _actionAppBar()),
  456. body: KeyboardDismisser(
  457. child: MultiBlocProvider(
  458. providers: [
  459. BlocProvider<ExpansionListBloc>(
  460. create: (context) => ExpansionListBloc(),
  461. ),
  462. BlocProvider<StatusAddFormBloc>(
  463. create: (context) => StatusAddFormBloc(),
  464. )
  465. ],
  466. child: Form(
  467. key: _formKey,
  468. autovalidate: _autoValidate,
  469. child: SingleChildScrollView(
  470. padding: EdgeInsets.all(8.0),
  471. child: Column(
  472. children: <Widget>[
  473. Container(
  474. width: double.infinity,
  475. child: Text(
  476. "Ngày thực hiện",
  477. style: TextStyle(
  478. color: Colors.black54, fontSize: 13.0),
  479. ),
  480. ),
  481. _btnExecuteTimePicker(),
  482. SizedBox(
  483. height: 8.0,
  484. ),
  485. Container(
  486. width: double.infinity,
  487. child: Text(
  488. "Tên giống",
  489. style: TextStyle(
  490. color: Colors.black54, fontSize: 13.0),
  491. ),
  492. ),
  493. _btnSelectSeed(),
  494. SizedBox(
  495. height: 8.0,
  496. ),
  497. _seedLengthField(),
  498. SizedBox(
  499. height: 8.0,
  500. ),
  501. _quantityField(),
  502. SizedBox(
  503. height: 8.0,
  504. ),
  505. _seedIncubationTimeField(),
  506. SizedBox(
  507. height: 8.0,
  508. ),
  509. _desciptionField(),
  510. SizedBox(
  511. height: 8.0,
  512. ),
  513. _btnAddWorker(),
  514. SizedBox(
  515. height: 8.0,
  516. ),
  517. _buildListAddWorker(),
  518. SizedBox(
  519. height: 8.0,
  520. ),
  521. WidgetMediaHelper(onChangeFiles: (filePaths) {
  522. Get.find<ChangeFileController>()
  523. .addAllFile(filePaths);
  524. // setState(() {
  525. // filePaths = filePaths;
  526. // });
  527. })
  528. ],
  529. ),
  530. ))))));
  531. @override
  532. void dispose() {
  533. _substrateController.dispose();
  534. _seedLengthController.dispose();
  535. _quantityController.dispose();
  536. _seedIncubationTimeController.dispose();
  537. _descriptionController.dispose();
  538. super.dispose();
  539. }
  540. }
  541. class ChangeSupply extends GetxController {
  542. Supply currentSupply;
  543. int selectedSupplyId;
  544. void initValue() {
  545. currentSupply = Supply();
  546. selectedSupplyId = -1;
  547. update();
  548. }
  549. void change(Supply supply) {
  550. currentSupply = supply;
  551. selectedSupplyId = supply.id;
  552. update();
  553. }
  554. }
  555. class ChangeFileController extends GetxController {
  556. List<String> files;
  557. void initValue() {
  558. files = [];
  559. update();
  560. }
  561. void addAllFile(List<String> filePaths) {
  562. files = [];
  563. files = filePaths;
  564. update();
  565. }
  566. void addFile(String filePath) {
  567. files.add(filePath);
  568. update();
  569. }
  570. void deleteFile(String filePath) {
  571. files.remove(filePath);
  572. update();
  573. }
  574. }