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.

246 lines
12KB

  1. import 'package:farm_tpf/custom_model/CropPlot.dart';
  2. import 'package:farm_tpf/data/api/app_exception.dart';
  3. import 'package:farm_tpf/data/repository/repository.dart';
  4. import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart';
  5. import 'package:farm_tpf/presentation/custom_widgets/bloc/widget_row_plot_info.dart';
  6. import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart';
  7. import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
  8. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  10. import 'package:farm_tpf/presentation/screens/plot_detail/bloc_plot_information.dart';
  11. import 'package:farm_tpf/utils/const_color.dart';
  12. import 'package:farm_tpf/utils/const_string.dart';
  13. import 'package:flutter/material.dart';
  14. import 'package:get/get.dart';
  15. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  16. import 'package:farm_tpf/utils/formatter.dart';
  17. class PlotInformationScreen extends StatefulWidget {
  18. final int cropId;
  19. final bool isShowAppbar;
  20. PlotInformationScreen({required this.cropId, this.isShowAppbar = false});
  21. @override
  22. _PlotInformationScreenState createState() => _PlotInformationScreenState();
  23. }
  24. class _PlotInformationScreenState extends State<PlotInformationScreen> with AutomaticKeepAliveClientMixin {
  25. final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  26. GlobalKey<FormState> _formKey = GlobalKey();
  27. TextEditingController _descriptionController = TextEditingController();
  28. bool _autoValidate = false;
  29. CropPlot cropPlot = CropPlot();
  30. TbCropDTO _crop = TbCropDTO();
  31. final controller = Get.put(DescriptionChangeControler());
  32. Repository _repository = Repository();
  33. String statusCrop = plot_status_unknown;
  34. String technicians = '';
  35. @override
  36. void initState() {
  37. super.initState();
  38. getPlotInfoBloc.getPlotInfo(widget.cropId, (data) {
  39. var result = data as CropPlot;
  40. cropPlot = result;
  41. _crop = result.tbCropDTO ?? TbCropDTO();
  42. switch (_crop.status) {
  43. case "STATUS_ARE_ACTIVE":
  44. statusCrop = plot_status_active;
  45. break;
  46. case "STATUS_FINISHED":
  47. statusCrop = plot_status_end;
  48. break;
  49. default:
  50. statusCrop = plot_status_unknown;
  51. }
  52. _descriptionController.text = _crop.description == null ? "" : _crop.description.toString();
  53. if (_crop.tbDetailUsers != null) {
  54. for (var i = 0; i < _crop.tbDetailUsers!.length; i++) {
  55. if (i == 0) {
  56. technicians += _crop.tbDetailUsers![i].fullName ?? '';
  57. } else {
  58. technicians += ', ${_crop.tbDetailUsers![i].fullName ?? ''}';
  59. }
  60. }
  61. }
  62. }, (err) {});
  63. }
  64. _validateInputs() async {
  65. if (_formKey.currentState!.validate()) {
  66. _formKey.currentState!.save();
  67. LoadingDialog.showLoadingDialog(context);
  68. _repository.updatePlot(_crop).then((value) {
  69. LoadingDialog.hideLoadingDialog(context);
  70. Utils.showSnackBarSuccess(message: label_update_success);
  71. controller.initValue();
  72. }).catchError((error) {
  73. LoadingDialog.hideLoadingDialog(context);
  74. Utils.showSnackBarError(message: AppException.handleError(error));
  75. });
  76. } else {
  77. _autoValidate = true;
  78. }
  79. }
  80. Widget _descriptionField() {
  81. return Container(
  82. padding: const EdgeInsets.all(8),
  83. color: AppColors.YELLOW.withOpacity(0.1),
  84. child: TextFormField(
  85. keyboardType: TextInputType.text,
  86. controller: _descriptionController,
  87. decoration: const InputDecoration(
  88. labelText: "Ghi chú", hintText: 'Ghi chú', enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 0.35))),
  89. onSaved: (newValue) {
  90. _crop.description = newValue ?? '';
  91. },
  92. onChanged: (newValue) {
  93. controller.changeValue(_crop.description ?? '', newValue);
  94. },
  95. ),
  96. );
  97. }
  98. @override
  99. Widget build(BuildContext context) => KeyboardDismisser(
  100. gestures: [GestureType.onTap],
  101. child: Container(
  102. color: AppColors.ITEM_BG,
  103. child: SafeArea(
  104. top: false,
  105. bottom: true,
  106. child: Scaffold(
  107. appBar: widget.isShowAppbar ? AppBarWidget() : null,
  108. key: _scaffoldKey,
  109. body: KeyboardDismisser(
  110. child: StreamBuilder(
  111. stream: getPlotInfoBloc.actions,
  112. builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
  113. if (snapshot.hasData) {
  114. return Form(
  115. key: _formKey,
  116. // autovalidate: _autoValidate,
  117. child: SingleChildScrollView(
  118. padding: const EdgeInsets.all(8.0),
  119. child: Column(
  120. children: <Widget>[
  121. WidgetRowPlotInfo(
  122. color: AppColors.DEFAULT.withOpacity(0.1), name: 'Mã lô', value: '${cropPlot.tbCropDTO?.code}'),
  123. WidgetRowPlotInfo(color: AppColors.DEFAULT.withOpacity(0.3), name: 'Trạng thái', value: '$statusCrop'),
  124. WidgetRowPlotInfo(
  125. color: AppColors.DEFAULT.withOpacity(0.1),
  126. name: 'Nhà màng',
  127. value: '${cropPlot.tbCropDTO?.netHouseName ?? '--'}'),
  128. WidgetRowPlotInfo(
  129. color: AppColors.DEFAULT.withOpacity(0.3),
  130. name: 'Giống',
  131. value: '${cropPlot.tbCropDTO?.suppliesName ?? '--'}'),
  132. WidgetRowPlotInfo(
  133. color: AppColors.DEFAULT.withOpacity(0.1),
  134. name: 'Ngày gieo trồng',
  135. value: cropPlot.tbCropDTO?.type == 0
  136. ? '${cropPlot.tbCropDTO?.startDate?.format_DDMMYY_HHmm() ?? '--'}'
  137. : '--'),
  138. WidgetRowPlotInfo(
  139. color: AppColors.DEFAULT.withOpacity(0.3),
  140. name: 'Ngày vô khây ươm',
  141. value: cropPlot.tbCropDTO?.type == 1
  142. ? '${cropPlot.tbCropDTO?.startDate?.format_DDMMYY_HHmm() ?? '--'}'
  143. : '--'),
  144. WidgetRowPlotInfo(
  145. color: AppColors.DEFAULT.withOpacity(0.1),
  146. name: 'Thời gian ngâm hạt',
  147. value: '${cropPlot.seedIncubationTime ?? '--'} ngày'),
  148. WidgetRowPlotInfo(
  149. color: AppColors.DEFAULT.withOpacity(0.3),
  150. name: 'Số lượng cây trồng',
  151. value: '${cropPlot.numberPlants ?? '--'}'),
  152. WidgetRowPlotInfo(
  153. color: AppColors.DEFAULT.withOpacity(0.1),
  154. name: 'Số lượng cây hiện tại',
  155. value: '${cropPlot.numberCurrentPlants ?? '--'}'),
  156. WidgetRowPlotInfo(
  157. color: AppColors.DEFAULT.withOpacity(0.3),
  158. name: 'Ngày kết thúc canh tác',
  159. value: '${cropPlot.tbCropDTO?.endDate?.format_DDMMYY_HHmm() ?? '--'}'),
  160. WidgetRowPlotInfo(color: AppColors.DEFAULT.withOpacity(0.1), name: 'Kỹ sư trực tiếp', value: '$technicians'),
  161. WidgetRowPlotInfo(
  162. color: AppColors.DEFAULT.withOpacity(0.3),
  163. name: 'Diện tích (m\u00B2)',
  164. value: '${cropPlot.tbCropDTO?.areaM2?.formatNumtoStringDecimal()}'),
  165. const SizedBox(
  166. height: 8,
  167. ),
  168. _descriptionField(),
  169. const SizedBox(
  170. height: 16,
  171. ),
  172. GetBuilder<DescriptionChangeControler>(
  173. builder: (_) {
  174. return SizedBox(
  175. width: double.infinity,
  176. height: 55,
  177. child: FlatButton(
  178. onPressed: controller.isChanged == false
  179. ? () {}
  180. : () {
  181. var currentFocus = FocusScope.of(context);
  182. if (!currentFocus.hasPrimaryFocus) {
  183. currentFocus.unfocus();
  184. }
  185. _validateInputs();
  186. },
  187. color: controller.isChanged ? AppColors.DEFAULT : Colors.grey[400],
  188. shape: RoundedRectangleBorder(
  189. borderRadius: BorderRadius.circular(7.0),
  190. ),
  191. child: Text('Cập nhật'.toUpperCase(),
  192. style: TextStyle(fontWeight: FontWeight.bold, color: AppColors.WHITE, fontSize: 18)),
  193. ),
  194. );
  195. },
  196. )
  197. ],
  198. ),
  199. ));
  200. } else if (snapshot.hasError) {
  201. return Center(
  202. child: Text(snapshot.error.toString()),
  203. );
  204. } else {
  205. return LoadingListPage();
  206. }
  207. }))))));
  208. @override
  209. void dispose() {
  210. _descriptionController.dispose();
  211. super.dispose();
  212. }
  213. @override
  214. bool get wantKeepAlive => true;
  215. }
  216. class DescriptionChangeControler extends GetxController {
  217. bool isChanged = false;
  218. void initValue() {
  219. isChanged = false;
  220. update();
  221. }
  222. void changeValue(String oldValue, String newValue) {
  223. if (oldValue != newValue) {
  224. isChanged = true;
  225. } else {
  226. isChanged = false;
  227. }
  228. if (oldValue.isNullOrBlank && newValue.isEmpty) {
  229. isChanged = false;
  230. }
  231. update();
  232. }
  233. }