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.

560 lines
22KB

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