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.

596 lines
23KB

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