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.

534 lines
21KB

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