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.

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